aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/file.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2010-07-31 14:29:06 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-08-03 22:06:07 -0400
commitaf7fa16506bf9b6323e862a61e14c20555152bb3 (patch)
treea9d5e5713d1d4662c0fb2097f506e60036404a37 /fs/nfs/file.c
parent77041ed9b49a9e10f374bfa6e482d30ee7a3d46e (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.c51
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 */
214static 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 */
232static int 207static int
233nfs_file_flush(struct file *file, fl_owner_t id) 208nfs_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
251static ssize_t 225static 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 */
324static int 305static int
325nfs_file_fsync(struct file *file, int datasync) 306nfs_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 }