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: Trond Myklebust <Trond.Myklebust@netapp.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
This commit is contained in:
Trond Myklebust 2010-01-29 16:44:25 -05:00 committed by J. Bruce Fields
parent 37498292aa
commit aa696a6f34
1 changed files with 20 additions and 10 deletions

View File

@ -1141,8 +1141,9 @@ out:
#ifdef CONFIG_NFSD_V3
/*
* 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
* 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,
loff_t offset, unsigned long count)
{
struct file *file;
__be32 err;
loff_t end = LLONG_MAX;
__be32 err = nfserr_inval;
if ((u64)count > ~(u64)offset)
return nfserr_inval;
if (offset < 0)
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);
if (err)
return err;
goto out;
if (EX_ISSYNC(fhp->fh_export)) {
if (file->f_op && file->f_op->fsync) {
err = nfserrno(vfs_fsync(file, file->f_path.dentry, 0));
} else {
int err2 = vfs_fsync_range(file, file->f_path.dentry,
offset, end, 0);
if (err2 != -EINVAL)
err = nfserrno(err2);
else
err = nfserr_notsupp;
}
}
nfsd_close(file);
out:
return err;
}
#endif /* CONFIG_NFSD_V3 */