diff options
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r-- | fs/nfs/file.c | 49 |
1 files changed, 28 insertions, 21 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 8eb731d9be3e..f96367a2463e 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -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; @@ -489,7 +484,19 @@ static int nfs_launder_page(struct page *page) static int nfs_swap_activate(struct swap_info_struct *sis, struct file *file, sector_t *span) { + unsigned long blocks; + long long isize; struct rpc_clnt *clnt = NFS_CLIENT(file->f_mapping->host); + struct inode *inode = file->f_mapping->host; + + spin_lock(&inode->i_lock); + blocks = inode->i_blocks; + isize = inode->i_size; + spin_unlock(&inode->i_lock); + if (blocks*512 < isize) { + pr_warn("swap activate: swapfile has holes\n"); + return -EINVAL; + } *span = sis->pages; |