aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r--fs/nfs/file.c41
1 files changed, 29 insertions, 12 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index f692be97676d..582bb8866131 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -259,7 +259,7 @@ nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync)
259 struct dentry *dentry = file->f_path.dentry; 259 struct dentry *dentry = file->f_path.dentry;
260 struct nfs_open_context *ctx = nfs_file_open_context(file); 260 struct nfs_open_context *ctx = nfs_file_open_context(file);
261 struct inode *inode = dentry->d_inode; 261 struct inode *inode = dentry->d_inode;
262 int have_error, status; 262 int have_error, do_resend, status;
263 int ret = 0; 263 int ret = 0;
264 264
265 dprintk("NFS: fsync file(%s/%s) datasync %d\n", 265 dprintk("NFS: fsync file(%s/%s) datasync %d\n",
@@ -267,15 +267,23 @@ nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync)
267 datasync); 267 datasync);
268 268
269 nfs_inc_stats(inode, NFSIOS_VFSFSYNC); 269 nfs_inc_stats(inode, NFSIOS_VFSFSYNC);
270 do_resend = test_and_clear_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags);
270 have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); 271 have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
271 status = nfs_commit_inode(inode, FLUSH_SYNC); 272 status = nfs_commit_inode(inode, FLUSH_SYNC);
272 if (status >= 0 && ret < 0)
273 status = ret;
274 have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); 273 have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
275 if (have_error) 274 if (have_error) {
276 ret = xchg(&ctx->error, 0); 275 ret = xchg(&ctx->error, 0);
277 if (!ret && status < 0) 276 if (ret)
277 goto out;
278 }
279 if (status < 0) {
278 ret = status; 280 ret = status;
281 goto out;
282 }
283 do_resend |= test_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags);
284 if (do_resend)
285 ret = -EAGAIN;
286out:
279 return ret; 287 return ret;
280} 288}
281EXPORT_SYMBOL_GPL(nfs_file_fsync_commit); 289EXPORT_SYMBOL_GPL(nfs_file_fsync_commit);
@@ -286,13 +294,22 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
286 int ret; 294 int ret;
287 struct inode *inode = file->f_path.dentry->d_inode; 295 struct inode *inode = file->f_path.dentry->d_inode;
288 296
289 ret = filemap_write_and_wait_range(inode->i_mapping, start, end); 297 do {
290 if (ret != 0) 298 ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
291 goto out; 299 if (ret != 0)
292 mutex_lock(&inode->i_mutex); 300 break;
293 ret = nfs_file_fsync_commit(file, start, end, datasync); 301 mutex_lock(&inode->i_mutex);
294 mutex_unlock(&inode->i_mutex); 302 ret = nfs_file_fsync_commit(file, start, end, datasync);
295out: 303 mutex_unlock(&inode->i_mutex);
304 /*
305 * If nfs_file_fsync_commit detected a server reboot, then
306 * resend all dirty pages that might have been covered by
307 * the NFS_CONTEXT_RESEND_WRITES flag
308 */
309 start = 0;
310 end = LLONG_MAX;
311 } while (ret == -EAGAIN);
312
296 return ret; 313 return ret;
297} 314}
298 315