diff options
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r-- | fs/nfs/file.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 0abf3f331f56..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 | ||
@@ -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,6 +479,11 @@ const struct address_space_operations nfs_file_aops = { | |||
451 | .launder_page = nfs_launder_page, | 479 | .launder_page = nfs_launder_page, |
452 | }; | 480 | }; |
453 | 481 | ||
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 | */ | ||
454 | static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | 487 | static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) |
455 | { | 488 | { |
456 | struct page *page = vmf->page; | 489 | struct page *page = vmf->page; |
@@ -465,6 +498,9 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
465 | filp->f_mapping->host->i_ino, | 498 | filp->f_mapping->host->i_ino, |
466 | (long long)page_offset(page)); | 499 | (long long)page_offset(page)); |
467 | 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 | |||
468 | lock_page(page); | 504 | lock_page(page); |
469 | mapping = page->mapping; | 505 | mapping = page->mapping; |
470 | if (mapping != dentry->d_inode->i_mapping) | 506 | if (mapping != dentry->d_inode->i_mapping) |