From: Mel Gorman <mgorman@suse.de>
Date: Wed, 9 Mar 2011 12:26:23 +0000
Subject: [PATCH] netvm: Do not mark requests for swapfile writes as dirty or kswapd fails to free the page
Patch-mainline: Not yet
References: bnc#678472

When writing back NFS pages from kswapd, the inode and pages are getting
marked dirty before IO has even started. The expectation of kswapd is
that it calls clear_page_dirty_for_io(), submits IO and the filesystem
remarks the page dirty if necessary. Without this patch, the page always
comes back under writeback and still dirty. kswapd continually launders
but never frees leading to deadlock.

Signed-off-by: Mel Gorman <mgorman@suse.de>
---
 fs/nfs/write.c |   14 ++++++++++++--
 1 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 2375c7d..fe05d78 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -744,11 +744,21 @@ static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page,
	req = nfs_setup_write_request(ctx, page, offset, count);
	if (IS_ERR(req))
		return PTR_ERR(req);
-	nfs_mark_request_dirty(req);
+
+	/*
+	 * There is no need to mark swapfile requests as dirty like normal
+	 * writepage requests as page dirtying and cleaning is managed
+	 * from the mm. If a PageSwapCache page is marked dirty like this,
+	 * it will still be dirty after kswapd calls writepage and may
+	 * never be released
+	 */
+	if (!PageSwapCache(page))
+		nfs_mark_request_dirty(req);
	/* Update file length */
	nfs_grow_file(page, offset, count);
	nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes);
-	nfs_mark_request_dirty(req);
+	if (!PageSwapCache(page))
+		nfs_mark_request_dirty(req);
	nfs_clear_page_tag_locked(req);
	return 0;
 }
