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>
---
 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];
+               }
+               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
-- 
2.7.4

--
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

Reply via email to