]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
btrfs: do not handle non-shareable roots in backref cache
authorJosef Bacik <josef@toxicpanda.com>
Thu, 3 Oct 2024 15:43:09 +0000 (11:43 -0400)
committerDavid Sterba <dsterba@suse.com>
Mon, 13 Jan 2025 13:53:15 +0000 (14:53 +0100)
Now that we handle relocation for non-shareable roots without using the
backref cache, remove the ->cowonly field from the backref nodes and
update the handling to throw an error.

Reviewed-by: Boris Burkov <boris@bur.io>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/backref.c
fs/btrfs/backref.h
fs/btrfs/relocation.c

index f686f01cdd9b8b46cca38927a53a3b1c36537630..2e0e36487b332befd0094203fa9557a0febf17ce 100644 (file)
@@ -3314,8 +3314,12 @@ static int handle_indirect_tree_backref(struct btrfs_trans_handle *trans,
        root = btrfs_get_fs_root(fs_info, ref_key->offset, false);
        if (IS_ERR(root))
                return PTR_ERR(root);
-       if (!test_bit(BTRFS_ROOT_SHAREABLE, &root->state))
-               cur->cowonly = 1;
+
+       /* We shouldn't be using backref cache for non-shareable roots. */
+       if (unlikely(!test_bit(BTRFS_ROOT_SHAREABLE, &root->state))) {
+               btrfs_put_root(root);
+               return -EUCLEAN;
+       }
 
        if (btrfs_root_level(&root->root_item) == cur->level) {
                /* Tree root */
@@ -3401,8 +3405,15 @@ static int handle_indirect_tree_backref(struct btrfs_trans_handle *trans,
                                goto out;
                        }
                        upper->owner = btrfs_header_owner(eb);
-                       if (!test_bit(BTRFS_ROOT_SHAREABLE, &root->state))
-                               upper->cowonly = 1;
+
+                       /* We shouldn't be using backref cache for non shareable roots. */
+                       if (unlikely(!test_bit(BTRFS_ROOT_SHAREABLE, &root->state))) {
+                               btrfs_put_root(root);
+                               btrfs_backref_free_edge(cache, edge);
+                               btrfs_backref_free_node(cache, upper);
+                               ret = -EUCLEAN;
+                               goto out;
+                       }
 
                        /*
                         * If we know the block isn't shared we can avoid
@@ -3593,15 +3604,10 @@ int btrfs_backref_finish_upper_links(struct btrfs_backref_cache *cache,
 
        ASSERT(start->checked);
 
-       /* Insert this node to cache if it's not COW-only */
-       if (!start->cowonly) {
-               rb_node = rb_simple_insert(&cache->rb_root, start->bytenr,
-                                          &start->rb_node);
-               if (rb_node)
-                       btrfs_backref_panic(cache->fs_info, start->bytenr,
-                                           -EEXIST);
-               list_add_tail(&start->lower, &cache->leaves);
-       }
+       rb_node = rb_simple_insert(&cache->rb_root, start->bytenr, &start->rb_node);
+       if (rb_node)
+               btrfs_backref_panic(cache->fs_info, start->bytenr, -EEXIST);
+       list_add_tail(&start->lower, &cache->leaves);
 
        /*
         * Use breadth first search to iterate all related edges.
@@ -3655,23 +3661,13 @@ int btrfs_backref_finish_upper_links(struct btrfs_backref_cache *cache,
                        return -EUCLEAN;
                }
 
-               /* Sanity check, COW-only node has non-COW-only parent */
-               if (start->cowonly != upper->cowonly) {
-                       ASSERT(0);
+               rb_node = rb_simple_insert(&cache->rb_root, upper->bytenr,
+                                          &upper->rb_node);
+               if (unlikely(rb_node)) {
+                       btrfs_backref_panic(cache->fs_info, upper->bytenr, -EEXIST);
                        return -EUCLEAN;
                }
 
-               /* Only cache non-COW-only (subvolume trees) tree blocks */
-               if (!upper->cowonly) {
-                       rb_node = rb_simple_insert(&cache->rb_root, upper->bytenr,
-                                                  &upper->rb_node);
-                       if (rb_node) {
-                               btrfs_backref_panic(cache->fs_info,
-                                               upper->bytenr, -EEXIST);
-                               return -EUCLEAN;
-                       }
-               }
-
                list_add_tail(&edge->list[UPPER], &upper->lower);
 
                /*
index 7220bde1fc31c009098cd3c33ae0dbf1a6431196..c52bc5f450414c146f1d64a47f4a04dfc260bd95 100644 (file)
@@ -341,8 +341,6 @@ struct btrfs_backref_node {
        struct extent_buffer *eb;
        /* Level of the tree block */
        unsigned int level:8;
-       /* Is the block in a non-shareable tree */
-       unsigned int cowonly:1;
        /* 1 if no child node is in the cache */
        unsigned int lowest:1;
        /* Is the extent buffer locked */
index c8f35d456a612276765d2a3b4a574e5844cb0d50..fe4e2528c8061d6e1061d544901cc550f67e4a04 100644 (file)
@@ -2542,7 +2542,7 @@ static int relocate_tree_block(struct btrfs_trans_handle *trans,
                ret = do_relocation(trans, rc, node, key, path, 1);
        }
 out:
-       if (ret || node->level == 0 || node->cowonly)
+       if (ret || node->level == 0)
                btrfs_backref_cleanup_node(&rc->backref_cache, node);
        return ret;
 }