diff -uNr linux-2.5.26-rmap-slablru/fs/proc/proc_misc.c linux-2.5.26-rmap-slablru-stats/fs/proc/proc_misc.c --- linux-2.5.26-rmap-slablru/fs/proc/proc_misc.c Thu Jul 18 19:20:03 2002 +++ linux-2.5.26-rmap-slablru-stats/fs/proc/proc_misc.c Fri Jul 19 00:21:47 2002 @@ -162,7 +162,11 @@ "SwapTotal: %8lu kB\n" "SwapFree: %8lu kB\n" "Dirty: %8lu kB\n" - "Writeback: %8lu kB\n", + "Writeback: %8lu kB\n" + "PageTables: %8lu kB\n" + "PteChainTot: %8lu kB\n" + "PteChainUsed: %8lu kB\n" + "PteChainActv: %8lu\n", K(i.totalram), K(i.freeram), K(i.sharedram), @@ -179,7 +183,11 @@ K(i.totalswap), K(i.freeswap), K(ps.nr_dirty), - K(ps.nr_writeback) + K(ps.nr_writeback), + K(ps.nr_page_table_pages), + K(ps.nr_pte_chain_pages), + ps.used_pte_chains_bytes >> 10, + ps.nr_active_pte_chains ); return proc_calc_metrics(page, start, off, count, eof, len); @@ -352,9 +360,29 @@ } len += sprintf(page + len, - "\nctxt %lu\n" + "\npageallocs %u\n" + "pagefrees %u\n" + "pageactiv %u\n" + "pagedeact %u\n" + "pagefault %u\n" + "majorfault %u\n" + "pagescan %u\n" + "pagesteal %u\n" + "pageoutrun %u\n" + "allocstall %u\n" + "ctxt %lu\n" "btime %lu\n" "processes %lu\n", + kstat.pgalloc, + kstat.pgfree, + kstat.pgactivate, + kstat.pgdeactivate, + kstat.pgfault, + kstat.pgmajfault, + kstat.pgscan, + kstat.pgsteal, + kstat.pageoutrun, + kstat.allocstall, nr_context_switches(), xtime.tv_sec - jif / HZ, total_forks); diff -uNr linux-2.5.26-rmap-slablru/include/asm-generic/rmap.h linux-2.5.26-rmap-slablru-stats/include/asm-generic/rmap.h --- linux-2.5.26-rmap-slablru/include/asm-generic/rmap.h Thu Jul 18 19:19:53 2002 +++ linux-2.5.26-rmap-slablru-stats/include/asm-generic/rmap.h Thu Jul 18 23:54:41 2002 @@ -27,12 +27,14 @@ #endif page->mapping = (void *)mm; page->index = address & ~((PTRS_PER_PTE * PAGE_SIZE) - 1); + inc_page_state(nr_page_table_pages); } static inline void pgtable_remove_rmap(struct page * page) { page->mapping = NULL; page->index = 0; + dec_page_state(nr_page_table_pages); } static inline struct mm_struct * ptep_to_mm(pte_t * ptep) diff -uNr linux-2.5.26-rmap-slablru/include/linux/kernel_stat.h linux-2.5.26-rmap-slablru-stats/include/linux/kernel_stat.h --- linux-2.5.26-rmap-slablru/include/linux/kernel_stat.h Thu Jul 18 19:16:02 2002 +++ linux-2.5.26-rmap-slablru-stats/include/linux/kernel_stat.h Thu Jul 18 23:54:42 2002 @@ -26,6 +26,11 @@ unsigned int dk_drive_wblk[DK_MAX_MAJOR][DK_MAX_DISK]; unsigned int pgpgin, pgpgout; unsigned int pswpin, pswpout; + unsigned int pgalloc, pgfree; + unsigned int pgactivate, pgdeactivate; + unsigned int pgfault, pgmajfault; + unsigned int pgscan, pgsteal; + unsigned int pageoutrun, allocstall; #if !defined(CONFIG_ARCH_S390) unsigned int irqs[NR_CPUS][NR_IRQS]; #endif @@ -35,6 +40,13 @@ extern unsigned long nr_context_switches(void); +/* + * Maybe we need to smp-ify kernel_stat some day. It would be nice to do + * that without having to modify all the code that increments the stats. + */ +#define KERNEL_STAT_INC(x) kstat.x++ +#define KERNEL_STAT_ADD(x, y) kstat.x += y + #if !defined(CONFIG_ARCH_S390) /* * Number of interrupts per specific IRQ source, since bootup diff -uNr linux-2.5.26-rmap-slablru/include/linux/page-flags.h linux-2.5.26-rmap-slablru-stats/include/linux/page-flags.h --- linux-2.5.26-rmap-slablru/include/linux/page-flags.h Thu Jul 18 19:20:03 2002 +++ linux-2.5.26-rmap-slablru-stats/include/linux/page-flags.h Fri Jul 19 00:22:20 2002 @@ -79,6 +79,10 @@ unsigned long nr_active_pages; /* on active_list LRU */ unsigned long nr_inactive_clean_pages; /* on inactive_clean_list LRU */ unsigned long nr_inactive_dirty_pages; /* on inactive_dirty_list LRU */ + unsigned long nr_page_table_pages; + unsigned long nr_pte_chain_pages; + unsigned long used_pte_chains_bytes; + unsigned long nr_active_pte_chains; } ____cacheline_aligned_in_smp page_states[NR_CPUS]; extern void get_page_state(struct page_state *ret); diff -uNr linux-2.5.26-rmap-slablru/init/main.c linux-2.5.26-rmap-slablru-stats/init/main.c --- linux-2.5.26-rmap-slablru/init/main.c Thu Jul 18 19:18:47 2002 +++ linux-2.5.26-rmap-slablru-stats/init/main.c Thu Jul 18 23:54:42 2002 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -502,6 +503,8 @@ free_initmem(); unlock_kernel(); + kstat.pgfree = 0; + if (open("/dev/console", O_RDWR, 0) < 0) printk("Warning: unable to open an initial console.\n"); diff -uNr linux-2.5.26-rmap-slablru/mm/filemap.c linux-2.5.26-rmap-slablru-stats/mm/filemap.c --- linux-2.5.26-rmap-slablru/mm/filemap.c Thu Jul 18 19:20:03 2002 +++ linux-2.5.26-rmap-slablru-stats/mm/filemap.c Thu Jul 18 23:54:42 2002 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -1541,6 +1542,7 @@ return NULL; page_not_uptodate: + KERNEL_STAT_INC(pgmajfault); lock_page(page); /* Did it get unhashed while we waited for it? */ diff -uNr linux-2.5.26-rmap-slablru/mm/memory.c linux-2.5.26-rmap-slablru-stats/mm/memory.c --- linux-2.5.26-rmap-slablru/mm/memory.c Thu Jul 18 19:20:03 2002 +++ linux-2.5.26-rmap-slablru-stats/mm/memory.c Thu Jul 18 23:54:42 2002 @@ -36,6 +36,7 @@ * (Gerhard.Wichert@pdb.siemens.de) */ +#include #include #include #include @@ -1182,6 +1183,7 @@ /* Had to read the page from swap area: Major fault */ ret = VM_FAULT_MAJOR; + KERNEL_STAT_INC(pgmajfault); } lock_page(page); @@ -1434,6 +1436,7 @@ free_high(ALL_ZONES) > 0) rss_free_pages(GFP_HIGHUSER); + KERNEL_STAT_INC(pgfault); /* * We need the page table lock to synchronize with kswapd * and the SMP-safe atomic PTE updates. diff -uNr linux-2.5.26-rmap-slablru/mm/page_alloc.c linux-2.5.26-rmap-slablru-stats/mm/page_alloc.c --- linux-2.5.26-rmap-slablru/mm/page_alloc.c Thu Jul 18 19:20:03 2002 +++ linux-2.5.26-rmap-slablru-stats/mm/page_alloc.c Fri Jul 19 00:22:54 2002 @@ -13,6 +13,7 @@ */ #include +#include #include #include #include @@ -87,6 +88,8 @@ struct page *base; zone_t *zone; + KERNEL_STAT_ADD(pgfree, 1<mapping != NULL); @@ -320,6 +323,8 @@ int min, direct_reclaim = 0; struct page * page; + KERNEL_STAT_ADD(pgalloc, 1<flags & PF_MEMALLOC)) { /* * Are we dealing with a higher order allocation? @@ -696,6 +702,10 @@ ret->nr_active_pages += ps->nr_active_pages; ret->nr_inactive_clean_pages += ps->nr_inactive_clean_pages; ret->nr_inactive_dirty_pages += ps->nr_inactive_dirty_pages; + ret->nr_page_table_pages += ps->nr_page_table_pages; + ret->nr_pte_chain_pages += ps->nr_pte_chain_pages; + ret->used_pte_chains_bytes += ps->used_pte_chains_bytes; + ret->nr_active_pte_chains += ps->nr_active_pte_chains; } } diff -uNr linux-2.5.26-rmap-slablru/mm/rmap.c linux-2.5.26-rmap-slablru-stats/mm/rmap.c --- linux-2.5.26-rmap-slablru/mm/rmap.c Thu Jul 18 19:20:03 2002 +++ linux-2.5.26-rmap-slablru-stats/mm/rmap.c Fri Jul 19 00:24:01 2002 @@ -143,6 +143,7 @@ } pte_chain_unlock(page); + inc_page_state(nr_active_pte_chains); } /** @@ -203,6 +204,7 @@ out: pte_chain_unlock(page); + dec_page_state(nr_active_pte_chains); return; } @@ -422,6 +424,7 @@ static inline void pte_chain_free(struct pte_chain * pte_chain, struct pte_chain * prev_pte_chain, struct page * page) { + mod_page_state(used_pte_chains_bytes, -sizeof(struct pte_chain)); if (prev_pte_chain) prev_pte_chain->next = pte_chain->next; else if (page) @@ -454,6 +457,7 @@ spin_unlock(&pte_chain_freelist_lock); + mod_page_state(used_pte_chains_bytes, sizeof(struct pte_chain)); return pte_chain; } @@ -474,6 +478,7 @@ int i = PAGE_SIZE / sizeof(struct pte_chain); if (pte_chain) { + inc_page_state(nr_pte_chain_pages); for (; i-- > 0; pte_chain++) pte_chain_push(pte_chain); } else { diff -uNr linux-2.5.26-rmap-slablru/mm/swap.c linux-2.5.26-rmap-slablru-stats/mm/swap.c --- linux-2.5.26-rmap-slablru/mm/swap.c Thu Jul 18 19:20:03 2002 +++ linux-2.5.26-rmap-slablru-stats/mm/swap.c Fri Jul 19 00:05:44 2002 @@ -118,9 +118,11 @@ if (PageInactiveDirty(page)) { del_page_from_inactive_dirty_list(page); add_page_to_active_list(page); + KERNEL_STAT_INC(pgactivate); } else if (PageInactiveClean(page)) { del_page_from_inactive_clean_list(page); add_page_to_active_list(page); + KERNEL_STAT_INC(pgactivate); } /* Make sure the page gets a fair chance at staying active. */ diff -uNr linux-2.5.26-rmap-slablru/mm/vmscan.c linux-2.5.26-rmap-slablru-stats/mm/vmscan.c --- linux-2.5.26-rmap-slablru/mm/vmscan.c Thu Jul 18 19:20:07 2002 +++ linux-2.5.26-rmap-slablru-stats/mm/vmscan.c Fri Jul 19 00:18:02 2002 @@ -224,6 +224,7 @@ list_del(entry); list_add(entry, &zone->inactive_dirty_list); + KERNEL_STAT_INC(pgscan); /* Wrong page on list?! (list corruption, should not happen) */ if (!PageInactiveDirty(page)) { @@ -263,6 +264,7 @@ page->age = max((int)page->age, PAGE_AGE_START); pte_chain_unlock(page); unlock_page(page); + KERNEL_STAT_INC(pgactivate); continue; } @@ -363,6 +365,7 @@ /* effectively free the page here */ unlock_page(page); page_cache_release(page); + KERNEL_STAT_INC(pgsteal); spin_lock(&pagemap_lru_lock); cleaned_pages++; continue; @@ -413,6 +416,7 @@ add_page_to_active_list(page); pte_chain_unlock(page); unlock_page(page); + KERNEL_STAT_INC(pgactivate); } } spin_unlock(&pagemap_lru_lock); @@ -483,6 +487,7 @@ if (TestSetPageLocked(page)) { list_del(page_lru); list_add(page_lru, &zone->active_list); + KERNEL_STAT_INC(pgscan); continue; } @@ -544,6 +549,7 @@ list_add(page_lru, &zone->active_list); } else { deactivate_page_nolock(page); + KERNEL_STAT_INC(pgdeactivate); if (++nr_deactivated > target) { pte_chain_unlock(page); unlock_page(page); @@ -835,6 +841,7 @@ { int ret = 1; if (gfp_mask & __GFP_WAIT) { + KERNEL_STAT_INC(pageoutrun); current->flags |= PF_MEMALLOC; ret = do_try_to_free_pages(gfp_mask); current->flags &= ~PF_MEMALLOC;