* [PATCH v2 0/2] btrfs: tag tree block repair and RAID5/6 metadata I/O with REQ_META
@ 2026-11-06 17:33 Mark Korenberg via B4 Relay
2026-11-06 17:33 ` [PATCH v2 1/2] btrfs: tag tree block repair writes " Mark Korenberg via B4 Relay
2026-11-06 17:33 ` [PATCH v2 2/2] btrfs: raid56: pass REQ_META to per-device bios Mark Korenberg via B4 Relay
0 siblings, 2 replies; 5+ messages in thread
From: Mark Korenberg via B4 Relay @ 2026-11-06 17:33 UTC (permalink / raw)
To: David Sterba, Chris Mason
Cc: Qu Wenruo, linux-btrfs, linux-kernel, Mark Korenberg
Tree block reads and writes carry REQ_META, so the layers below see
them as metadata I/O: blk-cgroup issues them as root to avoid priority
inversion, wbt does not throttle them, blktrace shows them as such, and
ublk passes the flag to its server as UBLK_IO_F_META. Two paths of
normal operation lose the flag:
- Patch 1: when a tree block read finds a bad copy, the rewrite from a
good copy goes out as a plain write.
- Patch 2: on RAID5/6 the rbio builds new per-device bios and drops the
flag, so all tree block writes, and tree block reads rebuilt from the
other stripes (for example with a missing device), go out as data
I/O. On the other profiles the per-device bios are clones and keep
it. Now the flag follows the bios the rbio serves, P/Q included, so
mixed block groups need no special case.
Thanks to Qu for the review of v1. I agree that background work
should not get the priority of metadata I/O, so v2 drops the scrub,
dev-replace and relocation parts: they stay untagged even when they
handle metadata, and so do the rebuilds and parity checks that scrub
does on RAID5/6.
RAID5/6 stays, as its own patch, because what it tags is regular
operation, not background work. The writes are the normal tree block
writeback, which carries REQ_META on every other profile. A rebuild
read serves a tree block read, the same read that carries REQ_META when
no rebuild is needed.
Zoned devices see no change: they support neither RAID5/6 nor in-place
repair, btrfs_repair_one_zone() relocates the block group instead.
Testing: virtme-ng VM, memory backed null_blk, tracefs
block:block_bio_queue, every bio classified by the chunk type of its
dev extent:
- RAID5 metadata and data, copy /usr/include: all metadata bios, P/Q
and RMW reads included, carry REQ_META (before: none). Scrub and the
copy of a dev-replace carry none.
- RAID5 with one device missing, mounted degraded, all files read: all
696 metadata bios carry REQ_META (before: the 344 rebuild reads did
not).
- DUP metadata with one copy of a leaf corrupted, read back: the repair
write carries REQ_META.
No bio to a data chunk carries the flag, no new warnings, W=1 build
clean.
Changes in v2:
- Leave scrub, dev-replace and remap relocation untagged, including the
super block reads of scrub: background work (Qu).
- RAID5/6: take REQ_META from the bios the rbio serves instead of the
chunk type, which also covers rebuild reads and mixed block groups,
and move it to its own patch (Qu).
- Link to v1: https://lore.kernel.org/r/20261104-btrfs-sb-read-req-meta-v1-1-e06b4d059897@gmail.com
The audit, the patches and the tests were drafted with the help of an
AI assistant (Claude Opus 5.5).
---
Mark Korenberg (2):
btrfs: tag tree block repair writes with REQ_META
btrfs: raid56: pass REQ_META to per-device bios
fs/btrfs/bio.c | 3 ++-
fs/btrfs/raid56.c | 14 +++++++++++---
fs/btrfs/raid56.h | 7 +++++++
3 files changed, 20 insertions(+), 4 deletions(-)
---
base-commit: df5b88a7914e18488908ddf13e14e31ab39f954c
change-id: 20261104-btrfs-sb-read-req-meta-7be597aaaa51
Best regards,
--
Mark Korenberg <socketpair@gmail.com>
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH v2 1/2] btrfs: tag tree block repair writes with REQ_META
2026-11-06 17:33 [PATCH v2 0/2] btrfs: tag tree block repair and RAID5/6 metadata I/O with REQ_META Mark Korenberg via B4 Relay
@ 2026-11-06 17:33 ` Mark Korenberg via B4 Relay
2026-11-06 20:31 ` Qu Wenruo
2026-11-06 17:33 ` [PATCH v2 2/2] btrfs: raid56: pass REQ_META to per-device bios Mark Korenberg via B4 Relay
1 sibling, 1 reply; 5+ messages in thread
From: Mark Korenberg via B4 Relay @ 2026-11-06 17:33 UTC (permalink / raw)
To: David Sterba, Chris Mason
Cc: Qu Wenruo, linux-btrfs, linux-kernel, Mark Korenberg
From: Mark Korenberg <socketpair@gmail.com>
When a tree block read finds a bad copy, btrfs_repair_eb_io_failure()
rewrites it from a good one through btrfs_repair_bbio_failure(). That
rewrite is a plain REQ_OP_WRITE | REQ_SYNC, while the read that found
the bad copy and all other tree block writes carry REQ_META.
Tag it with REQ_META when the bbio belongs to the btree inode.
Signed-off-by: Mark Korenberg <socketpair@gmail.com>
---
fs/btrfs/bio.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/fs/btrfs/bio.c b/fs/btrfs/bio.c
index 2e12a6d7e16f..efbce4d549ff 100644
--- a/fs/btrfs/bio.c
+++ b/fs/btrfs/bio.c
@@ -951,7 +951,8 @@ int btrfs_repair_bbio_failure(struct btrfs_bio *bbio, const struct bvec_iter *or
}
repair_bio = bio_alloc(smap.dev->bdev, max(1, length >> PAGE_SHIFT),
- REQ_OP_WRITE | REQ_SYNC, GFP_NOFS);
+ REQ_OP_WRITE | REQ_SYNC |
+ (is_data_inode(inode) ? 0 : REQ_META), GFP_NOFS);
repair_bio->bi_iter.bi_sector = smap.physical >> SECTOR_SHIFT;
while (cur < length) {
struct page *page = bio_iter_page(&bbio->bio, iter);
--
2.56.0
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH v2 1/2] btrfs: tag tree block repair writes with REQ_META
2026-11-06 17:33 ` [PATCH v2 1/2] btrfs: tag tree block repair writes " Mark Korenberg via B4 Relay
@ 2026-11-06 20:31 ` Qu Wenruo
0 siblings, 0 replies; 5+ messages in thread
From: Qu Wenruo @ 2026-11-06 20:31 UTC (permalink / raw)
To: socketpair, David Sterba, Chris Mason; +Cc: linux-btrfs, linux-kernel
在 2026/11/7 04:03, Mark Korenberg via B4 Relay 写道:
> From: Mark Korenberg <socketpair@gmail.com>
>
> When a tree block read finds a bad copy, btrfs_repair_eb_io_failure()
> rewrites it from a good one through btrfs_repair_bbio_failure(). That
> rewrite is a plain REQ_OP_WRITE | REQ_SYNC, while the read that found
> the bad copy and all other tree block writes carry REQ_META.
>
> Tag it with REQ_META when the bbio belongs to the btree inode.
>
> Signed-off-by: Mark Korenberg <socketpair@gmail.com>
This part looks fine to me.
Reviewed-by: Qu Wenruo <wqu@suse.com>
Thanks,
Qu
> ---
> fs/btrfs/bio.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/fs/btrfs/bio.c b/fs/btrfs/bio.c
> index 2e12a6d7e16f..efbce4d549ff 100644
> --- a/fs/btrfs/bio.c
> +++ b/fs/btrfs/bio.c
> @@ -951,7 +951,8 @@ int btrfs_repair_bbio_failure(struct btrfs_bio *bbio, const struct bvec_iter *or
> }
>
> repair_bio = bio_alloc(smap.dev->bdev, max(1, length >> PAGE_SHIFT),
> - REQ_OP_WRITE | REQ_SYNC, GFP_NOFS);
> + REQ_OP_WRITE | REQ_SYNC |
> + (is_data_inode(inode) ? 0 : REQ_META), GFP_NOFS);
> repair_bio->bi_iter.bi_sector = smap.physical >> SECTOR_SHIFT;
> while (cur < length) {
> struct page *page = bio_iter_page(&bbio->bio, iter);
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 2/2] btrfs: raid56: pass REQ_META to per-device bios
2026-11-06 17:33 [PATCH v2 0/2] btrfs: tag tree block repair and RAID5/6 metadata I/O with REQ_META Mark Korenberg via B4 Relay
2026-11-06 17:33 ` [PATCH v2 1/2] btrfs: tag tree block repair writes " Mark Korenberg via B4 Relay
@ 2026-11-06 17:33 ` Mark Korenberg via B4 Relay
2026-11-06 20:26 ` Qu Wenruo
1 sibling, 1 reply; 5+ messages in thread
From: Mark Korenberg via B4 Relay @ 2026-11-06 17:33 UTC (permalink / raw)
To: David Sterba, Chris Mason
Cc: Qu Wenruo, linux-btrfs, linux-kernel, Mark Korenberg
From: Mark Korenberg <socketpair@gmail.com>
RAID5/6 writes, and reads that need a rebuild, go through an rbio,
which builds new per-device bios from a bare REQ_OP_READ or
REQ_OP_WRITE. So all tree block writes on RAID5/6 lose REQ_META, while
on the other profiles the per-device bios are clones and keep it. The
same goes for a tree block read rebuilt from the other stripes, for
example with a missing device.
Pass REQ_META on to all per-device bios of an rbio, data and P/Q alike,
if any bio it serves has it. Scrub and relocation do not set REQ_META,
so their rbios stay untagged, as do rbios that only serve file data.
Signed-off-by: Mark Korenberg <socketpair@gmail.com>
---
fs/btrfs/raid56.c | 14 +++++++++++---
fs/btrfs/raid56.h | 7 +++++++
2 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
index a8a8004bb14c..63b5acbf107e 100644
--- a/fs/btrfs/raid56.c
+++ b/fs/btrfs/raid56.c
@@ -1202,10 +1202,15 @@ static int rbio_add_io_paddrs(struct btrfs_raid_bio *rbio, struct bio_list *bio_
}
}
- /* put a new bio on the list */
+ /*
+ * Put a new bio on the list. Every per-device bio, data and P/Q
+ * alike, serves the bios in rbio->bio_list, so it is metadata I/O if
+ * any of them is: a tree block write, or a tree block read rebuilt
+ * from the other stripes.
+ */
bio = bio_alloc(stripe->dev->bdev,
max(rbio->bioc->stripe_len >> PAGE_SHIFT, 1),
- op, GFP_NOFS);
+ op | rbio->req_meta, GFP_NOFS);
bio->bi_iter.bi_sector = disk_start >> SECTOR_SHIFT;
bio->bi_private = rbio;
@@ -1246,8 +1251,11 @@ static void index_rbio_pages(struct btrfs_raid_bio *rbio)
struct bio *bio;
spin_lock(&rbio->bio_list_lock);
- bio_list_for_each(bio, &rbio->bio_list)
+ rbio->req_meta = 0;
+ bio_list_for_each(bio, &rbio->bio_list) {
index_one_bio(rbio, bio);
+ rbio->req_meta |= bio->bi_opf & REQ_META;
+ }
spin_unlock(&rbio->bio_list_lock);
}
diff --git a/fs/btrfs/raid56.h b/fs/btrfs/raid56.h
index 8700910b8dc9..a5a0ff8e4a03 100644
--- a/fs/btrfs/raid56.h
+++ b/fs/btrfs/raid56.h
@@ -139,6 +139,13 @@ struct btrfs_raid_bio {
*/
enum btrfs_rbio_ops operation;
+ /*
+ * REQ_META if any bio in bio_list has it. Set under bio_list_lock by
+ * index_rbio_pages(), which runs before every assembly of per-device
+ * bios.
+ */
+ blk_opf_t req_meta;
+
/* How many pages there are for the full stripe including P/Q */
u16 nr_pages;
--
2.56.0
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH v2 2/2] btrfs: raid56: pass REQ_META to per-device bios
2026-11-06 17:33 ` [PATCH v2 2/2] btrfs: raid56: pass REQ_META to per-device bios Mark Korenberg via B4 Relay
@ 2026-11-06 20:26 ` Qu Wenruo
0 siblings, 0 replies; 5+ messages in thread
From: Qu Wenruo @ 2026-11-06 20:26 UTC (permalink / raw)
To: socketpair, David Sterba, Chris Mason; +Cc: linux-btrfs, linux-kernel
在 2026/11/7 04:03, Mark Korenberg via B4 Relay 写道:
> From: Mark Korenberg <socketpair@gmail.com>
>
> RAID5/6 writes, and reads that need a rebuild, go through an rbio,
> which builds new per-device bios from a bare REQ_OP_READ or
> REQ_OP_WRITE. So all tree block writes on RAID5/6 lose REQ_META, while
> on the other profiles the per-device bios are clones and keep it. The
> same goes for a tree block read rebuilt from the other stripes, for
> example with a missing device.
>
> Pass REQ_META on to all per-device bios of an rbio, data and P/Q alike,
> if any bio it serves has it. Scrub and relocation do not set REQ_META,
> so their rbios stay untagged, as do rbios that only serve file data.
>
> Signed-off-by: Mark Korenberg <socketpair@gmail.com>
NACK.
One should not even use RAID56 for metadata chunks in the first place.
Nor we're any different from other RAID56 implementation.
> ---
> fs/btrfs/raid56.c | 14 +++++++++++---
> fs/btrfs/raid56.h | 7 +++++++
> 2 files changed, 18 insertions(+), 3 deletions(-)
>
> diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
> index a8a8004bb14c..63b5acbf107e 100644
> --- a/fs/btrfs/raid56.c
> +++ b/fs/btrfs/raid56.c
> @@ -1202,10 +1202,15 @@ static int rbio_add_io_paddrs(struct btrfs_raid_bio *rbio, struct bio_list *bio_
> }
> }
>
> - /* put a new bio on the list */
> + /*
> + * Put a new bio on the list. Every per-device bio, data and P/Q
> + * alike, serves the bios in rbio->bio_list, so it is metadata I/O if
> + * any of them is: a tree block write, or a tree block read rebuilt
> + * from the other stripes.
> + */
> bio = bio_alloc(stripe->dev->bdev,
> max(rbio->bioc->stripe_len >> PAGE_SHIFT, 1),
> - op, GFP_NOFS);
> + op | rbio->req_meta, GFP_NOFS);
> bio->bi_iter.bi_sector = disk_start >> SECTOR_SHIFT;
> bio->bi_private = rbio;
>
> @@ -1246,8 +1251,11 @@ static void index_rbio_pages(struct btrfs_raid_bio *rbio)
> struct bio *bio;
>
> spin_lock(&rbio->bio_list_lock);
> - bio_list_for_each(bio, &rbio->bio_list)
> + rbio->req_meta = 0;
> + bio_list_for_each(bio, &rbio->bio_list) {
> index_one_bio(rbio, bio);
> + rbio->req_meta |= bio->bi_opf & REQ_META;
> + }
>
> spin_unlock(&rbio->bio_list_lock);
> }
> diff --git a/fs/btrfs/raid56.h b/fs/btrfs/raid56.h
> index 8700910b8dc9..a5a0ff8e4a03 100644
> --- a/fs/btrfs/raid56.h
> +++ b/fs/btrfs/raid56.h
> @@ -139,6 +139,13 @@ struct btrfs_raid_bio {
> */
> enum btrfs_rbio_ops operation;
>
> + /*
> + * REQ_META if any bio in bio_list has it. Set under bio_list_lock by
> + * index_rbio_pages(), which runs before every assembly of per-device
> + * bios.
> + */
> + blk_opf_t req_meta;
> +
> /* How many pages there are for the full stripe including P/Q */
> u16 nr_pages;
>
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-11-06 20:31 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-06 17:33 [PATCH v2 0/2] btrfs: tag tree block repair and RAID5/6 metadata I/O with REQ_META Mark Korenberg via B4 Relay
2026-11-06 17:33 ` [PATCH v2 1/2] btrfs: tag tree block repair writes " Mark Korenberg via B4 Relay
2026-11-06 20:31 ` Qu Wenruo
2026-11-06 17:33 ` [PATCH v2 2/2] btrfs: raid56: pass REQ_META to per-device bios Mark Korenberg via B4 Relay
2026-11-06 20:26 ` Qu Wenruo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®