|
@@ -141,6 +141,8 @@ static void add_extent_changeset(struct extent_state *state, unsigned bits,
|
|
return;
|
|
return;
|
|
if (set && (state->state & bits) == bits)
|
|
if (set && (state->state & bits) == bits)
|
|
return;
|
|
return;
|
|
|
|
+ if (!set && (state->state & bits) == 0)
|
|
|
|
+ return;
|
|
changeset->bytes_changed += state->end - state->start + 1;
|
|
changeset->bytes_changed += state->end - state->start + 1;
|
|
ret = ulist_add(changeset->range_changed, state->start, state->end,
|
|
ret = ulist_add(changeset->range_changed, state->start, state->end,
|
|
GFP_ATOMIC);
|
|
GFP_ATOMIC);
|
|
@@ -529,7 +531,8 @@ static struct extent_state *next_state(struct extent_state *state)
|
|
*/
|
|
*/
|
|
static struct extent_state *clear_state_bit(struct extent_io_tree *tree,
|
|
static struct extent_state *clear_state_bit(struct extent_io_tree *tree,
|
|
struct extent_state *state,
|
|
struct extent_state *state,
|
|
- unsigned *bits, int wake)
|
|
|
|
|
|
+ unsigned *bits, int wake,
|
|
|
|
+ struct extent_changeset *changeset)
|
|
{
|
|
{
|
|
struct extent_state *next;
|
|
struct extent_state *next;
|
|
unsigned bits_to_clear = *bits & ~EXTENT_CTLBITS;
|
|
unsigned bits_to_clear = *bits & ~EXTENT_CTLBITS;
|
|
@@ -540,6 +543,7 @@ static struct extent_state *clear_state_bit(struct extent_io_tree *tree,
|
|
tree->dirty_bytes -= range;
|
|
tree->dirty_bytes -= range;
|
|
}
|
|
}
|
|
clear_state_cb(tree, state, bits);
|
|
clear_state_cb(tree, state, bits);
|
|
|
|
+ add_extent_changeset(state, bits_to_clear, changeset, 0);
|
|
state->state &= ~bits_to_clear;
|
|
state->state &= ~bits_to_clear;
|
|
if (wake)
|
|
if (wake)
|
|
wake_up(&state->wq);
|
|
wake_up(&state->wq);
|
|
@@ -587,10 +591,10 @@ static void extent_io_tree_panic(struct extent_io_tree *tree, int err)
|
|
*
|
|
*
|
|
* This takes the tree lock, and returns 0 on success and < 0 on error.
|
|
* This takes the tree lock, and returns 0 on success and < 0 on error.
|
|
*/
|
|
*/
|
|
-int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
|
|
|
|
- unsigned bits, int wake, int delete,
|
|
|
|
- struct extent_state **cached_state,
|
|
|
|
- gfp_t mask)
|
|
|
|
|
|
+static int __clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
|
|
|
|
+ unsigned bits, int wake, int delete,
|
|
|
|
+ struct extent_state **cached_state,
|
|
|
|
+ gfp_t mask, struct extent_changeset *changeset)
|
|
{
|
|
{
|
|
struct extent_state *state;
|
|
struct extent_state *state;
|
|
struct extent_state *cached;
|
|
struct extent_state *cached;
|
|
@@ -689,7 +693,8 @@ hit_next:
|
|
if (err)
|
|
if (err)
|
|
goto out;
|
|
goto out;
|
|
if (state->end <= end) {
|
|
if (state->end <= end) {
|
|
- state = clear_state_bit(tree, state, &bits, wake);
|
|
|
|
|
|
+ state = clear_state_bit(tree, state, &bits, wake,
|
|
|
|
+ changeset);
|
|
goto next;
|
|
goto next;
|
|
}
|
|
}
|
|
goto search_again;
|
|
goto search_again;
|
|
@@ -710,13 +715,13 @@ hit_next:
|
|
if (wake)
|
|
if (wake)
|
|
wake_up(&state->wq);
|
|
wake_up(&state->wq);
|
|
|
|
|
|
- clear_state_bit(tree, prealloc, &bits, wake);
|
|
|
|
|
|
+ clear_state_bit(tree, prealloc, &bits, wake, changeset);
|
|
|
|
|
|
prealloc = NULL;
|
|
prealloc = NULL;
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
- state = clear_state_bit(tree, state, &bits, wake);
|
|
|
|
|
|
+ state = clear_state_bit(tree, state, &bits, wake, changeset);
|
|
next:
|
|
next:
|
|
if (last_end == (u64)-1)
|
|
if (last_end == (u64)-1)
|
|
goto out;
|
|
goto out;
|
|
@@ -1151,7 +1156,7 @@ hit_next:
|
|
if (state->start == start && state->end <= end) {
|
|
if (state->start == start && state->end <= end) {
|
|
set_state_bits(tree, state, &bits, NULL);
|
|
set_state_bits(tree, state, &bits, NULL);
|
|
cache_state(state, cached_state);
|
|
cache_state(state, cached_state);
|
|
- state = clear_state_bit(tree, state, &clear_bits, 0);
|
|
|
|
|
|
+ state = clear_state_bit(tree, state, &clear_bits, 0, NULL);
|
|
if (last_end == (u64)-1)
|
|
if (last_end == (u64)-1)
|
|
goto out;
|
|
goto out;
|
|
start = last_end + 1;
|
|
start = last_end + 1;
|
|
@@ -1192,7 +1197,8 @@ hit_next:
|
|
if (state->end <= end) {
|
|
if (state->end <= end) {
|
|
set_state_bits(tree, state, &bits, NULL);
|
|
set_state_bits(tree, state, &bits, NULL);
|
|
cache_state(state, cached_state);
|
|
cache_state(state, cached_state);
|
|
- state = clear_state_bit(tree, state, &clear_bits, 0);
|
|
|
|
|
|
+ state = clear_state_bit(tree, state, &clear_bits, 0,
|
|
|
|
+ NULL);
|
|
if (last_end == (u64)-1)
|
|
if (last_end == (u64)-1)
|
|
goto out;
|
|
goto out;
|
|
start = last_end + 1;
|
|
start = last_end + 1;
|
|
@@ -1254,7 +1260,7 @@ hit_next:
|
|
|
|
|
|
set_state_bits(tree, prealloc, &bits, NULL);
|
|
set_state_bits(tree, prealloc, &bits, NULL);
|
|
cache_state(prealloc, cached_state);
|
|
cache_state(prealloc, cached_state);
|
|
- clear_state_bit(tree, prealloc, &clear_bits, 0);
|
|
|
|
|
|
+ clear_state_bit(tree, prealloc, &clear_bits, 0, NULL);
|
|
prealloc = NULL;
|
|
prealloc = NULL;
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
@@ -1309,6 +1315,14 @@ int set_record_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
|
|
changeset);
|
|
changeset);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
|
|
|
|
+ unsigned bits, int wake, int delete,
|
|
|
|
+ struct extent_state **cached, gfp_t mask)
|
|
|
|
+{
|
|
|
|
+ return __clear_extent_bit(tree, start, end, bits, wake, delete,
|
|
|
|
+ cached, mask, NULL);
|
|
|
|
+}
|
|
|
|
+
|
|
int clear_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
|
|
int clear_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
|
|
unsigned bits, gfp_t mask)
|
|
unsigned bits, gfp_t mask)
|
|
{
|
|
{
|
|
@@ -1320,6 +1334,20 @@ int clear_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
|
|
return clear_extent_bit(tree, start, end, bits, wake, 0, NULL, mask);
|
|
return clear_extent_bit(tree, start, end, bits, wake, 0, NULL, mask);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+int clear_record_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
|
|
|
|
+ unsigned bits, gfp_t mask,
|
|
|
|
+ struct extent_changeset *changeset)
|
|
|
|
+{
|
|
|
|
+ /*
|
|
|
|
+ * Don't support EXTENT_LOCKED case, same reason as
|
|
|
|
+ * set_record_extent_bits().
|
|
|
|
+ */
|
|
|
|
+ BUG_ON(bits & EXTENT_LOCKED);
|
|
|
|
+
|
|
|
|
+ return __clear_extent_bit(tree, start, end, bits, 0, 0, NULL, mask,
|
|
|
|
+ changeset);
|
|
|
|
+}
|
|
|
|
+
|
|
int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end,
|
|
int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end,
|
|
struct extent_state **cached_state, gfp_t mask)
|
|
struct extent_state **cached_state, gfp_t mask)
|
|
{
|
|
{
|