From: Daniel McNeil 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); } _