aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
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 */