btrfs: introduce BTRFS_NESTING_NEW_ROOT for adding new roots
authorJosef Bacik <josef@toxicpanda.com>
Thu, 20 Aug 2020 15:46:07 +0000 (11:46 -0400)
committerDavid Sterba <dsterba@suse.com>
Wed, 7 Oct 2020 10:12:17 +0000 (12:12 +0200)
The way we add new roots is confusing from a locking perspective for
lockdep.  We generally have the rule that we lock things in order from
highest level to lowest, but in the case of adding a new level to the
tree we actually allocate a new block for the root, which makes the
locking go in reverse.  A similar issue exists for snapshotting, we cow
the original root for the root of a new tree, however they're at the
same level.  Address this by using BTRFS_NESTING_NEW_ROOT for these
operations.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/ctree.c
fs/btrfs/locking.h

index 884c8b5a0e626d3037934236e2929233710664fe..d61ea238ad8a17ea51e2960f46b0560e7d164c22 100644 (file)
@@ -198,7 +198,8 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans,
                btrfs_node_key(buf, &disk_key, 0);
 
        cow = btrfs_alloc_tree_block(trans, root, 0, new_root_objectid,
-                       &disk_key, level, buf->start, 0, BTRFS_NESTING_NORMAL);
+                                    &disk_key, level, buf->start, 0,
+                                    BTRFS_NESTING_NEW_ROOT);
        if (IS_ERR(cow))
                return PTR_ERR(cow);
 
@@ -3407,7 +3408,7 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
 
        c = alloc_tree_block_no_bg_flush(trans, root, 0, &lower_key, level,
                                         root->node->start, 0,
-                                        BTRFS_NESTING_NORMAL);
+                                        BTRFS_NESTING_NEW_ROOT);
        if (IS_ERR(c))
                return PTR_ERR(c);
 
index a6b59808e04609e9f5c9cc0c56b1e3e6576efe12..3ea81ed3320b5fa8c448177fbbf9de89d21209fe 100644 (file)
@@ -61,6 +61,15 @@ enum btrfs_lock_nesting {
         */
        BTRFS_NESTING_SPLIT,
 
+       /*
+        * When promoting a new block to a root we need to have a special
+        * subclass so we don't confuse lockdep, as it will appear that we are
+        * locking a higher level node before a lower level one.  Copying also
+        * has this problem as it appears we're locking the same block again
+        * when we make a snapshot of an existing root.
+        */
+       BTRFS_NESTING_NEW_ROOT,
+
        /*
         * We are limited to MAX_LOCKDEP_SUBLCLASSES number of subclasses, so
         * add this in here and add a static_assert to keep us from going over