[Devel] [PATCH rh7 1/4] tswap: do not populate on global reclaim

Vladimir Davydov vdavydov at parallels.com
Thu Jul 16 02:03:29 PDT 2015


Tswap was introduced for storing swap cache pages that do not fit in
container RAM limit in order to avoid costly swap out when there is
enough free memory on the host. Therefore there is no point in moving
swap cache pages to tswap on global memory shortage. Moreover, it is
dangerous, because on tswap reclaim we do not actually free pages, but
move them back to swap cache in the hope that they will be written back
and freed soon. However, there is a chance that they won't, instead they
can be moved back to tswap again. As a result of such a page ping-pong,
the system may become unresponsive.

This patch therefore makes tswap only adopt swap cache pages on local
reclaim (PF_MEMALLOC is unset on current). Since after this change it is
valid to trigger global reclaim from inside tswap_frontswap_store, this
patch also makes tswap_frontswap_store use GFP_NOIO instead of
GFP_NOWAIT and issue radix tree preallocation before inserting a page to
tswap_page_tree.

https://jira.sw.ru/browse/PSBM-34876

Signed-off-by: Vladimir Davydov <vdavydov at parallels.com>
---
 mm/tswap.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/mm/tswap.c b/mm/tswap.c
index cdaa98ad2e2d..dc1253f8e5b2 100644
--- a/mm/tswap.c
+++ b/mm/tswap.c
@@ -14,6 +14,8 @@
 #include <linux/shrinker.h>
 #include <linux/frontswap.h>
 
+#define TSWAP_GFP_MASK		(GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN)
+
 static RADIX_TREE(tswap_page_tree, GFP_ATOMIC | __GFP_NOWARN);
 static DEFINE_SPINLOCK(tswap_lock);
 
@@ -67,6 +69,10 @@ static int tswap_insert_page(swp_entry_t entry, struct page *page)
 {
 	int err;
 
+	err = radix_tree_preload(TSWAP_GFP_MASK);
+	if (err)
+		return err;
+
 	set_page_private(page, entry.val);
 	spin_lock(&tswap_lock);
 	err = radix_tree_insert(&tswap_page_tree, entry.val, page);
@@ -75,6 +81,8 @@ static int tswap_insert_page(swp_entry_t entry, struct page *page)
 		tswap_nr_pages++;
 	}
 	spin_unlock(&tswap_lock);
+
+	radix_tree_preload_end();
 	return err;
 }
 
@@ -268,8 +276,10 @@ static int tswap_frontswap_store(unsigned type, pgoff_t offset,
 	if (cache_page)
 		goto copy;
 
-	cache_page = alloc_page(__GFP_HIGHMEM | __GFP_NORETRY |
-				__GFP_NOMEMALLOC | __GFP_NOWARN);
+	if (current->flags & PF_MEMALLOC)
+		return -1;
+
+	cache_page = alloc_page(TSWAP_GFP_MASK | __GFP_HIGHMEM);
 	if (!cache_page)
 		return -1;
 
-- 
2.1.4




More information about the Devel mailing list