Commit d38ed27f authored by Qu Wenruo's avatar Qu Wenruo Committed by Chris Mason

btrfs: extent_io: Introduce new function set_record_extent_bits

Introduce new function set_record_extent_bits(), which will not only set
given bits, but also record how many bytes are changed, and detailed
range info.

This is quite important for later qgroup reserve framework.
The number of bytes will be used to do qgroup reserve, and detailed
range info will be used to cleanup for EQUOT case.
Signed-off-by: default avatarQu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: default avatarChris Mason <clm@fb.com>
parent ac467772
...@@ -131,6 +131,23 @@ struct extent_page_data { ...@@ -131,6 +131,23 @@ struct extent_page_data {
unsigned int sync_io:1; unsigned int sync_io:1;
}; };
static void add_extent_changeset(struct extent_state *state, unsigned bits,
struct extent_changeset *changeset,
int set)
{
int ret;
if (!changeset)
return;
if (set && (state->state & bits) == bits)
return;
changeset->bytes_changed += state->end - state->start + 1;
ret = ulist_add(changeset->range_changed, state->start, state->end,
GFP_ATOMIC);
/* ENOMEM */
BUG_ON(ret < 0);
}
static noinline void flush_write_bio(void *data); static noinline void flush_write_bio(void *data);
static inline struct btrfs_fs_info * static inline struct btrfs_fs_info *
tree_fs_info(struct extent_io_tree *tree) tree_fs_info(struct extent_io_tree *tree)
...@@ -410,7 +427,8 @@ static void clear_state_cb(struct extent_io_tree *tree, ...@@ -410,7 +427,8 @@ static void clear_state_cb(struct extent_io_tree *tree,
} }
static void set_state_bits(struct extent_io_tree *tree, static void set_state_bits(struct extent_io_tree *tree,
struct extent_state *state, unsigned *bits); struct extent_state *state, unsigned *bits,
struct extent_changeset *changeset);
/* /*
* insert an extent_state struct into the tree. 'bits' are set on the * insert an extent_state struct into the tree. 'bits' are set on the
...@@ -426,7 +444,7 @@ static int insert_state(struct extent_io_tree *tree, ...@@ -426,7 +444,7 @@ static int insert_state(struct extent_io_tree *tree,
struct extent_state *state, u64 start, u64 end, struct extent_state *state, u64 start, u64 end,
struct rb_node ***p, struct rb_node ***p,
struct rb_node **parent, struct rb_node **parent,
unsigned *bits) unsigned *bits, struct extent_changeset *changeset)
{ {
struct rb_node *node; struct rb_node *node;
...@@ -436,7 +454,7 @@ static int insert_state(struct extent_io_tree *tree, ...@@ -436,7 +454,7 @@ static int insert_state(struct extent_io_tree *tree,
state->start = start; state->start = start;
state->end = end; state->end = end;
set_state_bits(tree, state, bits); set_state_bits(tree, state, bits, changeset);
node = tree_insert(&tree->state, NULL, end, &state->rb_node, p, parent); node = tree_insert(&tree->state, NULL, end, &state->rb_node, p, parent);
if (node) { if (node) {
...@@ -789,7 +807,7 @@ static void wait_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -789,7 +807,7 @@ static void wait_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
static void set_state_bits(struct extent_io_tree *tree, static void set_state_bits(struct extent_io_tree *tree,
struct extent_state *state, struct extent_state *state,
unsigned *bits) unsigned *bits, struct extent_changeset *changeset)
{ {
unsigned bits_to_set = *bits & ~EXTENT_CTLBITS; unsigned bits_to_set = *bits & ~EXTENT_CTLBITS;
...@@ -798,6 +816,7 @@ static void set_state_bits(struct extent_io_tree *tree, ...@@ -798,6 +816,7 @@ static void set_state_bits(struct extent_io_tree *tree,
u64 range = state->end - state->start + 1; u64 range = state->end - state->start + 1;
tree->dirty_bytes += range; tree->dirty_bytes += range;
} }
add_extent_changeset(state, bits_to_set, changeset, 1);
state->state |= bits_to_set; state->state |= bits_to_set;
} }
...@@ -835,7 +854,7 @@ static int __must_check ...@@ -835,7 +854,7 @@ static int __must_check
__set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, __set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
unsigned bits, unsigned exclusive_bits, unsigned bits, unsigned exclusive_bits,
u64 *failed_start, struct extent_state **cached_state, u64 *failed_start, struct extent_state **cached_state,
gfp_t mask) gfp_t mask, struct extent_changeset *changeset)
{ {
struct extent_state *state; struct extent_state *state;
struct extent_state *prealloc = NULL; struct extent_state *prealloc = NULL;
...@@ -873,7 +892,7 @@ __set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -873,7 +892,7 @@ __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, err = insert_state(tree, prealloc, start, end,
&p, &parent, &bits); &p, &parent, &bits, changeset);
if (err) if (err)
extent_io_tree_panic(tree, err); extent_io_tree_panic(tree, err);
...@@ -899,7 +918,7 @@ __set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -899,7 +918,7 @@ __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, changeset);
cache_state(state, cached_state); cache_state(state, cached_state);
merge_state(tree, state); merge_state(tree, state);
if (last_end == (u64)-1) if (last_end == (u64)-1)
...@@ -945,7 +964,7 @@ __set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -945,7 +964,7 @@ __set_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) {
set_state_bits(tree, state, &bits); set_state_bits(tree, state, &bits, changeset);
cache_state(state, cached_state); cache_state(state, cached_state);
merge_state(tree, state); merge_state(tree, state);
if (last_end == (u64)-1) if (last_end == (u64)-1)
...@@ -980,7 +999,7 @@ __set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -980,7 +999,7 @@ __set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
* the later extent. * the later extent.
*/ */
err = insert_state(tree, prealloc, start, this_end, err = insert_state(tree, prealloc, start, this_end,
NULL, NULL, &bits); NULL, NULL, &bits, changeset);
if (err) if (err)
extent_io_tree_panic(tree, err); extent_io_tree_panic(tree, err);
...@@ -1008,7 +1027,7 @@ __set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -1008,7 +1027,7 @@ __set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
if (err) if (err)
extent_io_tree_panic(tree, err); extent_io_tree_panic(tree, err);
set_state_bits(tree, prealloc, &bits); set_state_bits(tree, prealloc, &bits, changeset);
cache_state(prealloc, cached_state); cache_state(prealloc, cached_state);
merge_state(tree, prealloc); merge_state(tree, prealloc);
prealloc = NULL; prealloc = NULL;
...@@ -1038,7 +1057,7 @@ int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -1038,7 +1057,7 @@ int set_extent_bit(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)
{ {
return __set_extent_bit(tree, start, end, bits, 0, failed_start, return __set_extent_bit(tree, start, end, bits, 0, failed_start,
cached_state, mask); cached_state, mask, NULL);
} }
...@@ -1111,7 +1130,7 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -1111,7 +1130,7 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
goto out; goto out;
} }
err = insert_state(tree, prealloc, start, end, err = insert_state(tree, prealloc, start, end,
&p, &parent, &bits); &p, &parent, &bits, NULL);
if (err) if (err)
extent_io_tree_panic(tree, err); extent_io_tree_panic(tree, err);
cache_state(prealloc, cached_state); cache_state(prealloc, cached_state);
...@@ -1130,7 +1149,7 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -1130,7 +1149,7 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
* Just lock what we found and keep going * Just lock what we found and keep going
*/ */
if (state->start == start && state->end <= end) { if (state->start == start && state->end <= end) {
set_state_bits(tree, state, &bits); 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);
if (last_end == (u64)-1) if (last_end == (u64)-1)
...@@ -1171,7 +1190,7 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -1171,7 +1190,7 @@ int convert_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) {
set_state_bits(tree, state, &bits); 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);
if (last_end == (u64)-1) if (last_end == (u64)-1)
...@@ -1208,7 +1227,7 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -1208,7 +1227,7 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
* the later extent. * the later extent.
*/ */
err = insert_state(tree, prealloc, start, this_end, err = insert_state(tree, prealloc, start, this_end,
NULL, NULL, &bits); NULL, NULL, &bits, NULL);
if (err) if (err)
extent_io_tree_panic(tree, err); extent_io_tree_panic(tree, err);
cache_state(prealloc, cached_state); cache_state(prealloc, cached_state);
...@@ -1233,7 +1252,7 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -1233,7 +1252,7 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
if (err) if (err)
extent_io_tree_panic(tree, err); extent_io_tree_panic(tree, err);
set_state_bits(tree, prealloc, &bits); 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);
prealloc = NULL; prealloc = NULL;
...@@ -1274,6 +1293,22 @@ int set_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -1274,6 +1293,22 @@ int set_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
NULL, mask); NULL, mask);
} }
int set_record_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
unsigned bits, gfp_t mask,
struct extent_changeset *changeset)
{
/*
* We don't support EXTENT_LOCKED yet, as current changeset will
* record any bits changed, so for EXTENT_LOCKED case, it will
* either fail with -EEXIST or changeset will record the whole
* range.
*/
BUG_ON(bits & EXTENT_LOCKED);
return __set_extent_bit(tree, start, end, bits, 0, NULL, NULL, mask,
changeset);
}
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)
{ {
...@@ -1343,7 +1378,7 @@ int lock_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -1343,7 +1378,7 @@ int lock_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
while (1) { while (1) {
err = __set_extent_bit(tree, start, end, EXTENT_LOCKED | bits, err = __set_extent_bit(tree, start, end, EXTENT_LOCKED | bits,
EXTENT_LOCKED, &failed_start, EXTENT_LOCKED, &failed_start,
cached_state, GFP_NOFS); cached_state, GFP_NOFS, NULL);
if (err == -EEXIST) { if (err == -EEXIST) {
wait_extent_bit(tree, failed_start, end, EXTENT_LOCKED); wait_extent_bit(tree, failed_start, end, EXTENT_LOCKED);
start = failed_start; start = failed_start;
...@@ -1365,7 +1400,7 @@ int try_lock_extent(struct extent_io_tree *tree, u64 start, u64 end) ...@@ -1365,7 +1400,7 @@ int try_lock_extent(struct extent_io_tree *tree, u64 start, u64 end)
u64 failed_start; u64 failed_start;
err = __set_extent_bit(tree, start, end, EXTENT_LOCKED, EXTENT_LOCKED, err = __set_extent_bit(tree, start, end, EXTENT_LOCKED, EXTENT_LOCKED,
&failed_start, NULL, GFP_NOFS); &failed_start, NULL, GFP_NOFS, NULL);
if (err == -EEXIST) { if (err == -EEXIST) {
if (failed_start > start) if (failed_start > start)
clear_extent_bit(tree, start, failed_start - 1, clear_extent_bit(tree, start, failed_start - 1,
......
...@@ -227,6 +227,9 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, ...@@ -227,6 +227,9 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
struct extent_state **cached, gfp_t mask); struct extent_state **cached, gfp_t mask);
int set_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, int set_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
unsigned bits, gfp_t mask); unsigned bits, gfp_t mask);
int set_record_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
unsigned bits, gfp_t mask,
struct extent_changeset *changeset);
int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
unsigned bits, u64 *failed_start, unsigned bits, u64 *failed_start,
struct extent_state **cached_state, gfp_t mask); struct extent_state **cached_state, gfp_t mask);
......
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