diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2024-04-09 23:53:57 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2025-04-29 13:44:31 -0400 |
commit | cf9d9bb38b6e04462ab01c130fb15b5b360db810 (patch) | |
tree | 1d1eb004a70b1d0f407a0937a1b36092431ded49 | |
parent | fce82ecdd2010b9dda57c6bef6689c66f8a42e93 (diff) |
bcachefs: Path must be locked if trans->locked && path->should_be_locked
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r-- | fs/bcachefs/btree_iter.c | 4 | ||||
-rw-r--r-- | fs/bcachefs/btree_locking.c | 36 | ||||
-rw-r--r-- | fs/bcachefs/btree_locking.h | 11 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_interior.c | 5 |
4 files changed, 33 insertions, 23 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index bfd97d08a15a..56349265970d 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -232,7 +232,7 @@ static void bch2_btree_path_verify(struct btree_trans *trans, bch2_btree_path_verify_level(trans, path, i); } - bch2_btree_path_verify_locks(path); + bch2_btree_path_verify_locks(trans, path); } void bch2_trans_verify_paths(struct btree_trans *trans) @@ -977,7 +977,7 @@ static __always_inline int btree_path_down(struct btree_trans *trans, path->level = level; bch2_btree_path_level_init(trans, path, b); - bch2_btree_path_verify_locks(path); + bch2_btree_path_verify_locks(trans, path); err: bch2_bkey_buf_exit(&tmp, c); return ret; diff --git a/fs/bcachefs/btree_locking.c b/fs/bcachefs/btree_locking.c index 9cd496fc05a1..8b7c6508f8ed 100644 --- a/fs/bcachefs/btree_locking.c +++ b/fs/bcachefs/btree_locking.c @@ -620,7 +620,7 @@ bool bch2_btree_path_upgrade_nounlock(struct btree_trans *trans, } } - bch2_btree_path_verify_locks(path); + bch2_btree_path_verify_locks(trans, path); return path->locks_want == new_locks_want; } @@ -648,8 +648,10 @@ bool __bch2_btree_path_upgrade(struct btree_trans *trans, path->locks_want = new_locks_want; bool ret = btree_path_get_locks(trans, path, true, f); - if (ret) - goto out; + if (ret) { + bch2_trans_verify_locks(trans); + return true; + } /* * XXX: this is ugly - we'd prefer to not be mucking with other @@ -683,9 +685,8 @@ bool __bch2_btree_path_upgrade(struct btree_trans *trans, btree_path_get_locks(trans, linked, true, NULL); } } -out: - bch2_trans_verify_locks(trans); - return ret; + + return false; } void __bch2_btree_path_downgrade(struct btree_trans *trans, @@ -714,7 +715,7 @@ void __bch2_btree_path_downgrade(struct btree_trans *trans, } } - bch2_btree_path_verify_locks(path); + bch2_btree_path_verify_locks(trans, path); trace_path_downgrade(trans, _RET_IP_, path, old_locks_want); } @@ -852,16 +853,17 @@ int __bch2_trans_mutex_lock(struct btree_trans *trans, #ifdef CONFIG_BCACHEFS_DEBUG -void bch2_btree_path_verify_locks(struct btree_path *path) +void bch2_btree_path_verify_locks(struct btree_trans *trans, struct btree_path *path) { - /* - * A path may be uptodate and yet have nothing locked if and only if - * there is no node at path->level, which generally means we were - * iterating over all nodes and got to the end of the btree - */ - BUG_ON(path->uptodate == BTREE_ITER_UPTODATE && - btree_path_node(path, path->level) && - !path->nodes_locked); + if (!path->nodes_locked && btree_path_node(path, path->level)) { + /* + * A path may be uptodate and yet have nothing locked if and only if + * there is no node at path->level, which generally means we were + * iterating over all nodes and got to the end of the btree + */ + BUG_ON(path->uptodate == BTREE_ITER_UPTODATE); + BUG_ON(path->should_be_locked && trans->locked && !trans->restarted); + } if (!path->nodes_locked) return; @@ -904,7 +906,7 @@ void bch2_trans_verify_locks(struct btree_trans *trans) unsigned i; trans_for_each_path(trans, path, i) - bch2_btree_path_verify_locks(path); + bch2_btree_path_verify_locks(trans, path); } #endif diff --git a/fs/bcachefs/btree_locking.h b/fs/bcachefs/btree_locking.h index 568d4794e562..97754cd68a57 100644 --- a/fs/bcachefs/btree_locking.h +++ b/fs/bcachefs/btree_locking.h @@ -14,10 +14,10 @@ #include "six.h" #ifdef CONFIG_BCACHEFS_DEBUG -void bch2_btree_path_verify_locks(struct btree_path *); +void bch2_btree_path_verify_locks(struct btree_trans *, struct btree_path *); void bch2_trans_verify_locks(struct btree_trans *); #else -static inline void bch2_btree_path_verify_locks(struct btree_path *path) {} +static inline void bch2_btree_path_verify_locks(struct btree_trans *, struct btree_path *path) {} static inline void bch2_trans_verify_locks(struct btree_trans *trans) {} #endif @@ -165,6 +165,13 @@ static inline void __bch2_btree_path_unlock(struct btree_trans *trans, btree_node_unlock(trans, path, btree_path_lowest_level_locked(path)); } +static inline void bch2_btree_path_unlock_dontneed(struct btree_trans *trans, + struct btree_path *path) +{ + path->should_be_locked = false; + __bch2_btree_path_unlock(trans, path); +} + /* * Updates the saved lock sequence number, so that bch2_btree_node_relock() will * succeed: diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index 50790a919c52..17772094e43c 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -1611,6 +1611,7 @@ static int btree_split(struct btree_update *as, struct btree_trans *trans, u64 start_time = local_clock(); int ret = 0; + bch2_trans_verify_locks(trans); bch2_verify_btree_nr_keys(b); BUG_ON(!parent && (b != btree_node_root(c, b))); BUG_ON(parent && !btree_node_intent_locked(trans->paths + path, b->c.level + 1)); @@ -1749,11 +1750,11 @@ static int btree_split(struct btree_update *as, struct btree_trans *trans, bch2_trans_node_add(trans, trans->paths + path1, n1); out: if (path2) { - __bch2_btree_path_unlock(trans, trans->paths + path2); + bch2_btree_path_unlock_dontneed(trans, trans->paths + path2); bch2_path_put(trans, path2, true); } if (path1) { - __bch2_btree_path_unlock(trans, trans->paths + path1); + bch2_btree_path_unlock_dontneed(trans, trans->paths + path1); bch2_path_put(trans, path1, true); } |