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; |
