@@ -425,11 +425,10 @@ static struct extent_state *next_state(struct extent_state *state)
* If no bits are set on the state struct after clearing things, the
* struct is freed and removed from the tree
*/
-static struct extent_state *clear_state_bit(struct extent_io_tree *tree,
- struct extent_state *state,
- int *bits, int wake)
+static int __clear_state_bit(struct extent_io_tree *tree,
+ struct extent_state *state,
+ int *bits, int wake)
{
- struct extent_state *next;
int bits_to_clear = *bits & ~EXTENT_CTLBITS;
if ((bits_to_clear & EXTENT_DIRTY) && (state->state & EXTENT_DIRTY)) {
@@ -441,6 +440,14 @@ static struct extent_state *clear_state_bit(struct extent_io_tree *tree,
state->state &= ~bits_to_clear;
if (wake)
wake_up(&state->wq);
+ return 0;
+}
+
+static struct extent_state *
+try_free_or_merge_state(struct extent_io_tree *tree, struct extent_state *state)
+{
+ struct extent_state *next = NULL;
+
if (state->state == 0) {
next = next_state(state);
if (state->tree) {
@@ -457,6 +464,13 @@ static struct extent_state *clear_state_bit(struct extent_io_tree *tree,
return next;
}
+static struct extent_state *clear_state_bit(struct extent_io_tree *tree,
+ struct extent_state *state, int *bits, int wake)
+{
+ __clear_state_bit(tree, state, bits, wake);
+ return try_free_or_merge_state(tree, state);
+}
+
static struct extent_state *
alloc_extent_state_atomic(struct extent_state *prealloc)
{
clear_state_bit() can be broken into two parts: 1) a part for clearing bits, 2) a part for freeing the state or merging it with adjacent ones. And the first one does not need to touch the tree, so holding read locks is enough, and this gives us the oppotunity to rework tree's lock with rwlock. Signed-off-by: Liu Bo <liubo2009@cn.fujitsu.com> --- fs/btrfs/extent_io.c | 22 ++++++++++++++++++---- 1 files changed, 18 insertions(+), 4 deletions(-)