diff options
author | Li Zefan <lizf@cn.fujitsu.com> | 2009-01-15 16:51:26 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-15 19:39:41 -0500 |
commit | 068b38c1fa7a9210608f27ac521897ccc5f9b726 (patch) | |
tree | 6ae0ca440bab074c03a4cd4528e8c1467458753f /mm | |
parent | 0eb253e223c88b982461e59154fcad1b82597592 (diff) |
memcg: fix a race when setting memory.swappiness
(suppose: memcg->use_hierarchy == 0 and memcg->swappiness == 60)
echo 10 > /memcg/0/swappiness |
mem_cgroup_swappiness_write() |
... | echo 1 > /memcg/0/use_hierarchy
| mkdir /mnt/0/1
| sub_memcg->swappiness = 60;
memcg->swappiness = 10; |
In the above scenario, we end up having 2 different swappiness
values in a single hierarchy.
We should hold cgroup_lock() when cheking cgrp->children list.
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Acked-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>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/memcontrol.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index f0dc076adf05..4d0ea3ceba6d 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -1992,6 +1992,7 @@ static int mem_cgroup_swappiness_write(struct cgroup *cgrp, struct cftype *cft, | |||
1992 | { | 1992 | { |
1993 | struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp); | 1993 | struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp); |
1994 | struct mem_cgroup *parent; | 1994 | struct mem_cgroup *parent; |
1995 | |||
1995 | if (val > 100) | 1996 | if (val > 100) |
1996 | return -EINVAL; | 1997 | return -EINVAL; |
1997 | 1998 | ||
@@ -1999,15 +2000,22 @@ static int mem_cgroup_swappiness_write(struct cgroup *cgrp, struct cftype *cft, | |||
1999 | return -EINVAL; | 2000 | return -EINVAL; |
2000 | 2001 | ||
2001 | parent = mem_cgroup_from_cont(cgrp->parent); | 2002 | parent = mem_cgroup_from_cont(cgrp->parent); |
2003 | |||
2004 | cgroup_lock(); | ||
2005 | |||
2002 | /* If under hierarchy, only empty-root can set this value */ | 2006 | /* If under hierarchy, only empty-root can set this value */ |
2003 | if ((parent->use_hierarchy) || | 2007 | if ((parent->use_hierarchy) || |
2004 | (memcg->use_hierarchy && !list_empty(&cgrp->children))) | 2008 | (memcg->use_hierarchy && !list_empty(&cgrp->children))) { |
2009 | cgroup_unlock(); | ||
2005 | return -EINVAL; | 2010 | return -EINVAL; |
2011 | } | ||
2006 | 2012 | ||
2007 | spin_lock(&memcg->reclaim_param_lock); | 2013 | spin_lock(&memcg->reclaim_param_lock); |
2008 | memcg->swappiness = val; | 2014 | memcg->swappiness = val; |
2009 | spin_unlock(&memcg->reclaim_param_lock); | 2015 | spin_unlock(&memcg->reclaim_param_lock); |
2010 | 2016 | ||
2017 | cgroup_unlock(); | ||
2018 | |||
2011 | return 0; | 2019 | return 0; |
2012 | } | 2020 | } |
2013 | 2021 | ||