Skip to content

Commit

Permalink
don't busy retry the inode on failed grab_super_passive()
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Wu Fengguang committed Jul 31, 2011
1 parent 250f8e3 commit 0e99581
Showing 1 changed file with 6 additions and 1 deletion.
7 changes: 6 additions & 1 deletion fs/fs-writeback.c
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,12 @@ static long __writeback_inodes_wb(struct bdi_writeback *wb,
struct super_block *sb = inode->i_sb;

if (!grab_super_passive(sb)) {
requeue_io(inode, wb);
/*
* grab_super_passive() may fail consistently due to
* s_umount being grabbed by someone else. Don't use
* requeue_io() to avoid busy retrying the inode/sb.
*/
redirty_tail(inode, wb);
continue;
}
wrote += writeback_sb_inodes(sb, wb, work);
Expand Down

0 comments on commit 0e99581

Please sign in to comment.