From: Liu Shixin liushixin2@huawei.com
hulk inclusion category: bugfix bugzilla: 175105 CVE: NA
-------------------------------------------------
When !CONFIG_SYSCTL, drop_caches_loop_limit is invisible. Add cmdline "drop_caches_loop_limit=" to set it. This parameter can limit the number of loops per node.
Fixes: 90394d30702e ("mm/vmscan: add drop_caches_loop_limit to break loop in drop_slab_node") Signed-off-by: Liu Shixin liushixin2@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/drop_caches.c | 1 - include/linux/mm.h | 2 +- kernel/sysctl.c | 2 +- mm/vmscan.c | 19 +++++++++++++------ 4 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/fs/drop_caches.c b/fs/drop_caches.c index 1f866b32cd150..dc1a1d5d825b4 100644 --- a/fs/drop_caches.c +++ b/fs/drop_caches.c @@ -13,7 +13,6 @@
/* A global variable is a bit ugly, but it keeps the code simple */ int sysctl_drop_caches; -unsigned int sysctl_drop_caches_loop_limit __read_mostly;
static void drop_pagecache_sb(struct super_block *sb, void *unused) { diff --git a/include/linux/mm.h b/include/linux/mm.h index 6d457e38fec7f..8b5f9b8fb1a34 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2790,7 +2790,7 @@ extern bool process_shares_mm(struct task_struct *p, struct mm_struct *mm);
#ifdef CONFIG_SYSCTL extern int sysctl_drop_caches; -extern unsigned int sysctl_drop_caches_loop_limit; +extern unsigned int drop_caches_loop_limit; int drop_caches_sysctl_handler(struct ctl_table *, int, void __user *, size_t *, loff_t *); #endif diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 60d899cb8b4e6..0be7d2747888c 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1489,7 +1489,7 @@ static struct ctl_table vm_table[] = { }, { .procname = "drop_caches_loop_limit", - .data = &sysctl_drop_caches_loop_limit, + .data = &drop_caches_loop_limit, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_douintvec, diff --git a/mm/vmscan.c b/mm/vmscan.c index 79b5ab1c06f68..226bd89f2d00e 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -723,12 +723,21 @@ static unsigned long shrink_slab(gfp_t gfp_mask, int nid, return freed; }
+unsigned int drop_caches_loop_limit __read_mostly; +static int __init drop_caches_loop_limit_setup(char *s) +{ + int ret = kstrtouint(s, 10, &drop_caches_loop_limit); + + if (ret) + pr_info("Parse drop_caches_loop_limit failed: ret: %d\n", ret); + return 1; +} +__setup("drop_caches_loop_limit=", drop_caches_loop_limit_setup); + void drop_slab_node(int nid) { unsigned long freed; -#ifdef CONFIG_SYSCTL unsigned int counts = 0; -#endif
do { struct mem_cgroup *memcg = NULL; @@ -742,17 +751,15 @@ void drop_slab_node(int nid) freed += shrink_slab(GFP_KERNEL, nid, memcg, 0); } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL)) != NULL);
-#ifdef CONFIG_SYSCTL - if (unlikely(sysctl_drop_caches_loop_limit)) { + if (unlikely(drop_caches_loop_limit)) { counts++; - if (counts >= sysctl_drop_caches_loop_limit) { + if (counts >= drop_caches_loop_limit) { pr_info("%s (%d): drop_caches early break: %u loops\n", current->comm, task_pid_nr(current), counts); return; } } -#endif } while (freed > 10); }