Commit 5c939df5 authored by Yan Zheng's avatar Yan Zheng Committed by Chris Mason

btrfs: Fix set/clear_extent_bit for 'end == (u64)-1'

There are some 'start = state->end + 1;' like code in set_extent_bit
and clear_extent_bit. They overflow when end == (u64)-1.
Signed-off-by: default avatarYan Zheng <zheng.yan@oracle.com>
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 07a2039b
...@@ -476,6 +476,7 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -476,6 +476,7 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
struct extent_state *state; struct extent_state *state;
struct extent_state *prealloc = NULL; struct extent_state *prealloc = NULL;
struct rb_node *node; struct rb_node *node;
u64 last_end;
int err; int err;
int set = 0; int set = 0;
...@@ -498,6 +499,7 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -498,6 +499,7 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
if (state->start > end) if (state->start > end)
goto out; goto out;
WARN_ON(state->end < start); WARN_ON(state->end < start);
last_end = state->end;
/* /*
* | ---- desired range ---- | * | ---- desired range ---- |
...@@ -524,9 +526,11 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -524,9 +526,11 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
if (err) if (err)
goto out; goto out;
if (state->end <= end) { if (state->end <= end) {
start = state->end + 1;
set |= clear_state_bit(tree, state, bits, set |= clear_state_bit(tree, state, bits,
wake, delete); wake, delete);
if (last_end == (u64)-1)
goto out;
start = last_end + 1;
} else { } else {
start = state->start; start = state->start;
} }
...@@ -552,8 +556,10 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -552,8 +556,10 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
goto out; goto out;
} }
start = state->end + 1;
set |= clear_state_bit(tree, state, bits, wake, delete); set |= clear_state_bit(tree, state, bits, wake, delete);
if (last_end == (u64)-1)
goto out;
start = last_end + 1;
goto search_again; goto search_again;
out: out:
...@@ -707,8 +713,10 @@ static int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -707,8 +713,10 @@ static int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
goto out; goto out;
} }
set_state_bits(tree, state, bits); set_state_bits(tree, state, bits);
start = state->end + 1;
merge_state(tree, state); merge_state(tree, state);
if (last_end == (u64)-1)
goto out;
start = last_end + 1;
goto search_again; goto search_again;
} }
...@@ -742,8 +750,10 @@ static int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -742,8 +750,10 @@ static int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
goto out; goto out;
if (state->end <= end) { if (state->end <= end) {
set_state_bits(tree, state, bits); set_state_bits(tree, state, bits);
start = state->end + 1;
merge_state(tree, state); merge_state(tree, state);
if (last_end == (u64)-1)
goto out;
start = last_end + 1;
} else { } else {
start = state->start; start = state->start;
} }
......
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