]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bcachefs: Fix bch2_btree_trans_to_text()
authorKent Overstreet <kent.overstreet@gmail.com>
Fri, 5 Aug 2022 15:36:13 +0000 (11:36 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:37 +0000 (17:09 -0400)
bch2_btree_trans_to_text() is used to print btree_transactions owned by
other threads; thus, it needs to be particularly careful. This fixes a
null ptr deref caused by racing with the owning thread changing
path->l[].b.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
fs/bcachefs/btree_iter.c
fs/bcachefs/btree_locking.h
fs/bcachefs/btree_types.h

index 01ca27ee6314d588fc1449acf142ec2da2f496bd..171894d9347d47cb70aa51346ff96d32dbb3d5a2 100644 (file)
@@ -3417,19 +3417,19 @@ void bch2_trans_exit(struct btree_trans *trans)
 
 static void __maybe_unused
 bch2_btree_path_node_to_text(struct printbuf *out,
-                            struct btree_bkey_cached_common *_b,
+                            struct btree_bkey_cached_common *b,
                             bool cached)
 {
        prt_printf(out, "    l=%u %s:",
-              _b->level, bch2_btree_ids[_b->btree_id]);
-       bch2_bpos_to_text(out, btree_node_pos(_b, cached));
+              b->level, bch2_btree_ids[b->btree_id]);
+       bch2_bpos_to_text(out, btree_node_pos(b, cached));
 }
 
 #ifdef CONFIG_BCACHEFS_DEBUG_TRANSACTIONS
 void bch2_btree_trans_to_text(struct printbuf *out, struct btree_trans *trans)
 {
        struct btree_path *path;
-       struct btree *b;
+       struct btree_bkey_cached_common *b;
        static char lock_types[] = { 'r', 'i', 'w' };
        unsigned l;
 
@@ -3448,12 +3448,11 @@ void bch2_btree_trans_to_text(struct printbuf *out, struct btree_trans *trans)
                prt_printf(out, "\n");
 
                for (l = 0; l < BTREE_MAX_DEPTH; l++) {
-                       if (btree_node_locked(path, l)) {
+                       if (btree_node_locked(path, l) &&
+                           (unsigned long) (b = (void *) READ_ONCE(path->l[l].b)) >= 128) {
                                prt_printf(out, "    %s l=%u ",
                                       btree_node_intent_locked(path, l) ? "i" : "r", l);
-                               bch2_btree_path_node_to_text(out,
-                                               (void *) path->l[l].b,
-                                               path->cached);
+                               bch2_btree_path_node_to_text(out, b, path->cached);
                                prt_printf(out, "\n");
                        }
                }
@@ -3471,8 +3470,7 @@ void bch2_btree_trans_to_text(struct printbuf *out, struct btree_trans *trans)
                bch2_bpos_to_text(out, trans->locking_pos);
 
                prt_printf(out, " node ");
-               bch2_btree_path_node_to_text(out,
-                               (void *) b, path->cached);
+               bch2_btree_path_node_to_text(out, b, path->cached);
                prt_printf(out, "\n");
        }
 }
index 33a69e27c39e7889447abe8c9d4611a13ac26b1d..9d4e1a658eef06b15736466eb3e1baff1d3de1f3 100644 (file)
@@ -173,7 +173,7 @@ static inline int btree_node_lock_type(struct btree_trans *trans,
        trans->locking_btree_id = path->btree_id;
        trans->locking_level    = level;
        trans->locking_lock_type = type;
-       trans->locking          = b;
+       trans->locking          = &b->c;
        ret = six_lock_type(&b->c.lock, type, should_sleep_fn, p);
        trans->locking = NULL;
 
index bc1571fc2f1f0bafd63cb738538c0b9974066349..1c70dff591a2f90a08f4cd7f845dc82fe702a8a0 100644 (file)
@@ -392,7 +392,7 @@ struct btree_trans {
        const char              *fn;
        struct list_head        list;
        u64                     last_begin_time;
-       struct btree            *locking;
+       struct btree_bkey_cached_common *locking;
        unsigned                locking_path_idx;
        struct bpos             locking_pos;
        u8                      locking_btree_id;