diff options
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r-- | mm/memcontrol.c | 40 |
1 files changed, 15 insertions, 25 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 2fc6d6c48238..01c2d8f14685 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -932,7 +932,7 @@ static int __mem_cgroup_try_charge(struct mm_struct *mm, | |||
932 | if (unlikely(!mem)) | 932 | if (unlikely(!mem)) |
933 | return 0; | 933 | return 0; |
934 | 934 | ||
935 | VM_BUG_ON(mem_cgroup_is_obsolete(mem)); | 935 | VM_BUG_ON(!mem || mem_cgroup_is_obsolete(mem)); |
936 | 936 | ||
937 | while (1) { | 937 | while (1) { |
938 | int ret; | 938 | int ret; |
@@ -1024,9 +1024,7 @@ static struct mem_cgroup *try_get_mem_cgroup_from_swapcache(struct page *page) | |||
1024 | return NULL; | 1024 | return NULL; |
1025 | 1025 | ||
1026 | pc = lookup_page_cgroup(page); | 1026 | pc = lookup_page_cgroup(page); |
1027 | /* | 1027 | lock_page_cgroup(pc); |
1028 | * Used bit of swapcache is solid under page lock. | ||
1029 | */ | ||
1030 | if (PageCgroupUsed(pc)) { | 1028 | if (PageCgroupUsed(pc)) { |
1031 | mem = pc->mem_cgroup; | 1029 | mem = pc->mem_cgroup; |
1032 | if (mem && !css_tryget(&mem->css)) | 1030 | if (mem && !css_tryget(&mem->css)) |
@@ -1040,6 +1038,7 @@ static struct mem_cgroup *try_get_mem_cgroup_from_swapcache(struct page *page) | |||
1040 | mem = NULL; | 1038 | mem = NULL; |
1041 | rcu_read_unlock(); | 1039 | rcu_read_unlock(); |
1042 | } | 1040 | } |
1041 | unlock_page_cgroup(pc); | ||
1043 | return mem; | 1042 | return mem; |
1044 | } | 1043 | } |
1045 | 1044 | ||
@@ -1618,37 +1617,28 @@ void mem_cgroup_end_migration(struct mem_cgroup *mem, | |||
1618 | } | 1617 | } |
1619 | 1618 | ||
1620 | /* | 1619 | /* |
1621 | * 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. |
1622 | * This is typically used for page reclaiming for shmem for reducing side | 1621 | * Calling hierarchical_reclaim is not enough because we should update |
1623 | * 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. | ||
1624 | */ | 1626 | */ |
1625 | int mem_cgroup_shrink_usage(struct page *page, | 1627 | int mem_cgroup_shmem_charge_fallback(struct page *page, |
1626 | struct mm_struct *mm, | 1628 | struct mm_struct *mm, |
1627 | gfp_t gfp_mask) | 1629 | gfp_t gfp_mask) |
1628 | { | 1630 | { |
1629 | struct mem_cgroup *mem = NULL; | 1631 | struct mem_cgroup *mem = NULL; |
1630 | int progress = 0; | 1632 | int ret; |
1631 | int retry = MEM_CGROUP_RECLAIM_RETRIES; | ||
1632 | 1633 | ||
1633 | if (mem_cgroup_disabled()) | 1634 | if (mem_cgroup_disabled()) |
1634 | return 0; | 1635 | return 0; |
1635 | if (page) | ||
1636 | mem = try_get_mem_cgroup_from_swapcache(page); | ||
1637 | if (!mem && mm) | ||
1638 | mem = try_get_mem_cgroup_from_mm(mm); | ||
1639 | if (unlikely(!mem)) | ||
1640 | return 0; | ||
1641 | 1636 | ||
1642 | do { | 1637 | ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &mem); |
1643 | progress = mem_cgroup_hierarchical_reclaim(mem, | 1638 | if (!ret) |
1644 | gfp_mask, true, false); | 1639 | mem_cgroup_cancel_charge_swapin(mem); /* it does !mem check */ |
1645 | progress += mem_cgroup_check_under_limit(mem); | ||
1646 | } while (!progress && --retry); | ||
1647 | 1640 | ||
1648 | css_put(&mem->css); | 1641 | return ret; |
1649 | if (!retry) | ||
1650 | return -ENOMEM; | ||
1651 | return 0; | ||
1652 | } | 1642 | } |
1653 | 1643 | ||
1654 | static DEFINE_MUTEX(set_limit_mutex); | 1644 | static DEFINE_MUTEX(set_limit_mutex); |