diff options
| author | Jan Kara <jack@suse.cz> | 2013-03-13 07:57:08 -0400 |
|---|---|---|
| committer | Jan Kara <jack@suse.cz> | 2013-03-13 10:23:44 -0400 |
| commit | c288d2969627be7ffc90904ac8c6aae0295fbf9f (patch) | |
| tree | b8d9b4cafa65bf7b0c915b850c42e3df80dd5434 | |
| parent | af591ad896ef75585752ac2eab4fba9437f23322 (diff) | |
ext2: Fix BUG_ON in evict() on inode deletion
Commit 8e3dffc6 introduced a regression where deleting inode with
large extended attributes leads to triggering
BUG_ON(inode->i_state != (I_FREEING | I_CLEAR))
in fs/inode.c:evict(). That happens because freeing of xattr block
dirtied the inode and it happened after clear_inode() has been called.
Fix the issue by moving removal of xattr block into ext2_evict_inode()
before clear_inode() call close to a place where data blocks are
truncated. That is also more logical place and removes surprising
requirement that ext2_free_blocks() mustn't dirty the inode.
Reported-by: Tyler Hicks <tyhicks@canonical.com>
Signed-off-by: Jan Kara <jack@suse.cz>
| -rw-r--r-- | fs/ext2/ialloc.c | 1 | ||||
| -rw-r--r-- | fs/ext2/inode.c | 2 |
2 files changed, 2 insertions, 1 deletions
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index 8f370e012e61..7cadd823bb31 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c | |||
| @@ -118,7 +118,6 @@ void ext2_free_inode (struct inode * inode) | |||
| 118 | * as writing the quota to disk may need the lock as well. | 118 | * as writing the quota to disk may need the lock as well. |
| 119 | */ | 119 | */ |
| 120 | /* Quota is already initialized in iput() */ | 120 | /* Quota is already initialized in iput() */ |
| 121 | ext2_xattr_delete_inode(inode); | ||
| 122 | dquot_free_inode(inode); | 121 | dquot_free_inode(inode); |
| 123 | dquot_drop(inode); | 122 | dquot_drop(inode); |
| 124 | 123 | ||
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index c3881e56662e..fe60cc1117d8 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include "ext2.h" | 34 | #include "ext2.h" |
| 35 | #include "acl.h" | 35 | #include "acl.h" |
| 36 | #include "xip.h" | 36 | #include "xip.h" |
| 37 | #include "xattr.h" | ||
| 37 | 38 | ||
| 38 | static int __ext2_write_inode(struct inode *inode, int do_sync); | 39 | static int __ext2_write_inode(struct inode *inode, int do_sync); |
| 39 | 40 | ||
| @@ -88,6 +89,7 @@ void ext2_evict_inode(struct inode * inode) | |||
| 88 | inode->i_size = 0; | 89 | inode->i_size = 0; |
| 89 | if (inode->i_blocks) | 90 | if (inode->i_blocks) |
| 90 | ext2_truncate_blocks(inode, 0); | 91 | ext2_truncate_blocks(inode, 0); |
| 92 | ext2_xattr_delete_inode(inode); | ||
| 91 | } | 93 | } |
| 92 | 94 | ||
| 93 | invalidate_inode_buffers(inode); | 95 | invalidate_inode_buffers(inode); |
