diff options
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r-- | fs/nfs/file.c | 75 |
1 files changed, 57 insertions, 18 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 90f292b520d2..3523b895eb4b 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include "delegation.h" | 35 | #include "delegation.h" |
36 | #include "internal.h" | 36 | #include "internal.h" |
37 | #include "iostat.h" | 37 | #include "iostat.h" |
38 | #include "fscache.h" | ||
38 | 39 | ||
39 | #define NFSDBG_FACILITY NFSDBG_FILE | 40 | #define NFSDBG_FACILITY NFSDBG_FILE |
40 | 41 | ||
@@ -64,11 +65,7 @@ const struct file_operations nfs_file_operations = { | |||
64 | .write = do_sync_write, | 65 | .write = do_sync_write, |
65 | .aio_read = nfs_file_read, | 66 | .aio_read = nfs_file_read, |
66 | .aio_write = nfs_file_write, | 67 | .aio_write = nfs_file_write, |
67 | #ifdef CONFIG_MMU | ||
68 | .mmap = nfs_file_mmap, | 68 | .mmap = nfs_file_mmap, |
69 | #else | ||
70 | .mmap = generic_file_mmap, | ||
71 | #endif | ||
72 | .open = nfs_file_open, | 69 | .open = nfs_file_open, |
73 | .flush = nfs_file_flush, | 70 | .flush = nfs_file_flush, |
74 | .release = nfs_file_release, | 71 | .release = nfs_file_release, |
@@ -141,9 +138,6 @@ nfs_file_release(struct inode *inode, struct file *filp) | |||
141 | dentry->d_parent->d_name.name, | 138 | dentry->d_parent->d_name.name, |
142 | dentry->d_name.name); | 139 | dentry->d_name.name); |
143 | 140 | ||
144 | /* Ensure that dirty pages are flushed out with the right creds */ | ||
145 | if (filp->f_mode & FMODE_WRITE) | ||
146 | nfs_wb_all(dentry->d_inode); | ||
147 | nfs_inc_stats(inode, NFSIOS_VFSRELEASE); | 141 | nfs_inc_stats(inode, NFSIOS_VFSRELEASE); |
148 | return nfs_release(inode, filp); | 142 | return nfs_release(inode, filp); |
149 | } | 143 | } |
@@ -235,7 +229,6 @@ nfs_file_flush(struct file *file, fl_owner_t id) | |||
235 | struct nfs_open_context *ctx = nfs_file_open_context(file); | 229 | struct nfs_open_context *ctx = nfs_file_open_context(file); |
236 | struct dentry *dentry = file->f_path.dentry; | 230 | struct dentry *dentry = file->f_path.dentry; |
237 | struct inode *inode = dentry->d_inode; | 231 | struct inode *inode = dentry->d_inode; |
238 | int status; | ||
239 | 232 | ||
240 | dprintk("NFS: flush(%s/%s)\n", | 233 | dprintk("NFS: flush(%s/%s)\n", |
241 | dentry->d_parent->d_name.name, | 234 | dentry->d_parent->d_name.name, |
@@ -245,11 +238,8 @@ nfs_file_flush(struct file *file, fl_owner_t id) | |||
245 | return 0; | 238 | return 0; |
246 | nfs_inc_stats(inode, NFSIOS_VFSFLUSH); | 239 | nfs_inc_stats(inode, NFSIOS_VFSFLUSH); |
247 | 240 | ||
248 | /* Ensure that data+attribute caches are up to date after close() */ | 241 | /* Flush writes to the server and return any errors */ |
249 | status = nfs_do_fsync(ctx, inode); | 242 | return nfs_do_fsync(ctx, inode); |
250 | if (!status) | ||
251 | nfs_revalidate_inode(NFS_SERVER(inode), inode); | ||
252 | return status; | ||
253 | } | 243 | } |
254 | 244 | ||
255 | static ssize_t | 245 | static ssize_t |
@@ -304,11 +294,13 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) | |||
304 | dprintk("NFS: mmap(%s/%s)\n", | 294 | dprintk("NFS: mmap(%s/%s)\n", |
305 | dentry->d_parent->d_name.name, dentry->d_name.name); | 295 | dentry->d_parent->d_name.name, dentry->d_name.name); |
306 | 296 | ||
307 | status = nfs_revalidate_mapping(inode, file->f_mapping); | 297 | /* Note: generic_file_mmap() returns ENOSYS on nommu systems |
298 | * so we call that before revalidating the mapping | ||
299 | */ | ||
300 | status = generic_file_mmap(file, vma); | ||
308 | if (!status) { | 301 | if (!status) { |
309 | vma->vm_ops = &nfs_file_vm_ops; | 302 | vma->vm_ops = &nfs_file_vm_ops; |
310 | vma->vm_flags |= VM_CAN_NONLINEAR; | 303 | status = nfs_revalidate_mapping(inode, file->f_mapping); |
311 | file_accessed(file); | ||
312 | } | 304 | } |
313 | return status; | 305 | return status; |
314 | } | 306 | } |
@@ -354,6 +346,15 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping, | |||
354 | file->f_path.dentry->d_name.name, | 346 | file->f_path.dentry->d_name.name, |
355 | mapping->host->i_ino, len, (long long) pos); | 347 | mapping->host->i_ino, len, (long long) pos); |
356 | 348 | ||
349 | /* | ||
350 | * Prevent starvation issues if someone is doing a consistency | ||
351 | * sync-to-disk | ||
352 | */ | ||
353 | ret = wait_on_bit(&NFS_I(mapping->host)->flags, NFS_INO_FLUSHING, | ||
354 | nfs_wait_bit_killable, TASK_KILLABLE); | ||
355 | if (ret) | ||
356 | return ret; | ||
357 | |||
357 | page = grab_cache_page_write_begin(mapping, index, flags); | 358 | page = grab_cache_page_write_begin(mapping, index, flags); |
358 | if (!page) | 359 | if (!page) |
359 | return -ENOMEM; | 360 | return -ENOMEM; |
@@ -409,6 +410,13 @@ static int nfs_write_end(struct file *file, struct address_space *mapping, | |||
409 | return copied; | 410 | return copied; |
410 | } | 411 | } |
411 | 412 | ||
413 | /* | ||
414 | * Partially or wholly invalidate a page | ||
415 | * - Release the private state associated with a page if undergoing complete | ||
416 | * page invalidation | ||
417 | * - Called if either PG_private or PG_fscache is set on the page | ||
418 | * - Caller holds page lock | ||
419 | */ | ||
412 | static void nfs_invalidate_page(struct page *page, unsigned long offset) | 420 | static void nfs_invalidate_page(struct page *page, unsigned long offset) |
413 | { | 421 | { |
414 | dfprintk(PAGECACHE, "NFS: invalidate_page(%p, %lu)\n", page, offset); | 422 | dfprintk(PAGECACHE, "NFS: invalidate_page(%p, %lu)\n", page, offset); |
@@ -417,23 +425,43 @@ static void nfs_invalidate_page(struct page *page, unsigned long offset) | |||
417 | return; | 425 | return; |
418 | /* Cancel any unstarted writes on this page */ | 426 | /* Cancel any unstarted writes on this page */ |
419 | nfs_wb_page_cancel(page->mapping->host, page); | 427 | nfs_wb_page_cancel(page->mapping->host, page); |
428 | |||
429 | nfs_fscache_invalidate_page(page, page->mapping->host); | ||
420 | } | 430 | } |
421 | 431 | ||
432 | /* | ||
433 | * Attempt to release the private state associated with a page | ||
434 | * - Called if either PG_private or PG_fscache is set on the page | ||
435 | * - Caller holds page lock | ||
436 | * - Return true (may release page) or false (may not) | ||
437 | */ | ||
422 | static int nfs_release_page(struct page *page, gfp_t gfp) | 438 | static int nfs_release_page(struct page *page, gfp_t gfp) |
423 | { | 439 | { |
424 | dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); | 440 | dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); |
425 | 441 | ||
426 | /* If PagePrivate() is set, then the page is not freeable */ | 442 | /* If PagePrivate() is set, then the page is not freeable */ |
427 | return 0; | 443 | if (PagePrivate(page)) |
444 | return 0; | ||
445 | return nfs_fscache_release_page(page, gfp); | ||
428 | } | 446 | } |
429 | 447 | ||
448 | /* | ||
449 | * Attempt to clear the private state associated with a page when an error | ||
450 | * occurs that requires the cached contents of an inode to be written back or | ||
451 | * destroyed | ||
452 | * - Called if either PG_private or fscache is set on the page | ||
453 | * - Caller holds page lock | ||
454 | * - Return 0 if successful, -error otherwise | ||
455 | */ | ||
430 | static int nfs_launder_page(struct page *page) | 456 | static int nfs_launder_page(struct page *page) |
431 | { | 457 | { |
432 | struct inode *inode = page->mapping->host; | 458 | struct inode *inode = page->mapping->host; |
459 | struct nfs_inode *nfsi = NFS_I(inode); | ||
433 | 460 | ||
434 | dfprintk(PAGECACHE, "NFS: launder_page(%ld, %llu)\n", | 461 | dfprintk(PAGECACHE, "NFS: launder_page(%ld, %llu)\n", |
435 | inode->i_ino, (long long)page_offset(page)); | 462 | inode->i_ino, (long long)page_offset(page)); |
436 | 463 | ||
464 | nfs_fscache_wait_on_page_write(nfsi, page); | ||
437 | return nfs_wb_page(inode, page); | 465 | return nfs_wb_page(inode, page); |
438 | } | 466 | } |
439 | 467 | ||
@@ -451,8 +479,14 @@ const struct address_space_operations nfs_file_aops = { | |||
451 | .launder_page = nfs_launder_page, | 479 | .launder_page = nfs_launder_page, |
452 | }; | 480 | }; |
453 | 481 | ||
454 | static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page) | 482 | /* |
483 | * Notification that a PTE pointing to an NFS page is about to be made | ||
484 | * writable, implying that someone is about to modify the page through a | ||
485 | * shared-writable mapping | ||
486 | */ | ||
487 | static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | ||
455 | { | 488 | { |
489 | struct page *page = vmf->page; | ||
456 | struct file *filp = vma->vm_file; | 490 | struct file *filp = vma->vm_file; |
457 | struct dentry *dentry = filp->f_path.dentry; | 491 | struct dentry *dentry = filp->f_path.dentry; |
458 | unsigned pagelen; | 492 | unsigned pagelen; |
@@ -464,6 +498,9 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page) | |||
464 | filp->f_mapping->host->i_ino, | 498 | filp->f_mapping->host->i_ino, |
465 | (long long)page_offset(page)); | 499 | (long long)page_offset(page)); |
466 | 500 | ||
501 | /* make sure the cache has finished storing the page */ | ||
502 | nfs_fscache_wait_on_page_write(NFS_I(dentry->d_inode), page); | ||
503 | |||
467 | lock_page(page); | 504 | lock_page(page); |
468 | mapping = page->mapping; | 505 | mapping = page->mapping; |
469 | if (mapping != dentry->d_inode->i_mapping) | 506 | if (mapping != dentry->d_inode->i_mapping) |
@@ -483,6 +520,8 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page) | |||
483 | ret = pagelen; | 520 | ret = pagelen; |
484 | out_unlock: | 521 | out_unlock: |
485 | unlock_page(page); | 522 | unlock_page(page); |
523 | if (ret) | ||
524 | ret = VM_FAULT_SIGBUS; | ||
486 | return ret; | 525 | return ret; |
487 | } | 526 | } |
488 | 527 | ||