From: Sun YangKai <sunk67188@gmail.com>
To: linux-btrfs@vger.kernel.org
Cc: Sun YangKai <sunk67188@gmail.com>
Subject: [PATCH 4/4] btrfs: ctree: cleanup btrfs_prev_leaf()
Date: Tue, 9 Dec 2025 11:27:21 +0800 [thread overview]
Message-ID: <20251209033747.31010-5-sunk67188@gmail.com> (raw)
In-Reply-To: <20251209033747.31010-1-sunk67188@gmail.com>
There's a common parttern in callers of btrfs_prev_leaf:
p->slots[0]-- if p->slots[0] points to a slot with invalid item(nritem).
So just make btrfs_prev_leaf() ensure that path->slots[0] points to a
valid slot and cleanup its over complex logic.
Reading and comparing keys in btrfs_prev_leaf() is unnecessary because
when got a ret>0 from btrfs_search_slot(), slots[0] points to where we
should insert the key. So just slots[0]-- is enough to get the previous
item.
And then remove the related logic and cleanup the callers.
ASSERT(path->slots[0] < btrfs_header_nritems(path->nodes[0]))
is enough to make sure that nritems != 0 and slots[0] points to a valid
btrfs_item.
And getting a `nritems==0` when btrfs_prev_leaf() returns 0 is a logic
error because btrfs_pref_leaf() should always
1. either find a non-empty leaf
2. or return 1
So we can use ASSERT here.
No functional changes.
Signed-off-by: Sun YangKai <sunk67188@gmail.com>
---
fs/btrfs/ctree.c | 100 +++++++++--------------------------------------
1 file changed, 19 insertions(+), 81 deletions(-)
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index bb886f9508e2..07e6433cde61 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -2365,12 +2365,9 @@ int btrfs_search_old_slot(struct btrfs_root *root, const struct btrfs_key *key,
static int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path)
{
struct btrfs_key key;
- struct btrfs_key orig_key;
- struct btrfs_disk_key found_key;
int ret;
btrfs_item_key_to_cpu(path->nodes[0], &key, 0);
- orig_key = key;
if (key.offset > 0) {
key.offset--;
@@ -2390,48 +2387,12 @@ static int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path)
if (ret <= 0)
return ret;
- /*
- * Previous key not found. Even if we were at slot 0 of the leaf we had
- * before releasing the path and calling btrfs_search_slot(), we now may
- * be in a slot pointing to the same original key - this can happen if
- * after we released the path, one of more items were moved from a
- * sibling leaf into the front of the leaf we had due to an insertion
- * (see push_leaf_right()).
- * If we hit this case and our slot is > 0 and just decrement the slot
- * so that the caller does not process the same key again, which may or
- * may not break the caller, depending on its logic.
- */
- if (path->slots[0] < btrfs_header_nritems(path->nodes[0])) {
- btrfs_item_key(path->nodes[0], &found_key, path->slots[0]);
- ret = btrfs_comp_keys(&found_key, &orig_key);
- if (ret == 0) {
- if (path->slots[0] > 0) {
- path->slots[0]--;
- return 0;
- }
- /*
- * At slot 0, same key as before, it means orig_key is
- * the lowest, leftmost, key in the tree. We're done.
- */
- return 1;
- }
- }
+ /* There's no smaller keys in the whole tree. */
+ if (path->slots[0] == 0)
+ return 1;
- btrfs_item_key(path->nodes[0], &found_key, 0);
- ret = btrfs_comp_keys(&found_key, &key);
- /*
- * We might have had an item with the previous key in the tree right
- * before we released our path. And after we released our path, that
- * item might have been pushed to the first slot (0) of the leaf we
- * were holding due to a tree balance. Alternatively, an item with the
- * previous key can exist as the only element of a leaf (big fat item).
- * Therefore account for these 2 cases, so that our callers (like
- * btrfs_previous_item) don't miss an existing item with a key matching
- * the previous key we computed above.
- */
- if (ret <= 0)
- return 0;
- return 1;
+ path->slots[0]--;
+ return 0;
}
/*
@@ -2461,19 +2422,10 @@ int btrfs_search_slot_for_read(struct btrfs_root *root,
if (p->slots[0] >= btrfs_header_nritems(p->nodes[0]))
return btrfs_next_leaf(root, p);
} else {
- if (p->slots[0] == 0) {
- ret = btrfs_prev_leaf(root, p);
- if (ret < 0)
- return ret;
- if (!ret) {
- if (p->slots[0] == btrfs_header_nritems(p->nodes[0]))
- p->slots[0]--;
- return 0;
- }
- return 1;
- } else {
- p->slots[0]--;
- }
+ if (p->slots[0] == 0)
+ return btrfs_prev_leaf(root, p);
+
+ p->slots[0]--;
}
return 0;
}
@@ -4957,26 +4909,19 @@ int btrfs_previous_item(struct btrfs_root *root,
int type)
{
struct btrfs_key found_key;
- struct extent_buffer *leaf;
- u32 nritems;
int ret;
while (1) {
if (path->slots[0] == 0) {
ret = btrfs_prev_leaf(root, path);
- if (ret != 0)
+ if (ret)
return ret;
- } else {
- path->slots[0]--;
- }
- leaf = path->nodes[0];
- nritems = btrfs_header_nritems(leaf);
- if (nritems == 0)
- return 1;
- if (path->slots[0] == nritems)
+ } else
path->slots[0]--;
- btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
+ ASSERT(path->slots[0] < btrfs_header_nritems(path->nodes[0]));
+
+ btrfs_item_key_to_cpu(path->nodes[0], &found_key, path->slots[0]);
if (found_key.objectid < min_objectid)
break;
if (found_key.type == type)
@@ -4998,26 +4943,19 @@ int btrfs_previous_extent_item(struct btrfs_root *root,
struct btrfs_path *path, u64 min_objectid)
{
struct btrfs_key found_key;
- struct extent_buffer *leaf;
- u32 nritems;
int ret;
while (1) {
if (path->slots[0] == 0) {
ret = btrfs_prev_leaf(root, path);
- if (ret != 0)
+ if (ret)
return ret;
- } else {
- path->slots[0]--;
- }
- leaf = path->nodes[0];
- nritems = btrfs_header_nritems(leaf);
- if (nritems == 0)
- return 1;
- if (path->slots[0] == nritems)
+ } else
path->slots[0]--;
- btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
+ ASSERT(path->slots[0] < btrfs_header_nritems(path->nodes[0]));
+
+ btrfs_item_key_to_cpu(path->nodes[0], &found_key, path->slots[0]);
if (found_key.objectid < min_objectid)
break;
if (found_key.type == BTRFS_EXTENT_ITEM_KEY ||
--
2.51.2
next prev parent reply other threads:[~2025-12-09 3:38 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-09 3:27 [PATCH 0/4] btrfs: some cleanups for two ctree functions Sun YangKai
2025-12-09 3:27 ` [PATCH 1/4] btrfs: don't set @return_any for btrfs_search_slot_for_read in btrfs_read_qgroup_config Sun YangKai
2025-12-09 3:27 ` [PATCH 2/4] btrfs: don't set return_any @return_any for btrfs_search_slot_for_read in get_last_extent() Sun YangKai
2025-12-09 3:27 ` [PATCH 3/4] btrfs: cleanup btrfs_search_slot_for_read() Sun YangKai
2025-12-09 3:27 ` Sun YangKai [this message]
2025-12-09 4:05 ` [PATCH 4/4] btrfs: ctree: cleanup btrfs_prev_leaf() Sun Yangkai
2025-12-09 12:05 ` Filipe Manana
2025-12-09 12:27 ` Sun Yangkai
2026-02-07 8:50 ` Sun YangKai
2026-02-07 10:18 ` Qu Wenruo
2026-02-07 15:07 ` Sun YangKai
2025-12-09 13:57 ` Sun Yangkai
2025-12-09 14:04 ` Sun Yangkai
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251209033747.31010-5-sunk67188@gmail.com \
--to=sunk67188@gmail.com \
--cc=linux-btrfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.