diff options
-rw-r--r-- | Documentation/controllers/memory.txt | 24 | ||||
-rw-r--r-- | mm/memory.c | 25 | ||||
-rw-r--r-- | mm/rmap.c | 4 |
3 files changed, 29 insertions, 24 deletions
diff --git a/Documentation/controllers/memory.txt b/Documentation/controllers/memory.txt index 9b53d5827361..1c07547d3f81 100644 --- a/Documentation/controllers/memory.txt +++ b/Documentation/controllers/memory.txt | |||
@@ -112,14 +112,22 @@ the per cgroup LRU. | |||
112 | 112 | ||
113 | 2.2.1 Accounting details | 113 | 2.2.1 Accounting details |
114 | 114 | ||
115 | All mapped pages (RSS) and unmapped user pages (Page Cache) are accounted. | 115 | All mapped anon pages (RSS) and cache pages (Page Cache) are accounted. |
116 | RSS pages are accounted at the time of page_add_*_rmap() unless they've already | 116 | (some pages which never be reclaimable and will not be on global LRU |
117 | been accounted for earlier. A file page will be accounted for as Page Cache; | 117 | are not accounted. we just accounts pages under usual vm management.) |
118 | it's mapped into the page tables of a process, duplicate accounting is carefully | 118 | |
119 | avoided. Page Cache pages are accounted at the time of add_to_page_cache(). | 119 | RSS pages are accounted at page_fault unless they've already been accounted |
120 | The corresponding routines that remove a page from the page tables or removes | 120 | for earlier. A file page will be accounted for as Page Cache when it's |
121 | a page from Page Cache is used to decrement the accounting counters of the | 121 | inserted into inode (radix-tree). While it's mapped into the page tables of |
122 | cgroup. | 122 | processes, duplicate accounting is carefully avoided. |
123 | |||
124 | A RSS page is unaccounted when it's fully unmapped. A PageCache page is | ||
125 | unaccounted when it's removed from radix-tree. | ||
126 | |||
127 | At page migration, accounting information is kept. | ||
128 | |||
129 | Note: we just account pages-on-lru because our purpose is to control amount | ||
130 | of used pages. not-on-lru pages are tend to be out-of-control from vm view. | ||
123 | 131 | ||
124 | 2.3 Shared Page Accounting | 132 | 2.3 Shared Page Accounting |
125 | 133 | ||
diff --git a/mm/memory.c b/mm/memory.c index 54cf20ee0a83..3a6c4a658325 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -1323,18 +1323,14 @@ static int insert_page(struct vm_area_struct *vma, unsigned long addr, | |||
1323 | pte_t *pte; | 1323 | pte_t *pte; |
1324 | spinlock_t *ptl; | 1324 | spinlock_t *ptl; |
1325 | 1325 | ||
1326 | retval = mem_cgroup_charge(page, mm, GFP_KERNEL); | ||
1327 | if (retval) | ||
1328 | goto out; | ||
1329 | |||
1330 | retval = -EINVAL; | 1326 | retval = -EINVAL; |
1331 | if (PageAnon(page)) | 1327 | if (PageAnon(page)) |
1332 | goto out_uncharge; | 1328 | goto out; |
1333 | retval = -ENOMEM; | 1329 | retval = -ENOMEM; |
1334 | flush_dcache_page(page); | 1330 | flush_dcache_page(page); |
1335 | pte = get_locked_pte(mm, addr, &ptl); | 1331 | pte = get_locked_pte(mm, addr, &ptl); |
1336 | if (!pte) | 1332 | if (!pte) |
1337 | goto out_uncharge; | 1333 | goto out; |
1338 | retval = -EBUSY; | 1334 | retval = -EBUSY; |
1339 | if (!pte_none(*pte)) | 1335 | if (!pte_none(*pte)) |
1340 | goto out_unlock; | 1336 | goto out_unlock; |
@@ -1350,8 +1346,6 @@ static int insert_page(struct vm_area_struct *vma, unsigned long addr, | |||
1350 | return retval; | 1346 | return retval; |
1351 | out_unlock: | 1347 | out_unlock: |
1352 | pte_unmap_unlock(pte, ptl); | 1348 | pte_unmap_unlock(pte, ptl); |
1353 | out_uncharge: | ||
1354 | mem_cgroup_uncharge_page(page); | ||
1355 | out: | 1349 | out: |
1356 | return retval; | 1350 | return retval; |
1357 | } | 1351 | } |
@@ -2463,6 +2457,7 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2463 | struct page *page; | 2457 | struct page *page; |
2464 | pte_t entry; | 2458 | pte_t entry; |
2465 | int anon = 0; | 2459 | int anon = 0; |
2460 | int charged = 0; | ||
2466 | struct page *dirty_page = NULL; | 2461 | struct page *dirty_page = NULL; |
2467 | struct vm_fault vmf; | 2462 | struct vm_fault vmf; |
2468 | int ret; | 2463 | int ret; |
@@ -2503,6 +2498,12 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2503 | ret = VM_FAULT_OOM; | 2498 | ret = VM_FAULT_OOM; |
2504 | goto out; | 2499 | goto out; |
2505 | } | 2500 | } |
2501 | if (mem_cgroup_charge(page, mm, GFP_KERNEL)) { | ||
2502 | ret = VM_FAULT_OOM; | ||
2503 | page_cache_release(page); | ||
2504 | goto out; | ||
2505 | } | ||
2506 | charged = 1; | ||
2506 | /* | 2507 | /* |
2507 | * Don't let another task, with possibly unlocked vma, | 2508 | * Don't let another task, with possibly unlocked vma, |
2508 | * keep the mlocked page. | 2509 | * keep the mlocked page. |
@@ -2543,11 +2544,6 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2543 | 2544 | ||
2544 | } | 2545 | } |
2545 | 2546 | ||
2546 | if (mem_cgroup_charge(page, mm, GFP_KERNEL)) { | ||
2547 | ret = VM_FAULT_OOM; | ||
2548 | goto out; | ||
2549 | } | ||
2550 | |||
2551 | page_table = pte_offset_map_lock(mm, pmd, address, &ptl); | 2547 | page_table = pte_offset_map_lock(mm, pmd, address, &ptl); |
2552 | 2548 | ||
2553 | /* | 2549 | /* |
@@ -2585,7 +2581,8 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2585 | /* no need to invalidate: a not-present page won't be cached */ | 2581 | /* no need to invalidate: a not-present page won't be cached */ |
2586 | update_mmu_cache(vma, address, entry); | 2582 | update_mmu_cache(vma, address, entry); |
2587 | } else { | 2583 | } else { |
2588 | mem_cgroup_uncharge_page(page); | 2584 | if (charged) |
2585 | mem_cgroup_uncharge_page(page); | ||
2589 | if (anon) | 2586 | if (anon) |
2590 | page_cache_release(page); | 2587 | page_cache_release(page); |
2591 | else | 2588 | else |
@@ -727,8 +727,8 @@ void page_remove_rmap(struct page *page, struct vm_area_struct *vma) | |||
727 | page_clear_dirty(page); | 727 | page_clear_dirty(page); |
728 | set_page_dirty(page); | 728 | set_page_dirty(page); |
729 | } | 729 | } |
730 | 730 | if (PageAnon(page)) | |
731 | mem_cgroup_uncharge_page(page); | 731 | mem_cgroup_uncharge_page(page); |
732 | __dec_zone_page_state(page, | 732 | __dec_zone_page_state(page, |
733 | PageAnon(page) ? NR_ANON_PAGES : NR_FILE_MAPPED); | 733 | PageAnon(page) ? NR_ANON_PAGES : NR_FILE_MAPPED); |
734 | /* | 734 | /* |