diff options
-rw-r--r-- | include/linux/memcontrol.h | 4 | ||||
-rw-r--r-- | mm/memcontrol.c | 33 | ||||
-rw-r--r-- | mm/shmem.c | 8 |
3 files changed, 20 insertions, 25 deletions
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index a9e3b76aa884..25b9ca93d232 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h | |||
@@ -56,7 +56,7 @@ extern void mem_cgroup_move_lists(struct page *page, | |||
56 | enum lru_list from, enum lru_list to); | 56 | enum lru_list from, enum lru_list to); |
57 | extern void mem_cgroup_uncharge_page(struct page *page); | 57 | extern void mem_cgroup_uncharge_page(struct page *page); |
58 | extern void mem_cgroup_uncharge_cache_page(struct page *page); | 58 | extern void mem_cgroup_uncharge_cache_page(struct page *page); |
59 | extern int mem_cgroup_shrink_usage(struct page *page, | 59 | extern int mem_cgroup_shmem_charge_fallback(struct page *page, |
60 | struct mm_struct *mm, gfp_t gfp_mask); | 60 | struct mm_struct *mm, gfp_t gfp_mask); |
61 | 61 | ||
62 | extern unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan, | 62 | extern unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan, |
@@ -155,7 +155,7 @@ static inline void mem_cgroup_uncharge_cache_page(struct page *page) | |||
155 | { | 155 | { |
156 | } | 156 | } |
157 | 157 | ||
158 | static inline int mem_cgroup_shrink_usage(struct page *page, | 158 | static inline int mem_cgroup_shmem_charge_fallback(struct page *page, |
159 | struct mm_struct *mm, gfp_t gfp_mask) | 159 | struct mm_struct *mm, gfp_t gfp_mask) |
160 | { | 160 | { |
161 | return 0; | 161 | return 0; |
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) { |