aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorWu Fengguang <fengguang.wu@intel.com>2011-07-30 00:14:35 -0400
committerWu Fengguang <fengguang.wu@intel.com>2011-07-31 10:52:08 -0400
commit0e995816f4fb69cef602b7fe82da68ced6be3b41 (patch)
tree841ce0af67dfaef41e5297fdbfa52255a1343f0b /fs
parent250f8e3db646028353a2a737ddb7a894c97a1098 (diff)
don't busy retry the inode on failed grab_super_passive()
This fixes a soft lockup on conditions a) the flusher is working on a work by __bdi_start_writeback(), while b) someone else calls writeback_inodes_sb*() or sync_inodes_sb(), which grab sb->s_umount and enqueue a new work for the flusher to execute The s_umount grabbed by (b) will fail the grab_super_passive() in (a). Then if the inode is requeued, wb_writeback() will busy retry on it. As a result, wb_writeback() loops for ever without releasing wb->list_lock, which further blocks other tasks. Fix the busy loop by redirtying the inode. This may undesirably delay the writeback of the inode, however most likely it will be picked up soon by the queued work by writeback_inodes_sb*(), sync_inodes_sb() or even writeback_inodes_wb(). bug url: http://www.spinics.net/lists/linux-fsdevel/msg47292.html Reported-by: Christoph Hellwig <hch@infradead.org> Tested-by: Christoph Hellwig <hch@infradead.org> Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/fs-writeback.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 1599aa985fe2..04cf3b91e501 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -618,7 +618,12 @@ static long __writeback_inodes_wb(struct bdi_writeback *wb,
618 struct super_block *sb = inode->i_sb; 618 struct super_block *sb = inode->i_sb;
619 619
620 if (!grab_super_passive(sb)) { 620 if (!grab_super_passive(sb)) {
621 requeue_io(inode, wb); 621 /*
622 * grab_super_passive() may fail consistently due to
623 * s_umount being grabbed by someone else. Don't use
624 * requeue_io() to avoid busy retrying the inode/sb.
625 */
626 redirty_tail(inode, wb);
622 continue; 627 continue;
623 } 628 }
624 wrote += writeback_sb_inodes(sb, wb, work); 629 wrote += writeback_sb_inodes(sb, wb, work);