]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
fs: nfs: inform the VM about pages being committed or unstable
authorMel Gorman <mgorman@suse.de>
Thu, 27 Jun 2013 23:51:30 +0000 (09:51 +1000)
committerStephen Rothwell <sfr@canb.auug.org.au>
Fri, 28 Jun 2013 06:37:32 +0000 (16:37 +1000)
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>
fs/nfs/file.c

index 6b4a79f4ad1d30a0ddf036df224ab80594274f38..94e94bd11aae6d0a6c32acf5c16491448edb93f8 100644 (file)
@@ -495,6 +495,35 @@ static int nfs_release_page(struct page *page, gfp_t gfp)
        return nfs_fscache_release_page(page, gfp);
 }
 
+static void nfs_check_dirty_writeback(struct page *page,
+                               bool *dirty, bool *writeback)
+{
+       struct nfs_inode *nfsi;
+       struct address_space *mapping = page_file_mapping(page);
+
+       if (!mapping || PageSwapCache(page))
+               return;
+
+       /*
+        * Check if an unstable page is currently being committed and
+        * if so, have the VM treat it as if the page is under writeback
+        * so it will not block due to pages that will shortly be freeable.
+        */
+       nfsi = NFS_I(mapping->host);
+       if (test_bit(NFS_INO_COMMIT, &nfsi->flags)) {
+               *writeback = true;
+               return;
+       }
+
+       /*
+        * If PagePrivate() is set, then the page is not freeable and as the
+        * inode is not being committed, it's not going to be cleaned in the
+        * near future so treat it as dirty
+        */
+       if (PagePrivate(page))
+               *dirty = true;
+}
+
 /*
  * Attempt to clear the private state associated with a page when an error
  * 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 = {
        .direct_IO = nfs_direct_IO,
        .migratepage = nfs_migrate_page,
        .launder_page = nfs_launder_page,
+       .is_dirty_writeback = nfs_check_dirty_writeback,
        .error_remove_page = generic_error_remove_page,
 #ifdef CONFIG_NFS_SWAP
        .swap_activate = nfs_swap_activate,