diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2021-11-03 12:08:02 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:09:15 -0400 |
commit | f527afea5a2f3c2645080584dafeb6cc5314b652 (patch) | |
tree | e3efcef9f65c35e6016631e08327bc29678fd9d1 | |
parent | d7407292723ea79028afe6729432602ced243972 (diff) |
bcachefs: Fix upgrade_readers()
The bch2_btree_path_upgrade() call was failing and tripping an assert -
path->level + 1 is in this case not necessarily exactly what we want,
fix it by upgrading exactly the locks we want.
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r-- | fs/bcachefs/btree_iter.c | 4 | ||||
-rw-r--r-- | fs/bcachefs/btree_iter.h | 3 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_leaf.c | 11 |
3 files changed, 15 insertions, 3 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index 806663799a08..2c28e65fdeb5 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -180,8 +180,8 @@ bool __bch2_btree_node_relock(struct btree_trans *trans, } } -static bool bch2_btree_node_upgrade(struct btree_trans *trans, - struct btree_path *path, unsigned level) +bool bch2_btree_node_upgrade(struct btree_trans *trans, + struct btree_path *path, unsigned level) { struct btree *b = path->l[level].b; diff --git a/fs/bcachefs/btree_iter.h b/fs/bcachefs/btree_iter.h index 16fa0fe1c5b7..64a3969db263 100644 --- a/fs/bcachefs/btree_iter.h +++ b/fs/bcachefs/btree_iter.h @@ -192,6 +192,9 @@ static inline int btree_trans_restart(struct btree_trans *trans) return -EINTR; } +bool bch2_btree_node_upgrade(struct btree_trans *, + struct btree_path *, unsigned); + bool __bch2_btree_path_upgrade(struct btree_trans *, struct btree_path *, unsigned); diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c index 8b4933add017..43ae2d83cfa7 100644 --- a/fs/bcachefs/btree_update_leaf.c +++ b/fs/bcachefs/btree_update_leaf.c @@ -507,6 +507,15 @@ err: return ret; } +static inline void path_upgrade_readers(struct btree_trans *trans, struct btree_path *path) +{ + unsigned l; + + for (l = 0; l < BTREE_MAX_DEPTH; l++) + if (btree_node_read_locked(path, l)) + BUG_ON(!bch2_btree_node_upgrade(trans, path, l)); +} + static inline void upgrade_readers(struct btree_trans *trans, struct btree_path *path) { struct btree *b = path_l(path)->b; @@ -514,7 +523,7 @@ static inline void upgrade_readers(struct btree_trans *trans, struct btree_path do { if (path->nodes_locked && path->nodes_locked != path->nodes_intent_locked) - BUG_ON(!bch2_btree_path_upgrade(trans, path, path->level + 1)); + path_upgrade_readers(trans, path); } while ((path = prev_btree_path(trans, path)) && path_l(path)->b == b); } |