btrfs: introduce btrfs_search_backwards function
authorMarcos Paulo de Souza <mpdesouza@suse.com>
Thu, 29 Jul 2021 08:22:16 +0000 (05:22 -0300)
committerDavid Sterba <dsterba@suse.com>
Mon, 23 Aug 2021 11:19:09 +0000 (13:19 +0200)
It's a common practice to start a search using offset (u64)-1, which is
the u64 maximum value, meaning that we want the search_slot function to
be set in the last item with the same objectid and type.

Once we are in this position, it's a matter to start a search backwards
by calling btrfs_previous_item, which will check if we'll need to go to
a previous leaf and other necessary checks, only to be sure that we are
in last offset of the same object and type.

The new btrfs_search_backwards function does the all these steps when
necessary, and can be used to avoid code duplication.

Signed-off-by: Marcos Paulo de Souza <mpdesouza@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/ioctl.c
fs/btrfs/super.c
fs/btrfs/volumes.c

index 99b33a5..84627cb 100644 (file)
@@ -2102,6 +2102,27 @@ again:
 }
 
 /*
+ * Execute search and call btrfs_previous_item to traverse backwards if the item
+ * was not found.
+ *
+ * Return 0 if found, 1 if not found and < 0 if error.
+ */
+int btrfs_search_backwards(struct btrfs_root *root, struct btrfs_key *key,
+                          struct btrfs_path *path)
+{
+       int ret;
+
+       ret = btrfs_search_slot(NULL, root, key, path, 0, 0);
+       if (ret > 0)
+               ret = btrfs_previous_item(root, path, key->objectid, key->type);
+
+       if (ret == 0)
+               btrfs_item_key_to_cpu(path->nodes[0], key, path->slots[0]);
+
+       return ret;
+}
+
+/*
  * adjust the pointers going up the tree, starting at level
  * making sure the right key of each node is points to 'key'.
  * This is used after shifting pointers to the left, so it stops
index f17be4b..a898257 100644 (file)
@@ -2908,6 +2908,10 @@ static inline int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
 int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path);
 int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path,
                        u64 time_seq);
+
+int btrfs_search_backwards(struct btrfs_root *root, struct btrfs_key *key,
+                          struct btrfs_path *path);
+
 static inline int btrfs_next_old_item(struct btrfs_root *root,
                                      struct btrfs_path *p, u64 time_seq)
 {
index 85c8b5a..ba1dab6 100644 (file)
@@ -2389,23 +2389,16 @@ static noinline int btrfs_search_path_in_tree(struct btrfs_fs_info *info,
        key.offset = (u64)-1;
 
        while (1) {
-               ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+               ret = btrfs_search_backwards(root, &key, path);
                if (ret < 0)
                        goto out;
                else if (ret > 0) {
-                       ret = btrfs_previous_item(root, path, dirid,
-                                                 BTRFS_INODE_REF_KEY);
-                       if (ret < 0)
-                               goto out;
-                       else if (ret > 0) {
-                               ret = -ENOENT;
-                               goto out;
-                       }
+                       ret = -ENOENT;
+                       goto out;
                }
 
                l = path->nodes[0];
                slot = path->slots[0];
-               btrfs_item_key_to_cpu(l, &key, slot);
 
                iref = btrfs_item_ptr(l, slot, struct btrfs_inode_ref);
                len = btrfs_inode_ref_name_len(l, iref);
@@ -2480,23 +2473,16 @@ static int btrfs_search_path_in_tree_user(struct inode *inode,
                key.type = BTRFS_INODE_REF_KEY;
                key.offset = (u64)-1;
                while (1) {
-                       ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
-                       if (ret < 0) {
+                       ret = btrfs_search_backwards(root, &key, path);
+                       if (ret < 0)
+                               goto out_put;
+                       else if (ret > 0) {
+                               ret = -ENOENT;
                                goto out_put;
-                       } else if (ret > 0) {
-                               ret = btrfs_previous_item(root, path, dirid,
-                                                         BTRFS_INODE_REF_KEY);
-                               if (ret < 0) {
-                                       goto out_put;
-                               } else if (ret > 0) {
-                                       ret = -ENOENT;
-                                       goto out_put;
-                               }
                        }
 
                        leaf = path->nodes[0];
                        slot = path->slots[0];
-                       btrfs_item_key_to_cpu(leaf, &key, slot);
 
                        iref = btrfs_item_ptr(leaf, slot, struct btrfs_inode_ref);
                        len = btrfs_inode_ref_name_len(leaf, iref);
index d444338..409bee3 100644 (file)
@@ -1201,21 +1201,14 @@ char *btrfs_get_subvol_name_from_objectid(struct btrfs_fs_info *fs_info,
                key.type = BTRFS_ROOT_BACKREF_KEY;
                key.offset = (u64)-1;
 
-               ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+               ret = btrfs_search_backwards(root, &key, path);
                if (ret < 0) {
                        goto err;
                } else if (ret > 0) {
-                       ret = btrfs_previous_item(root, path, subvol_objectid,
-                                                 BTRFS_ROOT_BACKREF_KEY);
-                       if (ret < 0) {
-                               goto err;
-                       } else if (ret > 0) {
-                               ret = -ENOENT;
-                               goto err;
-                       }
+                       ret = -ENOENT;
+                       goto err;
                }
 
-               btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
                subvol_objectid = key.offset;
 
                root_ref = btrfs_item_ptr(path->nodes[0], path->slots[0],
@@ -1248,21 +1241,14 @@ char *btrfs_get_subvol_name_from_objectid(struct btrfs_fs_info *fs_info,
                        key.type = BTRFS_INODE_REF_KEY;
                        key.offset = (u64)-1;
 
-                       ret = btrfs_search_slot(NULL, fs_root, &key, path, 0, 0);
+                       ret = btrfs_search_backwards(fs_root, &key, path);
                        if (ret < 0) {
                                goto err;
                        } else if (ret > 0) {
-                               ret = btrfs_previous_item(fs_root, path, dirid,
-                                                         BTRFS_INODE_REF_KEY);
-                               if (ret < 0) {
-                                       goto err;
-                               } else if (ret > 0) {
-                                       ret = -ENOENT;
-                                       goto err;
-                               }
+                               ret = -ENOENT;
+                               goto err;
                        }
 
-                       btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
                        dirid = key.offset;
 
                        inode_ref = btrfs_item_ptr(path->nodes[0],
index 230192d..536e60c 100644 (file)
@@ -1586,14 +1586,9 @@ again:
        key.offset = search_start;
        key.type = BTRFS_DEV_EXTENT_KEY;
 
-       ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+       ret = btrfs_search_backwards(root, &key, path);
        if (ret < 0)
                goto out;
-       if (ret > 0) {
-               ret = btrfs_previous_item(root, path, key.objectid, key.type);
-               if (ret < 0)
-                       goto out;
-       }
 
        while (1) {
                l = path->nodes[0];