aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2010-01-29 16:44:25 -0500
committerJ. Bruce Fields <bfields@citi.umich.edu>2010-01-29 18:53:11 -0500
commitaa696a6f349638428982bb52763f4cda851632fa (patch)
tree0a539326e81aa2eaacb2a57c9882d37e988058b3 /fs
parent37498292aa97658a5d0a9bb84699ce8c1016bb74 (diff)
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfsd/vfs.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 79d216f276d9..ed024d329056 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1141,8 +1141,9 @@ out:
1141#ifdef CONFIG_NFSD_V3 1141#ifdef CONFIG_NFSD_V3
1142/* 1142/*
1143 * Commit all pending writes to stable storage. 1143 * Commit all pending writes to stable storage.
1144 * Strictly speaking, we could sync just the indicated file region here, 1144 *
1145 * but there's currently no way we can ask the VFS to do so. 1145 * Note: we only guarantee that data that lies within the range specified
1146 * by the 'offset' and 'count' parameters will be synced.
1146 * 1147 *
1147 * Unfortunately we cannot lock the file to make sure we return full WCC 1148 * Unfortunately we cannot lock the file to make sure we return full WCC
1148 * data to the client, as locking happens lower down in the filesystem. 1149 * 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 loff_t offset, unsigned long count) 1153 loff_t offset, unsigned long count)
1153{ 1154{
1154 struct file *file; 1155 struct file *file;
1155 __be32 err; 1156 loff_t end = LLONG_MAX;
1157 __be32 err = nfserr_inval;
1156 1158
1157 if ((u64)count > ~(u64)offset) 1159 if (offset < 0)
1158 return nfserr_inval; 1160 goto out;
1161 if (count != 0) {
1162 end = offset + (loff_t)count - 1;
1163 if (end < offset)
1164 goto out;
1165 }
1159 1166
1160 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file); 1167 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file);
1161 if (err) 1168 if (err)
1162 return err; 1169 goto out;
1163 if (EX_ISSYNC(fhp->fh_export)) { 1170 if (EX_ISSYNC(fhp->fh_export)) {
1164 if (file->f_op && file->f_op->fsync) { 1171 int err2 = vfs_fsync_range(file, file->f_path.dentry,
1165 err = nfserrno(vfs_fsync(file, file->f_path.dentry, 0)); 1172 offset, end, 0);
1166 } else { 1173
1174 if (err2 != -EINVAL)
1175 err = nfserrno(err2);
1176 else
1167 err = nfserr_notsupp; 1177 err = nfserr_notsupp;
1168 }
1169 } 1178 }
1170 1179
1171 nfsd_close(file); 1180 nfsd_close(file);
1181out:
1172 return err; 1182 return err;
1173} 1183}
1174#endif /* CONFIG_NFSD_V3 */ 1184#endif /* CONFIG_NFSD_V3 */