aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorHugh Dickins <hugh@veritas.com>2004-10-27 18:17:23 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-10-27 18:17:23 -0700
commit8586febd93ed02668b9d0ad87963610425e44977 (patch)
tree0af00bc05254a13d8d1c37c67673fed816e2cb5e /mm
parentda63671a5c506729abb8fe383704c264967c53c0 (diff)
downloadhistory-8586febd93ed02668b9d0ad87963610425e44977.tar.gz
[PATCH] statm: shared = rss - anon_rss
The third "shared" field of /proc/$pid/statm in 2.4 was a count of pages in the mm whose page_count is more than 1 (oddly, including pages shared just with swapcache). That's too costly to calculate each time, so 2.6 changed it to the total file-backed extent. But Andrea knows apps and users surprised when (rss - shared) goes negative: we need to provide an rss-like statistic, close to the 2.4 interpretation. Something that's quick and easy to maintain accurately is mm->anon_rss, the count of anonymous pages in the mm. Then shared = rss - anon_rss gives a pretty good and meaningful approximation to 2.4's intention: wli confirms that this will be useful to Oracle too. Where to show it? I think it's best to treat this as a bugfix and show it in the third field of /proc/$pid/statm, after resident, as before - there's no evidence that the total file-backed extent was found useful. Albert would like other fields to revert to page counts, but that's a lot harder: if mprotect can change the category of a page, then it can't be accounted as simply as this. Only go that route if real need shown. Signed-off-by: Hugh Dickins <hugh@veritas.com> Acked-by: William Irwin <wli@holomorphy.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/memory.c8
-rw-r--r--mm/rmap.c3
2 files changed, 10 insertions, 1 deletions
diff --git a/mm/memory.c b/mm/memory.c
index 170f3f90cc0220..e5c68a782442bb 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -334,6 +334,8 @@ skip_copy_pte_range:
pte = pte_mkold(pte);
get_page(page);
dst->rss++;
+ if (PageAnon(page))
+ dst->anon_rss++;
set_pte(dst_pte, pte);
page_dup_rmap(page);
cont_copy_pte_range_noset:
@@ -424,7 +426,9 @@ static void zap_pte_range(struct mmu_gather *tlb,
set_pte(ptep, pgoff_to_pte(page->index));
if (pte_dirty(pte))
set_page_dirty(page);
- if (pte_young(pte) && !PageAnon(page))
+ if (PageAnon(page))
+ tlb->mm->anon_rss--;
+ else if (pte_young(pte))
mark_page_accessed(page);
tlb->freed++;
page_remove_rmap(page);
@@ -1109,6 +1113,8 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
spin_lock(&mm->page_table_lock);
page_table = pte_offset_map(pmd, address);
if (likely(pte_same(*page_table, pte))) {
+ if (PageAnon(old_page))
+ mm->anon_rss--;
if (PageReserved(old_page))
++mm->rss;
else
diff --git a/mm/rmap.c b/mm/rmap.c
index d4a9a6a50fc87b..b2f242f76cd734 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -432,6 +432,8 @@ void page_add_anon_rmap(struct page *page,
BUG_ON(PageReserved(page));
BUG_ON(!anon_vma);
+ vma->vm_mm->anon_rss++;
+
anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON;
index = (address - vma->vm_start) >> PAGE_SHIFT;
index += vma->vm_pgoff;
@@ -584,6 +586,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma)
}
set_pte(pte, swp_entry_to_pte(entry));
BUG_ON(pte_file(*pte));
+ mm->anon_rss--;
}
mm->rss--;