From: Niklas Cassel <cassel@kernel.org>
To: Stefan Hajnoczi <stefanha@redhat.com>,
Kevin Wolf <kwolf@redhat.com>, Hanna Reitz <hreitz@redhat.com>,
Fam Zheng <fam@euphon.net>, "Michael S. Tsirkin" <mst@redhat.com>
Cc: Sam Li <faithilikerun@gmail.com>,
Damien Le Moal <dlemoal@kernel.org>,
Niklas Cassel <cassel@kernel.org>,
qemu-block@nongnu.org, qemu-devel@nongnu.org
Subject: [PATCH v4 03/12] block: add a helper for the index of the zone an offset falls in
Date: Mon, 7 Sep 2026 13:07:38 +0200 [thread overview]
Message-ID: <20260907110748.1868714-4-cassel@kernel.org> (raw)
In-Reply-To: <20260907110748.1868714-1-cassel@kernel.org>
Deriving the zone that an offset belongs to is open coded in five places,
in two files, as a division of the offset by BlockLimits.zone_size.
The zone size of a zoned device is always a power of two. Linux requires
that of every zoned device it accepts, in blk_revalidate_disk_zones() and
in each of the drivers that report one, and qcow2 rejects an image whose
header says otherwise. So the division is a shift, and the shift is worth
deriving once rather than at every use: record it in BlockLimits as
zone_size_bits, next to the size it comes from, and assert the property
that it relies on where it is computed.
Add bdrv_zone_index() and use it. No functional change; the count of zones
that a management operation spans stays a division, since it is a length
rather than an offset.
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Niklas Cassel <cassel@kernel.org>
---
block/file-posix.c | 8 ++++----
block/io.c | 12 ++++++++++++
hw/block/virtio-blk.c | 2 +-
include/block/block-io.h | 2 ++
include/block/block_int-common.h | 7 +++++++
5 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/block/file-posix.c b/block/file-posix.c
index c0d6ee30e4..00323f7a9f 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -1359,7 +1359,7 @@ static int get_zones_wp(BlockDriverState *bs, int fd, int64_t offset,
size_t rep_size;
uint64_t sector = offset >> BDRV_SECTOR_BITS;
BlockZoneWps *wps = bs->wps;
- unsigned int j = offset / bs->bl.zone_size;
+ unsigned int j = bdrv_zone_index(bs, offset);
unsigned int n = 0, i = 0;
int ret;
rep_size = sizeof(struct blk_zone_report) + nrz * sizeof(struct blk_zone);
@@ -2560,7 +2560,7 @@ raw_co_prw(BlockDriverState *bs, int64_t *offset_ptr, uint64_t bytes,
bs->bl.zoned != BLK_Z_NONE) {
qemu_co_mutex_lock(&bs->wps->colock);
if (type & QEMU_AIO_ZONE_APPEND) {
- int index = offset / bs->bl.zone_size;
+ int index = bdrv_zone_index(bs, offset);
offset = bs->wps->wp[index];
}
}
@@ -2615,7 +2615,7 @@ out:
bs->bl.zoned != BLK_Z_NONE) {
BlockZoneWps *wps = bs->wps;
if (ret == 0) {
- uint64_t *wp = &wps->wp[offset / bs->bl.zone_size];
+ uint64_t *wp = &wps->wp[bdrv_zone_index(bs, offset)];
if (!BDRV_ZT_IS_CONV(*wp)) {
if (type & QEMU_AIO_ZONE_APPEND) {
*offset_ptr = *wp;
@@ -3513,7 +3513,7 @@ static int coroutine_fn raw_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op,
return -EINVAL;
}
- uint32_t i = offset / bs->bl.zone_size;
+ uint32_t i = bdrv_zone_index(bs, offset);
uint32_t nrz = len / bs->bl.zone_size;
uint64_t *wp = &wps->wp[i];
if (BDRV_ZT_IS_CONV(*wp) && len != capacity) {
diff --git a/block/io.c b/block/io.c
index a916b236c3..cef23ee5bc 100644
--- a/block/io.c
+++ b/block/io.c
@@ -227,6 +227,11 @@ void bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp)
}
}
+ if (bs->bl.zone_size) {
+ assert(is_power_of_2(bs->bl.zone_size));
+ bs->bl.zone_size_bits = ctz64(bs->bl.zone_size);
+ }
+
if (bs->bl.request_alignment > BDRV_MAX_ALIGNMENT) {
error_setg(errp, "Driver requires too large request alignment");
}
@@ -3361,6 +3366,13 @@ out:
return co.ret;
}
+uint32_t bdrv_zone_index(BlockDriverState *bs, uint64_t offset)
+{
+ IO_CODE();
+
+ return offset >> bs->bl.zone_size_bits;
+}
+
void *qemu_blockalign(BlockDriverState *bs, size_t size)
{
IO_CODE();
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index ffcd327803..8c5b87793e 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -527,7 +527,7 @@ static bool check_zoned_request(VirtIOBlock *s, int64_t offset, int64_t len,
}
}
- index = offset / bs->bl.zone_size;
+ index = bdrv_zone_index(bs, offset);
if (BDRV_ZT_IS_CONV(bs->wps->wp[index])) {
*status = VIRTIO_BLK_S_ZONE_INVALID_CMD;
return false;
diff --git a/include/block/block-io.h b/include/block/block-io.h
index d34d846bb2..9d1c0eb7fb 100644
--- a/include/block/block-io.h
+++ b/include/block/block-io.h
@@ -126,6 +126,8 @@ int coroutine_fn GRAPH_RDLOCK bdrv_co_zone_append(BlockDriverState *bs,
int64_t *offset,
QEMUIOVector *qiov,
BdrvRequestFlags flags);
+/* The index of the zone that @offset falls in. */
+uint32_t bdrv_zone_index(BlockDriverState *bs, uint64_t offset);
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
index 7571ed9968..82aa0c1a6e 100644
--- a/include/block/block_int-common.h
+++ b/include/block/block_int-common.h
@@ -903,6 +903,13 @@ typedef struct BlockLimits {
/* zone size expressed in bytes */
uint64_t zone_size;
+ /*
+ * log2 of zone_size, derived by bdrv_refresh_limits(). A zoned device
+ * always has a zone size that is a power of two, so the zone an offset
+ * falls in is a shift rather than a division. See bdrv_zone_index().
+ */
+ uint32_t zone_size_bits;
+
/* total number of zones */
uint32_t nr_zones;
--
2.55.0
next prev parent reply other threads:[~2026-09-07 11:09 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-07 11:07 [PATCH v4 00/12] block: fix the zone write granularity and the zone append limit Niklas Cassel
2026-09-07 11:07 ` [PATCH v4 01/12] block: widen BlockLimits.zone_size to uint64_t Niklas Cassel
2026-09-09 18:04 ` Stefan Hajnoczi
2026-09-07 11:07 ` [PATCH v4 02/12] virtio-blk: do not merge requests across a zone boundary Niklas Cassel
2026-09-07 11:07 ` Niklas Cassel [this message]
2026-09-09 18:05 ` [PATCH v4 03/12] block: add a helper for the index of the zone an offset falls in Stefan Hajnoczi
2026-09-07 11:07 ` [PATCH v4 04/12] virtio-blk: report the effective zone write granularity Niklas Cassel
2026-09-09 18:27 ` Stefan Hajnoczi
2026-09-07 11:07 ` [PATCH v4 05/12] virtio-blk: check the write granularity of writes to sequential zones Niklas Cassel
2026-09-09 18:31 ` Stefan Hajnoczi
2026-09-07 11:07 ` [PATCH v4 06/12] hw/block: reject a zoned device whose write pointers are unaddressable Niklas Cassel
2026-09-09 18:34 ` Stefan Hajnoczi
2026-09-07 11:07 ` [PATCH v4 07/12] block: reject zone appends that are not a multiple of the sector size Niklas Cassel
2026-09-09 18:37 ` Stefan Hajnoczi
2026-09-09 18:42 ` Stefan Hajnoczi
2026-09-07 11:07 ` [PATCH v4 08/12] file-posix: remove the zone append write granularity check Niklas Cassel
2026-09-09 18:38 ` Stefan Hajnoczi
2026-09-07 11:07 ` [PATCH v4 09/12] file-posix: base the zone append limit on the transfer limit Niklas Cassel
2026-09-09 18:43 ` Stefan Hajnoczi
2026-09-07 11:07 ` [PATCH v4 10/12] virtio-blk: derive the maximum zone append size Niklas Cassel
2026-09-09 18:52 ` Stefan Hajnoczi
2026-09-07 11:07 ` [PATCH v4 11/12] file-posix: reject a zone append past the device capacity Niklas Cassel
2026-09-09 18:53 ` Stefan Hajnoczi
2026-09-07 11:07 ` [PATCH v4 12/12] file-posix: reject a zone append to a full or conventional zone Niklas Cassel
2026-09-09 18:54 ` Stefan Hajnoczi
2026-09-09 18:58 ` [PATCH v4 00/12] block: fix the zone write granularity and the zone append limit Stefan Hajnoczi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260907110748.1868714-4-cassel@kernel.org \
--to=cassel@kernel.org \
--cc=dlemoal@kernel.org \
--cc=faithilikerun@gmail.com \
--cc=fam@euphon.net \
--cc=hreitz@redhat.com \
--cc=kwolf@redhat.com \
--cc=mst@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.