Skip to content

Commit 375476c

Browse files
author
Kent Overstreet
committed
bcachefs: Add lockdep support for btree node locks
This adds lockdep tracking for held btree locks with a single dep_map in btree_trans, i.e. tracking all held btree locks as one object. This is more practical and more useful than having lockdep track held btree locks individually, because - we can take more locks than lockdep can track (unbounded, now that we have dynamically resizable btree paths) - there's no lock ordering between btree locks for lockdep to track (we do cycle detection) - and this makes it easy to teach lockdep that btree locks are not safe to hold while invoking memory reclaim. The last rule is one that lockdep would never learn, because we only do trylock() from within shrinkers - but we very much do not want to be invoking memory reclaim while holding btree node locks. Signed-off-by: Kent Overstreet <[email protected]>
1 parent 1a616c2 commit 375476c

File tree

3 files changed

+26
-3
lines changed

3 files changed

+26
-3
lines changed

fs/bcachefs/btree_iter.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3171,6 +3171,9 @@ struct btree_trans *__bch2_trans_get(struct bch_fs *c, unsigned fn_idx)
31713171

31723172
trans->paths_allocated[0] = 1;
31733173

3174+
static struct lock_class_key lockdep_key;
3175+
lockdep_init_map(&trans->dep_map, "bcachefs_btree", &lockdep_key, 0);
3176+
31743177
if (fn_idx < BCH_TRANSACTIONS_NR) {
31753178
trans->fn = bch2_btree_transaction_fns[fn_idx];
31763179

@@ -3440,7 +3443,22 @@ int bch2_fs_btree_iter_init(struct bch_fs *c)
34403443
mempool_init_kmalloc_pool(&c->btree_trans_mem_pool, 1,
34413444
BTREE_TRANS_MEM_MAX) ?:
34423445
init_srcu_struct(&c->btree_trans_barrier);
3443-
if (!ret)
3444-
c->btree_trans_barrier_initialized = true;
3445-
return ret;
3446+
if (ret)
3447+
return ret;
3448+
3449+
/*
3450+
* static annotation (hackily done) for lock ordering of reclaim vs.
3451+
* btree node locks:
3452+
*/
3453+
#ifdef CONFIG_LOCKDEP
3454+
fs_reclaim_acquire(GFP_KERNEL);
3455+
struct btree_trans *trans = bch2_trans_get(c);
3456+
trans_set_locked(trans);
3457+
bch2_trans_put(trans);
3458+
fs_reclaim_release(GFP_KERNEL);
3459+
#endif
3460+
3461+
c->btree_trans_barrier_initialized = true;
3462+
return 0;
3463+
34463464
}

fs/bcachefs/btree_locking.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ int bch2_six_check_for_deadlock(struct six_lock *lock, void *p);
197197
static inline void trans_set_locked(struct btree_trans *trans)
198198
{
199199
if (!trans->locked) {
200+
lock_acquire_exclusive(&trans->dep_map, 0, 0, NULL, _THIS_IP_);
200201
trans->locked = true;
201202
trans->last_unlock_ip = 0;
202203

@@ -208,6 +209,7 @@ static inline void trans_set_locked(struct btree_trans *trans)
208209
static inline void trans_set_unlocked(struct btree_trans *trans)
209210
{
210211
if (trans->locked) {
212+
lock_release(&trans->dep_map, _THIS_IP_);
211213
trans->locked = false;
212214
trans->last_unlock_ip = _RET_IP_;
213215

fs/bcachefs/btree_types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,9 @@ struct btree_trans {
523523
unsigned journal_u64s;
524524
unsigned extra_disk_res; /* XXX kill */
525525

526+
#ifdef CONFIG_DEBUG_LOCK_ALLOC
527+
struct lockdep_map dep_map;
528+
#endif
526529
/* Entries before this are zeroed out on every bch2_trans_get() call */
527530

528531
struct list_head list;

0 commit comments

Comments
 (0)