--- zzzz-none-000/linux-2.6.13.1/mm/vmscan.c 2005-09-10 02:42:58.000000000 +0000 +++ ohio-7170-487/linux-2.6.13.1/mm/vmscan.c 2006-06-13 09:24:26.000000000 +0000 @@ -39,6 +39,9 @@ #include + +/*--- #define DEBUG_FREE_MEMORY ---*/ + /* possible outcome of pageout() */ typedef enum { /* failed to write page out, page is locked */ @@ -573,12 +576,21 @@ * returns how many pages were moved onto *@dst. */ static int isolate_lru_pages(int nr_to_scan, struct list_head *src, - struct list_head *dst, int *scanned) + struct list_head *dst, int *scanned +#ifdef DEBUG_FREE_MEMORY + , char *who, char *name +#endif /*--- #ifdef DEBUG_FREE_MEMORY ---*/ + ) { int nr_taken = 0; struct page *page; int scan = 0; +#ifdef DEBUG_FREE_MEMORY + name = name ? name : ""; + printk("[%s(%s): %u nr_to_scan]", who, name, nr_to_scan); +#endif /*--- #ifdef DEBUG_FREE_MEMORY ---*/ + while (scan++ < nr_to_scan && !list_empty(src)) { page = lru_to_page(src); prefetchw_prev_lru_page(page, src, flags); @@ -599,11 +611,136 @@ nr_taken++; } } +#ifdef DEBUG_FREE_MEMORY + printk("[%u taken]", nr_taken); + { + int left = 0; + struct list_head *head = src; + while (src) { + src = src->next; + left++; + if(src == head) + break; + } + printk("[%u left]\n", left); + } +#endif /*--- #ifdef DEBUG_FREE_MEMORY ---*/ *scanned = scan; return nr_taken; } +#ifdef DEBUG_FREE_MEMORY +#include +static int debug_flag = 0; +void check_all_memmap_blocks(void) { + unsigned long start; + unsigned long end; + struct page *page; + unsigned int count[32]; + struct { + unsigned long start, end; + unsigned int index; + } check[32], *C = NULL; + char *count_names[] = { + "PG_locked", "PG_error", "PG_referenced", "PG_uptodate", + "PG_dirty", "PG_lru", "PG_active", "PG_slab", + "PG_checked", "PG_arch_1", "PG_reserved", "PG_private", + "PG_writeback", "PG_nosave", "PG_compound", "PG_swapcache", + "PG_mappedtodisk", "PG_reclaim", "PG_nosave_free", "PG_uncached", + "free" } ; + int skip[] = { + 0, /*--- PG_locked ---*/ + 0, /*--- PG_error ---*/ + 1, /*--- PG_referenced ---*/ + 1, /*--- PG_uptodate ---*/ + 0, /*--- PG_dirty ---*/ + 0, /*--- PG_lru ---*/ + 1, /*--- PG_active ---*/ + 1, /*--- PG_slab ---*/ + 0, /*--- PG_checked ---*/ + 0, /*--- PG_arch_1 ---*/ + 0, /*--- PG_reserved ---*/ + 1, /*--- PG_private ---*/ + 0, /*--- PG_writeback ---*/ + 0, /*--- PG_nosave ---*/ + 0, /*--- PG_compound ---*/ + 0, /*--- PG_swapcache ---*/ + 0, /*--- PG_mappedtodisk ---*/ + 0, /*--- PG_reclaim ---*/ + 0, /*--- PG_nosave_free ---*/ + 0, /*--- PG_uncached ---*/ + 0 /*--- free ---*/ + }; +#define PG__free (PG_uncached + 1) +#define PG__last (PG_uncached + 2) + int i; + + if(debug_flag == 0) + return; + + memset(count, 0, sizeof(count)); + memset(check, 0, sizeof(check)); +#define CHECK_START(idx) if(check[(idx)].start == 0UL) check[(idx)].start = start +#define CHECK_END(idx) if(check[(idx)].start != 0UL) { \ + if(skip[(idx)] == 0) { \ + printk("[%s] 0x%lx - 0x%lx (%u blocks)\n", count_names[(idx)], \ + check[(idx)].start, start, (start - check[(idx)].start) >> 12); \ + check[(idx)].start = 0UL; \ + } \ + } +#define CHECK(idx) CHECK_START(idx) ; } else { CHECK_END(idx) + + /*--------------------------------------------------------------------------------------*\ + \*--------------------------------------------------------------------------------------*/ +#if 0 + start = 0x94000000; + end = start + (1 << 20) * 16; + printk("scan mem_map[0x%lx - 0x%lx] ...\n", start, end); + for(i = 0 ; i < PG__last ; i++) { + start = 0x94000000; + end = start + (1 << 20) * 16; + while(start < end) { + page = pfn_to_page(start >> PAGE_SHIFT); + if(i == PG__free) { + if(page->flags == 0) { + count[PG__free]++; + CHECK(PG__free); + } + } else if(page->flags & (1 << i)) { + count[i]++; + CHECK(i); + } + start += PAGE_SIZE; + } + } +#endif + + /*--------------------------------------------------------------------------------------*\ + \*--------------------------------------------------------------------------------------*/ + start = 0x94000000; + end = start + (1 << 20) * 16; + while(start < end) { + page = pfn_to_page(start >> PAGE_SHIFT); + + for(i = 0 ; i < PG__free ; i++) { + if(page->flags & (1 << PG_locked)) { + count[i]++; + /*--- CHECK(i); ---*/ + } + } + if(page->flags == 0) { + count[PG__free]++; + /*--- CHECK(PG__free); ---*/ + } + start += PAGE_SIZE; + } + for(i = 0 ; i < PG__last; i++) { + printk("[%s] = %u\n", count_names[i], count[i]); + } + debug_flag = 0; +} +#endif /*--- #ifdef DEBUG_FREE_MEMORY ---*/ /* * shrink_cache() adds the number of pages reclaimed to sc->nr_reclaimed */ @@ -625,7 +762,11 @@ nr_taken = isolate_lru_pages(sc->swap_cluster_max, &zone->inactive_list, - &page_list, &nr_scan); + &page_list, &nr_scan +#ifdef DEBUG_FREE_MEMORY + , "shrink_cache", NULL +#endif /*--- #ifdef DEBUG_FREE_MEMORY ---*/ + ); zone->nr_inactive -= nr_taken; zone->pages_scanned += nr_scan; spin_unlock_irq(&zone->lru_lock); @@ -705,8 +846,27 @@ lru_add_drain(); spin_lock_irq(&zone->lru_lock); +#ifdef DEBUG_FREE_MEMORY + { + int left = 0; + struct list_head *head = &zone->inactive_list; + struct list_head *src = &zone->inactive_list; + while (src) { + src = src->next; + left++; + if(src == head) + break; + } + printk("[%u inaktiv]\n", left); + check_all_memmap_blocks(); + } +#endif /*--- #ifdef DEBUG_FREE_MEMORY ---*/ pgmoved = isolate_lru_pages(nr_pages, &zone->active_list, - &l_hold, &pgscanned); + &l_hold, &pgscanned +#ifdef DEBUG_FREE_MEMORY + , "refill_inactive_zone", zone->name +#endif /*--- #ifdef DEBUG_FREE_MEMORY ---*/ + ); zone->pages_scanned += pgscanned; zone->nr_active -= pgmoved; spin_unlock_irq(&zone->lru_lock); @@ -847,6 +1007,9 @@ sc->nr_to_scan = min(nr_active, (unsigned long)sc->swap_cluster_max); nr_active -= sc->nr_to_scan; +#ifdef DEBUG_FREE_MEMORY + printk("[shrink_zone] \n"); +#endif /*--- #ifdef DEBUG_FREE_MEMORY ---*/ refill_inactive_zone(zone, sc); } @@ -901,6 +1064,10 @@ continue; /* Let kswapd poll it */ atomic_inc(&zone->reclaim_in_progress); +#ifdef DEBUG_FREE_MEMORY + printk("[shrink_caches]\n"); + debug_flag = 1; +#endif /*--- #ifdef DEBUG_FREE_MEMORY ---*/ shrink_zone(zone, sc); atomic_dec(&zone->reclaim_in_progress); } @@ -1113,6 +1280,10 @@ sc.priority = priority; sc.swap_cluster_max = nr_pages? nr_pages : SWAP_CLUSTER_MAX; atomic_inc(&zone->reclaim_in_progress); +#ifdef DEBUG_FREE_MEMORY + printk("[balance_pgdat]\n"); + debug_flag = 1; +#endif /*--- #ifdef DEBUG_FREE_MEMORY ---*/ shrink_zone(zone, &sc); atomic_dec(&zone->reclaim_in_progress); reclaim_state->reclaimed_slab = 0; @@ -1234,6 +1405,9 @@ } finish_wait(&pgdat->kswapd_wait, &wait); +#ifdef DEBUG_FREE_MEMORY + printk("\n ****** [kswapd] ******\n"); +#endif /*--- #ifdef DEBUG_FREE_MEMORY ---*/ balance_pgdat(pgdat, 0, order); } return 0; @@ -1361,6 +1535,10 @@ if (!atomic_inc_and_test(&zone->reclaim_in_progress)) goto out; +#ifdef DEBUG_FREE_MEMORY + printk("[zone_reclaim]\n"); + debug_flag = 1; +#endif /*--- #ifdef DEBUG_FREE_MEMORY ---*/ shrink_zone(zone, &sc); total_reclaimed = sc.nr_reclaimed;