Commit 53d32359 authored by David Sterba's avatar David Sterba

btrfs: embed extent_changeset::range_changed to the structure

We can embed range_changed to the extent changeset to address following
problems:

- no need to allocate ulist dynamically, we also get rid of the GFP_NOFS
  for free
- fix lack of allocation failure checking in btrfs_qgroup_reserve_data

The stack consuption where extent_changeset is used slightly increases:

before: 16
after: 16 - 8 (for pointer) + 32 (sizeof ulist) = 40

Which is bearable.
Reviewed-by: default avatarQu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 9d037933
...@@ -144,7 +144,7 @@ static void add_extent_changeset(struct extent_state *state, unsigned bits, ...@@ -144,7 +144,7 @@ static void add_extent_changeset(struct extent_state *state, unsigned bits,
if (!set && (state->state & bits) == 0) if (!set && (state->state & bits) == 0)
return; 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);
/* ENOMEM */ /* ENOMEM */
BUG_ON(ret < 0); BUG_ON(ret < 0);
......
...@@ -193,7 +193,7 @@ struct extent_changeset { ...@@ -193,7 +193,7 @@ struct extent_changeset {
u64 bytes_changed; u64 bytes_changed;
/* Changed ranges */ /* Changed ranges */
struct ulist *range_changed; struct ulist range_changed;
}; };
static inline void extent_set_compress_type(unsigned long *bio_flags, static inline void extent_set_compress_type(unsigned long *bio_flags,
......
...@@ -2828,7 +2828,7 @@ int btrfs_qgroup_reserve_data(struct inode *inode, u64 start, u64 len) ...@@ -2828,7 +2828,7 @@ int btrfs_qgroup_reserve_data(struct inode *inode, u64 start, u64 len)
return 0; return 0;
changeset.bytes_changed = 0; changeset.bytes_changed = 0;
changeset.range_changed = ulist_alloc(GFP_NOFS); ulist_init(&changeset.range_changed);
ret = set_record_extent_bits(&BTRFS_I(inode)->io_tree, start, ret = set_record_extent_bits(&BTRFS_I(inode)->io_tree, start,
start + len -1, EXTENT_QGROUP_RESERVED, &changeset); start + len -1, EXTENT_QGROUP_RESERVED, &changeset);
trace_btrfs_qgroup_reserve_data(inode, start, len, trace_btrfs_qgroup_reserve_data(inode, start, len,
...@@ -2840,17 +2840,17 @@ int btrfs_qgroup_reserve_data(struct inode *inode, u64 start, u64 len) ...@@ -2840,17 +2840,17 @@ int btrfs_qgroup_reserve_data(struct inode *inode, u64 start, u64 len)
if (ret < 0) if (ret < 0)
goto cleanup; goto cleanup;
ulist_free(changeset.range_changed); ulist_fini(&changeset.range_changed);
return ret; return ret;
cleanup: cleanup:
/* cleanup already reserved ranges */ /* cleanup already reserved ranges */
ULIST_ITER_INIT(&uiter); ULIST_ITER_INIT(&uiter);
while ((unode = ulist_next(changeset.range_changed, &uiter))) while ((unode = ulist_next(&changeset.range_changed, &uiter)))
clear_extent_bit(&BTRFS_I(inode)->io_tree, unode->val, clear_extent_bit(&BTRFS_I(inode)->io_tree, unode->val,
unode->aux, EXTENT_QGROUP_RESERVED, 0, 0, NULL, unode->aux, EXTENT_QGROUP_RESERVED, 0, 0, NULL,
GFP_NOFS); GFP_NOFS);
ulist_free(changeset.range_changed); ulist_fini(&changeset.range_changed);
return ret; return ret;
} }
...@@ -2862,10 +2862,7 @@ static int __btrfs_qgroup_release_data(struct inode *inode, u64 start, u64 len, ...@@ -2862,10 +2862,7 @@ static int __btrfs_qgroup_release_data(struct inode *inode, u64 start, u64 len,
int ret; int ret;
changeset.bytes_changed = 0; changeset.bytes_changed = 0;
changeset.range_changed = ulist_alloc(GFP_NOFS); ulist_init(&changeset.range_changed);
if (!changeset.range_changed)
return -ENOMEM;
ret = clear_record_extent_bits(&BTRFS_I(inode)->io_tree, start, ret = clear_record_extent_bits(&BTRFS_I(inode)->io_tree, start,
start + len -1, EXTENT_QGROUP_RESERVED, &changeset); start + len -1, EXTENT_QGROUP_RESERVED, &changeset);
if (ret < 0) if (ret < 0)
...@@ -2878,7 +2875,7 @@ static int __btrfs_qgroup_release_data(struct inode *inode, u64 start, u64 len, ...@@ -2878,7 +2875,7 @@ static int __btrfs_qgroup_release_data(struct inode *inode, u64 start, u64 len,
trace_btrfs_qgroup_release_data(inode, start, len, trace_btrfs_qgroup_release_data(inode, start, len,
changeset.bytes_changed, trace_op); changeset.bytes_changed, trace_op);
out: out:
ulist_free(changeset.range_changed); ulist_fini(&changeset.range_changed);
return ret; return ret;
} }
...@@ -2976,22 +2973,19 @@ void btrfs_qgroup_check_reserved_leak(struct inode *inode) ...@@ -2976,22 +2973,19 @@ void btrfs_qgroup_check_reserved_leak(struct inode *inode)
int ret; int ret;
changeset.bytes_changed = 0; changeset.bytes_changed = 0;
changeset.range_changed = ulist_alloc(GFP_NOFS); ulist_init(&changeset.range_changed);
if (WARN_ON(!changeset.range_changed))
return;
ret = clear_record_extent_bits(&BTRFS_I(inode)->io_tree, 0, (u64)-1, ret = clear_record_extent_bits(&BTRFS_I(inode)->io_tree, 0, (u64)-1,
EXTENT_QGROUP_RESERVED, &changeset); EXTENT_QGROUP_RESERVED, &changeset);
WARN_ON(ret < 0); WARN_ON(ret < 0);
if (WARN_ON(changeset.bytes_changed)) { if (WARN_ON(changeset.bytes_changed)) {
ULIST_ITER_INIT(&iter); ULIST_ITER_INIT(&iter);
while ((unode = ulist_next(changeset.range_changed, &iter))) { while ((unode = ulist_next(&changeset.range_changed, &iter))) {
btrfs_warn(BTRFS_I(inode)->root->fs_info, btrfs_warn(BTRFS_I(inode)->root->fs_info,
"leaking qgroup reserved space, ino: %lu, start: %llu, end: %llu", "leaking qgroup reserved space, ino: %lu, start: %llu, end: %llu",
inode->i_ino, unode->val, unode->aux); inode->i_ino, unode->val, unode->aux);
} }
qgroup_free(BTRFS_I(inode)->root, changeset.bytes_changed); qgroup_free(BTRFS_I(inode)->root, changeset.bytes_changed);
} }
ulist_free(changeset.range_changed); ulist_fini(&changeset.range_changed);
} }
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