Commit aa696a6f authored by Trond Myklebust's avatar Trond Myklebust Committed by J. Bruce Fields

nfsd: Use vfs_fsync_range() in nfsd_commit

The NFS COMMIT operation allows the client to specify the exact byte range
that it wishes to sync to disk in order to optimise server performance.
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
parent 37498292
...@@ -1141,8 +1141,9 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, ...@@ -1141,8 +1141,9 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
#ifdef CONFIG_NFSD_V3 #ifdef CONFIG_NFSD_V3
/* /*
* Commit all pending writes to stable storage. * Commit all pending writes to stable storage.
* Strictly speaking, we could sync just the indicated file region here, *
* but there's currently no way we can ask the VFS to do so. * Note: we only guarantee that data that lies within the range specified
* by the 'offset' and 'count' parameters will be synced.
* *
* Unfortunately we cannot lock the file to make sure we return full WCC * Unfortunately we cannot lock the file to make sure we return full WCC
* data to the client, as locking happens lower down in the filesystem. * data to the client, as locking happens lower down in the filesystem.
...@@ -1152,23 +1153,32 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, ...@@ -1152,23 +1153,32 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
loff_t offset, unsigned long count) loff_t offset, unsigned long count)
{ {
struct file *file; struct file *file;
__be32 err; loff_t end = LLONG_MAX;
__be32 err = nfserr_inval;
if ((u64)count > ~(u64)offset) if (offset < 0)
return nfserr_inval; goto out;
if (count != 0) {
end = offset + (loff_t)count - 1;
if (end < offset)
goto out;
}
err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file); err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file);
if (err) if (err)
return err; goto out;
if (EX_ISSYNC(fhp->fh_export)) { if (EX_ISSYNC(fhp->fh_export)) {
if (file->f_op && file->f_op->fsync) { int err2 = vfs_fsync_range(file, file->f_path.dentry,
err = nfserrno(vfs_fsync(file, file->f_path.dentry, 0)); offset, end, 0);
} else {
if (err2 != -EINVAL)
err = nfserrno(err2);
else
err = nfserr_notsupp; err = nfserr_notsupp;
}
} }
nfsd_close(file); nfsd_close(file);
out:
return err; return err;
} }
#endif /* CONFIG_NFSD_V3 */ #endif /* CONFIG_NFSD_V3 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment