]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
btrfs: split inode extref processing from __add_inode_ref() into a helper
authorFilipe Manana <fdmanana@suse.com>
Mon, 23 Jun 2025 11:54:40 +0000 (12:54 +0100)
committerDavid Sterba <dsterba@suse.com>
Mon, 21 Jul 2025 21:58:04 +0000 (23:58 +0200)
The __add_inode_ref() function is quite big and with too much nesting, so
move the code that processes inode extrefs into a helper function, to make
the function easier to read and reduce the level of indentation too.

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/tree-log.c

index 9cefbf4370ca7161fec0a8bcb023bb0c76538e68..b8048613d41ebf55e1f199236804d5b663f02afd 100644 (file)
@@ -1094,6 +1094,73 @@ static int unlink_refs_not_in_log(struct btrfs_trans_handle *trans,
        return 0;
 }
 
+static int unlink_extrefs_not_in_log(struct btrfs_trans_handle *trans,
+                                    struct btrfs_path *path,
+                                    struct btrfs_root *root,
+                                    struct btrfs_root *log_root,
+                                    struct btrfs_key *search_key,
+                                    struct btrfs_inode *inode,
+                                    u64 inode_objectid,
+                                    u64 parent_objectid)
+{
+       struct extent_buffer *leaf = path->nodes[0];
+       const unsigned long base = btrfs_item_ptr_offset(leaf, path->slots[0]);
+       const u32 item_size = btrfs_item_size(leaf, path->slots[0]);
+       u32 cur_offset = 0;
+
+       while (cur_offset < item_size) {
+               struct btrfs_inode_extref *extref;
+               struct btrfs_inode *victim_parent;
+               struct fscrypt_str victim_name;
+               int ret;
+
+               extref = (struct btrfs_inode_extref *)(base + cur_offset);
+               victim_name.len = btrfs_inode_extref_name_len(leaf, extref);
+
+               if (btrfs_inode_extref_parent(leaf, extref) != parent_objectid)
+                       goto next;
+
+               ret = read_alloc_one_name(leaf, &extref->name, victim_name.len,
+                                         &victim_name);
+               if (ret)
+                       return ret;
+
+               search_key->objectid = inode_objectid;
+               search_key->type = BTRFS_INODE_EXTREF_KEY;
+               search_key->offset = btrfs_extref_hash(parent_objectid,
+                                                      victim_name.name,
+                                                      victim_name.len);
+               ret = backref_in_log(log_root, search_key, parent_objectid, &victim_name);
+               if (ret) {
+                       kfree(victim_name.name);
+                       if (ret < 0)
+                               return ret;
+next:
+                       cur_offset += victim_name.len + sizeof(*extref);
+                       continue;
+               }
+
+               victim_parent = btrfs_iget_logging(parent_objectid, root);
+               if (IS_ERR(victim_parent)) {
+                       kfree(victim_name.name);
+                       return PTR_ERR(victim_parent);
+               }
+
+               inc_nlink(&inode->vfs_inode);
+               btrfs_release_path(path);
+
+               ret = unlink_inode_for_log_replay(trans, victim_parent, inode,
+                                                 &victim_name);
+               iput(&victim_parent->vfs_inode);
+               kfree(victim_name.name);
+               if (ret)
+                       return ret;
+               return -EAGAIN;
+       }
+
+       return 0;
+}
+
 static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
                                  struct btrfs_root *root,
                                  struct btrfs_path *path,
@@ -1104,7 +1171,6 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
                                  u64 ref_index, struct fscrypt_str *name)
 {
        int ret;
-       struct extent_buffer *leaf;
        struct btrfs_dir_item *di;
        struct btrfs_key search_key;
        struct btrfs_inode_extref *extref;
@@ -1139,62 +1205,13 @@ again:
        if (IS_ERR(extref)) {
                return PTR_ERR(extref);
        } else if (extref) {
-               u32 item_size;
-               u32 cur_offset = 0;
-               unsigned long base;
-               struct btrfs_inode *victim_parent;
-
-               leaf = path->nodes[0];
-
-               item_size = btrfs_item_size(leaf, path->slots[0]);
-               base = btrfs_item_ptr_offset(leaf, path->slots[0]);
-
-               while (cur_offset < item_size) {
-                       struct fscrypt_str victim_name;
-
-                       extref = (struct btrfs_inode_extref *)(base + cur_offset);
-                       victim_name.len = btrfs_inode_extref_name_len(leaf, extref);
-
-                       if (btrfs_inode_extref_parent(leaf, extref) != parent_objectid)
-                               goto next;
-
-                       ret = read_alloc_one_name(leaf, &extref->name,
-                                                 victim_name.len, &victim_name);
-                       if (ret)
-                               return ret;
-
-                       search_key.objectid = inode_objectid;
-                       search_key.type = BTRFS_INODE_EXTREF_KEY;
-                       search_key.offset = btrfs_extref_hash(parent_objectid,
-                                                             victim_name.name,
-                                                             victim_name.len);
-                       ret = backref_in_log(log_root, &search_key,
-                                            parent_objectid, &victim_name);
-                       if (ret < 0) {
-                               kfree(victim_name.name);
-                               return ret;
-                       } else if (!ret) {
-                               victim_parent = btrfs_iget_logging(parent_objectid, root);
-                               if (IS_ERR(victim_parent)) {
-                                       ret = PTR_ERR(victim_parent);
-                               } else {
-                                       inc_nlink(&inode->vfs_inode);
-                                       btrfs_release_path(path);
-
-                                       ret = unlink_inode_for_log_replay(trans,
-                                                       victim_parent,
-                                                       inode, &victim_name);
-                                       iput(&victim_parent->vfs_inode);
-                               }
-                               kfree(victim_name.name);
-                               if (ret)
-                                       return ret;
-                               goto again;
-                       }
-                       kfree(victim_name.name);
-next:
-                       cur_offset += victim_name.len + sizeof(*extref);
-               }
+               ret = unlink_extrefs_not_in_log(trans, path, root, log_root,
+                                               &search_key, inode,
+                                               inode_objectid, parent_objectid);
+               if (ret == -EAGAIN)
+                       goto again;
+               else if (ret)
+                       return ret;
        }
        btrfs_release_path(path);