diff options
author | David S. Miller | 2017-10-30 14:10:01 +0900 |
---|---|---|
committer | David S. Miller | 2017-10-30 21:09:24 +0900 |
commit | e1ea2f9856b765a2eaabb403a6751f70efc9ba4c (patch) | |
tree | 771f0f96fdab1b27757730e96d911c73f5499ee4 /fs | |
parent | aad93c70b9a3b80dbc383a31e77a119f69bdd856 (diff) | |
parent | 0b07194bb55ed836c2cc7c22e866b87a14681984 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Several conflicts here.
NFP driver bug fix adding nfp_netdev_is_nfp_repr() check to
nfp_fl_output() needed some adjustments because the code block is in
an else block now.
Parallel additions to net/pkt_cls.h and net/sch_generic.h
A bug fix in __tcp_retransmit_skb() conflicted with some of
the rbtree changes in net-next.
The tc action RCU callback fixes in 'net' had some overlap with some
of the recent tcf_block reworking.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ceph/caps.c | 5 | ||||
-rw-r--r-- | fs/cifs/Kconfig | 5 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 8 | ||||
-rw-r--r-- | fs/cifs/smb2maperror.c | 2 | ||||
-rw-r--r-- | fs/cifs/smb2ops.c | 31 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 33 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.h | 5 | ||||
-rw-r--r-- | fs/cifs/smb2proto.h | 1 | ||||
-rw-r--r-- | fs/cifs/smb2transport.c | 26 | ||||
-rw-r--r-- | fs/fuse/dir.c | 3 | ||||
-rw-r--r-- | fs/overlayfs/inode.c | 20 | ||||
-rw-r--r-- | fs/overlayfs/namei.c | 32 | ||||
-rw-r--r-- | fs/overlayfs/overlayfs.h | 3 | ||||
-rw-r--r-- | fs/overlayfs/readdir.c | 11 | ||||
-rw-r--r-- | fs/overlayfs/super.c | 3 | ||||
-rw-r--r-- | fs/xfs/xfs_file.c | 21 |
16 files changed, 138 insertions, 71 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 157fe59fbabe..1978a8cb1cb1 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -1991,6 +1991,7 @@ static int try_flush_caps(struct inode *inode, u64 *ptid) retry: spin_lock(&ci->i_ceph_lock); if (ci->i_ceph_flags & CEPH_I_NOFLUSH) { + spin_unlock(&ci->i_ceph_lock); dout("try_flush_caps skipping %p I_NOFLUSH set\n", inode); goto out; } @@ -2008,8 +2009,10 @@ retry: mutex_lock(&session->s_mutex); goto retry; } - if (cap->session->s_state < CEPH_MDS_SESSION_OPEN) + if (cap->session->s_state < CEPH_MDS_SESSION_OPEN) { + spin_unlock(&ci->i_ceph_lock); goto out; + } flushing = __mark_caps_flushing(inode, session, true, &flush_tid, &oldest_flush_tid); diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index f7243617316c..d5b2e12b5d02 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig @@ -5,9 +5,14 @@ config CIFS select CRYPTO select CRYPTO_MD4 select CRYPTO_MD5 + select CRYPTO_SHA256 + select CRYPTO_CMAC select CRYPTO_HMAC select CRYPTO_ARC4 + select CRYPTO_AEAD2 + select CRYPTO_CCM select CRYPTO_ECB + select CRYPTO_AES select CRYPTO_DES help This is the client VFS module for the SMB3 family of NAS protocols, diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index de5b2e1fcce5..e185b2853eab 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -661,7 +661,9 @@ struct TCP_Server_Info { #endif unsigned int max_read; unsigned int max_write; - __u8 preauth_hash[512]; +#ifdef CONFIG_CIFS_SMB311 + __u8 preauth_sha_hash[64]; /* save initital negprot hash */ +#endif /* 3.1.1 */ struct delayed_work reconnect; /* reconnect workqueue job */ struct mutex reconnect_mutex; /* prevent simultaneous reconnects */ unsigned long echo_interval; @@ -849,7 +851,9 @@ struct cifs_ses { __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE]; __u8 smb3encryptionkey[SMB3_SIGN_KEY_SIZE]; __u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE]; - __u8 preauth_hash[512]; +#ifdef CONFIG_CIFS_SMB311 + __u8 preauth_sha_hash[64]; +#endif /* 3.1.1 */ }; static inline bool diff --git a/fs/cifs/smb2maperror.c b/fs/cifs/smb2maperror.c index 7ca9808a0daa..62c88dfed57b 100644 --- a/fs/cifs/smb2maperror.c +++ b/fs/cifs/smb2maperror.c @@ -214,7 +214,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = { {STATUS_DATATYPE_MISALIGNMENT, -EIO, "STATUS_DATATYPE_MISALIGNMENT"}, {STATUS_BREAKPOINT, -EIO, "STATUS_BREAKPOINT"}, {STATUS_SINGLE_STEP, -EIO, "STATUS_SINGLE_STEP"}, - {STATUS_BUFFER_OVERFLOW, -EIO, "STATUS_BUFFER_OVERFLOW"}, + {STATUS_BUFFER_OVERFLOW, -E2BIG, "STATUS_BUFFER_OVERFLOW"}, {STATUS_NO_MORE_FILES, -ENODATA, "STATUS_NO_MORE_FILES"}, {STATUS_WAKE_SYSTEM_DEBUGGER, -EIO, "STATUS_WAKE_SYSTEM_DEBUGGER"}, {STATUS_HANDLES_CLOSED, -EIO, "STATUS_HANDLES_CLOSED"}, diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 0dafdbae1f8c..bdb963d0ba32 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -522,6 +522,7 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_open_parms oparms; struct cifs_fid fid; struct smb2_file_full_ea_info *smb2_data; + int ea_buf_size = SMB2_MIN_EA_BUF; utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); if (!utf16_path) @@ -541,14 +542,32 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, return rc; } - smb2_data = kzalloc(SMB2_MAX_EA_BUF, GFP_KERNEL); - if (smb2_data == NULL) { - SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); - return -ENOMEM; + while (1) { + smb2_data = kzalloc(ea_buf_size, GFP_KERNEL); + if (smb2_data == NULL) { + SMB2_close(xid, tcon, fid.persistent_fid, + fid.volatile_fid); + return -ENOMEM; + } + + rc = SMB2_query_eas(xid, tcon, fid.persistent_fid, + fid.volatile_fid, + ea_buf_size, smb2_data); + + if (rc != -E2BIG) + break; + + kfree(smb2_data); + ea_buf_size <<= 1; + + if (ea_buf_size > SMB2_MAX_EA_BUF) { + cifs_dbg(VFS, "EA size is too large\n"); + SMB2_close(xid, tcon, fid.persistent_fid, + fid.volatile_fid); + return -ENOMEM; + } } - rc = SMB2_query_eas(xid, tcon, fid.persistent_fid, fid.volatile_fid, - smb2_data); SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); if (!rc) diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 6f0e6343c15e..5331631386a2 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -648,7 +648,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) { int rc = 0; struct validate_negotiate_info_req vneg_inbuf; - struct validate_negotiate_info_rsp *pneg_rsp; + struct validate_negotiate_info_rsp *pneg_rsp = NULL; u32 rsplen; u32 inbuflen; /* max of 4 dialects */ @@ -727,8 +727,9 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) rsplen); /* relax check since Mac returns max bufsize allowed on ioctl */ - if (rsplen > CIFSMaxBufSize) - return -EIO; + if ((rsplen > CIFSMaxBufSize) + || (rsplen < sizeof(struct validate_negotiate_info_rsp))) + goto err_rsp_free; } /* check validate negotiate info response matches what we got earlier */ @@ -747,10 +748,13 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) /* validate negotiate successful */ cifs_dbg(FYI, "validate negotiate info successful\n"); + kfree(pneg_rsp); return 0; vneg_out: cifs_dbg(VFS, "protocol revalidation - security settings mismatch\n"); +err_rsp_free: + kfree(pneg_rsp); return -EIO; } @@ -1255,7 +1259,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, struct smb2_tree_connect_req *req; struct smb2_tree_connect_rsp *rsp = NULL; struct kvec iov[2]; - struct kvec rsp_iov; + struct kvec rsp_iov = { NULL, 0 }; int rc = 0; int resp_buftype; int unc_path_len; @@ -1372,7 +1376,7 @@ tcon_exit: return rc; tcon_error_exit: - if (rsp->hdr.sync_hdr.Status == STATUS_BAD_NETWORK_NAME) { + if (rsp && rsp->hdr.sync_hdr.Status == STATUS_BAD_NETWORK_NAME) { cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); } goto tcon_exit; @@ -1975,6 +1979,9 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, } else iov[0].iov_len = get_rfc1002_length(req) + 4; + /* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */ + if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO) + req->hdr.sync_hdr.Flags |= SMB2_FLAGS_SIGNED; rc = SendReceive2(xid, ses, iov, n_iov, &resp_buftype, flags, &rsp_iov); cifs_small_buf_release(req); @@ -2191,9 +2198,13 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon, req->PersistentFileId = persistent_fid; req->VolatileFileId = volatile_fid; req->AdditionalInformation = cpu_to_le32(additional_info); - /* 4 for rfc1002 length field and 1 for Buffer */ - req->InputBufferOffset = - cpu_to_le16(sizeof(struct smb2_query_info_req) - 1 - 4); + + /* + * We do not use the input buffer (do not send extra byte) + */ + req->InputBufferOffset = 0; + inc_rfc1001_len(req, -1); + req->OutputBufferLength = cpu_to_le32(output_len); iov[0].iov_base = (char *)req; @@ -2233,12 +2244,12 @@ qinf_exit: } int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, - u64 persistent_fid, u64 volatile_fid, - struct smb2_file_full_ea_info *data) + u64 persistent_fid, u64 volatile_fid, + int ea_buf_size, struct smb2_file_full_ea_info *data) { return query_info(xid, tcon, persistent_fid, volatile_fid, FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE, 0, - SMB2_MAX_EA_BUF, + ea_buf_size, sizeof(struct smb2_file_full_ea_info), (void **)&data, NULL); diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index 6c9653a130c8..c2ec934be968 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h @@ -832,7 +832,7 @@ struct smb2_flush_rsp { /* Channel field for read and write: exactly one of following flags can be set*/ #define SMB2_CHANNEL_NONE 0x00000000 #define SMB2_CHANNEL_RDMA_V1 0x00000001 /* SMB3 or later */ -#define SMB2_CHANNEL_RDMA_V1_INVALIDATE 0x00000001 /* SMB3.02 or later */ +#define SMB2_CHANNEL_RDMA_V1_INVALIDATE 0x00000002 /* SMB3.02 or later */ /* SMB2 read request without RFC1001 length at the beginning */ struct smb2_read_plain_req { @@ -1178,7 +1178,8 @@ struct smb2_file_link_info { /* encoding of request for level 11 */ char FileName[0]; /* Name to be assigned to new link */ } __packed; /* level 11 Set */ -#define SMB2_MAX_EA_BUF 2048 +#define SMB2_MIN_EA_BUF 2048 +#define SMB2_MAX_EA_BUF 65536 struct smb2_file_full_ea_info { /* encoding of response for level 15 */ __le32 next_entry_offset; diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 003217099ef3..e9ab5227e7a8 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h @@ -134,6 +134,7 @@ extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_file_id, u64 volatile_file_id); extern int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_file_id, u64 volatile_file_id, + int ea_buf_size, struct smb2_file_full_ea_info *data); extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_file_id, u64 volatile_file_id, diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index 67367cf1f8cd..99493946e2f9 100644 --- a/fs/cifs/smb2transport.c +++ b/fs/cifs/smb2transport.c @@ -390,6 +390,7 @@ generate_smb30signingkey(struct cifs_ses *ses) return generate_smb3signingkey(ses, &triplet); } +#ifdef CONFIG_CIFS_SMB311 int generate_smb311signingkey(struct cifs_ses *ses) @@ -398,25 +399,26 @@ generate_smb311signingkey(struct cifs_ses *ses) struct derivation *d; d = &triplet.signing; - d->label.iov_base = "SMB2AESCMAC"; - d->label.iov_len = 12; - d->context.iov_base = "SmbSign"; - d->context.iov_len = 8; + d->label.iov_base = "SMBSigningKey"; + d->label.iov_len = 14; + d->context.iov_base = ses->preauth_sha_hash; + d->context.iov_len = 64; d = &triplet.encryption; - d->label.iov_base = "SMB2AESCCM"; - d->label.iov_len = 11; - d->context.iov_base = "ServerIn "; - d->context.iov_len = 10; + d->label.iov_base = "SMBC2SCipherKey"; + d->label.iov_len = 16; + d->context.iov_base = ses->preauth_sha_hash; + d->context.iov_len = 64; d = &triplet.decryption; - d->label.iov_base = "SMB2AESCCM"; - d->label.iov_len = 11; - d->context.iov_base = "ServerOut"; - d->context.iov_len = 10; + d->label.iov_base = "SMBS2CCipherKey"; + d->label.iov_len = 16; + d->context.iov_base = ses->preauth_sha_hash; + d->context.iov_len = 64; return generate_smb3signingkey(ses, &triplet); } +#endif /* 311 */ int smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 622081b97426..24967382a7b1 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -1308,7 +1308,8 @@ static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file, */ over = !dir_emit(ctx, dirent->name, dirent->namelen, dirent->ino, dirent->type); - ctx->pos = dirent->off; + if (!over) + ctx->pos = dirent->off; } buf += reclen; diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index a619addecafc..321511ed8c42 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -598,18 +598,30 @@ static bool ovl_verify_inode(struct inode *inode, struct dentry *lowerdentry, return true; } -struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry) +struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry, + struct dentry *index) { struct dentry *lowerdentry = ovl_dentry_lower(dentry); struct inode *realinode = upperdentry ? d_inode(upperdentry) : NULL; struct inode *inode; + /* Already indexed or could be indexed on copy up? */ + bool indexed = (index || (ovl_indexdir(dentry->d_sb) && !upperdentry)); + + if (WARN_ON(upperdentry && indexed && !lowerdentry)) + return ERR_PTR(-EIO); if (!realinode) realinode = d_inode(lowerdentry); - if (!S_ISDIR(realinode->i_mode) && - (upperdentry || (lowerdentry && ovl_indexdir(dentry->d_sb)))) { - struct inode *key = d_inode(lowerdentry ?: upperdentry); + /* + * Copy up origin (lower) may exist for non-indexed upper, but we must + * not use lower as hash key in that case. + * Hash inodes that are or could be indexed by origin inode and + * non-indexed upper inodes that could be hard linked by upper inode. + */ + if (!S_ISDIR(realinode->i_mode) && (upperdentry || indexed)) { + struct inode *key = d_inode(indexed ? lowerdentry : + upperdentry); unsigned int nlink; inode = iget5_locked(dentry->d_sb, (unsigned long) key, diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c index 654bea1a5ac9..a12dc10bf726 100644 --- a/fs/overlayfs/namei.c +++ b/fs/overlayfs/namei.c @@ -405,14 +405,13 @@ int ovl_verify_index(struct dentry *index, struct path *lowerstack, * be treated as stale (i.e. after unlink of the overlay inode). * We don't know the verification rules for directory and whiteout * index entries, because they have not been implemented yet, so return - * EROFS if those entries are found to avoid corrupting an index that - * was created by a newer kernel. + * EINVAL if those entries are found to abort the mount to avoid + * corrupting an index that was created by a newer kernel. */ - err = -EROFS; + err = -EINVAL; if (d_is_dir(index) || ovl_is_whiteout(index)) goto fail; - err = -EINVAL; if (index->d_name.len < sizeof(struct ovl_fh)*2) goto fail; @@ -507,6 +506,10 @@ static struct dentry *ovl_lookup_index(struct dentry *dentry, index = lookup_one_len_unlocked(name.name, ofs->indexdir, name.len); if (IS_ERR(index)) { err = PTR_ERR(index); + if (err == -ENOENT) { + index = NULL; + goto out; + } pr_warn_ratelimited("overlayfs: failed inode index lookup (ino=%lu, key=%*s, err=%i);\n" "overlayfs: mount with '-o index=off' to disable inodes index.\n", d_inode(origin)->i_ino, name.len, name.name, @@ -516,18 +519,9 @@ static struct dentry *ovl_lookup_index(struct dentry *dentry, inode = d_inode(index); if (d_is_negative(index)) { - if (upper && d_inode(origin)->i_nlink > 1) { - pr_warn_ratelimited("overlayfs: hard link with origin but no index (ino=%lu).\n", - d_inode(origin)->i_ino); - goto fail; - } - - dput(index); - index = NULL; + goto out_dput; } else if (upper && d_inode(upper) != inode) { - pr_warn_ratelimited("overlayfs: wrong index found (index=%pd2, ino=%lu, upper ino=%lu).\n", - index, inode->i_ino, d_inode(upper)->i_ino); - goto fail; + goto out_dput; } else if (ovl_dentry_weird(index) || ovl_is_whiteout(index) || ((inode->i_mode ^ d_inode(origin)->i_mode) & S_IFMT)) { /* @@ -547,6 +541,11 @@ out: kfree(name.name); return index; +out_dput: + dput(index); + index = NULL; + goto out; + fail: dput(index); index = ERR_PTR(-EIO); @@ -635,6 +634,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, } if (d.redirect) { + err = -ENOMEM; upperredirect = kstrdup(d.redirect, GFP_KERNEL); if (!upperredirect) goto out_put_upper; @@ -709,7 +709,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, upperdentry = dget(index); if (upperdentry || ctr) { - inode = ovl_get_inode(dentry, upperdentry); + inode = ovl_get_inode(dentry, upperdentry, index); err = PTR_ERR(inode); if (IS_ERR(inode)) goto out_free_oe; diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index c706a6f99928..d9a0edd4e57e 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -286,7 +286,8 @@ int ovl_update_time(struct inode *inode, struct timespec *ts, int flags); bool ovl_is_private_xattr(const char *name); struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, dev_t rdev); -struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry); +struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry, + struct dentry *index); static inline void ovl_copyattr(struct inode *from, struct inode *to) { to->i_uid = from->i_uid; diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c index 0f85ee9c3268..698b74dd750e 100644 --- a/fs/overlayfs/readdir.c +++ b/fs/overlayfs/readdir.c @@ -1021,13 +1021,12 @@ int ovl_indexdir_cleanup(struct dentry *dentry, struct vfsmount *mnt, break; } err = ovl_verify_index(index, lowerstack, numlower); - if (err) { - if (err == -EROFS) - break; + /* Cleanup stale and orphan index entries */ + if (err && (err == -ESTALE || err == -ENOENT)) err = ovl_cleanup(dir, index); - if (err) - break; - } + if (err) + break; + dput(index); index = NULL; } diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 092d150643c1..f5738e96a052 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -174,6 +174,9 @@ static struct inode *ovl_alloc_inode(struct super_block *sb) { struct ovl_inode *oi = kmem_cache_alloc(ovl_inode_cachep, GFP_KERNEL); + if (!oi) + return NULL; + oi->cache = NULL; oi->redirect = NULL; oi->version = 0; diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 56d0e526870c..6526ef0e2a23 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -237,11 +237,13 @@ xfs_file_dax_read( if (!count) return 0; /* skip atime */ - if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) { - if (iocb->ki_flags & IOCB_NOWAIT) + if (iocb->ki_flags & IOCB_NOWAIT) { + if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) return -EAGAIN; + } else { xfs_ilock(ip, XFS_IOLOCK_SHARED); } + ret = dax_iomap_rw(iocb, to, &xfs_iomap_ops); xfs_iunlock(ip, XFS_IOLOCK_SHARED); @@ -259,9 +261,10 @@ xfs_file_buffered_aio_read( trace_xfs_file_buffered_read(ip, iov_iter_count(to), iocb->ki_pos); - if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) { - if (iocb->ki_flags & IOCB_NOWAIT) + if (iocb->ki_flags & IOCB_NOWAIT) { + if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) return -EAGAIN; + } else { xfs_ilock(ip, XFS_IOLOCK_SHARED); } ret = generic_file_read_iter(iocb, to); @@ -552,9 +555,10 @@ xfs_file_dio_aio_write( iolock = XFS_IOLOCK_SHARED; } - if (!xfs_ilock_nowait(ip, iolock)) { - if (iocb->ki_flags & IOCB_NOWAIT) + if (iocb->ki_flags & IOCB_NOWAIT) { + if (!xfs_ilock_nowait(ip, iolock)) return -EAGAIN; + } else { xfs_ilock(ip, iolock); } @@ -606,9 +610,10 @@ xfs_file_dax_write( size_t count; loff_t pos; - if (!xfs_ilock_nowait(ip, iolock)) { - if (iocb->ki_flags & IOCB_NOWAIT) + if (iocb->ki_flags & IOCB_NOWAIT) { + if (!xfs_ilock_nowait(ip, iolock)) return -EAGAIN; + } else { xfs_ilock(ip, iolock); } |