diff options
author | KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> | 2012-05-29 18:07:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-29 19:22:27 -0400 |
commit | cc926f78420705817b807dbec0c5d3643827eba3 (patch) | |
tree | fea47aea4b5963fbf06e77c593abeee3afb1958b | |
parent | d01dd17f1067ca50dbb9d1d3400d33221ce339e7 (diff) |
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>
-rw-r--r-- | Documentation/cgroups/memory.txt | 13 | ||||
-rw-r--r-- | mm/memcontrol.c | 34 |
2 files changed, 19 insertions, 28 deletions
diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt index 6a066a270fc5..dd88540bb995 100644 --- a/Documentation/cgroups/memory.txt +++ b/Documentation/cgroups/memory.txt | |||
@@ -376,14 +376,15 @@ cgroup might have some charge associated with it, even though all | |||
376 | tasks have migrated away from it. (because we charge against pages, not | 376 | tasks have migrated away from it. (because we charge against pages, not |
377 | against tasks.) | 377 | against tasks.) |
378 | 378 | ||
379 | Such charges are freed or moved to their parent. At moving, both of RSS | 379 | We move the stats to root (if use_hierarchy==0) or parent (if |
380 | and CACHES are moved to parent. | 380 | use_hierarchy==1), and no change on the charge except uncharging |
381 | rmdir() may return -EBUSY if freeing/moving fails. See 5.1 also. | 381 | from the child. |
382 | 382 | ||
383 | Charges recorded in swap information is not updated at removal of cgroup. | 383 | Charges recorded in swap information is not updated at removal of cgroup. |
384 | Recorded information is discarded and a cgroup which uses swap (swapcache) | 384 | Recorded information is discarded and a cgroup which uses swap (swapcache) |
385 | will be charged as a new owner of it. | 385 | will be charged as a new owner of it. |
386 | 386 | ||
387 | About use_hierarchy, see Section 6. | ||
387 | 388 | ||
388 | 5. Misc. interfaces. | 389 | 5. Misc. interfaces. |
389 | 390 | ||
@@ -396,13 +397,15 @@ will be charged as a new owner of it. | |||
396 | 397 | ||
397 | Almost all pages tracked by this memory cgroup will be unmapped and freed. | 398 | Almost all pages tracked by this memory cgroup will be unmapped and freed. |
398 | Some pages cannot be freed because they are locked or in-use. Such pages are | 399 | Some pages cannot be freed because they are locked or in-use. Such pages are |
399 | moved to parent and this cgroup will be empty. This may return -EBUSY if | 400 | moved to parent(if use_hierarchy==1) or root (if use_hierarchy==0) and this |
400 | VM is too busy to free/move all pages immediately. | 401 | cgroup will be empty. |
401 | 402 | ||
402 | Typical use case of this interface is that calling this before rmdir(). | 403 | Typical use case of this interface is that calling this before rmdir(). |
403 | Because rmdir() moves all pages to parent, some out-of-use page caches can be | 404 | Because rmdir() moves all pages to parent, some out-of-use page caches can be |
404 | moved to the parent. If you want to avoid that, force_empty will be useful. | 405 | moved to the parent. If you want to avoid that, force_empty will be useful. |
405 | 406 | ||
407 | About use_hierarchy, see Section 6. | ||
408 | |||
406 | 5.2 stat file | 409 | 5.2 stat file |
407 | 410 | ||
408 | memory.stat file includes following statistics | 411 | memory.stat file includes following statistics |
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, | |||
2678 | struct mem_cgroup *child, | 2678 | struct mem_cgroup *child, |
2679 | gfp_t gfp_mask) | 2679 | gfp_t gfp_mask) |
2680 | { | 2680 | { |
2681 | struct cgroup *cg = child->css.cgroup; | ||
2682 | struct cgroup *pcg = cg->parent; | ||
2683 | struct mem_cgroup *parent; | 2681 | struct mem_cgroup *parent; |
2684 | unsigned int nr_pages; | 2682 | unsigned int nr_pages; |
2685 | unsigned long uninitialized_var(flags); | 2683 | unsigned long uninitialized_var(flags); |
2686 | int ret; | 2684 | int ret; |
2687 | 2685 | ||
2688 | /* Is ROOT ? */ | 2686 | /* Is ROOT ? */ |
2689 | if (!pcg) | 2687 | if (mem_cgroup_is_root(child)) |
2690 | return -EINVAL; | 2688 | return -EINVAL; |
2691 | 2689 | ||
2692 | ret = -EBUSY; | 2690 | ret = -EBUSY; |
@@ -2697,33 +2695,23 @@ static int mem_cgroup_move_parent(struct page *page, | |||
2697 | 2695 | ||
2698 | nr_pages = hpage_nr_pages(page); | 2696 | nr_pages = hpage_nr_pages(page); |
2699 | 2697 | ||
2700 | parent = mem_cgroup_from_cont(pcg); | 2698 | parent = parent_mem_cgroup(child); |
2701 | if (!parent->use_hierarchy) { | 2699 | /* |
2702 | ret = __mem_cgroup_try_charge(NULL, | 2700 | * If no parent, move charges to root cgroup. |
2703 | gfp_mask, nr_pages, &parent, false); | 2701 | */ |
2704 | if (ret) | 2702 | if (!parent) |
2705 | goto put_back; | 2703 | parent = root_mem_cgroup; |
2706 | } | ||
2707 | 2704 | ||
2708 | if (nr_pages > 1) | 2705 | if (nr_pages > 1) |
2709 | flags = compound_lock_irqsave(page); | 2706 | flags = compound_lock_irqsave(page); |
2710 | 2707 | ||
2711 | if (parent->use_hierarchy) { | 2708 | ret = mem_cgroup_move_account(page, nr_pages, |
2712 | ret = mem_cgroup_move_account(page, nr_pages, | 2709 | pc, child, parent, false); |
2713 | pc, child, parent, false); | 2710 | if (!ret) |
2714 | if (!ret) | 2711 | __mem_cgroup_cancel_local_charge(child, nr_pages); |
2715 | __mem_cgroup_cancel_local_charge(child, nr_pages); | ||
2716 | } else { | ||
2717 | ret = mem_cgroup_move_account(page, nr_pages, | ||
2718 | pc, child, parent, true); | ||
2719 | |||
2720 | if (ret) | ||
2721 | __mem_cgroup_cancel_charge(parent, nr_pages); | ||
2722 | } | ||
2723 | 2712 | ||
2724 | if (nr_pages > 1) | 2713 | if (nr_pages > 1) |
2725 | compound_unlock_irqrestore(page, flags); | 2714 | compound_unlock_irqrestore(page, flags); |
2726 | put_back: | ||
2727 | putback_lru_page(page); | 2715 | putback_lru_page(page); |
2728 | put: | 2716 | put: |
2729 | put_page(page); | 2717 | put_page(page); |