From 86b74451931790eafa018021fe900faea3230189 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 5 Aug 2022 11:36:13 -0400 Subject: [PATCH] bcachefs: Fix bch2_btree_trans_to_text() 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 --- fs/bcachefs/btree_iter.c | 18 ++++++++---------- fs/bcachefs/btree_locking.h | 2 +- fs/bcachefs/btree_types.h | 2 +- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index 01ca27ee6314d..171894d9347d4 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -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"); } } diff --git a/fs/bcachefs/btree_locking.h b/fs/bcachefs/btree_locking.h index 33a69e27c39e7..9d4e1a658eef0 100644 --- a/fs/bcachefs/btree_locking.h +++ b/fs/bcachefs/btree_locking.h @@ -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; diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h index bc1571fc2f1f0..1c70dff591a2f 100644 --- a/fs/bcachefs/btree_types.h +++ b/fs/bcachefs/btree_types.h @@ -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; -- 2.30.2