Skip to content

Commit 4f8d7a0

Browse files
Sun YangKaikdave
authored andcommitted
btrfs: fix nonzero lowest level handling in btrfs_search_forward()
Commit 323ac95 ("Btrfs: don't read leaf blocks containing only checksums during truncate") changed the condition from `level == 0` to `level == path->lowest_level`, while its origional purpose is just to do some leaf nodes handling (calling btrfs_item_key_to_cpu()) and skip some code that doesn't fit leaf nodes. After changing the condition, the code path 1. also handle the non-leaf nodes when path->lowest_level is nonzero, which is wrong. However, it seems that btrfs_search_forward() is never called with a nonzero path->lowest_level, which makes this bug not found before. 2. makes the later if block with the same condition, which is origionally used to handle non-leaf node (calling btrfs_node_key_to_cpu()) when lowest_level is not zero, dead code. So Use if conditions to skip the non-leaf handling code instead of using goto to make it more clear, and handle both leaf and non-leaf node in the lowest_level loop exit logic. This changes the behavior when btrfs_search_forward() is called with nonzero path->lowest_level. But this never happens in the current code base, and the previous behavior is wrong. So the change of behavior will not be a problem. Fix: commit 323ac95 ("Btrfs: don't read leaf blocks containing only checksums during truncate") Signed-off-by: Sun YangKai <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 9b82b46 commit 4f8d7a0

File tree

1 file changed

+19
-25
lines changed

1 file changed

+19
-25
lines changed

fs/btrfs/ctree.c

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4645,38 +4645,28 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
46454645
goto out;
46464646
}
46474647

4648-
/* at the lowest level, we're done, setup the path and exit */
4649-
if (level == path->lowest_level) {
4650-
if (slot >= nritems)
4651-
goto find_next_key;
4652-
ret = 0;
4653-
path->slots[level] = slot;
4654-
/* Save our key for returning back. */
4655-
btrfs_item_key_to_cpu(cur, min_key, slot);
4656-
goto out;
4657-
}
4658-
if (sret && slot > 0)
4648+
/*
4649+
* Not at the lowest level and not a perfect match,
4650+
* go back a slot if possible to search lower level.
4651+
*/
4652+
if (sret && slot > 0 && level > path->lowest_level)
46594653
slot--;
46604654
/*
4661-
* check this node pointer against the min_trans parameters.
4655+
* Check this node pointer against the min_trans parameters.
46624656
* If it is too old, skip to the next one.
46634657
*/
4664-
while (slot < nritems) {
4665-
u64 gen;
4666-
4667-
gen = btrfs_node_ptr_generation(cur, slot);
4668-
if (gen < min_trans) {
4658+
if (level > 0) {
4659+
while (slot < nritems) {
4660+
if (btrfs_node_ptr_generation(cur, slot) >= min_trans)
4661+
break;
46694662
slot++;
4670-
continue;
46714663
}
4672-
break;
46734664
}
4674-
find_next_key:
4665+
path->slots[level] = slot;
46754666
/*
4676-
* we didn't find a candidate key in this node, walk forward
4677-
* and find another one
4667+
* We didn't find a candidate key in this node, walk forward
4668+
* and find another one.
46784669
*/
4679-
path->slots[level] = slot;
46804670
if (slot >= nritems) {
46814671
sret = btrfs_find_next_key(root, path, min_key, level,
46824672
min_trans);
@@ -4687,12 +4677,16 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
46874677
goto out;
46884678
}
46894679
}
4680+
/* At the lowest level, we're done. Set the key and exit. */
46904681
if (level == path->lowest_level) {
46914682
ret = 0;
4692-
/* Save our key for returning back. */
4693-
btrfs_node_key_to_cpu(cur, min_key, slot);
4683+
if (level == 0)
4684+
btrfs_item_key_to_cpu(cur, min_key, slot);
4685+
else
4686+
btrfs_node_key_to_cpu(cur, min_key, slot);
46944687
goto out;
46954688
}
4689+
/* Search down to a lower level. */
46964690
cur = btrfs_read_node_slot(cur, slot);
46974691
if (IS_ERR(cur)) {
46984692
ret = PTR_ERR(cur);

0 commit comments

Comments
 (0)