diff options
author | Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> | 2009-04-30 18:08:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-05-02 18:36:09 -0400 |
commit | ae3abae64f177586be55b04a7fb7047a34b21a3e (patch) | |
tree | 05ba2ef8dca958cc4a02ac08e5aae03b8bc82a81 /mm | |
parent | 0816178638c15ce5472d39d771a96860dff4141a (diff) |
memcg: fix mem_cgroup_shrink_usage()
Current mem_cgroup_shrink_usage() has two problems.
1. It doesn't call mem_cgroup_out_of_memory and doesn't update
last_oom_jiffies, so pagefault_out_of_memory invokes global OOM.
2. Considering hierarchy, shrinking has to be done from the
mem_over_limit, not from the memcg which the page would be charged to.
mem_cgroup_try_charge_swapin() does all of these things properly, so we
use it and call cancel_charge_swapin when it succeeded.
The name of "shrink_usage" is not appropriate for this behavior, so we
change it too.
Signed-off-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Li Zefan <lizf@cn.fujitsu.cn>
Cc: Paul Menage <menage@google.com>
Cc: Dhaval Giani <dhaval@linux.vnet.ibm.com>
Cc: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
Cc: YAMAMOTO Takashi <yamamoto@valinux.co.jp>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: 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')
-rw-r--r-- | mm/memcontrol.c | 33 | ||||
-rw-r--r-- | mm/shmem.c | 8 |
2 files changed, 18 insertions, 23 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 575203ae2109..01c2d8f14685 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -1617,37 +1617,28 @@ void mem_cgroup_end_migration(struct mem_cgroup *mem, | |||
1617 | } | 1617 | } |
1618 | 1618 | ||
1619 | /* | 1619 | /* |
1620 | * A call to try to shrink memory usage under specified resource controller. | 1620 | * A call to try to shrink memory usage on charge failure at shmem's swapin. |
1621 | * This is typically used for page reclaiming for shmem for reducing side | 1621 | * Calling hierarchical_reclaim is not enough because we should update |
1622 | * effect of page allocation from shmem, which is used by some mem_cgroup. | 1622 | * last_oom_jiffies to prevent pagefault_out_of_memory from invoking global OOM. |
1623 | * Moreover considering hierarchy, we should reclaim from the mem_over_limit, | ||
1624 | * not from the memcg which this page would be charged to. | ||
1625 | * try_charge_swapin does all of these works properly. | ||
1623 | */ | 1626 | */ |
1624 | int mem_cgroup_shrink_usage(struct page *page, | 1627 | int mem_cgroup_shmem_charge_fallback(struct page *page, |
1625 | struct mm_struct *mm, | 1628 | struct mm_struct *mm, |
1626 | gfp_t gfp_mask) | 1629 | gfp_t gfp_mask) |
1627 | { | 1630 | { |
1628 | struct mem_cgroup *mem = NULL; | 1631 | struct mem_cgroup *mem = NULL; |
1629 | int progress = 0; | 1632 | int ret; |
1630 | int retry = MEM_CGROUP_RECLAIM_RETRIES; | ||
1631 | 1633 | ||
1632 | if (mem_cgroup_disabled()) | 1634 | if (mem_cgroup_disabled()) |
1633 | return 0; | 1635 | return 0; |
1634 | if (page) | ||
1635 | mem = try_get_mem_cgroup_from_swapcache(page); | ||
1636 | if (!mem && mm) | ||
1637 | mem = try_get_mem_cgroup_from_mm(mm); | ||
1638 | if (unlikely(!mem)) | ||
1639 | return 0; | ||
1640 | 1636 | ||
1641 | do { | 1637 | ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &mem); |
1642 | progress = mem_cgroup_hierarchical_reclaim(mem, | 1638 | if (!ret) |
1643 | gfp_mask, true, false); | 1639 | mem_cgroup_cancel_charge_swapin(mem); /* it does !mem check */ |
1644 | progress += mem_cgroup_check_under_limit(mem); | ||
1645 | } while (!progress && --retry); | ||
1646 | 1640 | ||
1647 | css_put(&mem->css); | 1641 | return ret; |
1648 | if (!retry) | ||
1649 | return -ENOMEM; | ||
1650 | return 0; | ||
1651 | } | 1642 | } |
1652 | 1643 | ||
1653 | static DEFINE_MUTEX(set_limit_mutex); | 1644 | static DEFINE_MUTEX(set_limit_mutex); |
diff --git a/mm/shmem.c b/mm/shmem.c index f9cb20ebb990..b25f95ce3db7 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -1340,8 +1340,12 @@ repeat: | |||
1340 | shmem_swp_unmap(entry); | 1340 | shmem_swp_unmap(entry); |
1341 | spin_unlock(&info->lock); | 1341 | spin_unlock(&info->lock); |
1342 | if (error == -ENOMEM) { | 1342 | if (error == -ENOMEM) { |
1343 | /* allow reclaim from this memory cgroup */ | 1343 | /* |
1344 | error = mem_cgroup_shrink_usage(swappage, | 1344 | * reclaim from proper memory cgroup and |
1345 | * call memcg's OOM if needed. | ||
1346 | */ | ||
1347 | error = mem_cgroup_shmem_charge_fallback( | ||
1348 | swappage, | ||
1345 | current->mm, | 1349 | current->mm, |
1346 | gfp); | 1350 | gfp); |
1347 | if (error) { | 1351 | if (error) { |