aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memcontrol.c
diff options
context:
space:
mode:
authorMichal Hocko <mhocko@suse.cz>2014-01-21 18:51:04 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-21 19:19:48 -0500
commit947b3dd1a84ba3fcb7163688fdc36671941786f4 (patch)
treef0965a81a28e24a2d0ed7cb075aa0ec15dbb475b /mm/memcontrol.c
parent286549dcaf4f128cb04f0ad56dfb677d7d19b500 (diff)
memcg, oom: lock mem_cgroup_print_oom_info
mem_cgroup_print_oom_info uses a static buffer (memcg_name) to store the name of the cgroup. This is not safe as pointed out by David Rientjes because memcg oom is locked only for its hierarchy and nothing prevents another parallel hierarchy to trigger oom as well and overwrite the already in-use buffer. This patch introduces oom_info_lock hidden inside mem_cgroup_print_oom_info which is held throughout the function. It makes access to memcg_name safe and as a bonus it also prevents parallel memcg ooms to interleave their statistics which would make the printed data hard to analyze otherwise. Signed-off-by: Michal Hocko <mhocko@suse.cz> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Acked-by: David Rientjes <rientjes@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r--mm/memcontrol.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 08541f680d90..57b16083f046 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -1647,13 +1647,13 @@ static void move_unlock_mem_cgroup(struct mem_cgroup *memcg,
1647 */ 1647 */
1648void mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p) 1648void mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p)
1649{ 1649{
1650 struct cgroup *task_cgrp;
1651 struct cgroup *mem_cgrp;
1652 /* 1650 /*
1653 * Need a buffer in BSS, can't rely on allocations. The code relies 1651 * protects memcg_name and makes sure that parallel ooms do not
1654 * on the assumption that OOM is serialized for memory controller. 1652 * interleave
1655 * If this assumption is broken, revisit this code.
1656 */ 1653 */
1654 static DEFINE_SPINLOCK(oom_info_lock);
1655 struct cgroup *task_cgrp;
1656 struct cgroup *mem_cgrp;
1657 static char memcg_name[PATH_MAX]; 1657 static char memcg_name[PATH_MAX];
1658 int ret; 1658 int ret;
1659 struct mem_cgroup *iter; 1659 struct mem_cgroup *iter;
@@ -1662,6 +1662,7 @@ void mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p)
1662 if (!p) 1662 if (!p)
1663 return; 1663 return;
1664 1664
1665 spin_lock(&oom_info_lock);
1665 rcu_read_lock(); 1666 rcu_read_lock();
1666 1667
1667 mem_cgrp = memcg->css.cgroup; 1668 mem_cgrp = memcg->css.cgroup;
@@ -1730,6 +1731,7 @@ done:
1730 1731
1731 pr_cont("\n"); 1732 pr_cont("\n");
1732 } 1733 }
1734 spin_unlock(&oom_info_lock);
1733} 1735}
1734 1736
1735/* 1737/*