From: Hugh Dickins 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; } _