blk_congestion_wait() will currently not wait if there are no write requests in flight. Which is a potential problem if all the dirty data is against NFS filesystems. For write(2) traffic against NFS, things work nicely, because writers throttle in nfs_wait_on_requests(). But for MAP_SHARED dirtyings we need to avoid spinning in balance_dirty_pages(). So allow callers to fall through to the explicit sleep in that case. This will also fix a weird lockup which the reiser4 developers report. In that case they have managed to have _all_ inodes against a superblock in locked state, yet there are no write requests in flight. Taking a nap in blk_congestion_wait() in this case will yield the CPU to the threads which are trying to write out pages. Also tune up the sleep durations in various callers - 250 milliseconds seems rather long. block/ll_rw_blk.c | 6 +----- page-writeback.c | 2 +- vmscan.c | 4 ++-- 3 files changed, 4 insertions(+), 8 deletions(-) diff -puN drivers/block/ll_rw_blk.c~balance_dirty_pages-lockup-fix drivers/block/ll_rw_blk.c --- 25/drivers/block/ll_rw_blk.c~balance_dirty_pages-lockup-fix 2003-02-14 18:24:05.000000000 -0800 +++ 25-akpm/drivers/block/ll_rw_blk.c 2003-02-14 18:24:05.000000000 -0800 @@ -1596,13 +1596,9 @@ void blk_congestion_wait(int rw, long ti DEFINE_WAIT(wait); struct congestion_state *cs = &congestion_states[rw]; - if (!atomic_read(&cs->nr_active_queues)) - return; - blk_run_queues(); prepare_to_wait(&cs->wqh, &wait, TASK_UNINTERRUPTIBLE); - if (atomic_read(&cs->nr_active_queues)) - io_schedule_timeout(timeout); + io_schedule_timeout(timeout); finish_wait(&cs->wqh, &wait); } diff -puN mm/vmscan.c~balance_dirty_pages-lockup-fix mm/vmscan.c --- 25/mm/vmscan.c~balance_dirty_pages-lockup-fix 2003-02-14 18:24:05.000000000 -0800 +++ 25-akpm/mm/vmscan.c 2003-02-14 18:24:05.000000000 -0800 @@ -835,7 +835,7 @@ try_to_free_pages(struct zone *classzone wakeup_bdflush(total_scanned); /* Take a nap, wait for some writeback to complete */ - blk_congestion_wait(WRITE, HZ/4); + blk_congestion_wait(WRITE, HZ/10); shrink_slab(total_scanned, gfp_mask); } if (gfp_mask & __GFP_FS) @@ -904,7 +904,7 @@ static int balance_pgdat(pg_data_t *pgda } if (all_zones_ok) break; - blk_congestion_wait(WRITE, HZ/4); + blk_congestion_wait(WRITE, HZ/10); } return nr_pages - to_free; } diff -puN mm/page-writeback.c~balance_dirty_pages-lockup-fix mm/page-writeback.c --- 25/mm/page-writeback.c~balance_dirty_pages-lockup-fix 2003-02-14 18:24:05.000000000 -0800 +++ 25-akpm/mm/page-writeback.c 2003-02-14 18:24:05.000000000 -0800 @@ -301,7 +301,7 @@ static void wb_kupdate(unsigned long arg writeback_inodes(&wbc); if (wbc.nr_to_write > 0) { if (wbc.encountered_congestion) - blk_congestion_wait(WRITE, HZ); + blk_congestion_wait(WRITE, HZ/10); else break; /* All the old data is written */ } _