mirror of
https://github.com/versity/scoutfs.git
synced 2026-06-09 05:02:35 +00:00
scoutfs: fix depth-first radix next bit search
The radix block next bit search could return a spurious -ENOENT if it ran out of references in a parent block further down the tree. It needs to bubble up to try the next ref in its parent so that it keeps performing a depth-first search of the entire tree. This lead to an assertion being tripped in _radix_merge. Getting an early -ENOENT caused it to start searching from 0 again. When it's iterating over a read-only input it could find the same leaf and try to clear source bits that were already cleared. Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
@@ -901,9 +901,29 @@ static int get_path(struct super_block *sb, struct scoutfs_radix_root *root,
|
||||
ind++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Didn't find a ref in the rest of the block at
|
||||
* this level. If we're the root block there's no
|
||||
* more next bits to return. If we're further down
|
||||
* we bubble up a level and continue on a depth-first
|
||||
* search. We check the next ref from our parent and reset
|
||||
* all the child inds to the left spine of the new
|
||||
* subtree.
|
||||
*/
|
||||
if (ind >= SCOUTFS_RADIX_REFS) {
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
if (level == root->height - 1) {
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
path->inds[level + 1]++;
|
||||
for (i = level; i >= 0; i--)
|
||||
path->inds[i] = 0;
|
||||
for (i = level; i <= level + 1; i++) {
|
||||
scoutfs_block_put(sb, path->bls[i]);
|
||||
path->bls[i] = NULL;
|
||||
}
|
||||
level += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* reset all lower indices if we searched */
|
||||
|
||||
Reference in New Issue
Block a user