[Devel] [PATCH rh7] mm/tcache, tswap: Don't try to shrink if tswap/tcache disabled.
Andrey Ryabinin
aryabinin at virtuozzo.com
Mon Oct 29 11:34:42 MSK 2018
shrink_tcrutches() calls tcache/tswap_shrink_scan() regardless of wether
tcache/tswap enabled or have any pages. If tcache was disabled at via
tcache.enabled=0 boot parameter, it will crash:
BUG: unable to handle kernel NULL pointer dereference at 0000000000000010
IP: [<ffffffffbe03794b>] tcache_lru_isolate+0x2b/0x1e0
Call Trace:
tcache_shrink_scan+0x46/0x130
shrink_tcrutches+0xe8/0x150
balance_pgdat+0x434/0x810
kswapd+0x173/0x440
kthread+0xd1/0xe0
ret_from_fork_nospec_begin+0x21/0x21
RIP [<ffffffffbe03794b>] tcache_lru_isolate+0x2b/0x1e0
Fix this by calling tcache/tswap_shrink_scan() only if tcache/tswap
enabled and have anything to reclaim.
https://jira.sw.ru/browse/HCI-168
Fixes: fe87c15bf3ac ("mm/vmscan: shrink tcache, tswap upfront everything else")
Signed-off-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
---
mm/internal.h | 28 ++++++++++++++++++++++++++--
mm/tcache.c | 4 ++--
mm/tswap.c | 4 ++--
3 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/mm/internal.h b/mm/internal.h
index c7265beced97..b34b03dc37f2 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -387,10 +387,22 @@ struct tlbflush_unmap_batch;
#ifdef CONFIG_TCACHE
unsigned long tswap_shrink_scan(struct shrinker *shrinker,
struct shrink_control *sc);
+unsigned long tswap_shrink_count(struct shrinker *shrink,
+ struct shrink_control *sc);
static inline unsigned long tswap_shrink(struct shrink_control *sc)
{
- unsigned long ret = tswap_shrink_scan(NULL, sc);
+ unsigned long ret;
+ extern bool tswap_enabled;
+
+ if (!READ_ONCE(tswap_enabled))
+ return 0;
+
+ ret = tswap_shrink_count(NULL, sc);
+ if (!ret)
+ return ret;
+
+ ret = tswap_shrink_scan(NULL, sc);
if (ret == SHRINK_STOP)
ret = 0;
return ret;
@@ -403,10 +415,22 @@ static inline tswap_shrink(struct shrink_control *sc)
#ifdef CONFIG_TSWAP
unsigned long tcache_shrink_scan(struct shrinker *shrinker,
struct shrink_control *sc);
+unsigned long tcache_shrink_count(struct shrinker *shrink,
+ struct shrink_control *sc);
static inline unsigned long tcache_shrink(struct shrink_control *sc)
{
- unsigned long ret = tcache_shrink_scan(NULL, sc);
+ unsigned long ret;
+ extern bool tcache_enabled;
+
+ if (!READ_ONCE(tcache_enabled))
+ return 0;
+
+ ret = tcache_shrink_count(NULL, sc);
+ if (!ret)
+ return ret;
+
+ ret = tcache_shrink_scan(NULL, sc);
if (ret == SHRINK_STOP)
ret = 0;
return ret;
diff --git a/mm/tcache.c b/mm/tcache.c
index 61f4a6ea26b3..a6afb0c510aa 100644
--- a/mm/tcache.c
+++ b/mm/tcache.c
@@ -177,7 +177,7 @@ static struct tcache_nodeinfo *tcache_nodeinfo;
*/
/* Enable/disable tcache backend (set at boot time) */
-static bool tcache_enabled __read_mostly = true;
+bool tcache_enabled __read_mostly = true;
module_param_named(enabled, tcache_enabled, bool, 0444);
/* Enable/disable populating the cache */
@@ -1196,7 +1196,7 @@ static struct page *tcache_alloc_page(struct tcache_pool *pool)
return page;
}
-static unsigned long tcache_shrink_count(struct shrinker *shrink,
+unsigned long tcache_shrink_count(struct shrinker *shrink,
struct shrink_control *sc)
{
atomic_long_t *nr_pages = &tcache_nodeinfo[sc->nid].nr_pages;
diff --git a/mm/tswap.c b/mm/tswap.c
index 73b1f85d5279..bf7644d5f033 100644
--- a/mm/tswap.c
+++ b/mm/tswap.c
@@ -35,7 +35,7 @@ struct tswap_lru {
static struct tswap_lru *tswap_lru_node;
/* Enable/disable tswap backend (set at boot time) */
-static bool tswap_enabled __read_mostly = true;
+bool tswap_enabled __read_mostly = true;
module_param_named(enabled, tswap_enabled, bool, 0444);
/* Enable/disable populating the cache */
@@ -126,7 +126,7 @@ static struct page *tswap_delete_page(swp_entry_t entry, struct page *expected)
return page;
}
-static unsigned long tswap_shrink_count(struct shrinker *shrink,
+unsigned long tswap_shrink_count(struct shrinker *shrink,
struct shrink_control *sc)
{
return tswap_lru_node[sc->nid].nr_items;
--
2.18.1
More information about the Devel
mailing list