diff options
-rw-r--r-- | fs/bcachefs/btree_iter.c | 21 | ||||
-rw-r--r-- | fs/bcachefs/btree_locking.c | 14 | ||||
-rw-r--r-- | fs/bcachefs/btree_locking.h | 9 | ||||
-rw-r--r-- | fs/bcachefs/btree_types.h | 6 |
4 files changed, 45 insertions, 5 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index 47d203cdb7b2..f1f4efc94589 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -2976,6 +2976,9 @@ got_trans: trans->paths_allocated[0] = 1; + static struct lock_class_key lockdep_key; + lockdep_init_map(&trans->dep_map, "bcachefs_btree", &lockdep_key, 0); + if (fn_idx < BCH_TRANSACTIONS_NR) { trans->fn = bch2_btree_transaction_fns[fn_idx]; @@ -3236,7 +3239,19 @@ int bch2_fs_btree_iter_init(struct bch_fs *c) mempool_init_kmalloc_pool(&c->btree_trans_mem_pool, 1, BTREE_TRANS_MEM_MAX) ?: init_srcu_struct(&c->btree_trans_barrier); - if (!ret) - c->btree_trans_barrier_initialized = true; - return ret; + if (ret) + return ret; + +#ifdef CONFIG_LOCKDEP + fs_reclaim_acquire(GFP_KERNEL); + struct btree_trans *trans = bch2_trans_get(c); + lock_acquire_exclusive(&trans->dep_map, 0, 0, NULL, _THIS_IP_); + trans->locks_held = true; + bch2_trans_put(trans); + fs_reclaim_release(GFP_KERNEL); + +#endif + c->btree_trans_barrier_initialized = true; + return 0; + } diff --git a/fs/bcachefs/btree_locking.c b/fs/bcachefs/btree_locking.c index 1ed8327a9fa2..a5ae421073d0 100644 --- a/fs/bcachefs/btree_locking.c +++ b/fs/bcachefs/btree_locking.c @@ -786,6 +786,13 @@ void bch2_trans_unlock_noassert(struct btree_trans *trans) trans_for_each_path(trans, path, i) __bch2_btree_path_unlock(trans, path); + +#ifdef CONFIG_LOCKDEP + if (trans->locks_held) { + lock_release(&trans->dep_map, _THIS_IP_); + trans->locks_held = false; + } +#endif } void bch2_trans_unlock(struct btree_trans *trans) @@ -795,6 +802,13 @@ void bch2_trans_unlock(struct btree_trans *trans) trans_for_each_path(trans, path, i) __bch2_btree_path_unlock(trans, path); + +#ifdef CONFIG_LOCKDEP + if (trans->locks_held) { + lock_release(&trans->dep_map, _THIS_IP_); + trans->locks_held = false; + } +#endif } void bch2_trans_unlock_long(struct btree_trans *trans) diff --git a/fs/bcachefs/btree_locking.h b/fs/bcachefs/btree_locking.h index 64810ea544c9..962fa8f5cf0b 100644 --- a/fs/bcachefs/btree_locking.h +++ b/fs/bcachefs/btree_locking.h @@ -202,13 +202,18 @@ static inline int __btree_node_lock_nopath(struct btree_trans *trans, bool lock_may_not_fail, unsigned long ip) { - int ret; +#ifdef CONFIG_LOCKDEP + if (!trans->locks_held) { + lock_acquire_exclusive(&trans->dep_map, 0, 0, NULL, ip); + trans->locks_held = true; + } +#endif trans->lock_may_not_fail = lock_may_not_fail; trans->lock_must_abort = false; trans->locking = b; - ret = six_lock_ip_waiter(&b->lock, type, &trans->locking_wait, + int ret = six_lock_ip_waiter(&b->lock, type, &trans->locking_wait, bch2_six_check_for_deadlock, trans, ip); WRITE_ONCE(trans->locking, NULL); WRITE_ONCE(trans->locking_wait.start_time, 0); diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h index e4ebfc25df8e..b2d428bbcf73 100644 --- a/fs/bcachefs/btree_types.h +++ b/fs/bcachefs/btree_types.h @@ -397,6 +397,9 @@ struct btree_trans { u8 lock_must_abort; bool lock_may_not_fail:1; bool srcu_held:1; +#ifdef CONFIG_LOCKDEP + bool locks_held:1; +#endif bool used_mempool:1; bool in_traverse_all:1; bool paths_sorted:1; @@ -433,6 +436,9 @@ struct btree_trans { unsigned extra_disk_res; /* XXX kill */ struct replicas_delta_list *fs_usage_deltas; +#ifdef CONFIG_DEBUG_LOCK_ALLOC + struct lockdep_map dep_map; +#endif /* Entries before this are zeroed out on every bch2_trans_get() call */ struct list_head list; |