mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 14:12:06 +00:00
bcachefs: More btree iterator fixes
- check for getting to the end of the btree in bch2_path_verify_locks and __btree_path_traverse_all(), this fixes an infinite loop in __btree_path_traverse_all(). - relax requirement in bch2_btree_node_upgrade() that we must want an intent lock, this fixes bugs with paths that point to interior nodes (nonzero level). - bch2_btree_node_update_key(): fix it to upgrade the path to an intent lock, if necessary Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
This commit is contained in:
parent
502027a8b2
commit
d697b9abba
@ -170,11 +170,20 @@ static bool bch2_btree_node_upgrade(struct btree_trans *trans,
|
||||
{
|
||||
struct btree *b = path->l[level].b;
|
||||
|
||||
EBUG_ON(btree_lock_want(path, level) != BTREE_NODE_INTENT_LOCKED);
|
||||
|
||||
if (!is_btree_node(path, level))
|
||||
return false;
|
||||
|
||||
switch (btree_lock_want(path, level)) {
|
||||
case BTREE_NODE_UNLOCKED:
|
||||
BUG_ON(btree_node_locked(path, level));
|
||||
return true;
|
||||
case BTREE_NODE_READ_LOCKED:
|
||||
BUG_ON(btree_node_intent_locked(path, level));
|
||||
return bch2_btree_node_relock(trans, path, level);
|
||||
case BTREE_NODE_INTENT_LOCKED:
|
||||
break;
|
||||
}
|
||||
|
||||
if (btree_node_intent_locked(path, level))
|
||||
return true;
|
||||
|
||||
@ -368,7 +377,8 @@ static void bch2_btree_path_verify_locks(struct btree_path *path)
|
||||
unsigned l;
|
||||
|
||||
if (!path->nodes_locked) {
|
||||
BUG_ON(path->uptodate == BTREE_ITER_UPTODATE);
|
||||
BUG_ON(path->uptodate == BTREE_ITER_UPTODATE &&
|
||||
btree_path_node(path, path->level));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1356,7 +1366,8 @@ retry_all:
|
||||
|
||||
EBUG_ON(!(trans->paths_allocated & (1ULL << path->idx)));
|
||||
|
||||
if (path->nodes_locked)
|
||||
if (path->nodes_locked ||
|
||||
!btree_path_node(path, path->level))
|
||||
i++;
|
||||
}
|
||||
|
||||
|
@ -1945,9 +1945,16 @@ int bch2_btree_node_update_key(struct btree_trans *trans, struct btree_iter *ite
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
struct btree *new_hash = NULL;
|
||||
struct btree_path *path = iter->path;
|
||||
struct closure cl;
|
||||
int ret = 0;
|
||||
|
||||
if (!btree_node_intent_locked(path, b->c.level) &&
|
||||
!bch2_btree_path_upgrade(trans, path, b->c.level + 1)) {
|
||||
btree_trans_restart(trans);
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
closure_init_stack(&cl);
|
||||
|
||||
/*
|
||||
@ -1966,8 +1973,10 @@ int bch2_btree_node_update_key(struct btree_trans *trans, struct btree_iter *ite
|
||||
new_hash = bch2_btree_node_mem_alloc(c);
|
||||
}
|
||||
|
||||
path->intent_ref++;
|
||||
ret = __bch2_btree_node_update_key(trans, iter, b, new_hash,
|
||||
new_key, skip_triggers);
|
||||
--path->intent_ref;
|
||||
|
||||
if (new_hash) {
|
||||
mutex_lock(&c->btree_cache.lock);
|
||||
|
Loading…
Reference in New Issue
Block a user