From nobody Mon Sep 28 00:09:31 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=kernel.org ARC-Seal: i=1; a=rsa-sha256; t=1787166684; cv=none; d=zohomail.com; s=zohoarc; b=P9uGlsxgDjEQPm0G1hP7M53bIRIx76jGSY/vq5srttJ1604WGzEkyH3s/RPEMiYFXftOx00JeAVATLgcgPzDDHuCh3Sze/PP2zTKaZ+sJaqvQgzSz78SLY2EvKWgpKOv34kHjfHp1nkwE4EVWLIvcxZdCbjRkwy4Wf9cVHRMsmg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787166684; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=QPxqmF6HxpLantW710NlQtv2E0xlp2I9cy+oJ74aQEA=; b=ArrWgZtH2KEFZHQOP3aNQ/Ij8jHRQPGH2vHgbZsb6b1yxcBkmnmHDUV8ihZ4k3Losq9G0dnx0FAe94QkKjIbRjPcPe/FrkRFYBjTd8AFPp9m2r7O6M5xufUxYoTiKwAA4PB7cfJhE/eEKjQzOmlGbWnkgNE4ZWCCTNVRSOdpmd4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787166684825269.5633049498523; Wed, 19 Aug 2026 12:11:24 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wwlgS-0005TI-OO; Wed, 19 Aug 2026 15:10:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wwlgR-0005St-JJ; Wed, 19 Aug 2026 15:10:43 -0400 Received: from tor.source.kernel.org ([2600:3c04:e001:324:0:1991:8:25]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wwlgQ-0002G7-24; Wed, 19 Aug 2026 15:10:43 -0400 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) by tor.source.kernel.org (Postfix) with ESMTP id 31DA861834; Wed, 19 Aug 2026 19:10:40 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id F0D581F000E9; Wed, 19 Aug 2026 19:10:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787166639; bh=QPxqmF6HxpLantW710NlQtv2E0xlp2I9cy+oJ74aQEA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=dzFAj38KvL9dAy9tN6rzRd/9NE0xZPUA/7rjM1YzJByhHtl92r30A+wLPHNs7exX4 XQiplp3qhbH/1lRfYZk5uUbB/fxXs6zKSzu2zcSdEtJ1pWkp1y/uXyfqHoM9S7+gG7 I8EGc2uk3EzUFQio5w1PoLHo5H3p1x8ZMI/M5Wn2u5GXQ8ICE+wrDzihcmyOTzQKHv SLVauVCbNUH2ghQFW5SFikytD3F483ohdlz3dPU4L2RgP3JkCFqbRVf7ppcwgzDJ5f /M/L1LQrOgphEbqrhXlMwHPVqqpm5kNyWOniZ0ue8KOM/u7uFCLXJa1YpK5jSycB0B GG8xRYKiS4I9w== From: Niklas Cassel To: Stefan Hajnoczi , "Michael S. Tsirkin" , Kevin Wolf , Hanna Reitz Cc: Sam Li , Damien Le Moal , Niklas Cassel , qemu-block@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH 1/2] virtio-blk: report the effective zone write granularity Date: Wed, 19 Aug 2026 21:10:30 +0200 Message-ID: <20260819191031.3001633-2-cassel@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260819191031.3001633-1-cassel@kernel.org> References: <20260819191031.3001633-1-cassel@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2600:3c04:e001:324:0:1991:8:25; envelope-from=cassel@kernel.org; helo=tor.source.kernel.org X-Spam_score_int: -23 X-Spam_score: -2.4 X-Spam_bar: -- X-Spam_report: (-2.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.341, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @kernel.org) X-ZM-MESSAGEID: 1787166686013158500 Content-Type: text/plain; charset="utf-8" For ZBC/ZAC devices the write granularity is the physical block size, so a 512e SMR disk exposed through a host_device backend has a logical block size of 512 and a zone write granularity of 4096. We told the driver 512 while raw_co_zone_append() rejects anything that is not 4096 byte aligned, so the driver saw a plain I/O error for a request it had been told was valid. Report the larger of the backend granularity and the logical block size instead. The driver cannot issue writes finer than the logical block size, so the larger of the two is the constraint that applies. This matches what a Linux guest derives for itself: blk_validate_zoned_limits() raises zone_write_granularity to the logical block size, and blk_stack_limits() stacks it with max(). Add it as a helper and use it for the zone append offset check in check_zoned_request(), which validated against bs->bl.write_granularity, so that the value reported to the driver and the value that requests are validated against cannot drift apart. The helper cannot return zero because blkconf_blocksizes() always leaves a logical block size behind, so the check no longer needs to guard against an unset granularity. Fixes: 4f7366506a96 ("virtio-blk: add zoned storage emulation for zoned dev= ices") Signed-off-by: Niklas Cassel --- hw/block/virtio-blk.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 6b92066aff..ef5581c1e6 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -478,6 +478,18 @@ typedef struct ZoneCmdData { }; } ZoneCmdData; =20 +/* + * The write granularity that the device reports to the driver in + * virtio_blk_zoned_characteristics: the offset and size alignment constra= int + * for writes and zone appends to sequential zones. + */ +static uint32_t virtio_blk_write_granularity(VirtIOBlock *s) +{ + BlockDriverState *bs =3D blk_bs(s->blk); + + return MAX(bs->bl.write_granularity, s->conf.conf.logical_block_size); +} + /* * check zoned_request: error checking before issuing requests. If all che= cks * passed, return true. @@ -500,11 +512,11 @@ static bool check_zoned_request(VirtIOBlock *s, int64= _t offset, int64_t len, } =20 if (append) { - if (bs->bl.write_granularity) { - if ((offset % bs->bl.write_granularity) !=3D 0) { - *status =3D VIRTIO_BLK_S_ZONE_UNALIGNED_WP; - return false; - } + uint32_t wg =3D virtio_blk_write_granularity(s); + + if ((offset % wg) !=3D 0) { + *status =3D VIRTIO_BLK_S_ZONE_UNALIGNED_WP; + return false; } =20 index =3D offset / bs->bl.zone_size; @@ -1254,7 +1266,8 @@ static void virtio_blk_update_config(VirtIODevice *vd= ev, uint8_t *config) bs->bl.max_active_zones); virtio_stl_p(vdev, &blkcfg.zoned.max_open_zones, bs->bl.max_open_zones); - virtio_stl_p(vdev, &blkcfg.zoned.write_granularity, blk_size); + virtio_stl_p(vdev, &blkcfg.zoned.write_granularity, + virtio_blk_write_granularity(s)); virtio_stl_p(vdev, &blkcfg.zoned.max_append_sectors, bs->bl.max_append_sectors); } else { --=20 2.55.0 From nobody Mon Sep 28 00:09:31 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=kernel.org ARC-Seal: i=1; a=rsa-sha256; t=1787166674; cv=none; d=zohomail.com; s=zohoarc; b=Jg035MaWh6Y+6Tw4EGb9zZVgOXbWbfDTnpkTpafiJ4IImu39EznslYrhjZZuyui0Xy43wVg5/kirolwIFaADmRSMsKQZiCFwbZxusIT/6OroinJNKg8yrerwaPsUhf//KTbjZCI1jh1ZnNCoBNPVOQ+ziMKleVdPf+oi3F7S2W4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787166674; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=b79w992CcGeaFPRTZAWb9+4+Yjxr9UMHRwyVdcYQ+vA=; b=Nht/5HhYZ9Ud+ce5eT5XmL0gH94u4TSfkChuqYIZ+8DB9idIc8eH2G63ntgQ3AV8YeOoGFskk/diA85K9XG1oRup1aFExV2nyJKGWV/l5j5/OI/3++B7/jOqKpZ7u57VYlYTBUWhkCMxoPH7nTDqzlRKq+GsdL+2WhqbyGytrzI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787166674524876.3189281592272; Wed, 19 Aug 2026 12:11:14 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wwlgU-0005U9-Nr; Wed, 19 Aug 2026 15:10:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wwlgT-0005Tw-DR; Wed, 19 Aug 2026 15:10:45 -0400 Received: from sea.source.kernel.org ([172.234.252.31]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wwlgR-0002GX-P5; Wed, 19 Aug 2026 15:10:45 -0400 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) by sea.source.kernel.org (Postfix) with ESMTP id 70D5543512; Wed, 19 Aug 2026 19:10:42 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 67E1B1F000E9; Wed, 19 Aug 2026 19:10:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787166642; bh=b79w992CcGeaFPRTZAWb9+4+Yjxr9UMHRwyVdcYQ+vA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=mdhw1ObNmZMUjsauZjXQf+3M9nd1DG1NqEXoC3+nqlRAWuRcLJJye2bXKt7Mkb8aP iTQyM+AdDii/5Q9WP79hmG2GlZCY1fVOq54zzt9uvEnzC1qEbjAy3I8OqozJd7DdJ/ t9GWvvvWlnoi0ur4DsMcYdX+yMEbzOe821OzdCNqV452NZGcAeMCvjsp4oFhkCsFHN oM1je1UjY/gNCu1mQtzLbJw4eSRwe8xbYv0U/B8JnMhxApqwf66uNhl5Jm2HECsxwK Ec31A8oOj9JxXv/L/2e2U4h9HCazrr7oPRxyXE8xBmng95z89PKX0/ZzFmnSqam9AY 3f6uIja7uw6pQ== From: Niklas Cassel To: "Michael S. Tsirkin" , Stefan Hajnoczi , Kevin Wolf , Hanna Reitz Cc: Sam Li , Damien Le Moal , Niklas Cassel , qemu-block@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH 2/2] virtio-blk: check the write granularity of writes to sequential zones Date: Wed, 19 Aug 2026 21:10:31 +0200 Message-ID: <20260819191031.3001633-3-cassel@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260819191031.3001633-1-cassel@kernel.org> References: <20260819191031.3001633-1-cassel@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=172.234.252.31; envelope-from=cassel@kernel.org; helo=sea.source.kernel.org X-Spam_score_int: -23 X-Spam_score: -2.4 X-Spam_bar: -- X-Spam_report: (-2.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.341, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @kernel.org) X-ZM-MESSAGEID: 1787166675962158500 Content-Type: text/plain; charset="utf-8" All VIRTIO_BLK_T_OUT requests issued to sequential zones and all VIRTIO_BLK_T_ZONE_APPEND requests must have an offset and a data size that are multiples of the write granularity reported by the device (virtio 1.4, 5.2.6.1), and a violation is reported as VIRTIO_BLK_S_ZONE_UNALIGNED_WP (virtio 1.4, 5.2.6). Neither request type was fully checked. Zone appends validated only the offset, while writes were not checked at all. Check the size of the appended data, and both the offset and the size of a write, against virtio_blk_write_granularity(), so that every request the device accepts is one that the driver was told is valid. Writes to conventional zones keep no alignment constraint beyond the logical block size. The write path performs the check after virtio_blk_sect_range_ok() so that the zone index derived from the guest supplied sector is known to be in range. Signed-off-by: Niklas Cassel --- hw/block/virtio-blk.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index ef5581c1e6..b1be0e9eda 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -514,7 +514,7 @@ static bool check_zoned_request(VirtIOBlock *s, int64_t= offset, int64_t len, if (append) { uint32_t wg =3D virtio_blk_write_granularity(s); =20 - if ((offset % wg) !=3D 0) { + if ((offset % wg) !=3D 0 || (len % wg) !=3D 0) { *status =3D VIRTIO_BLK_S_ZONE_UNALIGNED_WP; return false; } @@ -903,6 +903,28 @@ static int virtio_blk_handle_request(VirtIOBlockReq *r= eq, MultiReqBuffer *mrb) return 0; } =20 + if (is_write) { + BlockDriverState *bs =3D blk_bs(s->blk); + int64_t offset =3D req->sector_num << BDRV_SECTOR_BITS; + uint32_t wg =3D virtio_blk_write_granularity(s); + + /* + * Both the offset and the size of a write to a sequential zone + * must be a multiple of the write granularity reported by the + * device. Conventional zones are not constrained. The zone in= dex + * is derived from a guest supplied sector, so this must come = after + * virtio_blk_sect_range_ok() has bounded it. + */ + if (bs->bl.zoned !=3D BLK_Z_NONE && + ((offset % wg) !=3D 0 || (req->qiov.size % wg) !=3D 0) && + !BDRV_ZT_IS_CONV(bs->wps->wp[offset / bs->bl.zone_size])) { + virtio_blk_req_complete(req, VIRTIO_BLK_S_ZONE_UNALIGNED_W= P); + block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_WRITE= ); + g_free(req); + return 0; + } + } + block_acct_start(blk_get_stats(s->blk), &req->acct, req->qiov.size, is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_READ); =20 --=20 2.55.0