diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-07-31 14:29:06 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-08-03 22:06:07 -0400 |
commit | af7fa16506bf9b6323e862a61e14c20555152bb3 (patch) | |
tree | a9d5e5713d1d4662c0fb2097f506e60036404a37 /fs/nfs/file.c | |
parent | 77041ed9b49a9e10f374bfa6e482d30ee7a3d46e (diff) |
NFS: Fix up the fsync code
Christoph points out that the VFS will always flush out data before calling
nfs_fsync(), so we can dispense with a full call to nfs_wb_all(), and
replace that with a simpler call to nfs_commit_inode().
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r-- | fs/nfs/file.c | 51 |
1 files changed, 21 insertions, 30 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 36a5e74f51b4..f36581cd4767 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -202,37 +202,11 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) | |||
202 | } | 202 | } |
203 | 203 | ||
204 | /* | 204 | /* |
205 | * Helper for nfs_file_flush() and nfs_file_fsync() | ||
206 | * | ||
207 | * Notice that it clears the NFS_CONTEXT_ERROR_WRITE before synching to | ||
208 | * disk, but it retrieves and clears ctx->error after synching, despite | ||
209 | * the two being set at the same time in nfs_context_set_write_error(). | ||
210 | * This is because the former is used to notify the _next_ call to | ||
211 | * nfs_file_write() that a write error occured, and hence cause it to | ||
212 | * fall back to doing a synchronous write. | ||
213 | */ | ||
214 | static int nfs_do_fsync(struct nfs_open_context *ctx, struct inode *inode) | ||
215 | { | ||
216 | int have_error, status; | ||
217 | int ret = 0; | ||
218 | |||
219 | have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); | ||
220 | status = nfs_wb_all(inode); | ||
221 | have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); | ||
222 | if (have_error) | ||
223 | ret = xchg(&ctx->error, 0); | ||
224 | if (!ret) | ||
225 | ret = status; | ||
226 | return ret; | ||
227 | } | ||
228 | |||
229 | /* | ||
230 | * Flush all dirty pages, and check for write errors. | 205 | * Flush all dirty pages, and check for write errors. |
231 | */ | 206 | */ |
232 | static int | 207 | static int |
233 | nfs_file_flush(struct file *file, fl_owner_t id) | 208 | nfs_file_flush(struct file *file, fl_owner_t id) |
234 | { | 209 | { |
235 | struct nfs_open_context *ctx = nfs_file_open_context(file); | ||
236 | struct dentry *dentry = file->f_path.dentry; | 210 | struct dentry *dentry = file->f_path.dentry; |
237 | struct inode *inode = dentry->d_inode; | 211 | struct inode *inode = dentry->d_inode; |
238 | 212 | ||
@@ -245,7 +219,7 @@ nfs_file_flush(struct file *file, fl_owner_t id) | |||
245 | return 0; | 219 | return 0; |
246 | 220 | ||
247 | /* Flush writes to the server and return any errors */ | 221 | /* Flush writes to the server and return any errors */ |
248 | return nfs_do_fsync(ctx, inode); | 222 | return vfs_fsync(file, 0); |
249 | } | 223 | } |
250 | 224 | ||
251 | static ssize_t | 225 | static ssize_t |
@@ -320,6 +294,13 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) | |||
320 | * Flush any dirty pages for this process, and check for write errors. | 294 | * Flush any dirty pages for this process, and check for write errors. |
321 | * The return status from this call provides a reliable indication of | 295 | * The return status from this call provides a reliable indication of |
322 | * whether any write errors occurred for this process. | 296 | * whether any write errors occurred for this process. |
297 | * | ||
298 | * Notice that it clears the NFS_CONTEXT_ERROR_WRITE before synching to | ||
299 | * disk, but it retrieves and clears ctx->error after synching, despite | ||
300 | * the two being set at the same time in nfs_context_set_write_error(). | ||
301 | * This is because the former is used to notify the _next_ call to | ||
302 | * nfs_file_write() that a write error occured, and hence cause it to | ||
303 | * fall back to doing a synchronous write. | ||
323 | */ | 304 | */ |
324 | static int | 305 | static int |
325 | nfs_file_fsync(struct file *file, int datasync) | 306 | nfs_file_fsync(struct file *file, int datasync) |
@@ -327,13 +308,23 @@ nfs_file_fsync(struct file *file, int datasync) | |||
327 | struct dentry *dentry = file->f_path.dentry; | 308 | struct dentry *dentry = file->f_path.dentry; |
328 | struct nfs_open_context *ctx = nfs_file_open_context(file); | 309 | struct nfs_open_context *ctx = nfs_file_open_context(file); |
329 | struct inode *inode = dentry->d_inode; | 310 | struct inode *inode = dentry->d_inode; |
311 | int have_error, status; | ||
312 | int ret = 0; | ||
313 | |||
330 | 314 | ||
331 | dprintk("NFS: fsync file(%s/%s) datasync %d\n", | 315 | dprintk("NFS: fsync file(%s/%s) datasync %d\n", |
332 | dentry->d_parent->d_name.name, dentry->d_name.name, | 316 | dentry->d_parent->d_name.name, dentry->d_name.name, |
333 | datasync); | 317 | datasync); |
334 | 318 | ||
335 | nfs_inc_stats(inode, NFSIOS_VFSFSYNC); | 319 | nfs_inc_stats(inode, NFSIOS_VFSFSYNC); |
336 | return nfs_do_fsync(ctx, inode); | 320 | have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); |
321 | status = nfs_commit_inode(inode, FLUSH_SYNC); | ||
322 | have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); | ||
323 | if (have_error) | ||
324 | ret = xchg(&ctx->error, 0); | ||
325 | if (!ret) | ||
326 | ret = status; | ||
327 | return ret; | ||
337 | } | 328 | } |
338 | 329 | ||
339 | /* | 330 | /* |
@@ -639,7 +630,7 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, | |||
639 | 630 | ||
640 | /* Return error values for O_DSYNC and IS_SYNC() */ | 631 | /* Return error values for O_DSYNC and IS_SYNC() */ |
641 | if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) { | 632 | if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) { |
642 | int err = nfs_do_fsync(nfs_file_open_context(iocb->ki_filp), inode); | 633 | int err = vfs_fsync(iocb->ki_filp, 0); |
643 | if (err < 0) | 634 | if (err < 0) |
644 | result = err; | 635 | result = err; |
645 | } | 636 | } |
@@ -675,7 +666,7 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, | |||
675 | written = ret; | 666 | written = ret; |
676 | 667 | ||
677 | if (ret >= 0 && nfs_need_sync_write(filp, inode)) { | 668 | if (ret >= 0 && nfs_need_sync_write(filp, inode)) { |
678 | int err = nfs_do_fsync(nfs_file_open_context(filp), inode); | 669 | int err = vfs_fsync(filp, 0); |
679 | if (err < 0) | 670 | if (err < 0) |
680 | ret = err; | 671 | ret = err; |
681 | } | 672 | } |