Commit c2d904e0 authored by Jeff Mahoney's avatar Jeff Mahoney Committed by David Sterba

btrfs: Catch locking failures in {set,clear,convert}_extent_bit

The *_state functions can only return 0 or -EEXIST. This patch addresses
the cases where those functions returning -EEXIST represent a locking
failure. It handles them by panicking with an appropriate error message.
Signed-off-by: default avatarJeff Mahoney <jeffm@suse.com>
parent 8c342930
...@@ -53,6 +53,12 @@ struct extent_page_data { ...@@ -53,6 +53,12 @@ struct extent_page_data {
unsigned int sync_io:1; unsigned int sync_io:1;
}; };
static inline struct btrfs_fs_info *
tree_fs_info(struct extent_io_tree *tree)
{
return btrfs_sb(tree->mapping->host->i_sb);
}
int __init extent_io_init(void) int __init extent_io_init(void)
{ {
extent_state_cache = kmem_cache_create("extent_state", extent_state_cache = kmem_cache_create("extent_state",
...@@ -439,6 +445,13 @@ alloc_extent_state_atomic(struct extent_state *prealloc) ...@@ -439,6 +445,13 @@ alloc_extent_state_atomic(struct extent_state *prealloc)
return prealloc; return prealloc;
} }
void extent_io_tree_panic(struct extent_io_tree *tree, int err)
{
btrfs_panic(tree_fs_info(tree), err, "Locking error: "
"Extent tree was modified by another "
"thread while locked.");
}
/* /*
* clear some bits on a range in the tree. This may require splitting * clear some bits on a range in the tree. This may require splitting
* or inserting elements in the tree, so the gfp mask is used to * or inserting elements in the tree, so the gfp mask is used to
...@@ -542,7 +555,9 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -542,7 +555,9 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
prealloc = alloc_extent_state_atomic(prealloc); prealloc = alloc_extent_state_atomic(prealloc);
BUG_ON(!prealloc); BUG_ON(!prealloc);
err = split_state(tree, state, prealloc, start); err = split_state(tree, state, prealloc, start);
BUG_ON(err == -EEXIST); if (err)
extent_io_tree_panic(tree, err);
prealloc = NULL; prealloc = NULL;
if (err) if (err)
goto out; goto out;
...@@ -564,7 +579,9 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -564,7 +579,9 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
prealloc = alloc_extent_state_atomic(prealloc); prealloc = alloc_extent_state_atomic(prealloc);
BUG_ON(!prealloc); BUG_ON(!prealloc);
err = split_state(tree, state, prealloc, end + 1); err = split_state(tree, state, prealloc, end + 1);
BUG_ON(err == -EEXIST); if (err)
extent_io_tree_panic(tree, err);
if (wake) if (wake)
wake_up(&state->wq); wake_up(&state->wq);
...@@ -742,8 +759,10 @@ int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -742,8 +759,10 @@ int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
prealloc = alloc_extent_state_atomic(prealloc); prealloc = alloc_extent_state_atomic(prealloc);
BUG_ON(!prealloc); BUG_ON(!prealloc);
err = insert_state(tree, prealloc, start, end, &bits); err = insert_state(tree, prealloc, start, end, &bits);
if (err)
extent_io_tree_panic(tree, err);
prealloc = NULL; prealloc = NULL;
BUG_ON(err == -EEXIST);
goto out; goto out;
} }
state = rb_entry(node, struct extent_state, rb_node); state = rb_entry(node, struct extent_state, rb_node);
...@@ -809,7 +828,9 @@ int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -809,7 +828,9 @@ int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
prealloc = alloc_extent_state_atomic(prealloc); prealloc = alloc_extent_state_atomic(prealloc);
BUG_ON(!prealloc); BUG_ON(!prealloc);
err = split_state(tree, state, prealloc, start); err = split_state(tree, state, prealloc, start);
BUG_ON(err == -EEXIST); if (err)
extent_io_tree_panic(tree, err);
prealloc = NULL; prealloc = NULL;
if (err) if (err)
goto out; goto out;
...@@ -846,12 +867,9 @@ int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -846,12 +867,9 @@ int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
*/ */
err = insert_state(tree, prealloc, start, this_end, err = insert_state(tree, prealloc, start, this_end,
&bits); &bits);
BUG_ON(err == -EEXIST); if (err)
if (err) { extent_io_tree_panic(tree, err);
free_extent_state(prealloc);
prealloc = NULL;
goto out;
}
cache_state(prealloc, cached_state); cache_state(prealloc, cached_state);
prealloc = NULL; prealloc = NULL;
start = this_end + 1; start = this_end + 1;
...@@ -873,7 +891,8 @@ int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -873,7 +891,8 @@ int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
prealloc = alloc_extent_state_atomic(prealloc); prealloc = alloc_extent_state_atomic(prealloc);
BUG_ON(!prealloc); BUG_ON(!prealloc);
err = split_state(tree, state, prealloc, end + 1); err = split_state(tree, state, prealloc, end + 1);
BUG_ON(err == -EEXIST); if (err)
extent_io_tree_panic(tree, err);
set_state_bits(tree, prealloc, &bits); set_state_bits(tree, prealloc, &bits);
cache_state(prealloc, cached_state); cache_state(prealloc, cached_state);
...@@ -946,7 +965,8 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -946,7 +965,8 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
} }
err = insert_state(tree, prealloc, start, end, &bits); err = insert_state(tree, prealloc, start, end, &bits);
prealloc = NULL; prealloc = NULL;
BUG_ON(err == -EEXIST); if (err)
extent_io_tree_panic(tree, err);
goto out; goto out;
} }
state = rb_entry(node, struct extent_state, rb_node); state = rb_entry(node, struct extent_state, rb_node);
...@@ -1002,7 +1022,8 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -1002,7 +1022,8 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
goto out; goto out;
} }
err = split_state(tree, state, prealloc, start); err = split_state(tree, state, prealloc, start);
BUG_ON(err == -EEXIST); if (err)
extent_io_tree_panic(tree, err);
prealloc = NULL; prealloc = NULL;
if (err) if (err)
goto out; goto out;
...@@ -1041,12 +1062,8 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -1041,12 +1062,8 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
*/ */
err = insert_state(tree, prealloc, start, this_end, err = insert_state(tree, prealloc, start, this_end,
&bits); &bits);
BUG_ON(err == -EEXIST); if (err)
if (err) { extent_io_tree_panic(tree, err);
free_extent_state(prealloc);
prealloc = NULL;
goto out;
}
prealloc = NULL; prealloc = NULL;
start = this_end + 1; start = this_end + 1;
goto search_again; goto search_again;
...@@ -1065,7 +1082,8 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -1065,7 +1082,8 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
} }
err = split_state(tree, state, prealloc, end + 1); err = split_state(tree, state, prealloc, end + 1);
BUG_ON(err == -EEXIST); if (err)
extent_io_tree_panic(tree, err);
set_state_bits(tree, prealloc, &bits); set_state_bits(tree, prealloc, &bits);
clear_state_bit(tree, prealloc, &clear_bits, 0); clear_state_bit(tree, prealloc, &clear_bits, 0);
......
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