[Devel] [PATCH RHEL7 COMMIT] mm/tcache, tswap: Don't try to shrink if tswap/tcache disabled

Konstantin Khorenko khorenko at virtuozzo.com
Mon Oct 29 12:25:13 MSK 2018


The commit is pushed to "branch-rh7-3.10.0-862.14.4.vz7.72.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-862.14.4.vz7.72.14
------>
commit c57f0c47f1287bf42e0765695a38935fd6d2f022
Author: Andrey Ryabinin <aryabinin at virtuozzo.com>
Date:   Mon Oct 29 12:25:11 2018 +0300

    mm/tcache,tswap: Don't try to shrink if tswap/tcache disabled
    
    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>
    Reviewed-by: Konstantin Khorenko <khorenko 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;



More information about the Devel mailing list