diff options
author | Hugh Dickins <hugh@veritas.com> | 2005-10-29 21:16:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-30 00:40:38 -0400 |
commit | 4294621f41a85497019fae64341aa5351a1921b7 (patch) | |
tree | fdeb7eb44384a99d0679ffa6de5019bab0ea2166 /mm/memory.c | |
parent | 404351e67a9facb475abf1492245374a28d13e90 (diff) |
[PATCH] mm: rss = file_rss + anon_rss
I was lazy when we added anon_rss, and chose to change as few places as
possible. So currently each anonymous page has to be counted twice, in rss
and in anon_rss. Which won't be so good if those are atomic counts in some
configurations.
Change that around: keep file_rss and anon_rss separately, and add them
together (with get_mm_rss macro) when the total is needed - reading two
atomics is much cheaper than updating two atomics. And update anon_rss
upfront, typically in memory.c, not tucked away in page_add_anon_rmap.
Signed-off-by: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm/memory.c')
-rw-r--r-- | mm/memory.c | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/mm/memory.c b/mm/memory.c index 51eb38574830..59d42e50fa53 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -397,9 +397,10 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, | |||
397 | pte = pte_mkclean(pte); | 397 | pte = pte_mkclean(pte); |
398 | pte = pte_mkold(pte); | 398 | pte = pte_mkold(pte); |
399 | get_page(page); | 399 | get_page(page); |
400 | inc_mm_counter(dst_mm, rss); | ||
401 | if (PageAnon(page)) | 400 | if (PageAnon(page)) |
402 | inc_mm_counter(dst_mm, anon_rss); | 401 | inc_mm_counter(dst_mm, anon_rss); |
402 | else | ||
403 | inc_mm_counter(dst_mm, file_rss); | ||
403 | set_pte_at(dst_mm, addr, dst_pte, pte); | 404 | set_pte_at(dst_mm, addr, dst_pte, pte); |
404 | page_dup_rmap(page); | 405 | page_dup_rmap(page); |
405 | } | 406 | } |
@@ -581,8 +582,8 @@ static void zap_pte_range(struct mmu_gather *tlb, pmd_t *pmd, | |||
581 | set_page_dirty(page); | 582 | set_page_dirty(page); |
582 | if (pte_young(ptent)) | 583 | if (pte_young(ptent)) |
583 | mark_page_accessed(page); | 584 | mark_page_accessed(page); |
585 | dec_mm_counter(tlb->mm, file_rss); | ||
584 | } | 586 | } |
585 | dec_mm_counter(tlb->mm, rss); | ||
586 | page_remove_rmap(page); | 587 | page_remove_rmap(page); |
587 | tlb_remove_page(tlb, page); | 588 | tlb_remove_page(tlb, page); |
588 | continue; | 589 | continue; |
@@ -1290,13 +1291,15 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
1290 | spin_lock(&mm->page_table_lock); | 1291 | spin_lock(&mm->page_table_lock); |
1291 | page_table = pte_offset_map(pmd, address); | 1292 | page_table = pte_offset_map(pmd, address); |
1292 | if (likely(pte_same(*page_table, orig_pte))) { | 1293 | if (likely(pte_same(*page_table, orig_pte))) { |
1293 | if (PageAnon(old_page)) | ||
1294 | dec_mm_counter(mm, anon_rss); | ||
1295 | if (PageReserved(old_page)) | 1294 | if (PageReserved(old_page)) |
1296 | inc_mm_counter(mm, rss); | 1295 | inc_mm_counter(mm, anon_rss); |
1297 | else | 1296 | else { |
1298 | page_remove_rmap(old_page); | 1297 | page_remove_rmap(old_page); |
1299 | 1298 | if (!PageAnon(old_page)) { | |
1299 | inc_mm_counter(mm, anon_rss); | ||
1300 | dec_mm_counter(mm, file_rss); | ||
1301 | } | ||
1302 | } | ||
1300 | flush_cache_page(vma, address, pfn); | 1303 | flush_cache_page(vma, address, pfn); |
1301 | entry = mk_pte(new_page, vma->vm_page_prot); | 1304 | entry = mk_pte(new_page, vma->vm_page_prot); |
1302 | entry = maybe_mkwrite(pte_mkdirty(entry), vma); | 1305 | entry = maybe_mkwrite(pte_mkdirty(entry), vma); |
@@ -1701,7 +1704,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
1701 | 1704 | ||
1702 | /* The page isn't present yet, go ahead with the fault. */ | 1705 | /* The page isn't present yet, go ahead with the fault. */ |
1703 | 1706 | ||
1704 | inc_mm_counter(mm, rss); | 1707 | inc_mm_counter(mm, anon_rss); |
1705 | pte = mk_pte(page, vma->vm_page_prot); | 1708 | pte = mk_pte(page, vma->vm_page_prot); |
1706 | if (write_access && can_share_swap_page(page)) { | 1709 | if (write_access && can_share_swap_page(page)) { |
1707 | pte = maybe_mkwrite(pte_mkdirty(pte), vma); | 1710 | pte = maybe_mkwrite(pte_mkdirty(pte), vma); |
@@ -1774,7 +1777,7 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
1774 | page_cache_release(page); | 1777 | page_cache_release(page); |
1775 | goto unlock; | 1778 | goto unlock; |
1776 | } | 1779 | } |
1777 | inc_mm_counter(mm, rss); | 1780 | inc_mm_counter(mm, anon_rss); |
1778 | entry = mk_pte(page, vma->vm_page_prot); | 1781 | entry = mk_pte(page, vma->vm_page_prot); |
1779 | entry = maybe_mkwrite(pte_mkdirty(entry), vma); | 1782 | entry = maybe_mkwrite(pte_mkdirty(entry), vma); |
1780 | lru_cache_add_active(page); | 1783 | lru_cache_add_active(page); |
@@ -1887,19 +1890,19 @@ retry: | |||
1887 | */ | 1890 | */ |
1888 | /* Only go through if we didn't race with anybody else... */ | 1891 | /* Only go through if we didn't race with anybody else... */ |
1889 | if (pte_none(*page_table)) { | 1892 | if (pte_none(*page_table)) { |
1890 | if (!PageReserved(new_page)) | ||
1891 | inc_mm_counter(mm, rss); | ||
1892 | |||
1893 | flush_icache_page(vma, new_page); | 1893 | flush_icache_page(vma, new_page); |
1894 | entry = mk_pte(new_page, vma->vm_page_prot); | 1894 | entry = mk_pte(new_page, vma->vm_page_prot); |
1895 | if (write_access) | 1895 | if (write_access) |
1896 | entry = maybe_mkwrite(pte_mkdirty(entry), vma); | 1896 | entry = maybe_mkwrite(pte_mkdirty(entry), vma); |
1897 | set_pte_at(mm, address, page_table, entry); | 1897 | set_pte_at(mm, address, page_table, entry); |
1898 | if (anon) { | 1898 | if (anon) { |
1899 | inc_mm_counter(mm, anon_rss); | ||
1899 | lru_cache_add_active(new_page); | 1900 | lru_cache_add_active(new_page); |
1900 | page_add_anon_rmap(new_page, vma, address); | 1901 | page_add_anon_rmap(new_page, vma, address); |
1901 | } else | 1902 | } else if (!PageReserved(new_page)) { |
1903 | inc_mm_counter(mm, file_rss); | ||
1902 | page_add_file_rmap(new_page); | 1904 | page_add_file_rmap(new_page); |
1905 | } | ||
1903 | } else { | 1906 | } else { |
1904 | /* One of our sibling threads was faster, back out. */ | 1907 | /* One of our sibling threads was faster, back out. */ |
1905 | page_cache_release(new_page); | 1908 | page_cache_release(new_page); |
@@ -2192,7 +2195,7 @@ EXPORT_SYMBOL(vmalloc_to_pfn); | |||
2192 | void update_mem_hiwater(struct task_struct *tsk) | 2195 | void update_mem_hiwater(struct task_struct *tsk) |
2193 | { | 2196 | { |
2194 | if (tsk->mm) { | 2197 | if (tsk->mm) { |
2195 | unsigned long rss = get_mm_counter(tsk->mm, rss); | 2198 | unsigned long rss = get_mm_rss(tsk->mm); |
2196 | 2199 | ||
2197 | if (tsk->mm->hiwater_rss < rss) | 2200 | if (tsk->mm->hiwater_rss < rss) |
2198 | tsk->mm->hiwater_rss = rss; | 2201 | tsk->mm->hiwater_rss = rss; |