diff options
-rw-r--r-- | Documentation/cgroups/memory.txt | 9 | ||||
-rw-r--r-- | include/linux/swap.h | 9 | ||||
-rw-r--r-- | mm/memcontrol.c | 22 | ||||
-rw-r--r-- | mm/swapfile.c | 31 |
4 files changed, 18 insertions, 53 deletions
diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt index e479007f1a75..6a066a270fc5 100644 --- a/Documentation/cgroups/memory.txt +++ b/Documentation/cgroups/memory.txt | |||
@@ -184,12 +184,14 @@ behind this approach is that a cgroup that aggressively uses a shared | |||
184 | page will eventually get charged for it (once it is uncharged from | 184 | page will eventually get charged for it (once it is uncharged from |
185 | the cgroup that brought it in -- this will happen on memory pressure). | 185 | the cgroup that brought it in -- this will happen on memory pressure). |
186 | 186 | ||
187 | But see section 8.2: when moving a task to another cgroup, its pages may | ||
188 | be recharged to the new cgroup, if move_charge_at_immigrate has been chosen. | ||
189 | |||
187 | Exception: If CONFIG_CGROUP_CGROUP_MEM_RES_CTLR_SWAP is not used. | 190 | Exception: If CONFIG_CGROUP_CGROUP_MEM_RES_CTLR_SWAP is not used. |
188 | When you do swapoff and make swapped-out pages of shmem(tmpfs) to | 191 | When you do swapoff and make swapped-out pages of shmem(tmpfs) to |
189 | be backed into memory in force, charges for pages are accounted against the | 192 | be backed into memory in force, charges for pages are accounted against the |
190 | caller of swapoff rather than the users of shmem. | 193 | caller of swapoff rather than the users of shmem. |
191 | 194 | ||
192 | |||
193 | 2.4 Swap Extension (CONFIG_CGROUP_MEM_RES_CTLR_SWAP) | 195 | 2.4 Swap Extension (CONFIG_CGROUP_MEM_RES_CTLR_SWAP) |
194 | 196 | ||
195 | Swap Extension allows you to record charge for swap. A swapped-in page is | 197 | Swap Extension allows you to record charge for swap. A swapped-in page is |
@@ -615,8 +617,7 @@ memory cgroup. | |||
615 | bit | what type of charges would be moved ? | 617 | bit | what type of charges would be moved ? |
616 | -----+------------------------------------------------------------------------ | 618 | -----+------------------------------------------------------------------------ |
617 | 0 | A charge of an anonymous page(or swap of it) used by the target task. | 619 | 0 | A charge of an anonymous page(or swap of it) used by the target task. |
618 | | Those pages and swaps must be used only by the target task. You must | 620 | | You must enable Swap Extension(see 2.4) to enable move of swap charges. |
619 | | enable Swap Extension(see 2.4) to enable move of swap charges. | ||
620 | -----+------------------------------------------------------------------------ | 621 | -----+------------------------------------------------------------------------ |
621 | 1 | A charge of file pages(normal file, tmpfs file(e.g. ipc shared memory) | 622 | 1 | A charge of file pages(normal file, tmpfs file(e.g. ipc shared memory) |
622 | | and swaps of tmpfs file) mmapped by the target task. Unlike the case of | 623 | | and swaps of tmpfs file) mmapped by the target task. Unlike the case of |
@@ -629,8 +630,6 @@ memory cgroup. | |||
629 | 630 | ||
630 | 8.3 TODO | 631 | 8.3 TODO |
631 | 632 | ||
632 | - Implement madvise(2) to let users decide the vma to be moved or not to be | ||
633 | moved. | ||
634 | - All of moving charge operations are done under cgroup_mutex. It's not good | 633 | - All of moving charge operations are done under cgroup_mutex. It's not good |
635 | behavior to hold the mutex too long, so we may need some trick. | 634 | behavior to hold the mutex too long, so we may need some trick. |
636 | 635 | ||
diff --git a/include/linux/swap.h b/include/linux/swap.h index d965c4bfab3a..49c0fa9ef5cf 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h | |||
@@ -359,7 +359,6 @@ struct backing_dev_info; | |||
359 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR | 359 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR |
360 | extern void | 360 | extern void |
361 | mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout); | 361 | mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout); |
362 | extern int mem_cgroup_count_swap_user(swp_entry_t ent, struct page **pagep); | ||
363 | #else | 362 | #else |
364 | static inline void | 363 | static inline void |
365 | mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout) | 364 | mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout) |
@@ -470,14 +469,6 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent) | |||
470 | { | 469 | { |
471 | } | 470 | } |
472 | 471 | ||
473 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR | ||
474 | static inline int | ||
475 | mem_cgroup_count_swap_user(swp_entry_t ent, struct page **pagep) | ||
476 | { | ||
477 | return 0; | ||
478 | } | ||
479 | #endif | ||
480 | |||
481 | #endif /* CONFIG_SWAP */ | 472 | #endif /* CONFIG_SWAP */ |
482 | #endif /* __KERNEL__*/ | 473 | #endif /* __KERNEL__*/ |
483 | #endif /* _LINUX_SWAP_H */ | 474 | #endif /* _LINUX_SWAP_H */ |
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index d7ce417cae7c..e7db70f3d2d6 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -5154,7 +5154,7 @@ static struct page *mc_handle_present_pte(struct vm_area_struct *vma, | |||
5154 | return NULL; | 5154 | return NULL; |
5155 | if (PageAnon(page)) { | 5155 | if (PageAnon(page)) { |
5156 | /* we don't move shared anon */ | 5156 | /* we don't move shared anon */ |
5157 | if (!move_anon() || page_mapcount(page) > 2) | 5157 | if (!move_anon()) |
5158 | return NULL; | 5158 | return NULL; |
5159 | } else if (!move_file()) | 5159 | } else if (!move_file()) |
5160 | /* we ignore mapcount for file pages */ | 5160 | /* we ignore mapcount for file pages */ |
@@ -5165,26 +5165,32 @@ static struct page *mc_handle_present_pte(struct vm_area_struct *vma, | |||
5165 | return page; | 5165 | return page; |
5166 | } | 5166 | } |
5167 | 5167 | ||
5168 | #ifdef CONFIG_SWAP | ||
5168 | static struct page *mc_handle_swap_pte(struct vm_area_struct *vma, | 5169 | static struct page *mc_handle_swap_pte(struct vm_area_struct *vma, |
5169 | unsigned long addr, pte_t ptent, swp_entry_t *entry) | 5170 | unsigned long addr, pte_t ptent, swp_entry_t *entry) |
5170 | { | 5171 | { |
5171 | int usage_count; | ||
5172 | struct page *page = NULL; | 5172 | struct page *page = NULL; |
5173 | swp_entry_t ent = pte_to_swp_entry(ptent); | 5173 | swp_entry_t ent = pte_to_swp_entry(ptent); |
5174 | 5174 | ||
5175 | if (!move_anon() || non_swap_entry(ent)) | 5175 | if (!move_anon() || non_swap_entry(ent)) |
5176 | return NULL; | 5176 | return NULL; |
5177 | usage_count = mem_cgroup_count_swap_user(ent, &page); | 5177 | /* |
5178 | if (usage_count > 1) { /* we don't move shared anon */ | 5178 | * Because lookup_swap_cache() updates some statistics counter, |
5179 | if (page) | 5179 | * we call find_get_page() with swapper_space directly. |
5180 | put_page(page); | 5180 | */ |
5181 | return NULL; | 5181 | page = find_get_page(&swapper_space, ent.val); |
5182 | } | ||
5183 | if (do_swap_account) | 5182 | if (do_swap_account) |
5184 | entry->val = ent.val; | 5183 | entry->val = ent.val; |
5185 | 5184 | ||
5186 | return page; | 5185 | return page; |
5187 | } | 5186 | } |
5187 | #else | ||
5188 | static struct page *mc_handle_swap_pte(struct vm_area_struct *vma, | ||
5189 | unsigned long addr, pte_t ptent, swp_entry_t *entry) | ||
5190 | { | ||
5191 | return NULL; | ||
5192 | } | ||
5193 | #endif | ||
5188 | 5194 | ||
5189 | static struct page *mc_handle_file_pte(struct vm_area_struct *vma, | 5195 | static struct page *mc_handle_file_pte(struct vm_area_struct *vma, |
5190 | unsigned long addr, pte_t ptent, swp_entry_t *entry) | 5196 | unsigned long addr, pte_t ptent, swp_entry_t *entry) |
diff --git a/mm/swapfile.c b/mm/swapfile.c index b0c86e92f42c..457b10baef59 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -717,37 +717,6 @@ int free_swap_and_cache(swp_entry_t entry) | |||
717 | return p != NULL; | 717 | return p != NULL; |
718 | } | 718 | } |
719 | 719 | ||
720 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR | ||
721 | /** | ||
722 | * mem_cgroup_count_swap_user - count the user of a swap entry | ||
723 | * @ent: the swap entry to be checked | ||
724 | * @pagep: the pointer for the swap cache page of the entry to be stored | ||
725 | * | ||
726 | * Returns the number of the user of the swap entry. The number is valid only | ||
727 | * for swaps of anonymous pages. | ||
728 | * If the entry is found on swap cache, the page is stored to pagep with | ||
729 | * refcount of it being incremented. | ||
730 | */ | ||
731 | int mem_cgroup_count_swap_user(swp_entry_t ent, struct page **pagep) | ||
732 | { | ||
733 | struct page *page; | ||
734 | struct swap_info_struct *p; | ||
735 | int count = 0; | ||
736 | |||
737 | page = find_get_page(&swapper_space, ent.val); | ||
738 | if (page) | ||
739 | count += page_mapcount(page); | ||
740 | p = swap_info_get(ent); | ||
741 | if (p) { | ||
742 | count += swap_count(p->swap_map[swp_offset(ent)]); | ||
743 | spin_unlock(&swap_lock); | ||
744 | } | ||
745 | |||
746 | *pagep = page; | ||
747 | return count; | ||
748 | } | ||
749 | #endif | ||
750 | |||
751 | #ifdef CONFIG_HIBERNATION | 720 | #ifdef CONFIG_HIBERNATION |
752 | /* | 721 | /* |
753 | * Find the swap type that corresponds to given device (if any). | 722 | * Find the swap type that corresponds to given device (if any). |