NFS: Fix up fsync() when the server rebooted
Don't clear the NFS_CONTEXT_RESEND_WRITES flag until after calling nfs_commit_inode(). Otherwise, if nfs_commit_inode() returns an error, we end up with dirty pages in the page cache, but no tag to tell us that those pages need resending. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
parent
b32d285539
commit
2197e9b06c
|
@ -204,44 +204,39 @@ EXPORT_SYMBOL_GPL(nfs_file_mmap);
|
|||
static int
|
||||
nfs_file_fsync_commit(struct file *file, int datasync)
|
||||
{
|
||||
struct nfs_open_context *ctx = nfs_file_open_context(file);
|
||||
struct inode *inode = file_inode(file);
|
||||
int do_resend, status;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
dprintk("NFS: fsync file(%pD2) datasync %d\n", file, datasync);
|
||||
|
||||
nfs_inc_stats(inode, NFSIOS_VFSFSYNC);
|
||||
do_resend = test_and_clear_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags);
|
||||
status = nfs_commit_inode(inode, FLUSH_SYNC);
|
||||
if (status == 0)
|
||||
status = file_check_and_advance_wb_err(file);
|
||||
if (status < 0) {
|
||||
ret = status;
|
||||
goto out;
|
||||
}
|
||||
do_resend |= test_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags);
|
||||
if (do_resend)
|
||||
ret = -EAGAIN;
|
||||
out:
|
||||
return ret;
|
||||
ret = nfs_commit_inode(inode, FLUSH_SYNC);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return file_check_and_advance_wb_err(file);
|
||||
}
|
||||
|
||||
int
|
||||
nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
|
||||
{
|
||||
int ret;
|
||||
struct nfs_open_context *ctx = nfs_file_open_context(file);
|
||||
struct inode *inode = file_inode(file);
|
||||
int ret;
|
||||
|
||||
trace_nfs_fsync_enter(inode);
|
||||
|
||||
do {
|
||||
for (;;) {
|
||||
ret = file_write_and_wait_range(file, start, end);
|
||||
if (ret != 0)
|
||||
break;
|
||||
ret = nfs_file_fsync_commit(file, datasync);
|
||||
if (!ret)
|
||||
ret = pnfs_sync_inode(inode, !!datasync);
|
||||
if (ret != 0)
|
||||
break;
|
||||
ret = pnfs_sync_inode(inode, !!datasync);
|
||||
if (ret != 0)
|
||||
break;
|
||||
if (!test_and_clear_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags))
|
||||
break;
|
||||
/*
|
||||
* If nfs_file_fsync_commit detected a server reboot, then
|
||||
* resend all dirty pages that might have been covered by
|
||||
|
@ -249,7 +244,7 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
|
|||
*/
|
||||
start = 0;
|
||||
end = LLONG_MAX;
|
||||
} while (ret == -EAGAIN);
|
||||
}
|
||||
|
||||
trace_nfs_fsync_exit(inode, ret);
|
||||
return ret;
|
||||
|
|
Loading…
Reference in New Issue