? path->l[l].b->c.lock.state.seq
: 0);
fail_idx = l;
- btree_path_set_dirty(path, BTREE_ITER_NEED_TRAVERSE);
}
l++;
* can't be relocked so bch2_btree_path_traverse has to walk back up to
* the node that we failed to relock:
*/
- while (fail_idx >= 0) {
- btree_node_unlock(path, fail_idx);
- path->l[fail_idx].b = BTREE_ITER_NO_NODE_GET_LOCKS;
- --fail_idx;
+ if (fail_idx >= 0) {
+ __bch2_btree_path_unlock(path);
+ btree_path_set_dirty(path, BTREE_ITER_NEED_TRAVERSE);
+
+ do {
+ path->l[fail_idx].b = BTREE_ITER_NO_NODE_GET_LOCKS;
+ --fail_idx;
+ } while (fail_idx >= 0);
}
if (path->uptodate == BTREE_ITER_NEED_RELOCK)
{
unsigned l;
- for (l = 0; btree_path_node(path, l); l++) {
- if (path->uptodate >= BTREE_ITER_NEED_RELOCK &&
- !btree_node_locked(path, l))
- continue;
+ if (!path->nodes_locked) {
+ BUG_ON(path->uptodate == BTREE_ITER_UPTODATE);
+ return;
+ }
+ for (l = 0; btree_path_node(path, l); l++)
BUG_ON(btree_lock_want(path, l) !=
btree_node_locked_type(path, l));
- }
}
void bch2_trans_verify_locks(struct btree_trans *trans)
is_btree_node(path, l)
? path->l[l].b->c.lock.state.seq
: 0);
+ __bch2_btree_path_unlock(path);
btree_path_set_dirty(path, BTREE_ITER_NEED_TRAVERSE);
btree_trans_restart(trans);
return false;
{
struct btree_path *path;
- if (!bch2_debug_check_iterators)
- return;
-
trans_for_each_path(trans, path)
bch2_btree_path_verify(trans, path);
}
}
if (!parent_locked)
- btree_node_unlock(path, b->c.level + 1);
+ btree_node_unlock(path, plevel);
}
static inline void __btree_path_level_init(struct btree_path *path,
*/
void bch2_trans_node_add(struct btree_trans *trans, struct btree *b)
{
- enum btree_node_locked_type t;
struct btree_path *path;
trans_for_each_path(trans, path)
if (!path->cached &&
btree_path_pos_in_node(path, b)) {
- /*
- * bch2_btree_path_node_drop() has already been called -
- * the old node we're replacing has already been
- * unlocked and the pointer invalidated
- */
- BUG_ON(btree_node_locked(path, b->c.level));
+ enum btree_node_locked_type t =
+ btree_lock_want(path, b->c.level);
- t = btree_lock_want(path, b->c.level);
- if (t != BTREE_NODE_UNLOCKED) {
+ if (path->nodes_locked &&
+ t != BTREE_NODE_UNLOCKED) {
+ btree_node_unlock(path, b->c.level);
six_lock_increment(&b->c.lock, (enum six_lock_type) t);
mark_btree_node_locked(trans, path, b->c.level, (enum six_lock_type) t);
}
}
}
-void bch2_trans_node_drop(struct btree_trans *trans, struct btree *b)
-{
- struct btree_path *path;
- unsigned level = b->c.level;
-
- trans_for_each_path(trans, path)
- if (path->l[level].b == b) {
- btree_node_unlock(path, level);
- path->l[level].b = BTREE_ITER_NO_NODE_DROP;
- }
-}
-
/*
* A btree node has been modified in such a way as to invalidate iterators - fix
* them:
{
unsigned l = path->level;
+ if (!path->nodes_locked)
+ btree_path_get_locks(trans, path, false, _THIS_IP_);
+
while (btree_path_node(path, l) &&
!btree_path_good_node(trans, path, l, check_pos)) {
btree_node_unlock(path, l);
if (cmp < 0 ||
!btree_path_advance_to_pos(path, &path->l[l], 8))
__btree_path_level_init(path, l);
-
- /* Don't leave it locked if we're not supposed to: */
- if (btree_lock_want(path, l) == BTREE_NODE_UNLOCKED)
- btree_node_unlock(path, l);
}
- if (l != path->level)
+ if (l != path->level) {
btree_path_set_dirty(path, BTREE_ITER_NEED_TRAVERSE);
+ __bch2_btree_path_unlock(path);
+ }
out:
bch2_btree_path_verify(trans, path);
#ifdef CONFIG_BCACHEFS_DEBUG
if (!path->nodes_locked)
continue;
- pr_buf(out, " path %u %c %s:",
+ pr_buf(out, " path %u %c l=%u %s:",
path->idx,
path->cached ? 'c' : 'b',
+ path->level,
bch2_btree_ids[path->btree_id]);
bch2_bpos_to_text(out, path->pos);
pr_buf(out, "\n");
/* Successful split, update the path to point to the new nodes: */
six_lock_increment(&b->c.lock, SIX_LOCK_intent);
- bch2_trans_node_drop(trans, b);
if (n3)
bch2_trans_node_add(trans, n3);
if (n2)
bch2_keylist_add(&as->parent_keys, &delete);
bch2_keylist_add(&as->parent_keys, &n->key);
+ bch2_trans_verify_paths(trans);
+
bch2_btree_insert_node(as, trans, path, parent, &as->parent_keys, flags);
+ bch2_trans_verify_paths(trans);
+
bch2_btree_update_get_open_buckets(as, n);
six_lock_increment(&b->c.lock, SIX_LOCK_intent);
six_lock_increment(&m->c.lock, SIX_LOCK_intent);
- bch2_trans_node_drop(trans, b);
- bch2_trans_node_drop(trans, m);
bch2_trans_node_add(trans, n);
bch2_btree_update_get_open_buckets(as, n);
six_lock_increment(&b->c.lock, SIX_LOCK_intent);
- bch2_trans_node_drop(trans, b);
bch2_trans_node_add(trans, n);
bch2_btree_node_free_inmem(trans, b);
six_unlock_intent(&n->c.lock);