From 8202acc60f9703d8577a45d91f7949f259d559ff Mon Sep 17 00:00:00 2001 From: zhaoxiaoqiang11 Date: Wed, 25 Oct 2023 11:41:41 +0800 Subject: [PATCH] memcg/swap: add ability to disable memcg swap jingdong inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8AQ5E -------------------------------------------------- in cloud native environment, we need to disable container swap and enable it only in special cases. Usage: echo 2 > /proc/sys/vm/memcg_swap_qos_enable to enable this new feature. Note: some write operation will be invalid Valid change: 0 => 1 (enable swap qos, SWAP_TYPE_ALL) 0 => 2 (enable swap qos, SWAP_TYPE_NONE) 1 => 0 (disable swap qos) 2 => 0 (disable swap qos) Invalid change: 1 => 2 (SWAP_TYPE_ALL => SWAP_TYPE_NONE) 2 => 1 (SWAP_TYPE_NONE => SWAP_TYPE_ALL) and write operation will return -EINVAL Signed-off-by: zhaoxiaoqiang11 Reviewed-by: zhangwei123171 --- include/linux/memcontrol.h | 5 +++++ mm/memcontrol.c | 37 ++++++++++++++++++++++++++++--------- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 0219e670a436..24794b56eaaf 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -437,6 +437,11 @@ void memcg_print_bad_task(struct oom_control *oc); #ifdef CONFIG_MEMCG_SWAP_QOS DECLARE_STATIC_KEY_FALSE(memcg_swap_qos_key); + +#define MEMCG_SWAP_STAT_DISABLE 0 +#define MEMCG_SWAP_STAT_ALL 1 +#define MEMCG_SWAP_STAT_NONE 2 +#define MAX_MEMCG_SWAP_TYPE MEMCG_SWAP_STAT_NONE #endif /* diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 9603b6dff9aa..cd578c240101 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -4064,14 +4064,15 @@ DEFINE_STATIC_KEY_FALSE(memcg_swap_qos_key); #ifdef CONFIG_SYSCTL static int sysctl_memcg_swap_qos_stat; +static int swap_qos_type_max = MAX_MEMCG_SWAP_TYPE; -static void memcg_swap_qos_reset(void) +static void memcg_swap_qos_reset(int type) { struct mem_cgroup *memcg; for_each_mem_cgroup(memcg) { WRITE_ONCE(memcg->swap_dev->max, PAGE_COUNTER_MAX); - WRITE_ONCE(memcg->swap_dev->type, SWAP_TYPE_ALL); + WRITE_ONCE(memcg->swap_dev->type, type); } } @@ -4079,21 +4080,39 @@ static int sysctl_memcg_swap_qos_handler(struct ctl_table *table, int write, void __user *buffer, size_t *length, loff_t *ppos) { int ret; + int qos_stat_old = sysctl_memcg_swap_qos_stat; + int swap_type; ret = proc_dointvec_minmax(table, write, buffer, length, ppos); if (ret) return ret; + + if (qos_stat_old == sysctl_memcg_swap_qos_stat) + return 0; + if (write) { - if (sysctl_memcg_swap_qos_stat && - !static_branch_likely(&memcg_swap_qos_key)) { - memcg_swap_qos_reset(); + + switch (sysctl_memcg_swap_qos_stat) { + case MEMCG_SWAP_STAT_DISABLE: + static_branch_disable(&memcg_swap_qos_key); + return 0; + case MEMCG_SWAP_STAT_ALL: + swap_type = SWAP_TYPE_ALL; + break; + case MEMCG_SWAP_STAT_NONE: + swap_type = SWAP_TYPE_NONE; + break; + } + + if (!qos_stat_old) { + memcg_swap_qos_reset(swap_type); static_branch_enable(&memcg_swap_qos_key); enable_swap_slots_cache_max(); - } else if (!sysctl_memcg_swap_qos_stat && - static_branch_likely(&memcg_swap_qos_key)) { - static_branch_disable(&memcg_swap_qos_key); + } else { + return -EINVAL; } } + return 0; } @@ -4105,7 +4124,7 @@ static struct ctl_table memcg_swap_qos_sysctls[] = { .mode = 0644, .proc_handler = sysctl_memcg_swap_qos_handler, .extra1 = SYSCTL_ZERO, - .extra2 = SYSCTL_ONE, + .extra2 = &swap_qos_type_max, }, { } }; -- Gitee