mirror of
https://github.com/torvalds/linux.git
synced 2026-06-05 13:06:59 +02:00
btrfs: avoid unnecessary next node searches when clearing bits from extent range
When clearing bits for a range in an io tree, at clear_state_bit(), we always go search for the next node (through next_state() -> rb_next()) and return it. However if the current extent state record ends at or after the target range passed to btrfs_clear_extent_bit_changeset() or btrfs_convert_extent_bit(), we are just wasting time finding that next node since we won't use it in those functions. Improve on this by skipping the next node search if the current node ends at or after the target range. Reviewed-by: Boris Burkov <boris@bur.io> Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
3bf179e36d
commit
240dd0e1bb
|
|
@ -537,6 +537,18 @@ static int split_state(struct extent_io_tree *tree, struct extent_state *orig,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use this during tree iteration to avoid doing next node searches when it's
|
||||
* not needed (the current record ends at or after the target range's end).
|
||||
*/
|
||||
static inline struct extent_state *next_search_state(struct extent_state *state, u64 end)
|
||||
{
|
||||
if (state->end < end)
|
||||
return next_state(state);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility function to clear some bits in an extent state struct. It will
|
||||
* optionally wake up anyone waiting on this state (wake == 1).
|
||||
|
|
@ -546,7 +558,7 @@ static int split_state(struct extent_io_tree *tree, struct extent_state *orig,
|
|||
*/
|
||||
static struct extent_state *clear_state_bit(struct extent_io_tree *tree,
|
||||
struct extent_state *state,
|
||||
u32 bits, int wake,
|
||||
u32 bits, int wake, u64 end,
|
||||
struct extent_changeset *changeset)
|
||||
{
|
||||
struct extent_state *next;
|
||||
|
|
@ -562,7 +574,7 @@ static struct extent_state *clear_state_bit(struct extent_io_tree *tree,
|
|||
if (wake)
|
||||
wake_up(&state->wq);
|
||||
if (state->state == 0) {
|
||||
next = next_state(state);
|
||||
next = next_search_state(state, end);
|
||||
if (extent_state_in_tree(state)) {
|
||||
rb_erase(&state->rb_node, &tree->state);
|
||||
RB_CLEAR_NODE(&state->rb_node);
|
||||
|
|
@ -572,7 +584,7 @@ static struct extent_state *clear_state_bit(struct extent_io_tree *tree,
|
|||
}
|
||||
} else {
|
||||
merge_state(tree, state);
|
||||
next = next_state(state);
|
||||
next = next_search_state(state, end);
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
|
@ -666,7 +678,7 @@ int btrfs_clear_extent_bit_changeset(struct extent_io_tree *tree, u64 start, u64
|
|||
|
||||
/* The state doesn't have the wanted bits, go ahead. */
|
||||
if (!(state->state & bits)) {
|
||||
state = next_state(state);
|
||||
state = next_search_state(state, end);
|
||||
goto next;
|
||||
}
|
||||
|
||||
|
|
@ -696,7 +708,8 @@ int btrfs_clear_extent_bit_changeset(struct extent_io_tree *tree, u64 start, u64
|
|||
goto out;
|
||||
}
|
||||
if (state->end <= end) {
|
||||
state = clear_state_bit(tree, state, bits, wake, changeset);
|
||||
state = clear_state_bit(tree, state, bits, wake, end,
|
||||
changeset);
|
||||
goto next;
|
||||
}
|
||||
if (need_resched())
|
||||
|
|
@ -726,13 +739,13 @@ int btrfs_clear_extent_bit_changeset(struct extent_io_tree *tree, u64 start, u64
|
|||
if (wake)
|
||||
wake_up(&state->wq);
|
||||
|
||||
clear_state_bit(tree, prealloc, bits, wake, changeset);
|
||||
clear_state_bit(tree, prealloc, bits, wake, end, changeset);
|
||||
|
||||
prealloc = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
state = clear_state_bit(tree, state, bits, wake, changeset);
|
||||
state = clear_state_bit(tree, state, bits, wake, end, changeset);
|
||||
next:
|
||||
if (last_end >= end)
|
||||
goto out;
|
||||
|
|
@ -1357,7 +1370,7 @@ int btrfs_convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
|
|||
if (state->start == start && state->end <= end) {
|
||||
set_state_bits(tree, state, bits, NULL);
|
||||
cache_state(state, cached_state);
|
||||
state = clear_state_bit(tree, state, clear_bits, 0, NULL);
|
||||
state = clear_state_bit(tree, state, clear_bits, 0, end, NULL);
|
||||
if (last_end == (u64)-1)
|
||||
goto out;
|
||||
start = last_end + 1;
|
||||
|
|
@ -1397,7 +1410,7 @@ int btrfs_convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
|
|||
if (state->end <= end) {
|
||||
set_state_bits(tree, state, bits, NULL);
|
||||
cache_state(state, cached_state);
|
||||
state = clear_state_bit(tree, state, clear_bits, 0, NULL);
|
||||
state = clear_state_bit(tree, state, clear_bits, 0, end, NULL);
|
||||
if (last_end == (u64)-1)
|
||||
goto out;
|
||||
start = last_end + 1;
|
||||
|
|
@ -1469,7 +1482,7 @@ int btrfs_convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
|
|||
|
||||
set_state_bits(tree, prealloc, bits, NULL);
|
||||
cache_state(prealloc, cached_state);
|
||||
clear_state_bit(tree, prealloc, clear_bits, 0, NULL);
|
||||
clear_state_bit(tree, prealloc, clear_bits, 0, end, NULL);
|
||||
prealloc = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user