aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2010-07-30 15:31:54 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-07-30 15:38:42 -0400
commitb608b283a962caaa280756bc8563016a71712acf (patch)
tree217a745ab305219fab676d4a215c1a709004bd57 /fs
parent674b2222920012244ca59978b356b25412a8dcc7 (diff)
NFS: kswapd must not block in nfs_release_page
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> Cc: stable@kernel.org
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/file.c13
-rw-r--r--fs/nfs/write.c4
2 files changed, 13 insertions, 4 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 36a5e74f51b4..f036153d9f50 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -27,6 +27,7 @@
27#include <linux/pagemap.h> 27#include <linux/pagemap.h>
28#include <linux/aio.h> 28#include <linux/aio.h>
29#include <linux/gfp.h> 29#include <linux/gfp.h>
30#include <linux/swap.h>
30 31
31#include <asm/uaccess.h> 32#include <asm/uaccess.h>
32#include <asm/system.h> 33#include <asm/system.h>
@@ -493,11 +494,19 @@ static void nfs_invalidate_page(struct page *page, unsigned long offset)
493 */ 494 */
494static int nfs_release_page(struct page *page, gfp_t gfp) 495static int nfs_release_page(struct page *page, gfp_t gfp)
495{ 496{
497 struct address_space *mapping = page->mapping;
498
496 dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); 499 dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page);
497 500
498 /* Only do I/O if gfp is a superset of GFP_KERNEL */ 501 /* Only do I/O if gfp is a superset of GFP_KERNEL */
499 if ((gfp & GFP_KERNEL) == GFP_KERNEL) 502 if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL) {
500 nfs_wb_page(page->mapping->host, page); 503 int how = FLUSH_SYNC;
504
505 /* Don't let kswapd deadlock waiting for OOM RPC calls */
506 if (current_is_kswapd())
507 how = 0;
508 nfs_commit_inode(mapping->host, how);
509 }
501 /* If PagePrivate() is set, then the page is not freeable */ 510 /* If PagePrivate() is set, then the page is not freeable */
502 if (PagePrivate(page)) 511 if (PagePrivate(page))
503 return 0; 512 return 0;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 91679e2631ee..0a6c65a1f9d7 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1379,7 +1379,7 @@ static const struct rpc_call_ops nfs_commit_ops = {
1379 .rpc_release = nfs_commit_release, 1379 .rpc_release = nfs_commit_release,
1380}; 1380};
1381 1381
1382static int nfs_commit_inode(struct inode *inode, int how) 1382int nfs_commit_inode(struct inode *inode, int how)
1383{ 1383{
1384 LIST_HEAD(head); 1384 LIST_HEAD(head);
1385 int may_wait = how & FLUSH_SYNC; 1385 int may_wait = how & FLUSH_SYNC;
@@ -1443,7 +1443,7 @@ out_mark_dirty:
1443 return ret; 1443 return ret;
1444} 1444}
1445#else 1445#else
1446static int nfs_commit_inode(struct inode *inode, int how) 1446int nfs_commit_inode(struct inode *inode, int how)
1447{ 1447{
1448 return 0; 1448 return 0;
1449} 1449}