Index: linux-2.6.16-rc2/mm/vmscan.c =================================================================== --- linux-2.6.16-rc2.orig/mm/vmscan.c 2006-02-04 21:23:52.000000000 -0800 +++ linux-2.6.16-rc2/mm/vmscan.c 2006-02-04 21:39:02.000000000 -0800 @@ -54,12 +54,6 @@ typedef enum { struct scan_control { /* Incremented by the number of inactive pages that were scanned */ unsigned long nr_scanned; - - /* This context's SWAP_CLUSTER_MAX. If freeing memory for - * suspend, we effectively ignore SWAP_CLUSTER_MAX. - * In this context, it doesn't matter that we scan the - * whole list at once. */ - int swap_cluster_max; }; /* @@ -74,13 +68,9 @@ struct scan_control { * * nr_pages is the minimum number of pages we intend to free in the scan. */ -static inline void init_scan_control(struct scan_control *sc, int nr_pages) +static inline void init_scan_control(struct scan_control *sc) { sc->nr_scanned = 0; - if (nr_pages > SWAP_CLUSTER_MAX) - sc->swap_cluster_max = nr_pages; - else - sc->swap_cluster_max = SWAP_CLUSTER_MAX; } /* @@ -1087,7 +1077,7 @@ static int isolate_lru_pages(int nr_to_s * shrink_cache() adds the number of pages reclaimed to sc->nr_reclaimed */ static int shrink_cache(int max_scan, struct zone *zone, gfp_t gfp_mask, - struct scan_control *sc) + int swap_cluster_max, struct scan_control *sc) { LIST_HEAD(page_list); struct pagevec pvec; @@ -1103,7 +1093,7 @@ static int shrink_cache(int max_scan, st int nr_scan; int nr_freed; - nr_taken = isolate_lru_pages(sc->swap_cluster_max, + nr_taken = isolate_lru_pages(swap_cluster_max, &zone->inactive_list, &page_list, &nr_scan); zone->nr_inactive -= nr_taken; @@ -1299,7 +1289,8 @@ refill_inactive_zone(int nr_pages, struc * This is a basic per-zone page freer. Used by both kswapd and direct reclaim. */ static int -shrink_zone(int priority, struct zone *zone, gfp_t gfp_mask, struct scan_control *sc) +shrink_zone(int priority, struct zone *zone, gfp_t gfp_mask, + unsigned long swap_cluster_max, struct scan_control *sc) { unsigned long nr_active; unsigned long nr_inactive; @@ -1314,31 +1305,30 @@ shrink_zone(int priority, struct zone *z */ zone->nr_scan_active += (zone->nr_active >> priority) + 1; nr_active = zone->nr_scan_active; - if (nr_active >= sc->swap_cluster_max) + if (nr_active >= swap_cluster_max) zone->nr_scan_active = 0; else nr_active = 0; zone->nr_scan_inactive += (zone->nr_inactive >> priority) + 1; nr_inactive = zone->nr_scan_inactive; - if (nr_inactive >= sc->swap_cluster_max) + if (nr_inactive >= swap_cluster_max) zone->nr_scan_inactive = 0; else nr_inactive = 0; while (nr_active || nr_inactive) { if (nr_active) { - nr_to_scan = min(nr_active, - (unsigned long)sc->swap_cluster_max); + nr_to_scan = min(nr_active, swap_cluster_max); nr_active -= nr_to_scan; refill_inactive_zone(nr_to_scan, zone); } if (nr_inactive) { - nr_to_scan = min(nr_inactive, - (unsigned long)sc->swap_cluster_max); + nr_to_scan = min(nr_inactive, swap_cluster_max); nr_inactive -= nr_to_scan; - nr_reclaimed += shrink_cache(nr_to_scan, zone, gfp_mask, sc); + nr_reclaimed += shrink_cache(nr_to_scan, zone, gfp_mask, + swap_cluster_max, sc); } } @@ -1366,7 +1356,7 @@ shrink_zone(int priority, struct zone *z */ static int shrink_caches(int priority, struct zone **zones, gfp_t gfp_mask, - struct scan_control *sc) + int swap_cluster_max, struct scan_control *sc) { int i; int nr_reclaimed = 0; @@ -1387,7 +1377,8 @@ shrink_caches(int priority, struct zone if (zone->all_unreclaimable && priority != DEF_PRIORITY) continue; /* Let kswapd poll it */ - nr_reclaimed += shrink_zone(priority, zone, gfp_mask, sc); + nr_reclaimed += shrink_zone(priority, zone, gfp_mask, + swap_cluster_max, sc); } return nr_reclaimed; } @@ -1433,18 +1424,19 @@ int try_to_free_pages(struct zone **zone for (priority = DEF_PRIORITY; priority >= 0; priority--) { struct scan_control sc; - init_scan_control(&sc, SWAP_CLUSTER_MAX); + init_scan_control(&sc); if (!priority) disable_swap_token(); - total_reclaimed += shrink_caches(priority, zones, gfp_mask, &sc); + total_reclaimed += shrink_caches(priority, zones, gfp_mask, + SWAP_CLUSTER_MAX, &sc); shrink_slab(sc.nr_scanned, gfp_mask, lru_pages); if (reclaim_state) { total_reclaimed += reclaim_state->reclaimed_slab; reclaim_state->reclaimed_slab = 0; } total_scanned += sc.nr_scanned; - if (total_reclaimed >= sc.swap_cluster_max) { + if (total_reclaimed >= SWAP_CLUSTER_MAX) { ret = 1; goto out; } @@ -1456,7 +1448,7 @@ int try_to_free_pages(struct zone **zone * that's undesirable in laptop mode, where we *want* lumpy * writeout. So in laptop mode, write out the whole world. */ - if (total_scanned > sc.swap_cluster_max + sc.swap_cluster_max/2) { + if (total_scanned > SWAP_CLUSTER_MAX + SWAP_CLUSTER_MAX/2) { wakeup_pdflush(laptop_mode ? 0 : total_scanned); gfp_mask |= MAY_WRITEPAGE; } @@ -1598,10 +1590,11 @@ scan: if (zone->prev_priority > priority) zone->prev_priority = priority; - init_scan_control(&sc, nr_pages); + init_scan_control(&sc); atomic_inc(&zone->reclaim_in_progress); - total_reclaimed += shrink_zone(priority, zone, gfp_mask, &sc); + total_reclaimed += shrink_zone(priority, zone, gfp_mask, + max(nr_pages, SWAP_CLUSTER_MAX), &sc); atomic_dec(&zone->reclaim_in_progress); reclaim_state->reclaimed_slab = 0; nr_slab = shrink_slab(sc.nr_scanned, GFP_KERNEL, @@ -1881,7 +1874,7 @@ int zone_reclaim(struct zone *zone, gfp_ disable_swap_token(); nr_pages = 1 << order; - init_scan_control(&sc, nr_pages); + init_scan_control(&sc); total_reclaimed = 0; cond_resched(); @@ -1896,7 +1889,8 @@ int zone_reclaim(struct zone *zone, gfp_ for (priority = ZONE_RECLAIM_PRIORITY; priority >=0 && total_reclaimed < nr_pages; priority--) - total_reclaimed += shrink_zone(priority, zone, gfp_mask, &sc); + total_reclaimed += shrink_zone(priority, zone, gfp_mask, + max(nr_pages, SWAP_CLUSTER_MAX), &sc); if (total_reclaimed < nr_pages && (zone_reclaim_mode & RECLAIM_SLAB)) {