diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-08-03 17:22:16 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-10 10:20:36 -0700 |
commit | 0c88c156dfb335e3ae4fc50a76b88082544d1d3c (patch) | |
tree | bb4388bb86f871df9a48f11767b2b67529f89496 /fs/nfs/file.c | |
parent | a53c911be2f79cca99410110d88dc09f6639bc26 (diff) |
NFS: kswapd must not block in nfs_release_page
commit b608b283a962caaa280756bc8563016a71712acf upstream
See https://bugzilla.kernel.org/show_bug.cgi?id=16056
If other processes are blocked waiting for kswapd to free up some memory so
that they can make progress, then we cannot allow kswapd to block on those
processes.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r-- | fs/nfs/file.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 61b3bf503ee..9f83d9fe9a6 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -27,6 +27,8 @@ #include <linux/slab.h> #include <linux/pagemap.h> #include <linux/aio.h> +#include <linux/gfp.h> +#include <linux/swap.h> #include <asm/uaccess.h> #include <asm/system.h> @@ -484,11 +486,19 @@ static void nfs_invalidate_page(struct page *page, unsigned long offset) */ static int nfs_release_page(struct page *page, gfp_t gfp) { + struct address_space *mapping = page->mapping; + dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); /* Only do I/O if gfp is a superset of GFP_KERNEL */ - if ((gfp & GFP_KERNEL) == GFP_KERNEL) - nfs_wb_page(page->mapping->host, page); + if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL) { + int how = FLUSH_SYNC; + + /* Don't let kswapd deadlock waiting for OOM RPC calls */ + if (current_is_kswapd()) + how = 0; + nfs_commit_inode(mapping->host, how); + } /* If PagePrivate() is set, then the page is not freeable */ if (PagePrivate(page)) return 0; |