diff options
author | Andrea Arcangeli <andrea@suse.de> | 2005-11-01 01:08:54 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-01 01:22:04 +0300 |
commit | 659603ef692d3f6c7c216e80310990253864bf2e (patch) | |
tree | f1e8fe6176fdf4d34ef7f62fa2f1f9f619e9d26f /fs | |
parent | a717f77362d4fe044721c126c89e2a38e731a576 (diff) | |
download | linux-659603ef692d3f6c7c216e80310990253864bf2e.tar.xz |
[PATCH] fix __writeback_single_inode WARN_ON
When the inode count is zero in inode writeback, the
WARN_ON(!(inode->i_state & I_WILL_FREE));
is broken, and needs to test for either I_WILL_FREE|I_FREEING.
When the inode is in I_FREEING state, it's already out of the visibility
of the vm so it can't be freed so it doesn't require the __iget and the
generic_delete_inode path can call the sync internally to the lowlevel
fs callback during the last iput. So the inode being in I_FREEING is
also a valid condition for calling the sync with i_count == 0.
The specific stack trace is this:
0xc00000007b8fb6e0 0xc00000000010118c .__writeback_single_inode +0x5c
0xc00000007b8fb6e0 0xc0000000001014dc (lr) .sync_inode +0x3c
0xc00000007b8fb790 0xc0000000001014dc .sync_inode +0x3c
0xc00000007b8fb820 0xc0000000001a5020 .ext2_sync_inode +0x64
0xc00000007b8fb8f0 0xc0000000001a65b4 .ext2_truncate +0x3f8
0xc00000007b8fba40 0xc0000000001a6940 .ext2_delete_inode +0xdc
0xc00000007b8fbac0 0xc0000000000f7a5c .generic_delete_inode +0x124
0xc00000007b8fbb50 0xc0000000000f5fe0 .iput +0xb8
0xc00000007b8fbbe0 0xc0000000000e9fd4 .sys_unlink +0x2a8
0xc00000007b8fbd10 0xc00000000001048c .ret_from_syscall_1 +0x0
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fs-writeback.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index ffab4783ac64..c27f8d4098be 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -247,7 +247,7 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) wait_queue_head_t *wqh; if (!atomic_read(&inode->i_count)) - WARN_ON(!(inode->i_state & I_WILL_FREE)); + WARN_ON(!(inode->i_state & (I_WILL_FREE|I_FREEING))); else WARN_ON(inode->i_state & I_WILL_FREE); |