[PATCH 3.18 26/56] zswap: re-check zswap_is_full() after do zswap_shrink()

From: Greg Kroah-Hartman
Date: Mon Sep 03 2018 - 12:52:35 EST


3.18-stable review patch. If anyone has any objections, please let me know.

------------------

From: Li Wang <liwang@xxxxxxxxxx>

[ Upstream commit 16e536ef47f567289a5699abee9ff7bb304bc12d ]

/sys/../zswap/stored_pages keeps rising in a zswap test with
"zswap.max_pool_percent=0" parameter. But it should not compress or
store pages any more since there is no space in the compressed pool.

Reproduce steps:
1. Boot kernel with "zswap.enabled=1"
2. Set the max_pool_percent to 0
# echo 0 > /sys/module/zswap/parameters/max_pool_percent
3. Do memory stress test to see if some pages have been compressed
# stress --vm 1 --vm-bytes $mem_available"M" --timeout 60s
4. Watching the 'stored_pages' number increasing or not

The root cause is:

When zswap_max_pool_percent is set to 0 via kernel parameter,
zswap_is_full() will always return true due to zswap_shrink(). But if
the shinking is able to reclain a page successfully the code then
proceeds to compressing/storing another page, so the value of
stored_pages will keep changing.

To solve the issue, this patch adds a zswap_is_full() check again after
zswap_shrink() to make sure it's now under the max_pool_percent, and to
not compress/store if we reached the limit.

Link: http://lkml.kernel.org/r/20180530103936.17812-1-liwang@xxxxxxxxxx
Signed-off-by: Li Wang <liwang@xxxxxxxxxx>
Acked-by: Dan Streetman <ddstreet@xxxxxxxx>
Cc: Seth Jennings <sjenning@xxxxxxxxxx>
Cc: Huang Ying <huang.ying.caritas@xxxxxxxxx>
Cc: Yu Zhao <yuzhao@xxxxxxxxxx>
Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
Signed-off-by: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
Signed-off-by: Sasha Levin <alexander.levin@xxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
---
mm/zswap.c | 9 +++++++++
1 file changed, 9 insertions(+)

--- a/mm/zswap.c
+++ b/mm/zswap.c
@@ -662,6 +662,15 @@ static int zswap_frontswap_store(unsigne
ret = -ENOMEM;
goto reject;
}
+
+ /* A second zswap_is_full() check after
+ * zswap_shrink() to make sure it's now
+ * under the max_pool_percent
+ */
+ if (zswap_is_full()) {
+ ret = -ENOMEM;
+ goto reject;
+ }
}

/* allocate entry */