diff options
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r-- | fs/nfs/file.c | 84 |
1 files changed, 44 insertions, 40 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 8d965bddb87e..2d141a74ae82 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/pagemap.h> | 27 | #include <linux/pagemap.h> |
28 | #include <linux/aio.h> | 28 | #include <linux/aio.h> |
29 | #include <linux/gfp.h> | 29 | #include <linux/gfp.h> |
30 | #include <linux/swap.h> | ||
30 | 31 | ||
31 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> |
32 | #include <asm/system.h> | 33 | #include <asm/system.h> |
@@ -53,7 +54,7 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, | |||
53 | static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov, | 54 | static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov, |
54 | unsigned long nr_segs, loff_t pos); | 55 | unsigned long nr_segs, loff_t pos); |
55 | static int nfs_file_flush(struct file *, fl_owner_t id); | 56 | static int nfs_file_flush(struct file *, fl_owner_t id); |
56 | static int nfs_file_fsync(struct file *, struct dentry *dentry, int datasync); | 57 | static int nfs_file_fsync(struct file *, int datasync); |
57 | static int nfs_check_flags(int flags); | 58 | static int nfs_check_flags(int flags); |
58 | static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl); | 59 | static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl); |
59 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); | 60 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); |
@@ -161,14 +162,17 @@ static int nfs_revalidate_file_size(struct inode *inode, struct file *filp) | |||
161 | struct nfs_server *server = NFS_SERVER(inode); | 162 | struct nfs_server *server = NFS_SERVER(inode); |
162 | struct nfs_inode *nfsi = NFS_I(inode); | 163 | struct nfs_inode *nfsi = NFS_I(inode); |
163 | 164 | ||
164 | if (server->flags & NFS_MOUNT_NOAC) | 165 | if (nfs_have_delegated_attributes(inode)) |
165 | goto force_reval; | 166 | goto out_noreval; |
167 | |||
166 | if (filp->f_flags & O_DIRECT) | 168 | if (filp->f_flags & O_DIRECT) |
167 | goto force_reval; | 169 | goto force_reval; |
168 | if (nfsi->npages != 0) | 170 | if (nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) |
169 | return 0; | 171 | goto force_reval; |
170 | if (!(nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) && !nfs_attribute_timeout(inode)) | 172 | if (nfs_attribute_timeout(inode)) |
171 | return 0; | 173 | goto force_reval; |
174 | out_noreval: | ||
175 | return 0; | ||
172 | force_reval: | 176 | force_reval: |
173 | return __nfs_revalidate_inode(server, inode); | 177 | return __nfs_revalidate_inode(server, inode); |
174 | } | 178 | } |
@@ -199,37 +203,11 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) | |||
199 | } | 203 | } |
200 | 204 | ||
201 | /* | 205 | /* |
202 | * Helper for nfs_file_flush() and nfs_file_fsync() | ||
203 | * | ||
204 | * Notice that it clears the NFS_CONTEXT_ERROR_WRITE before synching to | ||
205 | * disk, but it retrieves and clears ctx->error after synching, despite | ||
206 | * the two being set at the same time in nfs_context_set_write_error(). | ||
207 | * This is because the former is used to notify the _next_ call to | ||
208 | * nfs_file_write() that a write error occured, and hence cause it to | ||
209 | * fall back to doing a synchronous write. | ||
210 | */ | ||
211 | static int nfs_do_fsync(struct nfs_open_context *ctx, struct inode *inode) | ||
212 | { | ||
213 | int have_error, status; | ||
214 | int ret = 0; | ||
215 | |||
216 | have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); | ||
217 | status = nfs_wb_all(inode); | ||
218 | have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); | ||
219 | if (have_error) | ||
220 | ret = xchg(&ctx->error, 0); | ||
221 | if (!ret) | ||
222 | ret = status; | ||
223 | return ret; | ||
224 | } | ||
225 | |||
226 | /* | ||
227 | * Flush all dirty pages, and check for write errors. | 206 | * Flush all dirty pages, and check for write errors. |
228 | */ | 207 | */ |
229 | static int | 208 | static int |
230 | nfs_file_flush(struct file *file, fl_owner_t id) | 209 | nfs_file_flush(struct file *file, fl_owner_t id) |
231 | { | 210 | { |
232 | struct nfs_open_context *ctx = nfs_file_open_context(file); | ||
233 | struct dentry *dentry = file->f_path.dentry; | 211 | struct dentry *dentry = file->f_path.dentry; |
234 | struct inode *inode = dentry->d_inode; | 212 | struct inode *inode = dentry->d_inode; |
235 | 213 | ||
@@ -242,7 +220,7 @@ nfs_file_flush(struct file *file, fl_owner_t id) | |||
242 | return 0; | 220 | return 0; |
243 | 221 | ||
244 | /* Flush writes to the server and return any errors */ | 222 | /* Flush writes to the server and return any errors */ |
245 | return nfs_do_fsync(ctx, inode); | 223 | return vfs_fsync(file, 0); |
246 | } | 224 | } |
247 | 225 | ||
248 | static ssize_t | 226 | static ssize_t |
@@ -317,19 +295,37 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) | |||
317 | * Flush any dirty pages for this process, and check for write errors. | 295 | * Flush any dirty pages for this process, and check for write errors. |
318 | * The return status from this call provides a reliable indication of | 296 | * The return status from this call provides a reliable indication of |
319 | * whether any write errors occurred for this process. | 297 | * whether any write errors occurred for this process. |
298 | * | ||
299 | * Notice that it clears the NFS_CONTEXT_ERROR_WRITE before synching to | ||
300 | * disk, but it retrieves and clears ctx->error after synching, despite | ||
301 | * the two being set at the same time in nfs_context_set_write_error(). | ||
302 | * This is because the former is used to notify the _next_ call to | ||
303 | * nfs_file_write() that a write error occured, and hence cause it to | ||
304 | * fall back to doing a synchronous write. | ||
320 | */ | 305 | */ |
321 | static int | 306 | static int |
322 | nfs_file_fsync(struct file *file, struct dentry *dentry, int datasync) | 307 | nfs_file_fsync(struct file *file, int datasync) |
323 | { | 308 | { |
309 | struct dentry *dentry = file->f_path.dentry; | ||
324 | struct nfs_open_context *ctx = nfs_file_open_context(file); | 310 | struct nfs_open_context *ctx = nfs_file_open_context(file); |
325 | struct inode *inode = dentry->d_inode; | 311 | struct inode *inode = dentry->d_inode; |
312 | int have_error, status; | ||
313 | int ret = 0; | ||
314 | |||
326 | 315 | ||
327 | dprintk("NFS: fsync file(%s/%s) datasync %d\n", | 316 | dprintk("NFS: fsync file(%s/%s) datasync %d\n", |
328 | dentry->d_parent->d_name.name, dentry->d_name.name, | 317 | dentry->d_parent->d_name.name, dentry->d_name.name, |
329 | datasync); | 318 | datasync); |
330 | 319 | ||
331 | nfs_inc_stats(inode, NFSIOS_VFSFSYNC); | 320 | nfs_inc_stats(inode, NFSIOS_VFSFSYNC); |
332 | return nfs_do_fsync(ctx, inode); | 321 | have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); |
322 | status = nfs_commit_inode(inode, FLUSH_SYNC); | ||
323 | have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); | ||
324 | if (have_error) | ||
325 | ret = xchg(&ctx->error, 0); | ||
326 | if (!ret) | ||
327 | ret = status; | ||
328 | return ret; | ||
333 | } | 329 | } |
334 | 330 | ||
335 | /* | 331 | /* |
@@ -489,11 +485,19 @@ static void nfs_invalidate_page(struct page *page, unsigned long offset) | |||
489 | */ | 485 | */ |
490 | static int nfs_release_page(struct page *page, gfp_t gfp) | 486 | static int nfs_release_page(struct page *page, gfp_t gfp) |
491 | { | 487 | { |
488 | struct address_space *mapping = page->mapping; | ||
489 | |||
492 | dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); | 490 | dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); |
493 | 491 | ||
494 | /* Only do I/O if gfp is a superset of GFP_KERNEL */ | 492 | /* Only do I/O if gfp is a superset of GFP_KERNEL */ |
495 | if ((gfp & GFP_KERNEL) == GFP_KERNEL) | 493 | if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL) { |
496 | nfs_wb_page(page->mapping->host, page); | 494 | int how = FLUSH_SYNC; |
495 | |||
496 | /* Don't let kswapd deadlock waiting for OOM RPC calls */ | ||
497 | if (current_is_kswapd()) | ||
498 | how = 0; | ||
499 | nfs_commit_inode(mapping->host, how); | ||
500 | } | ||
497 | /* If PagePrivate() is set, then the page is not freeable */ | 501 | /* If PagePrivate() is set, then the page is not freeable */ |
498 | if (PagePrivate(page)) | 502 | if (PagePrivate(page)) |
499 | return 0; | 503 | return 0; |
@@ -635,7 +639,7 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, | |||
635 | 639 | ||
636 | /* Return error values for O_DSYNC and IS_SYNC() */ | 640 | /* Return error values for O_DSYNC and IS_SYNC() */ |
637 | if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) { | 641 | if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) { |
638 | int err = nfs_do_fsync(nfs_file_open_context(iocb->ki_filp), inode); | 642 | int err = vfs_fsync(iocb->ki_filp, 0); |
639 | if (err < 0) | 643 | if (err < 0) |
640 | result = err; | 644 | result = err; |
641 | } | 645 | } |
@@ -671,7 +675,7 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, | |||
671 | written = ret; | 675 | written = ret; |
672 | 676 | ||
673 | if (ret >= 0 && nfs_need_sync_write(filp, inode)) { | 677 | if (ret >= 0 && nfs_need_sync_write(filp, inode)) { |
674 | int err = nfs_do_fsync(nfs_file_open_context(filp), inode); | 678 | int err = vfs_fsync(filp, 0); |
675 | if (err < 0) | 679 | if (err < 0) |
676 | ret = err; | 680 | ret = err; |
677 | } | 681 | } |