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) { |
