diff options
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r-- | mm/memcontrol.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index cb1c9dedf9b6..010d6c14129a 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -4108,8 +4108,6 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype, | |||
4108 | if (mem_cgroup_disabled()) | 4108 | if (mem_cgroup_disabled()) |
4109 | return NULL; | 4109 | return NULL; |
4110 | 4110 | ||
4111 | VM_BUG_ON(PageSwapCache(page)); | ||
4112 | |||
4113 | if (PageTransHuge(page)) { | 4111 | if (PageTransHuge(page)) { |
4114 | nr_pages <<= compound_order(page); | 4112 | nr_pages <<= compound_order(page); |
4115 | VM_BUG_ON(!PageTransHuge(page)); | 4113 | VM_BUG_ON(!PageTransHuge(page)); |
@@ -4205,6 +4203,18 @@ void mem_cgroup_uncharge_page(struct page *page) | |||
4205 | if (page_mapped(page)) | 4203 | if (page_mapped(page)) |
4206 | return; | 4204 | return; |
4207 | VM_BUG_ON(page->mapping && !PageAnon(page)); | 4205 | VM_BUG_ON(page->mapping && !PageAnon(page)); |
4206 | /* | ||
4207 | * If the page is in swap cache, uncharge should be deferred | ||
4208 | * to the swap path, which also properly accounts swap usage | ||
4209 | * and handles memcg lifetime. | ||
4210 | * | ||
4211 | * Note that this check is not stable and reclaim may add the | ||
4212 | * page to swap cache at any time after this. However, if the | ||
4213 | * page is not in swap cache by the time page->mapcount hits | ||
4214 | * 0, there won't be any page table references to the swap | ||
4215 | * slot, and reclaim will free it and not actually write the | ||
4216 | * page to disk. | ||
4217 | */ | ||
4208 | if (PageSwapCache(page)) | 4218 | if (PageSwapCache(page)) |
4209 | return; | 4219 | return; |
4210 | __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_ANON, false); | 4220 | __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_ANON, false); |