From b2b1ff3da6b27285c725eeb6f4c274da0a8e6a60 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 27 Jun 2018 16:25:40 -0400 Subject: NFS: Allow optimisation of lseek(fd, SEEK_CUR, 0) on directories There should be no need to grab the inode lock if we're only reading the file offset. Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'fs/nfs/dir.c') diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 7a9c14426855..8f8e9e9f2a79 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -904,23 +904,29 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int whence) dfprintk(FILE, "NFS: llseek dir(%pD2, %lld, %d)\n", filp, offset, whence); - inode_lock(inode); switch (whence) { - case 1: - offset += filp->f_pos; - case 0: - if (offset >= 0) - break; - default: - offset = -EINVAL; - goto out; + default: + return -EINVAL; + case SEEK_SET: + if (offset < 0) + return -EINVAL; + inode_lock(inode); + break; + case SEEK_CUR: + if (offset == 0) + return filp->f_pos; + inode_lock(inode); + offset += filp->f_pos; + if (offset < 0) { + inode_unlock(inode); + return -EINVAL; + } } if (offset != filp->f_pos) { filp->f_pos = offset; dir_ctx->dir_cookie = 0; dir_ctx->duped = 0; } -out: inode_unlock(inode); return offset; } -- cgit v1.2.3-59-g8ed1b From cf8340277f1128c4760976d0574359e6d765893c Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 20 Jul 2018 16:19:35 -0400 Subject: NFS: Fix excessive attribute revalidation in nfs_execute_ok() When nfs_update_inode() sets NFS_INO_INVALID_ACCESS it is a sign that we want to revalidate the access cache, not the inode attributes. In fact we only want to revalidate here if we see that the mode bits are invalid, so check for NFS_INO_INVALID_OTHER instead. Reported-by: Olga Kornievskaia Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/nfs/dir.c') diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 8f8e9e9f2a79..e7bc68fcbdf4 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -2500,7 +2500,7 @@ static int nfs_execute_ok(struct inode *inode, int mask) struct nfs_server *server = NFS_SERVER(inode); int ret = 0; - if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_ACCESS)) { + if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_OTHER)) { if (mask & MAY_NOT_BLOCK) return -ECHILD; ret = __nfs_revalidate_inode(server, inode); -- cgit v1.2.3-59-g8ed1b From 3825827ebf9973600347b16e848f3de52262ab6b Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 24 Jul 2018 14:27:11 -0400 Subject: NFS: More excessive attribute revalidation in nfs_execute_ok() execute_ok() will only check the mode bits if the object is not a directory, so we don't need to revalidate the attributes in that case. Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs/nfs/dir.c') diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index e7bc68fcbdf4..f0e39583af7e 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -2500,6 +2500,8 @@ static int nfs_execute_ok(struct inode *inode, int mask) struct nfs_server *server = NFS_SERVER(inode); int ret = 0; + if (S_ISDIR(inode->i_mode)) + return 0; if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_OTHER)) { if (mask & MAY_NOT_BLOCK) return -ECHILD; -- cgit v1.2.3-59-g8ed1b From a61246c96195fc5f7500f6842e883b9eb1567d8d Mon Sep 17 00:00:00 2001 From: Lance Shelton Date: Mon, 16 Jul 2018 13:05:36 -0400 Subject: Fix error code in nfs_lookup_verify_inode() Return -ESTALE to force a lookup when the file has no more links Signed-off-by: Lance Shelton Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/nfs/dir.c') diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index f0e39583af7e..a004b8fc02da 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1038,7 +1038,7 @@ int nfs_lookup_verify_inode(struct inode *inode, unsigned int flags) if (flags & LOOKUP_REVAL) goto out_force; out: - return (inode->i_nlink == 0) ? -ENOENT : 0; + return (inode->i_nlink == 0) ? -ESTALE : 0; out_force: if (flags & LOOKUP_RCU) return -ECHILD; -- cgit v1.2.3-59-g8ed1b