* [PATCH v2] zloop: zero out only the unread tail of short reads
@ 2026-07-30 7:26 Shin'ichiro Kawasaki
2026-07-30 7:28 ` Christoph Hellwig
2026-07-30 9:14 ` Damien Le Moal
0 siblings, 2 replies; 3+ messages in thread
From: Shin'ichiro Kawasaki @ 2026-07-30 7:26 UTC (permalink / raw)
To: linux-block, Damien Le Moal, Jens Axboe
Cc: Christoph Hellwig, Shin'ichiro Kawasaki
zloop_complete_rq() handles a short read from a zone's backing file by
zero-filling every bio in the request. This is correct when the entire
request is beyond the written part of the zone. When a read request
straddles the boundary between written and unwritten data, read_iter()
returns a partial byte count and zloop then zeroes the whole request
even for the partially read area with valid data.
Such an unexpected zero data read was observed with fio test script
t/zbd/test-zbd-support and its test case 69, failing with "bad magic
header 0".
Avoid the unexpected zero data read by zeroing out only the unread tail
part. When read data size cmd->ret is smaller than the request size,
call the new helper function zloop_fill_zero_rq() that walks through
each bio_vec and fills zeros from the specified start offset.
Fixes: eb0570c7df23 ("block: new zoned loop block device driver")
Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
---
The fio test case 69 of t/zbd/test-zbd-support started failing since the
recent kernel commit 9cbbac29d752 ("block: Remove redundant plug in
__submit_bio()"). My understanding is that this commit in block layer
changed request merge behavior, and unveiled the bug in zloop.
Changes from v1:
- Adjusted if-else form per review comment
- Link to v1: https://lore.kernel.org/linux-block/20260730055832.1826093-1-shinichiro.kawasaki@wdc.com/
drivers/block/zloop.c | 31 ++++++++++++++++++++++++-------
1 file changed, 24 insertions(+), 7 deletions(-)
diff --git a/drivers/block/zloop.c b/drivers/block/zloop.c
index 55eeb6aac0ea..947afe618795 100644
--- a/drivers/block/zloop.c
+++ b/drivers/block/zloop.c
@@ -798,6 +798,27 @@ static void zloop_cmd_workfn(struct work_struct *work)
current->flags = orig_flags;
}
+static void zloop_fill_zero_rq(struct request *rq, unsigned int zero_from)
+{
+ struct req_iterator iter;
+ struct bio_vec bv;
+ unsigned int pos = 0;
+ unsigned int end, off;
+
+ rq_for_each_segment(bv, rq, iter) {
+ end = pos + bv.bv_len;
+ if (end > zero_from) {
+ if (pos < zero_from)
+ off = zero_from - pos;
+ else
+ off = 0;
+ memzero_page(bv.bv_page, bv.bv_offset + off,
+ bv.bv_len - off);
+ }
+ pos = end;
+ }
+}
+
static void zloop_complete_rq(struct request *rq)
{
struct zloop_cmd *cmd = blk_mq_rq_to_pdu(rq);
@@ -812,13 +833,9 @@ static void zloop_complete_rq(struct request *rq)
pr_err("Zone %u: failed read sector %llu, %llu sectors\n",
zone_no, cmd->sector, cmd->nr_sectors);
- if (cmd->ret >= 0 && cmd->ret != blk_rq_bytes(rq)) {
- /* short read */
- struct bio *bio;
-
- __rq_for_each_bio(bio, rq)
- zero_fill_bio(bio);
- }
+ /* Short read. Zero out the unread tail beyond cmd->ret. */
+ if (cmd->ret >= 0 && cmd->ret != blk_rq_bytes(rq))
+ zloop_fill_zero_rq(rq, cmd->ret);
break;
case REQ_OP_WRITE:
case REQ_OP_ZONE_APPEND:
--
2.54.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v2] zloop: zero out only the unread tail of short reads
2026-07-30 7:26 [PATCH v2] zloop: zero out only the unread tail of short reads Shin'ichiro Kawasaki
@ 2026-07-30 7:28 ` Christoph Hellwig
2026-07-30 9:14 ` Damien Le Moal
1 sibling, 0 replies; 3+ messages in thread
From: Christoph Hellwig @ 2026-07-30 7:28 UTC (permalink / raw)
To: Shin'ichiro Kawasaki
Cc: linux-block, Damien Le Moal, Jens Axboe, Christoph Hellwig
Looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v2] zloop: zero out only the unread tail of short reads
2026-07-30 7:26 [PATCH v2] zloop: zero out only the unread tail of short reads Shin'ichiro Kawasaki
2026-07-30 7:28 ` Christoph Hellwig
@ 2026-07-30 9:14 ` Damien Le Moal
1 sibling, 0 replies; 3+ messages in thread
From: Damien Le Moal @ 2026-07-30 9:14 UTC (permalink / raw)
To: Shin'ichiro Kawasaki, linux-block, Jens Axboe; +Cc: Christoph Hellwig
On 2026/07/30 16:26, Shin'ichiro Kawasaki wrote:
> zloop_complete_rq() handles a short read from a zone's backing file by
> zero-filling every bio in the request. This is correct when the entire
> request is beyond the written part of the zone. When a read request
> straddles the boundary between written and unwritten data, read_iter()
> returns a partial byte count and zloop then zeroes the whole request
> even for the partially read area with valid data.
>
> Such an unexpected zero data read was observed with fio test script
> t/zbd/test-zbd-support and its test case 69, failing with "bad magic
> header 0".
>
> Avoid the unexpected zero data read by zeroing out only the unread tail
> part. When read data size cmd->ret is smaller than the request size,
> call the new helper function zloop_fill_zero_rq() that walks through
> each bio_vec and fills zeros from the specified start offset.
>
> Fixes: eb0570c7df23 ("block: new zoned loop block device driver")
> Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
--
Damien Le Moal
Western Digital Research
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-07-30 9:14 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-30 7:26 [PATCH v2] zloop: zero out only the unread tail of short reads Shin'ichiro Kawasaki
2026-07-30 7:28 ` Christoph Hellwig
2026-07-30 9:14 ` Damien Le Moal
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.