Commit b57f9215 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'btrfs' of git://git.kernel.dk/linux-2.6-block

* 'btrfs' of git://git.kernel.dk/linux-2.6-block:
  btrfs: fix inode rbtree corruption
parents b04e6373 03e860bd
...@@ -3099,8 +3099,12 @@ static void inode_tree_add(struct inode *inode) ...@@ -3099,8 +3099,12 @@ static void inode_tree_add(struct inode *inode)
{ {
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_inode *entry; struct btrfs_inode *entry;
struct rb_node **p = &root->inode_tree.rb_node; struct rb_node **p;
struct rb_node *parent = NULL; struct rb_node *parent;
again:
p = &root->inode_tree.rb_node;
parent = NULL;
spin_lock(&root->inode_lock); spin_lock(&root->inode_lock);
while (*p) { while (*p) {
...@@ -3108,13 +3112,16 @@ static void inode_tree_add(struct inode *inode) ...@@ -3108,13 +3112,16 @@ static void inode_tree_add(struct inode *inode)
entry = rb_entry(parent, struct btrfs_inode, rb_node); entry = rb_entry(parent, struct btrfs_inode, rb_node);
if (inode->i_ino < entry->vfs_inode.i_ino) if (inode->i_ino < entry->vfs_inode.i_ino)
p = &(*p)->rb_left; p = &parent->rb_left;
else if (inode->i_ino > entry->vfs_inode.i_ino) else if (inode->i_ino > entry->vfs_inode.i_ino)
p = &(*p)->rb_right; p = &parent->rb_right;
else { else {
WARN_ON(!(entry->vfs_inode.i_state & WARN_ON(!(entry->vfs_inode.i_state &
(I_WILL_FREE | I_FREEING | I_CLEAR))); (I_WILL_FREE | I_FREEING | I_CLEAR)));
break; rb_erase(parent, &root->inode_tree);
RB_CLEAR_NODE(parent);
spin_unlock(&root->inode_lock);
goto again;
} }
} }
rb_link_node(&BTRFS_I(inode)->rb_node, parent, p); rb_link_node(&BTRFS_I(inode)->rb_node, parent, p);
...@@ -3126,12 +3133,12 @@ static void inode_tree_del(struct inode *inode) ...@@ -3126,12 +3133,12 @@ static void inode_tree_del(struct inode *inode)
{ {
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
spin_lock(&root->inode_lock);
if (!RB_EMPTY_NODE(&BTRFS_I(inode)->rb_node)) { if (!RB_EMPTY_NODE(&BTRFS_I(inode)->rb_node)) {
spin_lock(&root->inode_lock);
rb_erase(&BTRFS_I(inode)->rb_node, &root->inode_tree); rb_erase(&BTRFS_I(inode)->rb_node, &root->inode_tree);
spin_unlock(&root->inode_lock);
RB_CLEAR_NODE(&BTRFS_I(inode)->rb_node); RB_CLEAR_NODE(&BTRFS_I(inode)->rb_node);
} }
spin_unlock(&root->inode_lock);
} }
static noinline void init_btrfs_i(struct inode *inode) static noinline void init_btrfs_i(struct inode *inode)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment