diff -x .* -x *.[oas] -urN ref/mm/Makefile linux/mm/Makefile --- ref/mm/Makefile Sun Aug 12 17:57:02 2001 +++ linux/mm/Makefile Mon Aug 27 11:51:41 2001 @@ -18,4 +18,5 @@ obj-$(CONFIG_HIGHMEM) += highmem.o +obj-y += debug.o include $(TOPDIR)/Rules.make diff -x .* -x *.[oas] -urN ref/mm/_xlk/debug.c linux/mm/_xlk/debug.c --- ref/mm/_xlk/debug.c Thu Jan 1 01:00:00 1970 +++ linux/mm/_xlk/debug.c Mon Aug 27 12:36:12 2001 @@ -0,0 +1,2 @@ +src +Mon Aug 27 12:36:12 2001 diff -x .* -x *.[oas] -urN ref/mm/debug.c linux/mm/debug.c --- ref/mm/debug.c Thu Jan 1 01:00:00 1970 +++ linux/mm/debug.c Mon Aug 27 12:32:24 2001 @@ -0,0 +1,175 @@ +/* + * linux/mm/debug.c + * + * Copyright (C) 2001 Russell King. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Dump out page information on SysRQ-G, and provide show_page_info() + * + * You are advised to use a serial console with this patch - it + * saturates a 38400baud link for 1 minute on a 32MB machine. + */ +#include +#include +#include +#include +#include + +/* + * We print out the following information for each page in the system: + * address: use count, age, mapping, [RSsr] rD [acd] + * + * The flags are: + * R - reserved + * S - in swapcache + * s - slab page + * r - ramdisk + * + * r - referenced + * D - dirty + * + * a - active page + * c - on inactive clean list + * d - on inactive dirty list + */ +static void page_detail(struct page *page) +{ + if (!page) + return; + + printk("%p: %2d %08lx %p [%c%c%c%c] %c%c [%c%c%c]\n", + page_address(page), + page_count(page), + page->age, + page->mapping, + + PageReserved(page) ? 'R' : '-', + PageSwapCache(page) ? 'S' : '-', + PageSlab(page) ? 's' : '-', + page_ramdisk(page) ? 'r' : '-', + + PageReferenced(page) ? 'r' : '-', + PageDirty(page) ? 'D' : '-', + + PageActive(page) ? 'a' : '-', + PageInactiveClean(page) ? 'c' : '-', + PageInactiveDirty(page) ? 'd' : '-'); +} + +/* + * This version collects statistics + */ +static int anon_pages, slab_pages, resvd_pages, unused_pages, ramdisk_pages; + +static void page_statistics(struct page *page) +{ + if (page) { + if (PageReserved(page)) + resvd_pages++; + else if (PageSlab(page)) + slab_pages++; + else if (page_ramdisk(page)) + ramdisk_pages++; + else if (!page_count(page)) + unused_pages ++; + else if (!page->mapping) + anon_pages ++; + return; + } + + printk(" anon: %d, slab: %d, reserved: %d, free: %d, ramdisk: %d\n", + anon_pages, slab_pages, resvd_pages, unused_pages, ramdisk_pages); +} + +static void show_zone_info(zone_t *zone, void (*fn)(struct page *)) +{ + int i; + + printk(" total %ld, free %ld, inactive clean %ld, inactive dirty %ld\n", + zone->size, + zone->free_pages, + zone->inactive_clean_pages, + zone->inactive_dirty_pages); + printk(" min %ld, low %ld, high %ld\n", + zone->pages_min, + zone->pages_low, + zone->pages_high); + + anon_pages = 0; + slab_pages = 0; + resvd_pages = 0; + unused_pages = 0; + ramdisk_pages = 0; + + for (i = 0; i < zone->size; i++) { + struct page *page = zone->zone_mem_map + i; + + fn(page); + } + + fn(NULL); +} + +static void show_node_info(pg_data_t *pg, void (*fn)(struct page *)) +{ + int type; + + for (type = 0; type < MAX_NR_ZONES; type++) { + zone_t *zone = pg->node_zones + type; + + if (zone->size == 0) + continue; + + printk("----- Zone %d ------\n", type); + + show_zone_info(zone, fn); + } +} + +static void __show_page_info(void (*fn)(struct page *)) +{ + pg_data_t *pg; + int pgdat = 0; + + for (pg = pgdat_list; pg; pg = pg->node_next) { + + printk("===== Node %d =====\n", pgdat++); + + show_node_info(pg, fn); + } +} + +void show_page_info(void) +{ + __show_page_info(page_detail); +} + +static void +show_pg_info(int key, struct pt_regs *regs, struct kbd_struct *kd, + struct tty_struct *tty) +{ + void (*fn)(struct page *); + show_mem(); + if (key == 'g') + fn = page_detail; + else + fn = page_statistics; + __show_page_info(fn); +} + +static struct sysrq_key_op page_info_op = { + handler: show_pg_info, + help_msg: "paGeinfo", + action_msg: "Page Info", +}; + +static int __init debug_mm_init(void) +{ + register_sysrq_key('g', &page_info_op); + register_sysrq_key('h', &page_info_op); +} + +__initcall(debug_mm_init); diff -x .* -x *.[oas] -urN ref/mm/page_alloc.c linux/mm/page_alloc.c --- ref/mm/page_alloc.c Tue Aug 21 22:30:51 2001 +++ linux/mm/page_alloc.c Sat Aug 25 23:19:41 2001 @@ -690,6 +690,8 @@ return (sum > 0 ? sum : 0); } +extern long count_ramdisk_pages(void); + /* * Show free area list (used inside shift_scroll-lock stuff) * We also calculate the percentage fragmentation. We do this by counting the @@ -743,6 +745,10 @@ #ifdef SWAP_CACHE_INFO show_swap_cache_info(); #endif + + printk("Page cache size: %d\n", atomic_read(&page_cache_size)); + printk("Buffer mem: %d\n", atomic_read(&buffermem_pages)); + printk("Ramdisk pages: %ld\n", count_ramdisk_pages()); } void show_free_areas(void) diff -x .* -x *.[oas] -urN ref/mm/vmscan.c linux/mm/vmscan.c --- ref/mm/vmscan.c Thu Aug 23 20:07:43 2001 +++ linux/mm/vmscan.c Sat Aug 25 19:11:46 2001 @@ -816,6 +816,24 @@ return nr_deactivated; } +long count_ramdisk_pages(void) +{ + struct list_head *page_lru; + struct page *page; + long nr_ramdisk = 0; + + spin_lock(&pagemap_lru_lock); + for (page_lru = active_list.next; page_lru != &active_list; + page_lru = page_lru->next) { + page = list_entry(page_lru, struct page, lru); + if (page_ramdisk(page)) + nr_ramdisk ++; + } + spin_unlock(&pagemap_lru_lock); + + return nr_ramdisk; +} + /* * Check if there are zones with a severe shortage of free pages, * or if all zones have a minor shortage.