]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
writeback: don't busy retry writeback on new/freeing inodes
authorWu Fengguang <fengguang.wu@intel.com>
Tue, 12 Jul 2011 06:08:50 +0000 (23:08 -0700)
committerWu Fengguang <fengguang.wu@intel.com>
Sun, 24 Jul 2011 02:46:51 +0000 (10:46 +0800)
Fix a system hang bug introduced by commit b7a2441f9966 ("writeback:
remove writeback_control.more_io") and e8dfc3058 ("writeback: elevate
queue_io() into wb_writeback()") easily reproducible with high memory
pressure and lots of file creation/deletions, for example, a kernel
build in limited memory.

It hangs when some inode is in the I_NEW, I_FREEING or I_WILL_FREE
state, the flusher will get stuck busy retrying that inode, never
releasing wb->list_lock. The lock in turn blocks all kinds of other
tasks when they are trying to grab it.

As put by Jan, it's a safe change regarding data integrity. I_FREEING or
I_WILL_FREE inodes are written back by iput_final() and it is reclaim
code that is responsible for eventually removing them. So writeback code
can safely ignore them. I_NEW inodes should move out of this state when
they are fully set up and in the writeback round following that, we will
consider them for writeback. So the change makes sense.

CC: Jan Kara <jack@suse.cz>
Reported-by: Hugh Dickins <hughd@google.com>
Tested-by: Hugh Dickins <hughd@google.com>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
fs/fs-writeback.c

index 50445cf0b83a9a0d6f683e44f1adb72791a21510..6d49439ca31dc2b0b89f659b55e46e361e303c1a 100644 (file)
@@ -593,7 +593,7 @@ static long writeback_sb_inodes(struct super_block *sb,
                spin_lock(&inode->i_lock);
                if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) {
                        spin_unlock(&inode->i_lock);
-                       requeue_io(inode, wb);
+                       redirty_tail(inode, wb);
                        continue;
                }
                __iget(inode);