

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 */
 		}

_
