summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCole Munz <[email protected]>2026-08-02 09:35:22 +0000
committerTom Rini <[email protected]>2026-08-10 12:38:57 -0600
commit1a5c8af2d4e4b4029739eb8787ce259d74977dfd (patch)
tree6491cc1314a081164bad9dcdf1bf1d406b466b3a
parent1cf825afd0d7ebb4857002833658574efbef6626 (diff)
fs: btrfs: release the path when btrfs_search_slot() fails
The U-Boot copy of btrfs_search_slot() returns on error with the nodes it has descended through still attached to the path. The kernel one releases the path on any error unless p->skip_release_on_error is set, and callers written against that convention treat a failed search as owning nothing. btrfs_size() is one: it returns straight away on a search error and never reaches its btrfs_release_path() call, so the attached extent buffer references leak. Route both error exits through a release of the path. The error returns of read_node_slot() carry no extra reference, so the path is the only thing to clean up. Suggested-by: Qu Wenruo <[email protected]> Signed-off-by: Cole Munz <[email protected]> Reviewed-by: Qu Wenruo <[email protected]>
-rw-r--r--fs/btrfs/ctree.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 8e932adc425..48c50e556b1 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -425,8 +425,10 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans,
level = btrfs_header_level(b);
p->nodes[level] = b;
ret = check_block(fs_info, p, level);
- if (ret)
- return -1;
+ if (ret) {
+ ret = -1;
+ goto err;
+ }
ret = btrfs_bin_search(b, key, &slot);
if (level != 0) {
if (ret && slot > 0)
@@ -461,8 +463,10 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans,
break;
b = read_node_slot(fs_info, b, slot);
- if (!extent_buffer_uptodate(b))
- return -EIO;
+ if (!extent_buffer_uptodate(b)) {
+ ret = -EIO;
+ goto err;
+ }
} else {
p->slots[level] = slot;
/*
@@ -479,6 +483,10 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans,
}
}
return 1;
+
+err:
+ btrfs_release_path(p);
+ return ret;
}
/*