From: Hugh Dickins <hugh@veritas.com>

2.6.3-mm UP without PREEMPT easily hangs looping around pdflush's
sync_sb_inodes, failing the down_read_trylock in do_writepages, but giving
the concurrent sync no chance to complete: just try while : ; do echo
$SECONDS; sync; cp /etc/termcap .; done


---

 mm/page-writeback.c |   28 ++++++++++++----------------
 1 files changed, 12 insertions(+), 16 deletions(-)

diff -puN mm/page-writeback.c~O_DIRECT-vs-buffered-fix-pdflush-hang-fix mm/page-writeback.c
--- 25/mm/page-writeback.c~O_DIRECT-vs-buffered-fix-pdflush-hang-fix	2004-02-24 12:19:55.000000000 -0800
+++ 25-akpm/mm/page-writeback.c	2004-02-24 12:19:55.000000000 -0800
@@ -483,30 +483,26 @@ void __init page_writeback_init(void)
 int do_writepages(struct address_space *mapping, struct writeback_control *wbc)
 {
 	int ret;
-	if (wbc->sync_mode == WB_SYNC_NONE) {
-		if (!down_read_trylock(&mapping->wb_rwsema))
-			/*
-			 * SYNC writeback in progress
-			 */
-			return 0;
-	} else {
-		/*
-		 * Only allow 1 SYNC writeback at a time, to be able
-		 * to wait for all i/o without worrying about racing
-		 * WB_SYNC_NONE writers.
-		 */
+
+	/*
+	 * Only allow 1 SYNC writeback at a time, to be able to wait for all
+	 * I/O without worrying about racing WB_SYNC_NONE writers.
+	 */
+	if (wbc->sync_mode == WB_SYNC_NONE)
+		down_read(&mapping->wb_rwsema);
+	else
 		down_write(&mapping->wb_rwsema);
-	}
 
 	if (mapping->a_ops->writepages)
 		ret = mapping->a_ops->writepages(mapping, wbc);
 	else
 		ret = generic_writepages(mapping, wbc);
-	if (wbc->sync_mode == WB_SYNC_NONE) {
+
+	if (wbc->sync_mode == WB_SYNC_NONE)
 		up_read(&mapping->wb_rwsema);
-	} else {
+	else
 		up_write(&mapping->wb_rwsema);
-	}
+
 	return ret;
 }
 

_