Commit 8202acc6 authored by zhaoxiaoqiang11's avatar zhaoxiaoqiang11
Browse files

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: default avatarzhaoxiaoqiang11 <zhaoxiaoqiang11@jd.com>
Reviewed-by: default avatarzhangwei123171 <zhangwei123171@jd.com>
parent 3e491e57
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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

/*
+28 −9
Original line number Diff line number Diff line
@@ -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,
	},
	{ }
};