summaryrefslogtreecommitdiff
path: root/fs/btrfs/backref.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2025-07-28 08:42:29 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2025-07-28 08:42:29 -0700
commitf92b71ffca8c7e45e194aecc85e31bd11582f4d2 (patch)
treeb965dd656e29ba6326091c6401e93b8bac5f7376 /fs/btrfs/backref.c
parent038d61fd642278bab63ee8ef722c50d10ab01e8f (diff)
parent005b0a0c24e1628313e951516b675109a92cacfe (diff)
Merge tag 'for-6.17-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs updates from David Sterba: "A number of usability and feature updates, scattered performance improvements and fixes. Highlight of the core changes is getting closer to enabling large folios (now behind a config option). User visible changes: - update defrag ioctl, add new flag to request no compression on existing extents - restrict writes to block devices after mount - in experimental config, enable large folios for data, almost complete but not widely tested - add stats tracking duration of critical section in transaction commit to /sys/fs/btrfs/FSID/commit_stats Performance improvements: - caching of lookup results of free space bitmap (20% runtime improvement on an empty file creation benchmark) - accessors to metadata (b-tree items) simplified and optimized, minor improvement in metadata-heavy workloads - readahead on compressed data improves sequential read - the xarray for extent buffers is indexed by denser keys, leading to better packing of the nodes (50-70% reduction of leaf nodes) Notable fixes: - stricter compression mount option parsing - send properly emits fallocate command for file holes when protocol v2 is used - fix overallocation of chunks with mount option 'ssd_spread', due to interaction with size classes not finding the right chunk (workaround: manual reclaim by 'usage' balance filter) - various quota enable/disable races with rescan, more verbose notifications about inconsistent state - populate otime in tree-log during log replay - handle ENOSPC when NOCOW file is used with mmap() Core: - large data folios enabled in experimental config - improved error handling, transaction abort call sites - in zoned mode, allocate reloc block group on mount to make sure there's always one available for zone reclaim under heavy load - rework device opening, they're always open as read-only and delayed until the super block is created, allowing the restricted writes after mount - preparatory work for adding blk_holder_ops, allowing device freeze/thaw in the future Cleanups, refactoring: - type and naming unifications (int/bool, return variables) - rb-tree helper refactoring and simplifications - reorder memory allocations to less critical places - RCU string (used for device name) refactoring and API removal - replace all remaining use of strcpy()" * tag 'for-6.17-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: (209 commits) btrfs: send: use fallocate for hole punching with send stream v2 btrfs: unfold transaction aborts when writing dirty block groups btrfs: use saner variable type and name to indicate extrefs at add_inode_ref() btrfs: don't skip remaining extrefs if dir not found during log replay btrfs: don't ignore inode missing when replaying log tree btrfs: enable large data folios for data reloc inode btrfs: output more info when btrfs_subpage_assert() failed btrfs: reloc: unconditionally invalidate the page cache for each cluster btrfs: defrag: add flag to force no-compression btrfs: fix ssd_spread overallocation btrfs: zoned: requeue to unused block group list if zone finish failed btrfs: zoned: do not remove unwritten non-data block group btrfs: remove btrfs_clear_extent_bits() btrfs: use cached state when falling back from NOCoW write to CoW write btrfs: set EXTENT_NORESERVE before range unlock in btrfs_truncate_block() btrfs: don't print relocation messages from auto reclaim btrfs: remove redundant auto reclaim log message btrfs: make btrfs_check_nocow_lock() check more than one extent btrfs: assert we can NOCOW the range in btrfs_truncate_block() btrfs: update function comment for btrfs_check_nocow_lock() ...
Diffstat (limited to 'fs/btrfs/backref.c')
-rw-r--r--fs/btrfs/backref.c47
1 files changed, 21 insertions, 26 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index ed497f5f8d1b..6a450be293b1 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -733,7 +733,6 @@ static int resolve_indirect_refs(struct btrfs_backref_walk_ctx *ctx,
struct preftrees *preftrees,
struct share_check *sc)
{
- int err;
int ret = 0;
struct ulist *parents;
struct ulist_node *node;
@@ -752,6 +751,7 @@ static int resolve_indirect_refs(struct btrfs_backref_walk_ctx *ctx,
*/
while ((rnode = rb_first_cached(&preftrees->indirect.root))) {
struct prelim_ref *ref;
+ int ret2;
ref = rb_entry(rnode, struct prelim_ref, rbnode);
if (WARN(ref->parent,
@@ -773,18 +773,18 @@ static int resolve_indirect_refs(struct btrfs_backref_walk_ctx *ctx,
ret = BACKREF_FOUND_SHARED;
goto out;
}
- err = resolve_indirect_ref(ctx, path, preftrees, ref, parents);
+ ret2 = resolve_indirect_ref(ctx, path, preftrees, ref, parents);
/*
* we can only tolerate ENOENT,otherwise,we should catch error
* and return directly.
*/
- if (err == -ENOENT) {
+ if (ret2 == -ENOENT) {
prelim_ref_insert(ctx->fs_info, &preftrees->direct, ref,
NULL);
continue;
- } else if (err) {
+ } else if (ret2) {
free_pref(ref);
- ret = err;
+ ret = ret2;
goto out;
}
@@ -2201,7 +2201,6 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
int ret;
u64 flags;
u64 size = 0;
- u32 item_size;
const struct extent_buffer *eb;
struct btrfs_extent_item *ei;
struct btrfs_key key;
@@ -2244,7 +2243,6 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
}
eb = path->nodes[0];
- item_size = btrfs_item_size(eb, path->slots[0]);
ei = btrfs_item_ptr(eb, path->slots[0], struct btrfs_extent_item);
flags = btrfs_extent_flags(eb, ei);
@@ -2252,7 +2250,7 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
btrfs_debug(fs_info,
"logical %llu is at position %llu within the extent (%llu EXTENT_ITEM %llu) flags %#llx size %u",
logical, logical - found_key->objectid, found_key->objectid,
- found_key->offset, flags, item_size);
+ found_key->offset, flags, btrfs_item_size(eb, path->slots[0]));
WARN_ON(!flags_ret);
if (flags_ret) {
@@ -2548,17 +2546,20 @@ static int build_ino_list(u64 inum, u64 offset, u64 num_bytes, u64 root, void *c
}
int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info,
- struct btrfs_path *path,
void *ctx, bool ignore_offset)
{
struct btrfs_backref_walk_ctx walk_ctx = { 0 };
int ret;
u64 flags = 0;
struct btrfs_key found_key;
- int search_commit_root = path->search_commit_root;
+ struct btrfs_path *path;
+
+ path = btrfs_alloc_path();
+ if (!path)
+ return -ENOMEM;
ret = extent_from_logical(fs_info, logical, path, &found_key, &flags);
- btrfs_release_path(path);
+ btrfs_free_path(path);
if (ret < 0)
return ret;
if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK)
@@ -2571,8 +2572,7 @@ int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info,
walk_ctx.extent_item_pos = logical - found_key.objectid;
walk_ctx.fs_info = fs_info;
- return iterate_extent_inodes(&walk_ctx, search_commit_root,
- build_ino_list, ctx);
+ return iterate_extent_inodes(&walk_ctx, false, build_ino_list, ctx);
}
static int inode_to_path(u64 inum, u32 name_len, unsigned long name_off,
@@ -3161,18 +3161,14 @@ void btrfs_backref_release_cache(struct btrfs_backref_cache *cache)
ASSERT(!cache->nr_edges);
}
-void btrfs_backref_link_edge(struct btrfs_backref_edge *edge,
- struct btrfs_backref_node *lower,
- struct btrfs_backref_node *upper,
- int link_which)
+static void btrfs_backref_link_edge(struct btrfs_backref_edge *edge,
+ struct btrfs_backref_node *lower,
+ struct btrfs_backref_node *upper)
{
ASSERT(upper && lower && upper->level == lower->level + 1);
edge->node[LOWER] = lower;
edge->node[UPPER] = upper;
- if (link_which & LINK_LOWER)
- list_add_tail(&edge->list[LOWER], &lower->upper);
- if (link_which & LINK_UPPER)
- list_add_tail(&edge->list[UPPER], &upper->lower);
+ list_add_tail(&edge->list[LOWER], &lower->upper);
}
/*
* Handle direct tree backref
@@ -3242,7 +3238,7 @@ static int handle_direct_tree_backref(struct btrfs_backref_cache *cache,
ASSERT(upper->checked);
INIT_LIST_HEAD(&edge->list[UPPER]);
}
- btrfs_backref_link_edge(edge, cur, upper, LINK_LOWER);
+ btrfs_backref_link_edge(edge, cur, upper);
return 0;
}
@@ -3412,7 +3408,7 @@ static int handle_indirect_tree_backref(struct btrfs_trans_handle *trans,
if (!upper->owner)
upper->owner = btrfs_header_owner(eb);
}
- btrfs_backref_link_edge(edge, lower, upper, LINK_LOWER);
+ btrfs_backref_link_edge(edge, lower, upper);
if (rb_node) {
btrfs_put_root(root);
@@ -3570,7 +3566,7 @@ int btrfs_backref_finish_upper_links(struct btrfs_backref_cache *cache,
ASSERT(start->checked);
- rb_node = rb_simple_insert(&cache->rb_root, start->bytenr, &start->rb_node);
+ rb_node = rb_simple_insert(&cache->rb_root, &start->simple_node);
if (rb_node)
btrfs_backref_panic(cache->fs_info, start->bytenr, -EEXIST);
@@ -3621,8 +3617,7 @@ int btrfs_backref_finish_upper_links(struct btrfs_backref_cache *cache,
return -EUCLEAN;
}
- rb_node = rb_simple_insert(&cache->rb_root, upper->bytenr,
- &upper->rb_node);
+ rb_node = rb_simple_insert(&cache->rb_root, &upper->simple_node);
if (unlikely(rb_node)) {
btrfs_backref_panic(cache->fs_info, upper->bytenr, -EEXIST);
return -EUCLEAN;