From: Nick Piggin This patch causes try_to_free_pages to wakeup_bdflush even if it has reclaimed the required # of pages on the first scan. It allows two scans at the two lowest priorities before breaking out or doing a blk_congestion_wait, for both try_to_free_pages and balance_pgdat. --- mm/vmscan.c | 38 +++++++++++++++++++++----------------- 1 files changed, 21 insertions(+), 17 deletions(-) diff -puN mm/vmscan.c~vm-tune-throttle mm/vmscan.c --- 25/mm/vmscan.c~vm-tune-throttle 2004-02-04 02:37:01.000000000 -0800 +++ 25-akpm/mm/vmscan.c 2004-02-04 02:37:01.000000000 -0800 @@ -930,22 +930,33 @@ int try_to_free_pages(struct zone **zone if (nr_reclaimed >= nr_pages) { ret = 1; + if (gfp_mask & __GFP_FS) + wakeup_bdflush(total_scanned); goto out; } + + /* Don't stall on the first run - it might be bad luck */ + if (likely(priority == DEF_PRIORITY)) + continue; + + /* Let the caller handle it */ if (!(gfp_mask & __GFP_FS)) - break; /* Let the caller handle it */ + goto out; + /* - * Try to write back as many pages as we just scanned. Not - * sure if that makes sense, but it's an attempt to avoid - * creating IO storms unnecessarily + * Try to write back as many pages as we just scanned. + * Not sure if that makes sense, but it's an attempt + * to avoid creating IO storms unnecessarily */ wakeup_bdflush(total_scanned); /* Take a nap, wait for some writeback to complete */ blk_congestion_wait(WRITE, HZ/10); } - if ((gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY)) + + if (!(gfp_mask & __GFP_NORETRY)) out_of_memory(); + out: for (i = 0; zones[i] != 0; i++) zones[i]->prev_priority = zones[i]->temp_priority; @@ -1004,6 +1015,7 @@ static int balance_pgdat(pg_data_t *pgda if (to_reclaim <= 0) continue; } + all_zones_ok = 0; zone->temp_priority = priority; reclaimed = shrink_zone(zone, GFP_KERNEL, to_reclaim, &nr_scanned, ps, priority); @@ -1017,16 +1029,6 @@ static int balance_pgdat(pg_data_t *pgda continue; if (zone->pages_scanned > zone->present_pages * 2) zone->all_unreclaimable = 1; - /* - * If this scan failed to reclaim `to_reclaim' or more - * pages, we're getting into trouble. Need to scan - * some more, and throttle kswapd. Note that this zone - * may now have sufficient free pages due to freeing - * activity by some other process. That's OK - we'll - * pick that info up on the next pass through the loop. - */ - if (reclaimed < to_reclaim) - all_zones_ok = 0; } if (nr_pages && to_free > 0) continue; /* swsusp: need to do more work */ @@ -1034,9 +1036,11 @@ static int balance_pgdat(pg_data_t *pgda break; /* kswapd: all done */ /* * OK, kswapd is getting into trouble. Take a nap, then take - * another pass across the zones. + * another pass across the zones. Don't stall on the first + * pass. */ - blk_congestion_wait(WRITE, HZ/10); + if (priority < DEF_PRIORITY) + blk_congestion_wait(WRITE, HZ/10); } for (i = 0; i < pgdat->nr_zones; i++) { _