diff options
-rw-r--r-- | include/linux/swap.h | 5 | ||||
-rw-r--r-- | mm/memcontrol.c | 17 | ||||
-rw-r--r-- | mm/swapfile.c | 16 |
3 files changed, 27 insertions, 11 deletions
diff --git a/include/linux/swap.h b/include/linux/swap.h index dca9b9999aeb..c88b36665f79 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h | |||
@@ -319,10 +319,11 @@ static inline void disable_swap_token(void) | |||
319 | } | 319 | } |
320 | 320 | ||
321 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR | 321 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR |
322 | extern void mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent); | 322 | extern void |
323 | mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout); | ||
323 | #else | 324 | #else |
324 | static inline void | 325 | static inline void |
325 | mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent) | 326 | mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout) |
326 | { | 327 | { |
327 | } | 328 | } |
328 | #endif | 329 | #endif |
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 3468c38adde6..a83e0395444b 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -189,6 +189,7 @@ enum charge_type { | |||
189 | MEM_CGROUP_CHARGE_TYPE_SHMEM, /* used by page migration of shmem */ | 189 | MEM_CGROUP_CHARGE_TYPE_SHMEM, /* used by page migration of shmem */ |
190 | MEM_CGROUP_CHARGE_TYPE_FORCE, /* used by force_empty */ | 190 | MEM_CGROUP_CHARGE_TYPE_FORCE, /* used by force_empty */ |
191 | MEM_CGROUP_CHARGE_TYPE_SWAPOUT, /* for accounting swapcache */ | 191 | MEM_CGROUP_CHARGE_TYPE_SWAPOUT, /* for accounting swapcache */ |
192 | MEM_CGROUP_CHARGE_TYPE_DROP, /* a page was unused swap cache */ | ||
192 | NR_CHARGE_TYPE, | 193 | NR_CHARGE_TYPE, |
193 | }; | 194 | }; |
194 | 195 | ||
@@ -1493,6 +1494,7 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype) | |||
1493 | 1494 | ||
1494 | switch (ctype) { | 1495 | switch (ctype) { |
1495 | case MEM_CGROUP_CHARGE_TYPE_MAPPED: | 1496 | case MEM_CGROUP_CHARGE_TYPE_MAPPED: |
1497 | case MEM_CGROUP_CHARGE_TYPE_DROP: | ||
1496 | if (page_mapped(page)) | 1498 | if (page_mapped(page)) |
1497 | goto unlock_out; | 1499 | goto unlock_out; |
1498 | break; | 1500 | break; |
@@ -1556,18 +1558,23 @@ void mem_cgroup_uncharge_cache_page(struct page *page) | |||
1556 | * called after __delete_from_swap_cache() and drop "page" account. | 1558 | * called after __delete_from_swap_cache() and drop "page" account. |
1557 | * memcg information is recorded to swap_cgroup of "ent" | 1559 | * memcg information is recorded to swap_cgroup of "ent" |
1558 | */ | 1560 | */ |
1559 | void mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent) | 1561 | void |
1562 | mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout) | ||
1560 | { | 1563 | { |
1561 | struct mem_cgroup *memcg; | 1564 | struct mem_cgroup *memcg; |
1565 | int ctype = MEM_CGROUP_CHARGE_TYPE_SWAPOUT; | ||
1566 | |||
1567 | if (!swapout) /* this was a swap cache but the swap is unused ! */ | ||
1568 | ctype = MEM_CGROUP_CHARGE_TYPE_DROP; | ||
1569 | |||
1570 | memcg = __mem_cgroup_uncharge_common(page, ctype); | ||
1562 | 1571 | ||
1563 | memcg = __mem_cgroup_uncharge_common(page, | ||
1564 | MEM_CGROUP_CHARGE_TYPE_SWAPOUT); | ||
1565 | /* record memcg information */ | 1572 | /* record memcg information */ |
1566 | if (do_swap_account && memcg) { | 1573 | if (do_swap_account && swapout && memcg) { |
1567 | swap_cgroup_record(ent, css_id(&memcg->css)); | 1574 | swap_cgroup_record(ent, css_id(&memcg->css)); |
1568 | mem_cgroup_get(memcg); | 1575 | mem_cgroup_get(memcg); |
1569 | } | 1576 | } |
1570 | if (memcg) | 1577 | if (swapout && memcg) |
1571 | css_put(&memcg->css); | 1578 | css_put(&memcg->css); |
1572 | } | 1579 | } |
1573 | #endif | 1580 | #endif |
diff --git a/mm/swapfile.c b/mm/swapfile.c index 28faa01cf578..d1ade1a48ee7 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -583,8 +583,9 @@ static int swap_entry_free(struct swap_info_struct *p, | |||
583 | swap_list.next = p - swap_info; | 583 | swap_list.next = p - swap_info; |
584 | nr_swap_pages++; | 584 | nr_swap_pages++; |
585 | p->inuse_pages--; | 585 | p->inuse_pages--; |
586 | mem_cgroup_uncharge_swap(ent); | ||
587 | } | 586 | } |
587 | if (!swap_count(count)) | ||
588 | mem_cgroup_uncharge_swap(ent); | ||
588 | return count; | 589 | return count; |
589 | } | 590 | } |
590 | 591 | ||
@@ -609,12 +610,19 @@ void swap_free(swp_entry_t entry) | |||
609 | void swapcache_free(swp_entry_t entry, struct page *page) | 610 | void swapcache_free(swp_entry_t entry, struct page *page) |
610 | { | 611 | { |
611 | struct swap_info_struct *p; | 612 | struct swap_info_struct *p; |
613 | int ret; | ||
612 | 614 | ||
613 | if (page) | ||
614 | mem_cgroup_uncharge_swapcache(page, entry); | ||
615 | p = swap_info_get(entry); | 615 | p = swap_info_get(entry); |
616 | if (p) { | 616 | if (p) { |
617 | swap_entry_free(p, entry, SWAP_CACHE); | 617 | ret = swap_entry_free(p, entry, SWAP_CACHE); |
618 | if (page) { | ||
619 | bool swapout; | ||
620 | if (ret) | ||
621 | swapout = true; /* the end of swap out */ | ||
622 | else | ||
623 | swapout = false; /* no more swap users! */ | ||
624 | mem_cgroup_uncharge_swapcache(page, entry, swapout); | ||
625 | } | ||
618 | spin_unlock(&swap_lock); | 626 | spin_unlock(&swap_lock); |
619 | } | 627 | } |
620 | return; | 628 | return; |