提交 b608b283 编写于 作者: T Trond Myklebust

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: NTrond Myklebust <Trond.Myklebust@netapp.com>
Cc: stable@kernel.org
上级 674b2222
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/aio.h> #include <linux/aio.h>
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/swap.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -493,11 +494,19 @@ static void nfs_invalidate_page(struct page *page, unsigned long offset) ...@@ -493,11 +494,19 @@ static void nfs_invalidate_page(struct page *page, unsigned long offset)
*/ */
static int nfs_release_page(struct page *page, gfp_t gfp) 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); dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page);
/* Only do I/O if gfp is a superset of GFP_KERNEL */ /* Only do I/O if gfp is a superset of GFP_KERNEL */
if ((gfp & GFP_KERNEL) == GFP_KERNEL) if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL) {
nfs_wb_page(page->mapping->host, page); 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() is set, then the page is not freeable */
if (PagePrivate(page)) if (PagePrivate(page))
return 0; return 0;
......
...@@ -1379,7 +1379,7 @@ static const struct rpc_call_ops nfs_commit_ops = { ...@@ -1379,7 +1379,7 @@ static const struct rpc_call_ops nfs_commit_ops = {
.rpc_release = nfs_commit_release, .rpc_release = nfs_commit_release,
}; };
static int nfs_commit_inode(struct inode *inode, int how) int nfs_commit_inode(struct inode *inode, int how)
{ {
LIST_HEAD(head); LIST_HEAD(head);
int may_wait = how & FLUSH_SYNC; int may_wait = how & FLUSH_SYNC;
...@@ -1443,7 +1443,7 @@ static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_contr ...@@ -1443,7 +1443,7 @@ static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_contr
return ret; return ret;
} }
#else #else
static int nfs_commit_inode(struct inode *inode, int how) int nfs_commit_inode(struct inode *inode, int how)
{ {
return 0; return 0;
} }
......
...@@ -493,6 +493,7 @@ extern int nfs_wb_all(struct inode *inode); ...@@ -493,6 +493,7 @@ extern int nfs_wb_all(struct inode *inode);
extern int nfs_wb_page(struct inode *inode, struct page* page); extern int nfs_wb_page(struct inode *inode, struct page* page);
extern int nfs_wb_page_cancel(struct inode *inode, struct page* page); extern int nfs_wb_page_cancel(struct inode *inode, struct page* page);
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
extern int nfs_commit_inode(struct inode *, int);
extern struct nfs_write_data *nfs_commitdata_alloc(void); extern struct nfs_write_data *nfs_commitdata_alloc(void);
extern void nfs_commit_free(struct nfs_write_data *wdata); extern void nfs_commit_free(struct nfs_write_data *wdata);
#endif #endif
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册