aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memcontrol.c
diff options
context:
space:
mode:
authorDaisuke Nishimura <nishimura@mxp.nes.nec.co.jp>2010-05-26 17:42:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-27 12:12:43 -0400
commit87946a72283be3de936adc754b7007df7d3e6aeb (patch)
tree0593c87ba36bae13d6a6d5dda65ebb41354954f8 /mm/memcontrol.c
parent90254a65833b67502d14736410b3857a15535c67 (diff)
memcg: move charge of file pages
This patch adds support for moving charge of file pages, which include normal file, tmpfs file and swaps of tmpfs file. It's enabled by setting bit 1 of <target cgroup>/memory.move_charge_at_immigrate. Unlike the case of anonymous pages, file pages(and swaps) in the range mmapped by the task will be moved even if the task hasn't done page fault, i.e. they might not be the task's "RSS", but other task's "RSS" that maps the same file. And mapcount of the page is ignored(the page can be moved even if page_mapcount(page) > 1). So, conditions that the page/swap should be met to be moved is that it must be in the range mmapped by the target task and it must be charged to the old cgroup. [akpm@linux-foundation.org: coding-style fixes] [akpm@linux-foundation.org: fix warning] Signed-off-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Balbir Singh <balbir@in.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r--mm/memcontrol.c56
1 files changed, 44 insertions, 12 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index e5277e8a42a8..be5f478351bd 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -250,6 +250,7 @@ struct mem_cgroup {
250 */ 250 */
251enum move_type { 251enum move_type {
252 MOVE_CHARGE_TYPE_ANON, /* private anonymous page and swap of it */ 252 MOVE_CHARGE_TYPE_ANON, /* private anonymous page and swap of it */
253 MOVE_CHARGE_TYPE_FILE, /* file page(including tmpfs) and swap of it */
253 NR_MOVE_TYPE, 254 NR_MOVE_TYPE,
254}; 255};
255 256
@@ -272,6 +273,12 @@ static bool move_anon(void)
272 &mc.to->move_charge_at_immigrate); 273 &mc.to->move_charge_at_immigrate);
273} 274}
274 275
276static bool move_file(void)
277{
278 return test_bit(MOVE_CHARGE_TYPE_FILE,
279 &mc.to->move_charge_at_immigrate);
280}
281
275/* 282/*
276 * Maximum loops in mem_cgroup_hierarchical_reclaim(), used for soft 283 * Maximum loops in mem_cgroup_hierarchical_reclaim(), used for soft
277 * limit reclaim to prevent infinite loops, if they ever occur. 284 * limit reclaim to prevent infinite loops, if they ever occur.
@@ -4179,11 +4186,8 @@ static struct page *mc_handle_present_pte(struct vm_area_struct *vma,
4179 /* we don't move shared anon */ 4186 /* we don't move shared anon */
4180 if (!move_anon() || page_mapcount(page) > 2) 4187 if (!move_anon() || page_mapcount(page) > 2)
4181 return NULL; 4188 return NULL;
4182 } else 4189 } else if (!move_file())
4183 /* 4190 /* we ignore mapcount for file pages */
4184 * TODO: We don't move charges of file(including shmem/tmpfs)
4185 * pages for now.
4186 */
4187 return NULL; 4191 return NULL;
4188 if (!get_page_unless_zero(page)) 4192 if (!get_page_unless_zero(page))
4189 return NULL; 4193 return NULL;
@@ -4212,6 +4216,39 @@ static struct page *mc_handle_swap_pte(struct vm_area_struct *vma,
4212 return page; 4216 return page;
4213} 4217}
4214 4218
4219static struct page *mc_handle_file_pte(struct vm_area_struct *vma,
4220 unsigned long addr, pte_t ptent, swp_entry_t *entry)
4221{
4222 struct page *page = NULL;
4223 struct inode *inode;
4224 struct address_space *mapping;
4225 pgoff_t pgoff;
4226
4227 if (!vma->vm_file) /* anonymous vma */
4228 return NULL;
4229 if (!move_file())
4230 return NULL;
4231
4232 inode = vma->vm_file->f_path.dentry->d_inode;
4233 mapping = vma->vm_file->f_mapping;
4234 if (pte_none(ptent))
4235 pgoff = linear_page_index(vma, addr);
4236 else /* pte_file(ptent) is true */
4237 pgoff = pte_to_pgoff(ptent);
4238
4239 /* page is moved even if it's not RSS of this task(page-faulted). */
4240 if (!mapping_cap_swap_backed(mapping)) { /* normal file */
4241 page = find_get_page(mapping, pgoff);
4242 } else { /* shmem/tmpfs file. we should take account of swap too. */
4243 swp_entry_t ent;
4244 mem_cgroup_get_shmem_target(inode, pgoff, &page, &ent);
4245 if (do_swap_account)
4246 entry->val = ent.val;
4247 }
4248
4249 return page;
4250}
4251
4215static int is_target_pte_for_mc(struct vm_area_struct *vma, 4252static int is_target_pte_for_mc(struct vm_area_struct *vma,
4216 unsigned long addr, pte_t ptent, union mc_target *target) 4253 unsigned long addr, pte_t ptent, union mc_target *target)
4217{ 4254{
@@ -4224,7 +4261,8 @@ static int is_target_pte_for_mc(struct vm_area_struct *vma,
4224 page = mc_handle_present_pte(vma, addr, ptent); 4261 page = mc_handle_present_pte(vma, addr, ptent);
4225 else if (is_swap_pte(ptent)) 4262 else if (is_swap_pte(ptent))
4226 page = mc_handle_swap_pte(vma, addr, ptent, &ent); 4263 page = mc_handle_swap_pte(vma, addr, ptent, &ent);
4227 /* TODO: handle swap of shmes/tmpfs */ 4264 else if (pte_none(ptent) || pte_file(ptent))
4265 page = mc_handle_file_pte(vma, addr, ptent, &ent);
4228 4266
4229 if (!page && !ent.val) 4267 if (!page && !ent.val)
4230 return 0; 4268 return 0;
@@ -4285,9 +4323,6 @@ static unsigned long mem_cgroup_count_precharge(struct mm_struct *mm)
4285 }; 4323 };
4286 if (is_vm_hugetlb_page(vma)) 4324 if (is_vm_hugetlb_page(vma))
4287 continue; 4325 continue;
4288 /* TODO: We don't move charges of shmem/tmpfs pages for now. */
4289 if (vma->vm_flags & VM_SHARED)
4290 continue;
4291 walk_page_range(vma->vm_start, vma->vm_end, 4326 walk_page_range(vma->vm_start, vma->vm_end,
4292 &mem_cgroup_count_precharge_walk); 4327 &mem_cgroup_count_precharge_walk);
4293 } 4328 }
@@ -4484,9 +4519,6 @@ static void mem_cgroup_move_charge(struct mm_struct *mm)
4484 }; 4519 };
4485 if (is_vm_hugetlb_page(vma)) 4520 if (is_vm_hugetlb_page(vma))
4486 continue; 4521 continue;
4487 /* TODO: We don't move charges of shmem/tmpfs pages for now. */
4488 if (vma->vm_flags & VM_SHARED)
4489 continue;
4490 ret = walk_page_range(vma->vm_start, vma->vm_end, 4522 ret = walk_page_range(vma->vm_start, vma->vm_end,
4491 &mem_cgroup_move_charge_walk); 4523 &mem_cgroup_move_charge_walk);
4492 if (ret) 4524 if (ret)