aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4file.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-09-11 16:01:22 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-09-28 16:03:05 -0400
commit05990d1bf2708b9e84d67074551f964d3738eedc (patch)
treeb4133627b503563eadea21aab695df78080402e1 /fs/nfs/nfs4file.c
parent795a88c968eef031f370973512b42124bacb2f17 (diff)
NFS: Fix fdatasync/fsync() when confronted with a server reboot
If the server reboots before it can commit the unstable writes to disk, then nfs_commit_release_pages() will detect this when it compares the verifier returned by COMMIT to the one returned by WRITE. When this happens, the client needs to resend those writes in order to guarantee that they make it to stable storage. This patch adds a signalling mechanism to notify fsync() that it needs to retry all writes before it can exit. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4file.c')
-rw-r--r--fs/nfs/nfs4file.c22
1 files changed, 12 insertions, 10 deletions
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
index eb5eb8eef4d3..eef1b38a1b08 100644
--- a/fs/nfs/nfs4file.c
+++ b/fs/nfs/nfs4file.c
@@ -95,16 +95,18 @@ nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
95 int ret; 95 int ret;
96 struct inode *inode = file->f_path.dentry->d_inode; 96 struct inode *inode = file->f_path.dentry->d_inode;
97 97
98 ret = filemap_write_and_wait_range(inode->i_mapping, start, end); 98 do {
99 if (ret != 0) 99 ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
100 goto out; 100 if (ret != 0)
101 mutex_lock(&inode->i_mutex); 101 break;
102 ret = nfs_file_fsync_commit(file, start, end, datasync); 102 mutex_lock(&inode->i_mutex);
103 if (!ret && !datasync) 103 ret = nfs_file_fsync_commit(file, start, end, datasync);
104 /* application has asked for meta-data sync */ 104 if (!ret && !datasync)
105 ret = pnfs_layoutcommit_inode(inode, true); 105 /* application has asked for meta-data sync */
106 mutex_unlock(&inode->i_mutex); 106 ret = pnfs_layoutcommit_inode(inode, true);
107out: 107 mutex_unlock(&inode->i_mutex);
108 } while (ret == -EAGAIN);
109
108 return ret; 110 return ret;
109} 111}
110 112