btrfs: introduce BTRFS_NESTING_LEFT/BTRFS_NESTING_RIGHT
authorJosef Bacik <josef@toxicpanda.com>
Thu, 20 Aug 2020 15:46:04 +0000 (11:46 -0400)
committerDavid Sterba <dsterba@suse.com>
Wed, 7 Oct 2020 10:12:16 +0000 (12:12 +0200)
Our lockdep maps are based on rootid+level, however in some cases we
will lock adjacent blocks on the same level, namely in searching forward
or in split/balance.  Because of this lockdep will complain, so we need
a separate subclass to indicate to lockdep that these are different
locks.

lock leaf -> BTRFS_NESTING_NORMAL
  cow leaf -> BTRFS_NESTING_COW
    split leaf
       lock left -> BTRFS_NESTING_LEFT
       lock right -> BTRFS_NESTING_RIGHT

The above graph illustrates the need for this new nesting subclass.

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 48178fd..94af1f3 100644 (file)
@@ -1896,7 +1896,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
                left = NULL;
 
        if (left) {
-               btrfs_tree_lock(left);
+               __btrfs_tree_lock(left, BTRFS_NESTING_LEFT);
                btrfs_set_lock_blocking_write(left);
                wret = btrfs_cow_block(trans, root, left,
                                       parent, pslot - 1, &left,
@@ -1912,7 +1912,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
                right = NULL;
 
        if (right) {
-               btrfs_tree_lock(right);
+               __btrfs_tree_lock(right, BTRFS_NESTING_RIGHT);
                btrfs_set_lock_blocking_write(right);
                wret = btrfs_cow_block(trans, root, right,
                                       parent, pslot + 1, &right,
@@ -2076,7 +2076,7 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans,
        if (left) {
                u32 left_nr;
 
-               btrfs_tree_lock(left);
+               __btrfs_tree_lock(left, BTRFS_NESTING_LEFT);
                btrfs_set_lock_blocking_write(left);
 
                left_nr = btrfs_header_nritems(left);
@@ -2131,7 +2131,7 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans,
        if (right) {
                u32 right_nr;
 
-               btrfs_tree_lock(right);
+               __btrfs_tree_lock(right, BTRFS_NESTING_RIGHT);
                btrfs_set_lock_blocking_write(right);
 
                right_nr = btrfs_header_nritems(right);
@@ -3806,7 +3806,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
        if (IS_ERR(right))
                return 1;
 
-       btrfs_tree_lock(right);
+       __btrfs_tree_lock(right, BTRFS_NESTING_RIGHT);
        btrfs_set_lock_blocking_write(right);
 
        free_space = btrfs_leaf_free_space(right);
@@ -4045,7 +4045,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
        if (IS_ERR(left))
                return 1;
 
-       btrfs_tree_lock(left);
+       __btrfs_tree_lock(left, BTRFS_NESTING_LEFT);
        btrfs_set_lock_blocking_write(left);
 
        free_space = btrfs_leaf_free_space(left);
@@ -5467,7 +5467,7 @@ again:
                        if (!ret) {
                                btrfs_set_path_blocking(path);
                                __btrfs_tree_read_lock(next,
-                                                      BTRFS_NESTING_NORMAL,
+                                                      BTRFS_NESTING_RIGHT,
                                                       path->recurse);
                        }
                        next_rw_lock = BTRFS_READ_LOCK;
@@ -5504,7 +5504,7 @@ again:
                        if (!ret) {
                                btrfs_set_path_blocking(path);
                                __btrfs_tree_read_lock(next,
-                                                      BTRFS_NESTING_NORMAL,
+                                                      BTRFS_NESTING_RIGHT,
                                                       path->recurse);
                        }
                        next_rw_lock = BTRFS_READ_LOCK;
index 8b47ba3..5844bc1 100644 (file)
@@ -32,6 +32,18 @@ enum btrfs_lock_nesting {
         */
        BTRFS_NESTING_COW,
 
+       /*
+        * Oftentimes we need to lock adjacent nodes on the same level while
+        * still holding the lock on the original node we searched to, such as
+        * for searching forward or for split/balance.
+        *
+        * Because of this we need to indicate to lockdep that this is
+        * acceptable by having a different subclass for each of these
+        * operations.
+        */
+       BTRFS_NESTING_LEFT,
+       BTRFS_NESTING_RIGHT,
+
        /*
         * 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