Commit 9c56751271e7a917783fb57ec49fe8382e0dc867
Committed by
Linus Torvalds
1 parent
34ec4de42b
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
mm, memcg: protect mem_cgroup_read_events for cpu hotplug
for_each_online_cpu() needs the protection of {get,put}_online_cpus() so cpu_online_mask doesn't change during the iteration. cpu_hotplug.lock is held while a cpu is going down, it's a coarse lock that is used kernel-wide to synchronize cpu hotplug activity. Memcg has a cpu hotplug notifier, called while there may not be any cpu hotplug refcounts, which drains per-cpu event counts to memcg->nocpu_base.events to maintain a cumulative event count as cpus disappear. Without get_online_cpus() in mem_cgroup_read_events(), it's possible to account for the event count on a dying cpu twice, and this value may be significantly large. In fact, all memcg->pcp_counter_lock use should be nested by {get,put}_online_cpus(). This fixes that issue and ensures the reported statistics are not vastly over-reported during cpu hotplug. Signed-off-by: David Rientjes <rientjes@google.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Michal Hocko <mhocko@suse.cz> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Acked-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 1 changed file with 2 additions and 0 deletions Side-by-side Diff
mm/memcontrol.c
... | ... | @@ -866,6 +866,7 @@ |
866 | 866 | unsigned long val = 0; |
867 | 867 | int cpu; |
868 | 868 | |
869 | + get_online_cpus(); | |
869 | 870 | for_each_online_cpu(cpu) |
870 | 871 | val += per_cpu(memcg->stat->events[idx], cpu); |
871 | 872 | #ifdef CONFIG_HOTPLUG_CPU |
... | ... | @@ -873,6 +874,7 @@ |
873 | 874 | val += memcg->nocpu_base.events[idx]; |
874 | 875 | spin_unlock(&memcg->pcp_counter_lock); |
875 | 876 | #endif |
877 | + put_online_cpus(); | |
876 | 878 | return val; |
877 | 879 | } |
878 | 880 |