aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorMel Gorman <mgorman@suse.de>2013-07-03 18:02:06 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-03 19:07:29 -0400
commitf919b19614f06711cba300c1bb1e3d94c9ca21b0 (patch)
treee8955f650cda07d7340ccc126538acfc4e99bf9f /fs/nfs
parentb45972265f823ed01eae0867a176320071665787 (diff)
fs: nfs: inform the VM about pages being committed or unstable
VM page reclaim uses dirty and writeback page states to determine if flushers are cleaning pages too slowly and that page reclaim should stall waiting on flushers to catch up. Page state in NFS is a bit more complex and a clean page can be unreclaimable due to being unstable which is effectively "dirty" from the perspective of the VM from reclaim context. Similarly, if the inode is currently being committed then it's similar to being under writeback. This patch adds a is_dirty_writeback() handled for NFS that checks if a pages backing inode is being committed and should be accounted as writeback and if a page has private state indicating that it is effectively dirty. Signed-off-by: Mel Gorman <mgorman@suse.de> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Michal Hocko <mhocko@suse.cz> Cc: Rik van Riel <riel@redhat.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Jiri Slaby <jslaby@suse.cz> Cc: Valdis Kletnieks <Valdis.Kletnieks@vt.edu> Cc: Zlatko Calusic <zcalusic@bitsync.net> Cc: dormando <dormando@rydia.net> Cc: Trond Myklebust <trond.myklebust@fys.uio.no> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/file.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 6b4a79f4ad1d..94e94bd11aae 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -495,6 +495,35 @@ static int nfs_release_page(struct page *page, gfp_t gfp)
495 return nfs_fscache_release_page(page, gfp); 495 return nfs_fscache_release_page(page, gfp);
496} 496}
497 497
498static void nfs_check_dirty_writeback(struct page *page,
499 bool *dirty, bool *writeback)
500{
501 struct nfs_inode *nfsi;
502 struct address_space *mapping = page_file_mapping(page);
503
504 if (!mapping || PageSwapCache(page))
505 return;
506
507 /*
508 * Check if an unstable page is currently being committed and
509 * if so, have the VM treat it as if the page is under writeback
510 * so it will not block due to pages that will shortly be freeable.
511 */
512 nfsi = NFS_I(mapping->host);
513 if (test_bit(NFS_INO_COMMIT, &nfsi->flags)) {
514 *writeback = true;
515 return;
516 }
517
518 /*
519 * If PagePrivate() is set, then the page is not freeable and as the
520 * inode is not being committed, it's not going to be cleaned in the
521 * near future so treat it as dirty
522 */
523 if (PagePrivate(page))
524 *dirty = true;
525}
526
498/* 527/*
499 * Attempt to clear the private state associated with a page when an error 528 * Attempt to clear the private state associated with a page when an error
500 * occurs that requires the cached contents of an inode to be written back or 529 * occurs that requires the cached contents of an inode to be written back or
@@ -542,6 +571,7 @@ const struct address_space_operations nfs_file_aops = {
542 .direct_IO = nfs_direct_IO, 571 .direct_IO = nfs_direct_IO,
543 .migratepage = nfs_migrate_page, 572 .migratepage = nfs_migrate_page,
544 .launder_page = nfs_launder_page, 573 .launder_page = nfs_launder_page,
574 .is_dirty_writeback = nfs_check_dirty_writeback,
545 .error_remove_page = generic_error_remove_page, 575 .error_remove_page = generic_error_remove_page,
546#ifdef CONFIG_NFS_SWAP 576#ifdef CONFIG_NFS_SWAP
547 .swap_activate = nfs_swap_activate, 577 .swap_activate = nfs_swap_activate,