[PATCH] btrfs: scrub: don't mark inline extents as errors on RST

From: Johannes Thumshirn
Date: Tue Aug 20 2024 - 10:35:10 EST


From: Johannes Thumshirn <johannes.thumshirn@xxxxxxx>

When scrubbing a RAID stripe-tree backed btrfs system, we're doing
extent based block mappings. These block mappings go through the RAID
stripe-tree to do logical to physical translation.

In case we're hitting an inline extent, there is no backing by the
RAID stripe-tree for it and the block mapping returns an error. So the
bit in the extent bitmap is marked as error.

Fix this by not marking mapping failures for inline extents as error.

Cc: Qu Wenru <wqu@xxxxxxxx>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@xxxxxxx>
---
fs/btrfs/scrub.c | 41 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 39 insertions(+), 2 deletions(-)

diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index b3afa6365823..8240b205699c 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -67,6 +67,7 @@ struct scrub_ctx;
/* Represent one sector and its needed info to verify the content. */
struct scrub_sector_verification {
bool is_metadata;
+ bool is_inline;

union {
/*
@@ -1479,6 +1480,34 @@ static int sync_write_pointer_for_zoned(struct scrub_ctx *sctx, u64 logical,
return ret;
}

+static bool extent_is_inline(struct btrfs_fs_info *fs_info,
+ u64 extent_start, u64 extent_len)
+{
+ struct btrfs_file_extent_item *ei;
+ struct extent_buffer *leaf;
+ struct btrfs_path *path;
+ struct btrfs_root *extent_root = btrfs_extent_root(fs_info, extent_start);
+ int ret;
+ bool is_inline = false;
+
+ path = btrfs_alloc_path();
+ if (!path)
+ return false;
+
+ ret = btrfs_lookup_file_extent(NULL, extent_root, path, extent_start, extent_len, 0);
+ if (ret < 0)
+ goto out;
+
+ leaf = path->nodes[0];
+ ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_file_extent_item);
+ if (btrfs_file_extent_type(leaf, ei) == BTRFS_FILE_EXTENT_INLINE)
+ is_inline = true;
+
+ out:
+ btrfs_free_path(path);
+ return is_inline;
+}
+
static void fill_one_extent_info(struct btrfs_fs_info *fs_info,
struct scrub_stripe *stripe,
u64 extent_start, u64 extent_len,
@@ -1497,6 +1526,9 @@ static void fill_one_extent_info(struct btrfs_fs_info *fs_info,
if (extent_flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
sector->is_metadata = true;
sector->generation = extent_gen;
+ } else {
+ sector->is_inline = extent_is_inline(
+ fs_info, extent_start, extent_len);
}
}
}
@@ -1704,8 +1736,13 @@ static void scrub_submit_extent_sector_read(struct scrub_ctx *sctx,
&stripe_len, &bioc, &io_stripe, &mirror);
btrfs_put_bioc(bioc);
if (err < 0) {
- set_bit(i, &stripe->io_error_bitmap);
- set_bit(i, &stripe->error_bitmap);
+ struct scrub_sector_verification *sector =
+ &stripe->sectors[i];
+
+ if (!sector->is_inline) {
+ set_bit(i, &stripe->io_error_bitmap);
+ set_bit(i, &stripe->error_bitmap);
+ }
continue;
}

--
2.43.0