summaryrefslogtreecommitdiffstats
path: root/mm/memcontrol.c
diff options
context:
space:
mode:
authorKAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>2009-01-07 18:08:32 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-08 08:31:10 -0800
commita7ba0eef3af51cd1b6fc4028e4705b3ea2ea9469 (patch)
tree70e43097041eed321be38d1af4ed65e41d1ebff9 /mm/memcontrol.c
parent03f3c433648a97ae7c86be789edba67690f6ea60 (diff)
downloadlinux-a7ba0eef3af51cd1b6fc4028e4705b3ea2ea9469.tar.gz
linux-a7ba0eef3af51cd1b6fc4028e4705b3ea2ea9469.tar.bz2
linux-a7ba0eef3af51cd1b6fc4028e4705b3ea2ea9469.zip
memcg: fix double free and make refcnt sane
1. Fix double-free BUG in error route of mem_cgroup_create(). mem_cgroup_free() itself frees per-zone-info. 2. Making refcnt of memcg simple. Add 1 refcnt at creation and call free when refcnt goes down to 0. Reviewed-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Balbir Singh <balbir@in.ibm.com> Cc: Paul Menage <menage@google.com> Cc: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> Cc: Li Zefan <lizf@cn.fujitsu.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.c21
1 files changed, 6 insertions, 15 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 0ed61e27d526..4f9a9c5a02e2 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2092,14 +2092,10 @@ static struct mem_cgroup *mem_cgroup_alloc(void)
* Removal of cgroup itself succeeds regardless of refs from swap.
*/
-static void mem_cgroup_free(struct mem_cgroup *mem)
+static void __mem_cgroup_free(struct mem_cgroup *mem)
{
int node;
- if (atomic_read(&mem->refcnt) > 0)
- return;
-
-
for_each_node_state(node, N_POSSIBLE)
free_mem_cgroup_per_zone_info(mem, node);
@@ -2116,11 +2112,8 @@ static void mem_cgroup_get(struct mem_cgroup *mem)
static void mem_cgroup_put(struct mem_cgroup *mem)
{
- if (atomic_dec_and_test(&mem->refcnt)) {
- if (!mem->obsolete)
- return;
- mem_cgroup_free(mem);
- }
+ if (atomic_dec_and_test(&mem->refcnt))
+ __mem_cgroup_free(mem);
}
@@ -2170,12 +2163,10 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
if (parent)
mem->swappiness = get_swappiness(parent);
-
+ atomic_set(&mem->refcnt, 1);
return &mem->css;
free_out:
- for_each_node_state(node, N_POSSIBLE)
- free_mem_cgroup_per_zone_info(mem, node);
- mem_cgroup_free(mem);
+ __mem_cgroup_free(mem);
return ERR_PTR(-ENOMEM);
}
@@ -2190,7 +2181,7 @@ static void mem_cgroup_pre_destroy(struct cgroup_subsys *ss,
static void mem_cgroup_destroy(struct cgroup_subsys *ss,
struct cgroup *cont)
{
- mem_cgroup_free(mem_cgroup_from_cont(cont));
+ mem_cgroup_put(mem_cgroup_from_cont(cont));
}
static int mem_cgroup_populate(struct cgroup_subsys *ss,