diff options
author | KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> | 2012-05-29 15:07:04 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-29 16:22:27 -0700 |
commit | cc926f78420705817b807dbec0c5d3643827eba3 (patch) | |
tree | fea47aea4b5963fbf06e77c593abeee3afb1958b /mm | |
parent | d01dd17f1067ca50dbb9d1d3400d33221ce339e7 (diff) | |
download | lwn-cc926f78420705817b807dbec0c5d3643827eba3.tar.gz lwn-cc926f78420705817b807dbec0c5d3643827eba3.zip |
memcg: move charges to root cgroup if use_hierarchy=0
Presently, at removal of cgroup, ->pre_destroy() is called and moves
charges to the parent cgroup. A major reason for returning -EBUSY from
->pre_destroy() is that the 'moving' hits the parent's resource
limitation. It happens only when use_hierarchy=0.
Considering use_hierarchy=0, all cgroups should be flat. So, no one
cannot justify moving charges to parent...parent and children are in flat
configuration, not hierarchical.
This patch modifes the code to move charges to the root cgroup at
rmdir/force_empty if use_hierarchy==0. This will much simplify rmdir()
and reduce error in ->pre_destroy.
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ying Han <yinghan@google.com>
Cc: Glauber Costa <glommer@parallels.com>
Reviewed-by: Tejun Heo <tj@kernel.org>
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 | 34 |
1 files changed, 11 insertions, 23 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 1262a8bc402b..96cd9ebefb2c 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2678,15 +2678,13 @@ static int mem_cgroup_move_parent(struct page *page, struct mem_cgroup *child, gfp_t gfp_mask) { - struct cgroup *cg = child->css.cgroup; - struct cgroup *pcg = cg->parent; struct mem_cgroup *parent; unsigned int nr_pages; unsigned long uninitialized_var(flags); int ret; /* Is ROOT ? */ - if (!pcg) + if (mem_cgroup_is_root(child)) return -EINVAL; ret = -EBUSY; @@ -2697,33 +2695,23 @@ static int mem_cgroup_move_parent(struct page *page, nr_pages = hpage_nr_pages(page); - parent = mem_cgroup_from_cont(pcg); - if (!parent->use_hierarchy) { - ret = __mem_cgroup_try_charge(NULL, - gfp_mask, nr_pages, &parent, false); - if (ret) - goto put_back; - } + parent = parent_mem_cgroup(child); + /* + * If no parent, move charges to root cgroup. + */ + if (!parent) + parent = root_mem_cgroup; if (nr_pages > 1) flags = compound_lock_irqsave(page); - if (parent->use_hierarchy) { - ret = mem_cgroup_move_account(page, nr_pages, - pc, child, parent, false); - if (!ret) - __mem_cgroup_cancel_local_charge(child, nr_pages); - } else { - ret = mem_cgroup_move_account(page, nr_pages, - pc, child, parent, true); - - if (ret) - __mem_cgroup_cancel_charge(parent, nr_pages); - } + ret = mem_cgroup_move_account(page, nr_pages, + pc, child, parent, false); + if (!ret) + __mem_cgroup_cancel_local_charge(child, nr_pages); if (nr_pages > 1) compound_unlock_irqrestore(page, flags); -put_back: putback_lru_page(page); put: put_page(page); |