summaryrefslogtreecommitdiff
path: root/fs/nfs/dir.c
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@hammerspace.com>2018-06-27 23:25:40 +0300
committerTrond Myklebust <trond.myklebust@hammerspace.com>2018-07-26 23:25:25 +0300
commitb2b1ff3da6b27285c725eeb6f4c274da0a8e6a60 (patch)
treee583bfe5f5af635b3db7866e57d7506acbeae2ba /fs/nfs/dir.c
parent411ae722d10a6d4eece758877eb5f395b35f6e9d (diff)
downloadlinux-b2b1ff3da6b27285c725eeb6f4c274da0a8e6a60.tar.xz
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 <trond.myklebust@hammerspace.com>
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r--fs/nfs/dir.c26
1 files changed, 16 insertions, 10 deletions
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;
}