On 19.06.2018 05:18, Su Yue wrote:
>
>
> On 06/18/2018 07:10 PM, Nikolay Borisov wrote:
>> check_chunks_and_extents does quite a number of distinct things. The
>> first of those is going through all root items in the root tree and
>> classify every root depending on whether they have a dropping operation
>> in progress or not. Lets factor out this code and move the variables
>> specific to this in a separate function so clean up
>> check_chunks_and_extents
>> a bit. Accidentally, this patch fixes some reference leaks since
>> in error conditions in the loop the code does "goto out" but at that
>> label we don't really release the path. Having this code extracted in a
>> separate function which always releases the path avoids this problem
>> entirely.
>>
>> Signed-off-by: Nikolay Borisov <nbori...@suse.com>
>
> Code looks okay. One nitpick belows.
>
>> ---
>> check/main.c | 141
>> +++++++++++++++++++++++++++++++++++------------------------
>> 1 file changed, 85 insertions(+), 56 deletions(-)
>>
>> diff --git a/check/main.c b/check/main.c
>> index a4d6855dccbf..fb5c86df21c9 100644
>> --- a/check/main.c
>> +++ b/check/main.c
>> @@ -8069,6 +8069,89 @@ static int deal_root_from_list(struct list_head
>> *list,
>> return ret;
>> }
>> +/**
>> + * parse_tree_roots - Go over all roots in the tree root and add each
>> one to
>> + * a list.
>> + *
>> + * @fs_info - pointer to fs_info struct of the file system.
>> + *
>> + * @normal_trees - list to contains all roots which don't have a drop
>> + * operation in progress
>> + *
>> + * @dropping_trees - list containing all roots which have a drop
>> operation
>> + * pending
>> + *
>> + * Returns 0 on success or a negative value indicating an error.
>> + *
>> + */
>> +static int parse_tree_roots(struct btrfs_fs_info *fs_info,
>> + struct list_head *normal_trees,
>> + struct list_head *dropping_trees)
>> +{
>> + struct btrfs_path path;
>> + struct btrfs_key key;
>> + struct btrfs_key found_key;
>> + struct btrfs_root_item ri;
>> + struct extent_buffer *leaf;
>> + int slot;
>> + int ret = 0;
>> +
>> + btrfs_init_path(&path);
>> + key.offset = 0;
>> + key.objectid = 0;
>> + key.type = BTRFS_ROOT_ITEM_KEY;
>> + ret = btrfs_search_slot(NULL, fs_info->tree_root, &key, &path, 0,
>> 0);
>> + if (ret < 0)
>> + goto out;
>> + while (1) {
>> + leaf = path.nodes[0];
>> + slot = path.slots[0];
>> + if (slot >= btrfs_header_nritems(path.nodes[0])) {
>> + ret = btrfs_next_leaf(fs_info->tree_root, &path);
>> + if (ret != 0)
>> + break;
>> + leaf = path.nodes[0];
>> + slot = path.slots[0];
>> + }
>
> Nit:
> I know the segment is just moved. The @slot is unused.
It's used in the if (slot >= btrfs_header_nritems(path.nodes[0])) check.
I guess the definition could be moved inside the while to reduce the
scope but it's a minor thing.
>> + btrfs_item_key_to_cpu(leaf, &found_key, path.slots[0]);
>> + if (found_key.type == BTRFS_ROOT_ITEM_KEY) {
>> + unsigned long offset;
>> + u64 last_snapshot;
>> + u8 level;
>> +
>> + offset = btrfs_item_ptr_offset(leaf, path.slots[0]);
>> + read_extent_buffer(leaf, &ri, offset, sizeof(ri));
>> + last_snapshot = btrfs_root_last_snapshot(&ri);
>> + level = btrfs_root_level(&ri);
>> + if (btrfs_disk_key_objectid(&ri.drop_progress) == 0) {
>> + ret = add_root_item_to_list(normal_trees,
>> + found_key.objectid,
>> + btrfs_root_bytenr(&ri),
>> + last_snapshot, level,
>> + 0, NULL);
>> + if (ret < 0)
>> + break;
>> + } else {
>> + u64 objectid = found_key.objectid;
>> + btrfs_disk_key_to_cpu(&found_key,
>> + &ri.drop_progress);
>> + ret = add_root_item_to_list(dropping_trees,
>> + objectid,
>> + btrfs_root_bytenr(&ri),
>> + last_snapshot, level,
>> + ri.drop_level, &found_key);
>> + if (ret < 0)
>> + break;
>> + }
>> + }
>> + path.slots[0]++;
>> + }
>> +
>> +out:
>> + btrfs_release_path(&path);
>> + return ret;
>> +}
>> +
>> static int check_chunks_and_extents(struct btrfs_fs_info *fs_info)
>> {
>> struct rb_root dev_cache;
>> @@ -8082,20 +8165,13 @@ static int check_chunks_and_extents(struct
>> btrfs_fs_info *fs_info)
>> struct cache_tree nodes;
>> struct extent_io_tree excluded_extents;
>> struct cache_tree corrupt_blocks;
>> - struct btrfs_path path;
>> - struct btrfs_key key;
>> - struct btrfs_key found_key;
>> int ret, err = 0;
>> struct block_info *bits;
>> int bits_nr;
>> - struct extent_buffer *leaf;
>> - int slot;
>> - struct btrfs_root_item ri;
>> struct list_head dropping_trees;
>> struct list_head normal_trees;
>> struct btrfs_root *root1;
>> struct btrfs_root *root;
>> - u64 objectid;
>> u8 level;
>> root = fs_info->fs_root;
>> @@ -8146,57 +8222,10 @@ static int check_chunks_and_extents(struct
>> btrfs_fs_info *fs_info)
>> root1->node->start, 0, level, 0, NULL);
>> if (ret < 0)
>> goto out;
>> - btrfs_init_path(&path);
>> - key.offset = 0;
>> - key.objectid = 0;
>> - key.type = BTRFS_ROOT_ITEM_KEY;
>> - ret = btrfs_search_slot(NULL, fs_info->tree_root, &key, &path, 0,
>> 0);
>> +
>> + ret = parse_tree_roots(fs_info, &normal_trees, &dropping_trees);
>> if (ret < 0)
>> goto out;
>> - while (1) {
>> - leaf = path.nodes[0];
>> - slot = path.slots[0];
>> - if (slot >= btrfs_header_nritems(path.nodes[0])) {
>> - ret = btrfs_next_leaf(fs_info->tree_root, &path);
>> - if (ret != 0)
>> - break;
>> - leaf = path.nodes[0];
>> - slot = path.slots[0];
>> - }
>> - btrfs_item_key_to_cpu(leaf, &found_key, path.slots[0]);
>> - if (found_key.type == BTRFS_ROOT_ITEM_KEY) {
>> - unsigned long offset;
>> - u64 last_snapshot;
>> -
>> - offset = btrfs_item_ptr_offset(leaf, path.slots[0]);
>> - read_extent_buffer(leaf, &ri, offset, sizeof(ri));
>> - last_snapshot = btrfs_root_last_snapshot(&ri);
>> - if (btrfs_disk_key_objectid(&ri.drop_progress) == 0) {
>> - level = btrfs_root_level(&ri);
>> - ret = add_root_item_to_list(&normal_trees,
>> - found_key.objectid,
>> - btrfs_root_bytenr(&ri),
>> - last_snapshot, level,
>> - 0, NULL);
>> - if (ret < 0)
>> - goto out;
>> - } else {
>> - level = btrfs_root_level(&ri);
>> - objectid = found_key.objectid;
>> - btrfs_disk_key_to_cpu(&found_key,
>> - &ri.drop_progress);
>> - ret = add_root_item_to_list(&dropping_trees,
>> - objectid,
>> - btrfs_root_bytenr(&ri),
>> - last_snapshot, level,
>> - ri.drop_level, &found_key);
>> - if (ret < 0)
>> - goto out;
>> - }
>> - }
>> - path.slots[0]++;
>> - }
>> - btrfs_release_path(&path);
>> /*
>> * check_block can return -EAGAIN if it fixes something, please
>> keep
>>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html