
From: Daniel McNeil <daniel@osdl.org>

Here is update to the wb_rwsema patch that adds back the trylock.  It
avoids the hang hugh was seeing by setting encountered_congestion if the
trylock fails and checking it in sync_sb_inodes().  Hugh tested this and
did not see the hang.

This prevents non-sync writebacks to from blocking behind sync writebacks.


---

 25-akpm/fs/fs-writeback.c |   18 ++++++++++++++----
 25-akpm/mm/filemap.c      |    7 ++++---
 2 files changed, 18 insertions(+), 7 deletions(-)

diff -puN fs/fs-writeback.c~restore-writeback-trylock fs/fs-writeback.c
--- 25/fs/fs-writeback.c~restore-writeback-trylock	Fri Mar  5 21:31:46 2004
+++ 25-akpm/fs/fs-writeback.c	Fri Mar  5 21:31:46 2004
@@ -158,10 +158,14 @@ __sync_single_inode(struct inode *inode,
 		 * for all i/o without worrying about racing WB_SYNC_NONE
 		 * writers.
 		 */
-		if (wait)
+		if (wait) {
 			down_write(&mapping->wb_rwsema);
-		else
-			down_read(&mapping->wb_rwsema);
+		} else {
+			if (!down_read_trylock(&mapping->wb_rwsema)) {
+				wbc->encountered_congestion = 1;
+				goto skip_writeback;
+			}
+		}
 	}
 
 	/*
@@ -184,6 +188,7 @@ __sync_single_inode(struct inode *inode,
 			up_read(&mapping->wb_rwsema);
 	}
 
+skip_writeback:
 	/* Don't write the inode if only I_DIRTY_PAGES was set */
 	if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC))
 		write_inode(inode, wait);
@@ -308,7 +313,12 @@ sync_sb_inodes(struct super_block *sb, s
 			break;
 		}
 
-		if (wbc->nonblocking && bdi_write_congested(bdi)) {
+		/*
+		 * wbc->encountered_congestion is set if we cannot get
+		 * the wb_rwsema.
+		 */
+		if (wbc->nonblocking &&
+		    (bdi_write_congested(bdi) || wbc->encountered_congestion)) {
 			wbc->encountered_congestion = 1;
 			if (sb != blockdev_superblock)
 				break;		/* Skip a congested fs */
diff -puN mm/filemap.c~restore-writeback-trylock mm/filemap.c
--- 25/mm/filemap.c~restore-writeback-trylock	Fri Mar  5 21:31:46 2004
+++ 25-akpm/mm/filemap.c	Fri Mar  5 21:31:46 2004
@@ -153,9 +153,10 @@ static int __filemap_fdatawrite(struct a
 		return 0;
 
 	if (!blkdev) {
-		if (sync_mode == WB_SYNC_NONE)
-			down_read(&mapping->wb_rwsema);
-		else
+		if (sync_mode == WB_SYNC_NONE) {
+			if (!down_read_trylock(&mapping->wb_rwsema))
+				return 0;
+		} else
 			down_write(&mapping->wb_rwsema);
 	}
 

_
