From: Jing Xiangfeng jingxiangfeng@huawei.com
hulk inclusion category: feature bugzilla: 51827 CVE: NA
--------------------------------------
Fix it by moving memcg_priority from struct mem_cgroup to struct mem_cgroup_extension.
Signed-off-by: Jing Xiangfeng jingxiangfeng@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- include/linux/memcontrol.h | 15 +++++++++------ mm/memcontrol.c | 34 +++++++++++++++++++++++++--------- mm/oom_kill.c | 8 ++++++-- 3 files changed, 40 insertions(+), 17 deletions(-)
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index c4d4658c7d6df..dce7aa54f2698 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -287,12 +287,6 @@ struct mem_cgroup { bool tcpmem_active; int tcpmem_pressure;
-#ifdef CONFIG_MEMCG_QOS - /* Currently support 0 and -1. - * in the future it can expand to other value. - */ - int memcg_priority; -#endif #ifdef CONFIG_MEMCG_KMEM /* Index in the kmem_cache->memcg_params.memcg_caches array */ int kmemcg_id; @@ -321,12 +315,21 @@ struct mem_cgroup { };
struct mem_cgroup_extension { +#ifdef CONFIG_MEMCG_QOS + /* Currently support 0 and -1. + * in the future it can expand to other value. + */ + int memcg_priority; +#endif spinlock_t split_queue_lock; struct list_head split_queue; unsigned long split_queue_len; struct mem_cgroup memcg; };
+#define to_memcg_ext(cgroup) \ + container_of(cgroup, struct mem_cgroup_extension, memcg) + #ifdef CONFIG_MEMCG_QOS bool memcg_low_priority_scan_tasks(int (*)(struct task_struct *, void *), void *); diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 31352be988114..bb6e7a0af502d 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -3407,29 +3407,42 @@ static int mem_cgroup_move_charge_write(struct cgroup_subsys_state *css, static void memcg_qos_init(struct mem_cgroup *memcg) { struct mem_cgroup *parent = parent_mem_cgroup(memcg); + struct mem_cgroup_extension *memcg_ext; + struct mem_cgroup_extension *parent_ext;
if (!parent) return;
- if (parent->memcg_priority && parent->use_hierarchy) - memcg->memcg_priority = parent->memcg_priority; + memcg_ext = to_memcg_ext(memcg); + parent_ext = to_memcg_ext(parent); + + if (parent_ext->memcg_priority && parent->use_hierarchy) + memcg_ext->memcg_priority = parent_ext->memcg_priority; }
static s64 memcg_qos_read(struct cgroup_subsys_state *css, struct cftype *cft) { - return mem_cgroup_from_css(css)->memcg_priority; + struct mem_cgroup *memcg = mem_cgroup_from_css(css); + struct mem_cgroup_extension *memcg_ext; + + memcg_ext = to_memcg_ext(memcg); + + return memcg_ext->memcg_priority; }
static int memcg_qos_write(struct cgroup_subsys_state *css, struct cftype *cft, s64 val) { struct mem_cgroup *memcg = mem_cgroup_from_css(css); + struct mem_cgroup_extension *memcg_ext; + + memcg_ext = to_memcg_ext(memcg);
if (val >= 0) - memcg->memcg_priority = 0; + memcg_ext->memcg_priority = 0; else - memcg->memcg_priority = -1; + memcg_ext->memcg_priority = -1;
return 0; } @@ -3438,13 +3451,15 @@ static struct mem_cgroup *memcg_find_max_usage(struct mem_cgroup *last) { struct mem_cgroup *iter, *max_memcg = NULL; struct cgroup_subsys_state *css; + struct mem_cgroup_extension *memcg_ext; unsigned long usage, max_usage = 0;
rcu_read_lock(); css_for_each_descendant_pre(css, &root_mem_cgroup->css) { iter = mem_cgroup_from_css(css); + memcg_ext = to_memcg_ext(iter);
- if (!iter->memcg_priority || iter == root_mem_cgroup || + if (!memcg_ext->memcg_priority || iter == root_mem_cgroup || iter == last) continue;
@@ -3504,12 +3519,13 @@ bool memcg_low_priority_scan_tasks(int (*fn)(struct task_struct *, void *), void memcg_print_bad_task(void *arg, int ret) { struct oom_control *oc = arg; + struct mem_cgroup *memcg; + struct mem_cgroup_extension *memcg_ext;
if (!ret && oc->chosen) { - struct mem_cgroup *memcg; - memcg = mem_cgroup_from_task(oc->chosen); - if (memcg->memcg_priority) + memcg_ext = to_memcg_ext(memcg); + if (memcg_ext->memcg_priority) pr_info("The bad task [%d:%s] is from low-priority memcg.\n", oc->chosen->pid, oc->chosen->comm); } diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 22a6f88d1f4d9..38710c51bb40a 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -327,6 +327,8 @@ static bool oom_next_task(struct task_struct *task, struct oom_control *oc, { struct mem_cgroup *cur_memcg; struct mem_cgroup *oc_memcg; + struct mem_cgroup_extension *cur_ext; + struct mem_cgroup_extension *oc_ext;
if (!points) @@ -337,14 +339,16 @@ static bool oom_next_task(struct task_struct *task, struct oom_control *oc,
oc_memcg = mem_cgroup_from_task(oc->chosen); cur_memcg = mem_cgroup_from_task(task); + oc_ext = to_memcg_ext(oc_memcg); + cur_ext = to_memcg_ext(cur_memcg);
- if (cur_memcg->memcg_priority == oc_memcg->memcg_priority) { + if (cur_ext->memcg_priority == oc_ext->memcg_priority) { if (points < oc->chosen_points) return true; return false; } /* if oc is low-priority, so skip the task */ - if (oc_memcg->memcg_priority) + if (oc_ext->memcg_priority) return true;
return false;