Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

sched/isolation: Flush memcg workqueues on cpuset isolated partition change

The HK_TYPE_DOMAIN housekeeping cpumask is now modifiable at runtime. In
order to synchronize against memcg workqueue to make sure that no
asynchronous draining is still pending or executing on a newly made
isolated CPU, the housekeeping susbsystem must flush the memcg
workqueues.

However the memcg workqueues can't be flushed easily since they are
queued to the main per-CPU workqueue pool.

Solve this with creating a memcg specific pool and provide and use the
appropriate flushing API.

Acked-by: Shakeel Butt <shakeel.butt@linux.dev>
Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Marco Crivellari <marco.crivellari@suse.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Tejun Heo <tj@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Waiman Long <longman@redhat.com>
Cc: cgroups@vger.kernel.org
Cc: linux-mm@kvack.org

+18 -1
+4
include/linux/memcontrol.h
··· 1037 1037 return id; 1038 1038 } 1039 1039 1040 + void mem_cgroup_flush_workqueue(void); 1041 + 1040 1042 extern int mem_cgroup_init(void); 1041 1043 #else /* CONFIG_MEMCG */ 1042 1044 ··· 1437 1435 { 1438 1436 return 0; 1439 1437 } 1438 + 1439 + static inline void mem_cgroup_flush_workqueue(void) { } 1440 1440 1441 1441 static inline int mem_cgroup_init(void) { return 0; } 1442 1442 #endif /* CONFIG_MEMCG */
+2
kernel/sched/isolation.c
··· 144 144 145 145 synchronize_rcu(); 146 146 147 + mem_cgroup_flush_workqueue(); 148 + 147 149 kfree(old); 148 150 149 151 return 0;
+1
kernel/sched/sched.h
··· 44 44 #include <linux/lockdep_api.h> 45 45 #include <linux/lockdep.h> 46 46 #include <linux/memblock.h> 47 + #include <linux/memcontrol.h> 47 48 #include <linux/minmax.h> 48 49 #include <linux/mm.h> 49 50 #include <linux/module.h>
+11 -1
mm/memcontrol.c
··· 96 96 /* BPF memory accounting disabled? */ 97 97 static bool cgroup_memory_nobpf __ro_after_init; 98 98 99 + static struct workqueue_struct *memcg_wq __ro_after_init; 100 + 99 101 static struct kmem_cache *memcg_cachep; 100 102 static struct kmem_cache *memcg_pn_cachep; 101 103 ··· 2015 2013 */ 2016 2014 guard(rcu)(); 2017 2015 if (!cpu_is_isolated(cpu)) 2018 - schedule_work_on(cpu, work); 2016 + queue_work_on(cpu, memcg_wq, work); 2019 2017 } 2020 2018 2021 2019 /* ··· 5127 5125 refill_stock(memcg, nr_pages); 5128 5126 } 5129 5127 5128 + void mem_cgroup_flush_workqueue(void) 5129 + { 5130 + flush_workqueue(memcg_wq); 5131 + } 5132 + 5130 5133 static int __init cgroup_memory(char *s) 5131 5134 { 5132 5135 char *token; ··· 5173 5166 5174 5167 cpuhp_setup_state_nocalls(CPUHP_MM_MEMCQ_DEAD, "mm/memctrl:dead", NULL, 5175 5168 memcg_hotplug_cpu_dead); 5169 + 5170 + memcg_wq = alloc_workqueue("memcg", WQ_PERCPU, 0); 5171 + WARN_ON(!memcg_wq); 5176 5172 5177 5173 for_each_possible_cpu(cpu) { 5178 5174 INIT_WORK(&per_cpu_ptr(&memcg_stock, cpu)->work,