diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfsd/vfs.c | 30 |
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); |
1181 | out: | ||
1172 | return err; | 1182 | return err; |
1173 | } | 1183 | } |
1174 | #endif /* CONFIG_NFSD_V3 */ | 1184 | #endif /* CONFIG_NFSD_V3 */ |