From nobody Tue Jun 9 01:15:17 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1780937580; cv=none; d=zohomail.com; s=zohoarc; b=HhioFjIZhwfV3QKeAQsMuMKs1tOCjppL9DLOQXI9y6aq/PzfGFi1Gp7yGPt053DclpqtZLdOiiVniKa9ae7fRABd5pNDazjem3DokzDozoKPHzXgC2CjiRgIkM7kB7oPCTqnp70ItlDWyvAh1iYdxFYZWVPpze9kBuDYTwzK0r0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1780937580; 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=wIcX7uBMIyel2ip0LO84Sit5TYZWwQDf62QYkZJwfuc=; b=ZvsXaRkYnN+tnPBDT8UHNQXmHazwRLrQ/a/861V8hbo/1eXVbu/WLJNCdFEFETGUn2h2nlQUUahtljJU5sIM3mHuQjDRkjmDN95Q5gnM12MMUDvwzcmAV4FZiRN/OqKgJ4UY5PksovxAHMYg3W29TjSRmjpVfwIiFVwDu9552gE= 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 1780937580592463.0892804013529; Mon, 8 Jun 2026 09:53:00 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wWdD4-00012T-8C; Mon, 08 Jun 2026 12:52:22 -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 1wWdD2-00011C-9F for qemu-devel@nongnu.org; Mon, 08 Jun 2026 12:52:20 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wWdD0-0007Nl-22 for qemu-devel@nongnu.org; Mon, 08 Jun 2026 12:52:20 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-134-75wkCgHdNZOqaUOubVGIRQ-1; Mon, 08 Jun 2026 12:52:15 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 42506180064A; Mon, 8 Jun 2026 16:52:14 +0000 (UTC) Received: from merkur.fritz.box (unknown [10.44.50.32]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id DAE4719540CD; Mon, 8 Jun 2026 16:52:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780937536; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=wIcX7uBMIyel2ip0LO84Sit5TYZWwQDf62QYkZJwfuc=; b=PyR0czXLBAI3JljriH/JNIrtfUSy6xwNho4Kgd7R1gl4gRBGmhMrnf2QHpPr2CmE9uElFM HJ3Lc8zP0acmXMteo6ZDM1bDeML9yakKpT5u88tH734VWrtjhPOsHaj43HFOHmVCTSalTN zgeG91ZgOgaT9T8VC0RDke/8bqgTaEk= X-MC-Unique: 75wkCgHdNZOqaUOubVGIRQ-1 X-Mimecast-MFC-AGG-ID: 75wkCgHdNZOqaUOubVGIRQ_1780937534 From: Kevin Wolf To: qemu-block@nongnu.org Cc: kwolf@redhat.com, stefanha@redhat.com, qemu-devel@nongnu.org Subject: [PULL 1/8] virtio-blk: add missing VIRTIO_BLK_T_SCSI_CMD size check (CVE-2026-48914) Date: Mon, 8 Jun 2026 18:52:00 +0200 Message-ID: <20260608165207.307488-2-kwolf@redhat.com> In-Reply-To: <20260608165207.307488-1-kwolf@redhat.com> References: <20260608165207.307488-1-kwolf@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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=170.10.133.124; envelope-from=kwolf@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -24 X-Spam_score: -2.5 X-Spam_bar: -- X-Spam_report: (-2.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.445, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=unavailable 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 @redhat.com) X-ZM-MESSAGEID: 1780937582975154100 Content-Type: text/plain; charset="utf-8" From: Stefan Hajnoczi Check that the iovec containing struct virtio_scsi_inhdr is large enough before storing an error value there. Feifan Qian pointed out that this can be used to corrupt heap memory when the descriptor uses an MMIO address and a length of 1, forcing QEMU to allocate a 1-byte heap bounce buffer. virtio_stl_p() stores 4 bytes and therefore corrupts whatever is beyond the bounce buffer. Fixes: CVE-2026-48914 Fixes: f34e73cd69bd ("virtio-blk: report non-zero status when failing SG_IO= requests") Reported-by: Feifan Qian Cc: Paolo Bonzini Signed-off-by: Stefan Hajnoczi Message-ID: <20260526154957.1741622-1-stefanha@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- hw/block/virtio-blk.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 9cb9f1fb2b2..6b92066aff4 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -199,10 +199,16 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *re= q) =20 /* * The scsi inhdr is placed in the second-to-last input segment, just - * before the regular inhdr. + * before the regular inhdr. VIRTIO implementations normally do not re= ly on + * the precise message framing, but legacy implementations did and so = we do + * too for the legacy virtio-blk SCSI request type. * * Just put anything nonzero so that the ioctl fails in the guest. */ + if (elem->in_sg[elem->in_num - 2].iov_len !=3D sizeof(*scsi)) { + status =3D VIRTIO_BLK_S_IOERR; + goto fail; + } scsi =3D (void *)elem->in_sg[elem->in_num - 2].iov_base; virtio_stl_p(vdev, &scsi->errors, 255); status =3D VIRTIO_BLK_S_UNSUPP; --=20 2.54.0 From nobody Tue Jun 9 01:15:17 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1780937643; cv=none; d=zohomail.com; s=zohoarc; b=AdeLN8UJnuNXIz58Mclz+B+k9nU1fZXPXfdKktV4fsdX8xJn3yCBxkokdbokSgdDlV6MLW48aR3nPSbkkIGVn/J4Cv+4l/Nye0LtnA0tap1p4JywUEuKUGP+HTTbeIF91i+vjRkxE/hPXUoMcPcRaiLxTlwraXjPQayij0Dq61Y= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1780937643; 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=LE8c/pl/LqdqddNHJP6y9NruhA7u8u6MoJm+ZyEsBZQ=; b=nQUqXoEHvPOlduIbf+3ndjIkKRbVuXsFfg0+XCKZjFOSr8eOwgPL1MlofA8mnJXOezXVLeVLo7bmvMXOM0wGbgh9DDq0oZ+7QoQqlWHteFDlQWNOrkETC5gXh3gs8bDnxw8NKLEdFLWdWvDm9nbgvjXIp0PrFhkF0kWGq4sCum4= 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 1780937643273504.7706353498652; Mon, 8 Jun 2026 09:54:03 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wWdD7-000149-Lg; Mon, 08 Jun 2026 12:52:25 -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 1wWdD5-000136-G6 for qemu-devel@nongnu.org; Mon, 08 Jun 2026 12:52:23 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wWdD3-0007Or-DO for qemu-devel@nongnu.org; Mon, 08 Jun 2026 12:52:23 -0400 Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-563-1lUSYJzcMbu6YdyIOp9neA-1; Mon, 08 Jun 2026 12:52:17 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 433621955F0B; Mon, 8 Jun 2026 16:52:16 +0000 (UTC) Received: from merkur.fritz.box (unknown [10.44.50.32]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id DC82419540CB; Mon, 8 Jun 2026 16:52:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780937540; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=LE8c/pl/LqdqddNHJP6y9NruhA7u8u6MoJm+ZyEsBZQ=; b=ZqkSsBKKTVtzf4AFE8lNElvkpKiBD7w7ApH4y5gAXvU+VhPaSEbfS7rC5COwe+j7GLavY5 GgGE7XapdkjZBhJhNAki1WQ/pnFhGARqAGcf+d9c4AmHFdVypSR7E075i/cbSW0WA0w5QF EP9+PLk3zMOlejXJ9mao7AIThhWksMg= X-MC-Unique: 1lUSYJzcMbu6YdyIOp9neA-1 X-Mimecast-MFC-AGG-ID: 1lUSYJzcMbu6YdyIOp9neA_1780937536 From: Kevin Wolf To: qemu-block@nongnu.org Cc: kwolf@redhat.com, stefanha@redhat.com, qemu-devel@nongnu.org Subject: [PULL 2/8] qemu-img: add sub-command --remove-all to 'qemu-img bitmap' Date: Mon, 8 Jun 2026 18:52:01 +0200 Message-ID: <20260608165207.307488-3-kwolf@redhat.com> In-Reply-To: <20260608165207.307488-1-kwolf@redhat.com> References: <20260608165207.307488-1-kwolf@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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=170.10.129.124; envelope-from=kwolf@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 8 X-Spam_score: 0.8 X-Spam_bar: / X-Spam_report: (0.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.445, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_SBL_CSS=3.335, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no 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 @redhat.com) X-ZM-MESSAGEID: 1780937644881158501 Content-Type: text/plain; charset="utf-8" From: "Denis V. Lunev" From time to time it is needed to remove all bitmaps from the image. Before this patch the process is not very convenient. One should perform qemu-img info and parse the output to obtain all names. After that one should sequentially call qemu-img bitmap --remove for each present bitmap. The patch adds --remove-all sub-command to 'qemu-img bitmap'. The new sub-command also composes with other bitmap actions in the same invocation, so a common "wipe and recreate" workflow can be expressed as qemu-img bitmap --remove-all --add NEW FILE instead of enumerating existing bitmaps, removing them one by one, and only then adding the fresh one. Cc: Kevin Wolf Cc: Hanna Czenczek Signed-off-by: Denis V. Lunev Message-ID: <20260520235952.500250-1-den@openvz.org> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- docs/tools/qemu-img.rst | 10 +++- qemu-img.c | 55 ++++++++++++++++--- tests/qemu-iotests/tests/qemu-img-bitmaps | 24 ++++++++ tests/qemu-iotests/tests/qemu-img-bitmaps.out | 46 ++++++++++++++++ 4 files changed, 125 insertions(+), 10 deletions(-) diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst index 558b0eb84d6..b0c798b77a0 100644 --- a/docs/tools/qemu-img.rst +++ b/docs/tools/qemu-img.rst @@ -301,15 +301,19 @@ Command description: For write tests, by default a buffer filled with zeros is written. This = can be overridden with a pattern byte specified by *PATTERN*. =20 -.. option:: bitmap (--merge SOURCE | --add | --remove | --clear | --enable= | --disable)... [-b SOURCE_FILE [-F SOURCE_FMT]] [-g GRANULARITY] [--objec= t OBJECTDEF] [--image-opts | -f FMT] FILENAME BITMAP +.. option:: bitmap (--merge SOURCE | --add | --remove | --remove-all | --c= lear | --enable | --disable)... [-b SOURCE_FILE [-F SOURCE_FMT]] [-g GRANUL= ARITY] [--object OBJECTDEF] [--image-opts | -f FMT] FILENAME [BITMAP] =20 - Perform one or more modifications of the persistent bitmap *BITMAP* - in the disk image *FILENAME*. The various modifications are: + Perform one or more modifications of persistent bitmaps in the disk + image *FILENAME*. Most operations require *BITMAP* to be specified; + ``--remove-all`` operates on all bitmaps and does not take *BITMAP*. + The various modifications are: =20 ``--add`` to create *BITMAP*, enabled to record future edits. =20 ``--remove`` to remove *BITMAP*. =20 + ``--remove-all`` to remove all bitmaps. + ``--clear`` to clear *BITMAP*. =20 ``--enable`` to change *BITMAP* to start recording future edits. diff --git a/qemu-img.c b/qemu-img.c index c42dd4e995e..2f63d311413 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -87,6 +87,7 @@ enum { OPTION_FORCE =3D 276, OPTION_SKIP_BROKEN =3D 277, OPTION_LIMITS =3D 278, + OPTION_REMOVE_ALL =3D 279, }; =20 typedef enum OutputFormat { @@ -5018,6 +5019,7 @@ enum ImgBitmapAct { BITMAP_ENABLE, BITMAP_DISABLE, BITMAP_MERGE, + BITMAP_REMOVE_ALL, }; typedef struct ImgBitmapAction { enum ImgBitmapAct act; @@ -5036,7 +5038,7 @@ static int img_bitmap(const img_cmd_t *ccmd, int argc= , char **argv) BlockDriverState *bs =3D NULL, *src_bs =3D NULL; bool image_opts =3D false; int64_t granularity =3D 0; - bool add =3D false, merge =3D false; + bool add =3D false, merge =3D false, need_bitmap_name =3D false; QSIMPLEQ_HEAD(, ImgBitmapAction) actions; ImgBitmapAction *act, *act_next; const char *op; @@ -5052,6 +5054,7 @@ static int img_bitmap(const img_cmd_t *ccmd, int argc= , char **argv) {"add", no_argument, 0, OPTION_ADD}, {"granularity", required_argument, 0, 'g'}, {"remove", no_argument, 0, OPTION_REMOVE}, + {"remove-all", no_argument, 0, OPTION_REMOVE_ALL}, {"clear", no_argument, 0, OPTION_CLEAR}, {"enable", no_argument, 0, OPTION_ENABLE}, {"disable", no_argument, 0, OPTION_DISABLE}, @@ -5070,9 +5073,9 @@ static int img_bitmap(const img_cmd_t *ccmd, int argc= , char **argv) switch (c) { case 'h': cmd_help(ccmd, "[-f FMT | --image-opts]\n" -" ( --add [-g SIZE] | --remove | --clear | --enable | --disable |\n" -" --merge SOURCE [-b SRC_FILE [-F SRC_FMT]] )..\n" -" [--object OBJDEF] FILE BITMAP\n" +" ( --add [-g SIZE] | --remove | --remove-all | --clear | --enable = |\n" +" --disable | --merge SOURCE [-b SRC_FILE [-F SRC_FMT]] )..\n" +" [--object OBJDEF] FILE [BITMAP]\n" , " -f, --format FMT\n" " specify FILE format explicitly (default: probing is used)\n" @@ -5086,6 +5089,8 @@ static int img_bitmap(const img_cmd_t *ccmd, int argc= , char **argv) " with optional multiplier suffix (in powers of 1024)\n" " --remove\n" " removes BITMAP from FILE\n" +" --remove-all\n" +" removes all bitmaps from FILE\n" " --clear\n" " clears BITMAP in FILE\n" " --enable, --disable\n" @@ -5116,6 +5121,7 @@ static int img_bitmap(const img_cmd_t *ccmd, int argc= , char **argv) act->act =3D BITMAP_ADD; QSIMPLEQ_INSERT_TAIL(&actions, act, next); add =3D true; + need_bitmap_name =3D true; break; case 'g': granularity =3D cvtnum("granularity", optarg, true); @@ -5127,21 +5133,30 @@ static int img_bitmap(const img_cmd_t *ccmd, int ar= gc, char **argv) act =3D g_new0(ImgBitmapAction, 1); act->act =3D BITMAP_REMOVE; QSIMPLEQ_INSERT_TAIL(&actions, act, next); + need_bitmap_name =3D true; + break; + case OPTION_REMOVE_ALL: + act =3D g_new0(ImgBitmapAction, 1); + act->act =3D BITMAP_REMOVE_ALL; + QSIMPLEQ_INSERT_TAIL(&actions, act, next); break; case OPTION_CLEAR: act =3D g_new0(ImgBitmapAction, 1); act->act =3D BITMAP_CLEAR; QSIMPLEQ_INSERT_TAIL(&actions, act, next); + need_bitmap_name =3D true; break; case OPTION_ENABLE: act =3D g_new0(ImgBitmapAction, 1); act->act =3D BITMAP_ENABLE; QSIMPLEQ_INSERT_TAIL(&actions, act, next); + need_bitmap_name =3D true; break; case OPTION_DISABLE: act =3D g_new0(ImgBitmapAction, 1); act->act =3D BITMAP_DISABLE; QSIMPLEQ_INSERT_TAIL(&actions, act, next); + need_bitmap_name =3D true; break; case OPTION_MERGE: act =3D g_new0(ImgBitmapAction, 1); @@ -5149,6 +5164,7 @@ static int img_bitmap(const img_cmd_t *ccmd, int argc= , char **argv) act->src =3D optarg; QSIMPLEQ_INSERT_TAIL(&actions, act, next); merge =3D true; + need_bitmap_name =3D true; break; case 'b': src_filename =3D optarg; @@ -5165,8 +5181,8 @@ static int img_bitmap(const img_cmd_t *ccmd, int argc= , char **argv) } =20 if (QSIMPLEQ_EMPTY(&actions)) { - error_report("Need at least one of --add, --remove, --clear, " - "--enable, --disable, or --merge"); + error_report("Need at least one of --add, --remove, --remove-all, " + "--clear, --enable, --disable, or --merge"); goto out; } =20 @@ -5184,11 +5200,22 @@ static int img_bitmap(const img_cmd_t *ccmd, int ar= gc, char **argv) goto out; } =20 - if (optind !=3D argc - 2) { + if (need_bitmap_name && optind !=3D argc - 2) { error_report("Expecting filename and bitmap name"); goto out; } =20 + /* + * Every action other than --remove-all sets need_bitmap_name, so + * !need_bitmap_name means the only action(s) given were --remove-all + * and the BITMAP positional argument must be omitted. Combinations + * like '--remove-all --add foo' remain valid via the branch above. + */ + if (!need_bitmap_name && optind !=3D argc - 1) { + error_report("Expecting filename"); + goto out; + } + filename =3D argv[optind]; bitmap =3D argv[optind + 1]; =20 @@ -5225,6 +5252,20 @@ static int img_bitmap(const img_cmd_t *ccmd, int arg= c, char **argv) qmp_block_dirty_bitmap_remove(bs->node_name, bitmap, &err); op =3D "remove"; break; + case BITMAP_REMOVE_ALL: { + BdrvDirtyBitmap *bm; + while ((bm =3D bdrv_dirty_bitmap_first(bs))) { + const char *name =3D bdrv_dirty_bitmap_name(bm); + qmp_block_dirty_bitmap_remove(bs->node_name, name, &err); + if (err) { + /* Save name for proper error reporting */ + bitmap =3D name; + break; + } + } + op =3D "remove-all"; + break; + } case BITMAP_CLEAR: qmp_block_dirty_bitmap_clear(bs->node_name, bitmap, &err); op =3D "clear"; diff --git a/tests/qemu-iotests/tests/qemu-img-bitmaps b/tests/qemu-iotests= /tests/qemu-img-bitmaps index 7a3fe8c3d37..979bc0d6c9c 100755 --- a/tests/qemu-iotests/tests/qemu-img-bitmaps +++ b/tests/qemu-iotests/tests/qemu-img-bitmaps @@ -161,6 +161,30 @@ $QEMU_IMG convert --bitmaps -O qcow2 "$TEST_IMG" "$TES= T_IMG.copy" TEST_IMG=3D"$TEST_IMG.copy" _img_info --format-specific \ | _filter_irrelevant_img_info =20 +echo +echo "=3D=3D=3D Check --remove-all =3D=3D=3D" +echo + +# Start from a fresh image so prior state does not bleed into the assertio= ns +_rm_test_img "$TEST_IMG" +_make_test_img 10M +$QEMU_IMG bitmap --add -f $IMGFMT "$TEST_IMG" b0 +$QEMU_IMG bitmap --add -f $IMGFMT "$TEST_IMG" b1 +$QEMU_IMG bitmap --add -f $IMGFMT "$TEST_IMG" b2 +_img_info --format-specific | _filter_irrelevant_img_info + +# Sweep every bitmap in a single command, no BITMAP positional +echo +$QEMU_IMG bitmap --remove-all -f $IMGFMT "$TEST_IMG" +_img_info --format-specific | _filter_irrelevant_img_info + +# Wipe + recreate in one invocation: only 'fresh' should remain +echo +$QEMU_IMG bitmap --add -f $IMGFMT "$TEST_IMG" b0 +$QEMU_IMG bitmap --add -f $IMGFMT "$TEST_IMG" b1 +$QEMU_IMG bitmap --remove-all --add -f $IMGFMT "$TEST_IMG" fresh +_img_info --format-specific | _filter_irrelevant_img_info + # success, all done echo '*** done' rm -f $seq.full diff --git a/tests/qemu-iotests/tests/qemu-img-bitmaps.out b/tests/qemu-iot= ests/tests/qemu-img-bitmaps.out index 74b81f703b0..99290d3ba5e 100644 --- a/tests/qemu-iotests/tests/qemu-img-bitmaps.out +++ b/tests/qemu-iotests/tests/qemu-img-bitmaps.out @@ -180,4 +180,50 @@ Format specific information: name: b2 granularity: 65536 corrupt: false + +=3D=3D=3D Check --remove-all =3D=3D=3D + +Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D10485760 +image: TEST_DIR/t.IMGFMT +file format: IMGFMT +virtual size: 10 MiB (10485760 bytes) +cluster_size: 65536 +Format specific information: + bitmaps: + [0]: + flags: + [0]: auto + name: b0 + granularity: 65536 + [1]: + flags: + [0]: auto + name: b1 + granularity: 65536 + [2]: + flags: + [0]: auto + name: b2 + granularity: 65536 + corrupt: false + +image: TEST_DIR/t.IMGFMT +file format: IMGFMT +virtual size: 10 MiB (10485760 bytes) +cluster_size: 65536 +Format specific information: + corrupt: false + +image: TEST_DIR/t.IMGFMT +file format: IMGFMT +virtual size: 10 MiB (10485760 bytes) +cluster_size: 65536 +Format specific information: + bitmaps: + [0]: + flags: + [0]: auto + name: fresh + granularity: 65536 + corrupt: false *** done --=20 2.54.0 From nobody Tue Jun 9 01:15:17 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1780937591; cv=none; d=zohomail.com; s=zohoarc; b=V73vafRCH9zZyvOFb+B0g6FAnITVWagaqCme7sIWctDf7uG0iSYKOwaBsgcCgacEtXvsz/8257JHtBa88lChi5ie2RZCdFT7MHuty8KFplMjTo+yFIFJZzbirFkUkEgYyRdsRKaMjNkwnUQGJaVTOcjGV6oJWKi/h7T7OcNrg7k= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1780937591; 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=Eic9GKGBf47K8jtvuXw5EiaNEoND+0CxI3NLGGfrcLE=; b=UtH9sIJq/nIPLwgItIZR8e2DmvAITXw7gFSnO/2Ot5R2dbAOKKTKY73UdEja1z+xwPxBW0Cs5EDt4hKIixknpVr+lw8H0icHxLY2kGtkm/sffq3oaSdjQKcUgdrhsiz5OILLJKCG1ZfCy7fDSc/wOvIBEeXuU3QvXkvbanI9Ixg= 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 178093759139490.27724075885703; Mon, 8 Jun 2026 09:53:11 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wWdD8-00014I-4P; Mon, 08 Jun 2026 12:52:26 -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 1wWdD6-00013b-MX for qemu-devel@nongnu.org; Mon, 08 Jun 2026 12:52:24 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wWdD4-0007PU-RY for qemu-devel@nongnu.org; Mon, 08 Jun 2026 12:52:24 -0400 Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-636-kpAv1JhaNc2sG3ob7vsHEw-1; Mon, 08 Jun 2026 12:52:19 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 14053195411C; Mon, 8 Jun 2026 16:52:18 +0000 (UTC) Received: from merkur.fritz.box (unknown [10.44.50.32]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id AE0EC19540CB; Mon, 8 Jun 2026 16:52:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780937542; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Eic9GKGBf47K8jtvuXw5EiaNEoND+0CxI3NLGGfrcLE=; b=cE4elFY4Oymy3Dz8shAu4wpRBeB6WBY8Aq56M3KeVg/9VdidiP7vjO2aXf/hkGtttRGYAq C0DxZG6I6G7dS85KXNBtgCLjDwUrzOwNIqB/VtA7h4RjtkODMCQIaDC4xCDcNwbeUtnlOW UP0yT1GfGx3IusfYBZDCjfI5BryA3ow= X-MC-Unique: kpAv1JhaNc2sG3ob7vsHEw-1 X-Mimecast-MFC-AGG-ID: kpAv1JhaNc2sG3ob7vsHEw_1780937538 From: Kevin Wolf To: qemu-block@nongnu.org Cc: kwolf@redhat.com, stefanha@redhat.com, qemu-devel@nongnu.org Subject: [PULL 3/8] iotests/136: Test stats-intervals with -blockdev/-device Date: Mon, 8 Jun 2026 18:52:02 +0200 Message-ID: <20260608165207.307488-4-kwolf@redhat.com> In-Reply-To: <20260608165207.307488-1-kwolf@redhat.com> References: <20260608165207.307488-1-kwolf@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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=170.10.133.124; envelope-from=kwolf@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 8 X-Spam_score: 0.8 X-Spam_bar: / X-Spam_report: (0.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.445, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_SBL_CSS=3.335, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no 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 @redhat.com) X-ZM-MESSAGEID: 1780937594852154101 Content-Type: text/plain; charset="utf-8" Commit 9f0c763e introduced the "stats-intervals" qdev property for block devices, a setting that was previously only accessible with -drive. Extend the corresponding test to include test cases that set the property on -device instead, both with -drive and -blockdev. We wouldn't really improve coverage with testing every combination of account_invalid and account_failed with all modes to set up statistics, so it seems good enough to test all combinations with the old way, and only both True or both False with the additional ways. Signed-off-by: Kevin Wolf Message-ID: <20260521101854.31997-1-kwolf@redhat.com> Reviewed-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- tests/qemu-iotests/136 | 87 ++++++++++++++++++++++++++++++++------ tests/qemu-iotests/136.out | 4 +- 2 files changed, 77 insertions(+), 14 deletions(-) diff --git a/tests/qemu-iotests/136 b/tests/qemu-iotests/136 index 8fce88bd677..58df876bafc 100755 --- a/tests/qemu-iotests/136 +++ b/tests/qemu-iotests/136 @@ -22,6 +22,7 @@ =20 import iotests import os +import json =20 interval_length =3D 10 nsec_per_sec =3D 1000000000 @@ -45,14 +46,22 @@ class BlockDeviceStatsTestCase(iotests.QMPTestCase): wr_highest_offset =3D 0 account_invalid =3D False account_failed =3D False + stats_in_device =3D False + use_blockdev =3D False =20 def blockstats(self, device): result =3D self.vm.qmp("query-blockstats") for r in result['return']: - if r['device'] =3D=3D device: + if r['device'] =3D=3D device or r['node-name'] =3D=3D device: return r['stats'] raise Exception("Device not found for blockstats: %s" % device) =20 + def qemu_io(self, cmd): + if self.use_blockdev: + self.vm.hmp_qemu_io("virtio0/virtio-backend", cmd, qdev=3DTrue) + else: + self.vm.hmp_qemu_io("drive0", cmd) + def create_blkdebug_file(self): file =3D open(blkdebug_file, 'w') file.write(''' @@ -73,17 +82,54 @@ sector =3D "%d" =20 @iotests.skip_if_unsupported(required_drivers) def setUp(self): - drive_args =3D [] - drive_args.append("stats-intervals.0=3D%d" % interval_length) - drive_args.append("stats-account-invalid=3D%s" % - (self.account_invalid and "on" or "off")) - drive_args.append("stats-account-failed=3D%s" % - (self.account_failed and "on" or "off")) - drive_args.append("file.image.read-zeroes=3Don") self.create_blkdebug_file() - self.vm =3D iotests.VM().add_drive('blkdebug:%s:%s://' % - (blkdebug_file, self.test_driver), - ','.join(drive_args)) + self.vm =3D iotests.VM() + + drive_args =3D [ + "file.image.read-zeroes=3Don", + ] + if self.stats_in_device: + interface =3D "none" + dev_args =3D { + "driver": "virtio-blk", + "id": "virtio0", + "drive": "drive0", + "stats-intervals": [ interval_length ], + "account-invalid": "on" if self.account_invalid else "off", + "account-failed": "on" if self.account_failed else "off", + } + self.vm.add_device(json.dumps(dev_args)) + else: + assert not self.use_blockdev + interface =3D "virtio" + drive_args +=3D [ + "stats-intervals.0=3D%d" % interval_length, + "stats-account-invalid=3D%s" % + (self.account_invalid and "on" or "off"), + "stats-account-failed=3D%s" % + (self.account_failed and "on" or "off"), + ] + + if self.use_blockdev: + blockdev_args =3D { + "node-name": "drive0", + "driver": "raw", + "file": { + "driver": "blkdebug", + "config": blkdebug_file, + "image": { + "driver": self.test_driver, + "read-zeroes": True, + }, + }, + } + self.vm.add_blockdev(json.dumps(blockdev_args)) + else: + self.vm.add_drive('blkdebug:%s:%s://' % + (blkdebug_file, self.test_driver), + ','.join(drive_args), + interface=3Dinterface) + self.vm.launch() # Set an initial value for the clock self.vm.qtest("clock_step %d" % nsec_per_sec) @@ -261,7 +307,7 @@ sector =3D "%d" =20 # Now perform all operations for op in ops: - self.vm.hmp_qemu_io("drive0", op) + self.qemu_io(op) =20 # Update the expected totals self.total_rd_bytes +=3D rd_ops * rd_size @@ -328,6 +374,12 @@ sector =3D "%d" # All values must be sane before doing any I/O self.check_values() =20 +class BlockDeviceStatsTestDevice(BlockDeviceStatsTestCase): + stats_in_device =3D True + +class BlockDeviceStatsTestBlockdev(BlockDeviceStatsTestCase): + stats_in_device =3D True + use_blockdev =3D True =20 class BlockDeviceStatsTestAccountInvalid(BlockDeviceStatsTestCase): account_invalid =3D True @@ -341,6 +393,17 @@ class BlockDeviceStatsTestAccountBoth(BlockDeviceStats= TestCase): account_invalid =3D True account_failed =3D True =20 +class BlockDeviceStatsTestAccountBothDevice(BlockDeviceStatsTestCase): + account_invalid =3D True + account_failed =3D True + stats_in_device =3D True + +class BlockDeviceStatsTestAccountBothBlockdev(BlockDeviceStatsTestCase): + account_invalid =3D True + account_failed =3D True + stats_in_device =3D True + use_blockdev =3D True + class BlockDeviceStatsTestCoroutine(BlockDeviceStatsTestCase): test_driver =3D "null-co" =20 diff --git a/tests/qemu-iotests/136.out b/tests/qemu-iotests/136.out index cfa5c0d0e66..4823c113d58 100644 --- a/tests/qemu-iotests/136.out +++ b/tests/qemu-iotests/136.out @@ -1,5 +1,5 @@ -................................... +............................................................... ---------------------------------------------------------------------- -Ran 35 tests +Ran 63 tests =20 OK --=20 2.54.0 From nobody Tue Jun 9 01:15:17 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1780937580; cv=none; d=zohomail.com; s=zohoarc; b=YHlJ1HEPDYY4FwOZifXj6oi+lejXnVSw0yE3P84aBokZVItYB3Ar9JdgW97zt2xqwEdPBmEgxxd9NybfFRi9l3XrxM5yGOEJ3hGZcNFl+qv/L1Uhs9WDEI3KPWGKkdpbkcCBGJYlfMuW00bCxaOu9mNOeI18xfH+YHRStEWu+HY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1780937580; 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=zvuuVNSZbz51c4hsITO2+CK9lFnoymnQfTg5fzme91o=; b=d/LgLD7ABW7/XW0TSOQFOR1FzN6983Ppxyz9wMspJLfNjbjmwZDrOGRwhtR/VKYNaz8JkHVTs6SXFOZVG4Jh9sIxIoxNnKe4aeMJnwa9nwI5JzAubdyOzqSZt+gELGLVjUTMQ+67Tg3RgXKfgvwx7HZXtYrq5RiK33Uum9NMnEg= 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 1780937580594320.3887805486081; Mon, 8 Jun 2026 09:53:00 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wWdD8-00014n-Jr; Mon, 08 Jun 2026 12:52:26 -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 1wWdD7-00013l-1o for qemu-devel@nongnu.org; Mon, 08 Jun 2026 12:52:25 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wWdD4-0007PR-ME for qemu-devel@nongnu.org; Mon, 08 Jun 2026 12:52:24 -0400 Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-661-oZXfcTY6ORWaX5WsaKx03Q-1; Mon, 08 Jun 2026 12:52:20 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id DB21219560A1; Mon, 8 Jun 2026 16:52:19 +0000 (UTC) Received: from merkur.fritz.box (unknown [10.44.50.32]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 7E8BC19540CD; Mon, 8 Jun 2026 16:52:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780937542; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=zvuuVNSZbz51c4hsITO2+CK9lFnoymnQfTg5fzme91o=; b=DUJWNDal4AyXx+PcuXITTLYqZ4TCzZjbext7QhVFqcZeBID+M/fd0GHPfHJJRzBnakoWzO YB69QI4xi3zfOSI7NinTTPOuCbyoYTKteG1UOp9NRAUbnGS3nL4FwKB1LSs9UGn07/YT8t 2cPVAlZqkNGPhAoaUmyGHtliUijt0p4= X-MC-Unique: oZXfcTY6ORWaX5WsaKx03Q-1 X-Mimecast-MFC-AGG-ID: oZXfcTY6ORWaX5WsaKx03Q_1780937540 From: Kevin Wolf To: qemu-block@nongnu.org Cc: kwolf@redhat.com, stefanha@redhat.com, qemu-devel@nongnu.org Subject: [PULL 4/8] qcow2: Fix data loss on zero write with detect-zeroes=unmap Date: Mon, 8 Jun 2026 18:52:03 +0200 Message-ID: <20260608165207.307488-5-kwolf@redhat.com> In-Reply-To: <20260608165207.307488-1-kwolf@redhat.com> References: <20260608165207.307488-1-kwolf@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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=170.10.129.124; envelope-from=kwolf@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 8 X-Spam_score: 0.8 X-Spam_bar: / X-Spam_report: (0.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.445, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_SBL_CSS=3.335, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no 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 @redhat.com) X-ZM-MESSAGEID: 1780937583091154100 Content-Type: text/plain; charset="utf-8" From: Thomas Lamprecht Commit b8bfb1478d ("qcow2: Fix corruption on discard during write with COW") added a wait_for_dependencies() at the start of qcow2_subcluster_zeroize(). That fixes the inconsistency it set out to fix, but turns the lock-protected pre-check in the caller, qcow2_co_pwrite_zeroes(), into a stale one: the wait yields s->lock, so an in-flight allocating write whose QCowL2Meta is already on s->cluster_allocs (but whose L2 entry is not yet linked) gets to link its entry during the yield. When the zeroize wakes, the cluster is now NORMAL, and with BDRV_REQ_MAY_UNMAP the free path in zero_in_l2_slice() unmaps the just-written cluster, silently dropping the data write's payload. This is reachable with detect-zeroes=3Dunmap (the default for VirtIO disks with discard on in Proxmox VE), under which the block layer auto-promotes all-zero buffers to BDRV_REQ_ZERO_WRITE | BDRV_REQ_MAY_UNMAP. A memory-constrained Debian guest running 'apt full-upgrade' on such a disk reproduces it as random SIGSEGVs: swapped-out code pages come back as zero. Wait for in-flight dependencies before the lock-protected check in qcow2_co_pwrite_zeroes(). If a write linked its L2 entry during the wait, the type check now fails and the block layer falls back to a bounce-buffered zero write that only touches the requested subrange, preserving the racing write's data. Promote wait_for_dependencies() to qcow2_wait_for_dependencies() so qcow2.c can call it. Fixes: b8bfb1478d ("qcow2: Fix corruption on discard during write with COW") Cc: qemu-stable@nongnu.org Tested-by: Fiona Ebner Reviewed-by: Fiona Ebner Signed-off-by: Thomas Lamprecht Message-ID: <20260522151318.238064-1-t.lamprecht@proxmox.com> [kwolf: Reverted unnecessary change to 'nr' assignment] Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/qcow2.h | 4 ++++ block/qcow2-cluster.c | 10 +++++----- block/qcow2.c | 8 +++++++- tests/qemu-iotests/046 | 23 +++++++++++++++++++++++ tests/qemu-iotests/046.out | 10 ++++++++++ 5 files changed, 49 insertions(+), 6 deletions(-) diff --git a/block/qcow2.h b/block/qcow2.h index 192a45d596b..ce517040c47 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -966,6 +966,10 @@ int coroutine_fn GRAPH_RDLOCK qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset, uint64_t b= ytes, int flags); =20 +void coroutine_mixed_fn +qcow2_wait_for_dependencies(BlockDriverState *bs, uint64_t guest_offset, + uint64_t bytes); + int GRAPH_RDLOCK qcow2_expand_zero_clusters(BlockDriverState *bs, BlockDriverAmendStatusCB *status_cb, diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 8b1e80bd0b3..e02fae6a0c6 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1474,9 +1474,9 @@ static int coroutine_fn handle_dependencies(BlockDriv= erState *bs, return 0; } =20 -static void coroutine_mixed_fn wait_for_dependencies(BlockDriverState *bs, - uint64_t guest_offset, - uint64_t bytes) +void coroutine_mixed_fn qcow2_wait_for_dependencies(BlockDriverState *bs, + uint64_t guest_offset, + uint64_t bytes) { BDRVQcow2State *s =3D bs->opaque; QCowL2Meta *m =3D NULL; @@ -2035,7 +2035,7 @@ int qcow2_cluster_discard(BlockDriverState *bs, uint6= 4_t offset, * We don't need to allocate a QCowL2Meta for the discard operation be= cause * s->lock is held for the duration of the whole operation. */ - wait_for_dependencies(bs, offset, bytes); + qcow2_wait_for_dependencies(bs, offset, bytes); =20 /* Caller must pass aligned values, except at image end */ assert(QEMU_IS_ALIGNED(offset, s->cluster_size)); @@ -2204,7 +2204,7 @@ int coroutine_fn qcow2_subcluster_zeroize(BlockDriver= State *bs, uint64_t offset, * We don't need to allocate a QCowL2Meta for the zeroize operation be= cause * s->lock is held for the duration of the whole operation. */ - wait_for_dependencies(bs, offset, bytes); + qcow2_wait_for_dependencies(bs, offset, bytes); =20 /* If we have to stay in sync with an external data file, zero out * s->data_file first. */ diff --git a/block/qcow2.c b/block/qcow2.c index 81fd299b4c7..19271b10a49 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -4234,10 +4234,16 @@ qcow2_co_pwrite_zeroes(BlockDriverState *bs, int64_= t offset, int64_t bytes, } =20 qemu_co_mutex_lock(&s->lock); - /* We can have new write after previous check */ offset -=3D head; bytes =3D s->subcluster_size; nr =3D s->subcluster_size; + /* + * Wait for in-flight allocating writes first: otherwise the type + * check below could pass on UNALLOCATED while a yet-to-link_l2 wr= ite + * completes during qcow2_subcluster_zeroize()'s own wait, letting= the + * resumed MAY_UNMAP discard the just-written data. + */ + qcow2_wait_for_dependencies(bs, offset, bytes); ret =3D qcow2_get_host_offset(bs, offset, &nr, &off, &type); if (ret < 0 || (type !=3D QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN && diff --git a/tests/qemu-iotests/046 b/tests/qemu-iotests/046 index e03dd401479..0d84b5c1c75 100755 --- a/tests/qemu-iotests/046 +++ b/tests/qemu-iotests/046 @@ -226,6 +226,26 @@ aio_write -z 0x140000 0x10000 resume A aio_flush EOF + +# Start an allocating write to a previously unallocated cluster and, before +# its L2 update is linked, issue a concurrent sub-cluster zero write with +# MAY_UNMAP that targets a disjoint range within the same cluster. The zero +# write's head/tail are zero (cluster is unallocated), so qcow2_co_pwrite_= zeroes +# would expand it to the full subcluster. Without waiting for dependencies +# before the zero write's "unallocated" type check, that check passes, +# qcow2_subcluster_zeroize then yields in wait_for_dependencies, the alloc= ating +# write links its L2 entry, and the resumed zeroize unmaps the cluster - +# silently discarding the just-written data. Waiting first makes the zero = write +# fall back to a bounce-buffered real write, which only touches its own +# subrange. +cat < (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 1780937584337411.6466606462749; Mon, 8 Jun 2026 09:53:04 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wWdDE-00017u-8U; Mon, 08 Jun 2026 12:52:32 -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 1wWdDB-000161-LJ for qemu-devel@nongnu.org; Mon, 08 Jun 2026 12:52:29 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wWdD9-0007RK-Jn for qemu-devel@nongnu.org; Mon, 08 Jun 2026 12:52:29 -0400 Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-515-kchEgXYeNt6xPA-ESevHSQ-1; Mon, 08 Jun 2026 12:52:22 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id ACF3519560BC; Mon, 8 Jun 2026 16:52:21 +0000 (UTC) Received: from merkur.fritz.box (unknown [10.44.50.32]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 5030D19540CD; Mon, 8 Jun 2026 16:52:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780937547; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=nDiqQrC3nUP4exfyx8PeHDHHKOZJHe0VpF/uyZDrUlA=; b=Ni/nfsT9nBEslXqIaxAliw8yXks5VhDQoU3FnY9vJOKZ6oQUP4zcqkGNHQdKmHXVhrsp52 oKUWB0/JqS5pyKjh/a48OM9o9pLPz+I/dzyvXb4NEe+zfqiLhOEJDseflaJLOFKEfsNGrL H8SvlONufW3pq5vDsgIjmDh4/bO39DY= X-MC-Unique: kchEgXYeNt6xPA-ESevHSQ-1 X-Mimecast-MFC-AGG-ID: kchEgXYeNt6xPA-ESevHSQ_1780937541 From: Kevin Wolf To: qemu-block@nongnu.org Cc: kwolf@redhat.com, stefanha@redhat.com, qemu-devel@nongnu.org Subject: [PULL 5/8] block/export/fuse: use struct fuse_init_in Date: Mon, 8 Jun 2026 18:52:04 +0200 Message-ID: <20260608165207.307488-6-kwolf@redhat.com> In-Reply-To: <20260608165207.307488-1-kwolf@redhat.com> References: <20260608165207.307488-1-kwolf@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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=170.10.129.124; envelope-from=kwolf@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 8 X-Spam_score: 0.8 X-Spam_bar: / X-Spam_report: (0.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.445, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_SBL_CSS=3.335, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no 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 @redhat.com) X-ZM-MESSAGEID: 1780937586559158500 Content-Type: text/plain; charset="utf-8" From: Fiona Ebner The code is switched to use the current 'struct fuse_init_in' in preparation to use the FUSE_DIRECT_IO_ALLOW_MMAP feature, which is part of the flags2 member that got added in protocol version 5.36. To not break compatibility with older kernels, the check for whether the full header of an operation was read in co_read_from_fuse_fd() needs to be adapted. In particular, for a FUSE_INIT operation, the protocol version must be considered, because the length of the header changed with protocol version 7.36. Always using the length of the old, shorter struct was inaccurate, since for newer protocol versions this might mean accepting a truncated read for FUSE_INIT. Users of the init header that want to use parts of the extended structure must check with the using_old_fuse_init_in() helper function if they may do so. Cc: qemu-stable@nongnu.org Fixes: a94a1d7699 ("fuse: Manually process requests (without libfuse)") Signed-off-by: Fiona Ebner Message-ID: <20260506145424.10249-2-f.ebner@proxmox.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/export/fuse.c | 56 +++++++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/block/export/fuse.c b/block/export/fuse.c index a2a478d2934..35218e31976 100644 --- a/block/export/fuse.c +++ b/block/export/fuse.c @@ -51,23 +51,16 @@ #define FUSE_MAX_READ_BYTES (MIN(BDRV_REQUEST_MAX_BYTES, 1 * 1024 * 1024)) #define FUSE_MAX_WRITE_BYTES (64 * 1024) =20 -/* - * fuse_init_in structure before 7.36. We don't need the flags2 field add= ed - * there, so we can work with the smaller older structure to stay compatib= le - * with older kernels. - */ -struct fuse_init_in_compat { - uint32_t major; - uint32_t minor; - uint32_t max_readahead; - uint32_t flags; -}; - typedef struct FuseRequestInHeader { struct fuse_in_header common; /* All supported requests */ union { - struct fuse_init_in_compat init; + /* + * When using_old_fuse_init_in() is true, then the smaller older s= truct + * is used by the kernel. The flags2 member and other new members = must + * be treated as absent then. + */ + struct fuse_init_in init; struct fuse_open_in open; struct fuse_setattr_in setattr; struct fuse_read_in read; @@ -629,6 +622,16 @@ static int clone_fuse_fd(int fd, Error **errp) return new_fd; } =20 +/** + * Check whether the smaller older fuse_init_in structure from before prot= ocol + * version 7.36 is used. The flags2 member and other new members must be t= reated + * as absent then. + */ +static bool using_old_fuse_init_in(const struct fuse_init_in *in) +{ + return in->major < 7 || (in->major =3D=3D 7 && in->minor < 36); +} + /** * Try to read a single request from the FUSE FD. * Takes a FuseQueue pointer in `opaque`. @@ -693,6 +696,31 @@ static void coroutine_fn co_read_from_fuse_fd(void *op= aque) goto no_request; } =20 + /* + * If the request is of type FUSE_INIT, need to check the version to + * actually determine the length of the fuse_init_in structure used by= the + * kernel. In protocol version 7.36, the structure was extended. + */ + if (in_hdr->common.opcode =3D=3D FUSE_INIT) { + /* Length of the fuse_init_in structure before 7.36. */ + size_t old_init_hdr_len =3D 16; + + /* + * Expect at least the size of the smaller older structure to ensu= re the + * version can be checked. + */ + if (unlikely(ret < sizeof(in_hdr->common) + old_init_hdr_len)) { + error_report("FUSE_INIT request truncated, read only %zi bytes= ", + ret); + fuse_write_err(fuse_fd, &in_hdr->common, -EINVAL); + goto no_request; + } + + if (using_old_fuse_init_in(&in_hdr->init)) { + op_hdr_len =3D old_init_hdr_len; + } + } + if (unlikely(ret < sizeof(in_hdr->common) + op_hdr_len)) { error_report("FUSE request truncated, expected %zu bytes, read %zi= " "bytes", @@ -826,7 +854,7 @@ static bool is_regular_file(const char *path, Error **e= rrp) */ static ssize_t coroutine_fn GRAPH_RDLOCK fuse_co_init(FuseExport *exp, struct fuse_init_out *out, - const struct fuse_init_in_compat *in) + const struct fuse_init_in *in) { const uint32_t supported_flags =3D FUSE_ASYNC_READ | FUSE_ASYNC_DIO; =20 --=20 2.54.0 From nobody Tue Jun 9 01:15:17 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1780937581; cv=none; d=zohomail.com; s=zohoarc; b=ibxqG8z4BXr7HtWlE59JGdw2dfC8PN3fmA9VcfQMwn51m5+v7tTBUbTtaTBcOw/JqmEFl8N4UIgvHS1PKjnkmxce7xsQyprhTXDFITvgw4emh3ai7TAkHl8p7jw+ao9x66V0NMxl3O7fnFc+GYR9N3miKDhpbwnoVpDtmwYKav0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1780937581; 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=BdkstQtJlrBa9g+LfmT+wxquA4LIIzMoYHUWQrCrWMg=; b=e3S1LGbnCgXmxkKf1MvsydPBbT1h7FY/2nd4QCqu79J+fWngP429EtEZTeB14yhB7Nh2QzDVb02Xkp5mKvHHtBUVhdDDTRxJF5d0yiBMSYH+a+ghVFh3salKAoG/ZvlU/UR8Oaxcs59fXlo9MpS4bjSE66XMmW45re1NOjbEhCI= 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 1780937581005924.8578921723073; Mon, 8 Jun 2026 09:53:01 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wWdDB-000163-Qi; Mon, 08 Jun 2026 12:52:29 -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 1wWdDA-00015T-7N for qemu-devel@nongnu.org; Mon, 08 Jun 2026 12:52:28 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wWdD8-0007Qw-LW for qemu-devel@nongnu.org; Mon, 08 Jun 2026 12:52:27 -0400 Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-569-Iftsn9zoOVaMd_bkKVgrWQ-1; Mon, 08 Jun 2026 12:52:24 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7EFAD195411C; Mon, 8 Jun 2026 16:52:23 +0000 (UTC) Received: from merkur.fritz.box (unknown [10.44.50.32]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 2274C19540CB; Mon, 8 Jun 2026 16:52:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780937546; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=BdkstQtJlrBa9g+LfmT+wxquA4LIIzMoYHUWQrCrWMg=; b=iJaXZiy0lFZVJiJYiJ76lk6oKMlUctkQ6499as2W++H8SAgAaTDcynupPfuXWQBlpickQG kyi0p+Srsg9e5arf06z/VSDVZt0T3Q3d+HCWA6QAE3YwqDeS7y57B34tsf+MNa7MDchUeC +Ip+ylQGWLgqSrLTZsSGuLNTuPHJF7U= X-MC-Unique: Iftsn9zoOVaMd_bkKVgrWQ-1 X-Mimecast-MFC-AGG-ID: Iftsn9zoOVaMd_bkKVgrWQ_1780937543 From: Kevin Wolf To: qemu-block@nongnu.org Cc: kwolf@redhat.com, stefanha@redhat.com, qemu-devel@nongnu.org Subject: [PULL 6/8] block/export/fuse: set FUSE_DIRECT_IO_ALLOW_MMAP flag to fix regression Date: Mon, 8 Jun 2026 18:52:05 +0200 Message-ID: <20260608165207.307488-7-kwolf@redhat.com> In-Reply-To: <20260608165207.307488-1-kwolf@redhat.com> References: <20260608165207.307488-1-kwolf@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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=170.10.129.124; envelope-from=kwolf@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 8 X-Spam_score: 0.8 X-Spam_bar: / X-Spam_report: (0.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.445, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_SBL_CSS=3.335, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no 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 @redhat.com) X-ZM-MESSAGEID: 1780937582983158500 Content-Type: text/plain; charset="utf-8" From: Fiona Ebner Commit 8599559580 ("fuse: Set direct_io and parallel_direct_writes") broke use cases that require mmap() with MAP_SHARED on the export. In particular, swtpm_setup using its 'file://' protocol requires this. From the kernel documentation [0]: > To allow shared mmap, the FUSE_DIRECT_IO_ALLOW_MMAP flag may be > enabled in the FUSE_INIT reply. Set the FUSE_DIRECT_IO_ALLOW_MMAP flag to restore compatibility with users requiring shared mmap. The FUSE_INIT_EXT flag needs to be set for the flags2 member to have an effect. [0]: https://www.kernel.org/doc/html/next/filesystems/fuse/fuse-io.html Cc: qemu-stable@nongnu.org Fixes: 8599559580 ("fuse: Set direct_io and parallel_direct_writes") Signed-off-by: Fiona Ebner Message-ID: <20260506145424.10249-3-f.ebner@proxmox.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/export/fuse.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/block/export/fuse.c b/block/export/fuse.c index 35218e31976..c0e8dfb6430 100644 --- a/block/export/fuse.c +++ b/block/export/fuse.c @@ -856,7 +856,8 @@ static ssize_t coroutine_fn GRAPH_RDLOCK fuse_co_init(FuseExport *exp, struct fuse_init_out *out, const struct fuse_init_in *in) { - const uint32_t supported_flags =3D FUSE_ASYNC_READ | FUSE_ASYNC_DIO; + uint32_t supported_flags =3D FUSE_ASYNC_READ | FUSE_ASYNC_DIO; + uint32_t flags2 =3D 0; =20 if (in->major !=3D 7) { error_report("FUSE major version mismatch: We have 7, but kernel h= as %" @@ -871,13 +872,21 @@ fuse_co_init(FuseExport *exp, struct fuse_init_out *o= ut, return -EINVAL; } =20 + if (!using_old_fuse_init_in(in)) { + /* The flags2 flags must be shifted down by 32 bits. */ + const uint32_t supported_flags2 =3D FUSE_DIRECT_IO_ALLOW_MMAP >> 3= 2; + /* flags2 is only considered if FUSE_INIT_EXT is set. */ + supported_flags =3D supported_flags | FUSE_INIT_EXT; + flags2 =3D in->flags2 & supported_flags2; + } + *out =3D (struct fuse_init_out) { .major =3D 7, .minor =3D MIN(FUSE_KERNEL_MINOR_VERSION, in->minor), .max_readahead =3D in->max_readahead, .max_write =3D FUSE_MAX_WRITE_BYTES, .flags =3D in->flags & supported_flags, - .flags2 =3D 0, + .flags2 =3D flags2, =20 /* libfuse maximum: 2^16 - 1 */ .max_background =3D UINT16_MAX, --=20 2.54.0 From nobody Tue Jun 9 01:15:17 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1780937629; cv=none; d=zohomail.com; s=zohoarc; b=lDeTwVUO8as6lEPcDir/Jw5zamHEgN2SHciVVggIwSBq9kfnIuIJq1Me5wM/yp5hsCXL14Bhas9t5lXVZy5RzjaxVl1mG1x2wIgmqwXpzmyPg8iiCFRvz8CozUk7MmnTCaolxOhkqbAgBS32ykVdF+tJKMnYwZkOXslPBuKlhoc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1780937629; 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=gIeebk1q6gdGRjMOS5TNro+4Fks1Jr7HbLNnxXTKGig=; b=V+FEy6YmlIyjAUzamZcEZIQiaWDqsVnKcD9nYbXx5qdsUPpli0a/EVA66ptB8CEup+z7SghX2sej1/L+rXTA/R46oYF+pjuHMqmgVFThKTh2DqCi9ci/X/Yk18909bM3lB9Obm5sD6D0zDWFd7BUn1kskejKPtN9DWdgEVgA6ks= 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 1780937629803624.4743286742007; Mon, 8 Jun 2026 09:53:49 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wWdDF-00018E-MQ; Mon, 08 Jun 2026 12:52:33 -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 1wWdDE-00017v-9e for qemu-devel@nongnu.org; Mon, 08 Jun 2026 12:52:32 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wWdDC-0007SS-Ez for qemu-devel@nongnu.org; Mon, 08 Jun 2026 12:52:31 -0400 Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-19-ZyueqmrUPWyPPJqQNTc2ag-1; Mon, 08 Jun 2026 12:52:26 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 508471954237; Mon, 8 Jun 2026 16:52:25 +0000 (UTC) Received: from merkur.fritz.box (unknown [10.44.50.32]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E919D19540CB; Mon, 8 Jun 2026 16:52:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780937549; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=gIeebk1q6gdGRjMOS5TNro+4Fks1Jr7HbLNnxXTKGig=; b=VUdB+dSI4RrezqWVY81BSh25flxLdsAfdMsmblFwComaIGx9FGNk8OhZyTGleRhQm6GcEH PPblFtlggPkFBeA3A6qblRdSlJWUteTIx4iYECmFlHLlb6GjTfrDmQdZZl4imD4yidxQDA hH9X3YmSM+L+rRcuHTwO5A3kJtH7BRM= X-MC-Unique: ZyueqmrUPWyPPJqQNTc2ag-1 X-Mimecast-MFC-AGG-ID: ZyueqmrUPWyPPJqQNTc2ag_1780937545 From: Kevin Wolf To: qemu-block@nongnu.org Cc: kwolf@redhat.com, stefanha@redhat.com, qemu-devel@nongnu.org Subject: [PULL 7/8] iotests: test shared mmap for fuse export Date: Mon, 8 Jun 2026 18:52:06 +0200 Message-ID: <20260608165207.307488-8-kwolf@redhat.com> In-Reply-To: <20260608165207.307488-1-kwolf@redhat.com> References: <20260608165207.307488-1-kwolf@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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=170.10.129.124; envelope-from=kwolf@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 8 X-Spam_score: 0.8 X-Spam_bar: / X-Spam_report: (0.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.445, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_SBL_CSS=3.335, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no 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 @redhat.com) X-ZM-MESSAGEID: 1780937631448154100 Content-Type: text/plain; charset="utf-8" From: Fiona Ebner This test would have worked before commit 8599559580 ("fuse: Set direct_io and parallel_direct_writes") and is working again since commit HEAD~1 ("block/export/fuse: set FUSE_DIRECT_IO_ALLOW_MMAP flag to fix regression"). Signed-off-by: Fiona Ebner Message-ID: <20260506145424.10249-4-f.ebner@proxmox.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- tests/qemu-iotests/tests/fuse-mmap-shared | 103 ++++++++++++++++++ tests/qemu-iotests/tests/fuse-mmap-shared.out | 5 + 2 files changed, 108 insertions(+) create mode 100755 tests/qemu-iotests/tests/fuse-mmap-shared create mode 100644 tests/qemu-iotests/tests/fuse-mmap-shared.out diff --git a/tests/qemu-iotests/tests/fuse-mmap-shared b/tests/qemu-iotests= /tests/fuse-mmap-shared new file mode 100755 index 00000000000..a0a10cea6ac --- /dev/null +++ b/tests/qemu-iotests/tests/fuse-mmap-shared @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +# group: rw +# +# Test that a FUSE export can be mmap()-ed with MAP_SHARED +# +# Copyright (C) 2026 Proxmox Server Solutions GmbH +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os +import itertools +import mmap +from mmap import MAP_SHARED +from pathlib import Path + +import iotests +from iotests import qemu_img, qemu_io, QemuStorageDaemon + +def test_fuse_support(mount_point): + test_qsd =3D QemuStorageDaemon('--blockdev', 'null-co,node-name=3Dnode= 0', + qmp=3DTrue) + res =3D test_qsd.qmp('block-export-add', { + 'id': 'exp0', + 'type': 'fuse', + 'node-name': 'node0', + 'mountpoint': mount_point, + 'allow-other': 'off' + }) + test_qsd.stop() + if 'error' in res: + assert (res['error']['desc'] =3D=3D + "Parameter 'type' does not accept value 'fuse'") + iotests.notrun('No FUSE support') + +# Shared mmap when using direct IO is only supported for Linux kernels >= =3D 6.6 +# with commit e78662e818f94 ("fuse: add a new fuse init flag to relax +# estrictions in no cache mode"). +def test_linux_kernel_support(): + [major, minor] =3D map(int, os.uname().release.split('.')[:2]) + if major < 6 or (major =3D=3D 6 and minor < 6): + iotests.notrun('No kernel support for shared mmap with direct IO') + +image_size =3D 1 * 1024 * 1024 +image =3D os.path.join(iotests.test_dir, 'image.' + iotests.imgfmt) +fuse_mount_point =3D os.path.join(iotests.test_dir, 'export.fuse') +Path(fuse_mount_point).touch() + +test_fuse_support(fuse_mount_point) +test_linux_kernel_support() + +class TestMmapShared(iotests.QMPTestCase): + + def setUp(self): + qemu_img('create', '-f', iotests.imgfmt, image, str(image_size)) + qemu_io(image, '-c', f'write -P 23 0 {image_size}') + + self.qsd =3D QemuStorageDaemon(qmp=3DTrue) + + self.qsd.cmd('blockdev-add', { + 'node-name': 'node0', + 'driver': iotests.imgfmt, + 'file': { + 'driver': 'file', + 'filename': image + } + }) + + self.qsd.cmd('block-export-add', { + 'id': 'exp0', + 'type': 'fuse', + 'node-name': 'node0', + 'mountpoint': fuse_mount_point, + 'writable': True, + 'allow-other': 'off' + }) + + def tearDown(self): + self.stop_qsd() + os.remove(image) + os.remove(fuse_mount_point) + + def stop_qsd(self): + if self.qsd: + self.qsd.stop() + self.qsd =3D None + + def test_mmap_shared(self): + with open(fuse_mount_point, 'r+b') as file: + with mmap.mmap(file.fileno(), image_size, flags=3DMAP_SHARED) = as mm: + buf =3D bytearray(image_size) + buf[:] =3D itertools.repeat(23, image_size) + assert mm.read(image_size) =3D=3D buf + buf[:] =3D itertools.repeat(42, image_size) + mm.seek(0) + mm.write(buf) + mm.flush() + self.stop_qsd() + qemu_io(image, '-c', f'read -P 42 0 {image_size}') + +if __name__ =3D=3D '__main__': + iotests.main(supported_fmts=3D['generic'], + supported_protocols=3D['file'], + supported_platforms=3D['linux']) diff --git a/tests/qemu-iotests/tests/fuse-mmap-shared.out b/tests/qemu-iot= ests/tests/fuse-mmap-shared.out new file mode 100644 index 00000000000..ae1213e6f86 --- /dev/null +++ b/tests/qemu-iotests/tests/fuse-mmap-shared.out @@ -0,0 +1,5 @@ +. +---------------------------------------------------------------------- +Ran 1 tests + +OK --=20 2.54.0 From nobody Tue Jun 9 01:15:17 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1780937607; cv=none; d=zohomail.com; s=zohoarc; b=blAnYGat/U9hoomk9pYXlqNpOivvNQgeExcJjzaZmvLYANC2geOBKEJWOFxK186zI4euqEyPx7QuPeXglYMKsyiKdIPSWkysAmHiXxK7ZEnas1jnI1COanrb1KtdCixgH0mn5eVF9ErolnPOSH/e3X5CgWu+I0sAsI5cf8Q9Zrk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1780937607; 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=kFatSLeHNba9Z+OqDy1gPE5uw+z+yLfNr64dou9P3L8=; b=mjI8zVuCrKGqWJI/UIkdbnI6wDgaUt7yVHYGPorJjT8bpXQ1F4YhsToIWoxKUFSWIQu9ygyvKw62+5qeSVBKhzaYP+Rnt3pFFhv/jtk8NKWrrIN1lJubW02eni8ve037p0u1OaDHg/8bn4rACiqAMyYD40nOsgDw/BKtIVGarwg= 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 1780937607051815.6903831620741; Mon, 8 Jun 2026 09:53:27 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wWdDI-000191-3J; Mon, 08 Jun 2026 12:52:36 -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 1wWdDH-00018d-6T for qemu-devel@nongnu.org; Mon, 08 Jun 2026 12:52:35 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wWdDE-0007US-Nn for qemu-devel@nongnu.org; Mon, 08 Jun 2026 12:52:34 -0400 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-562-JlSEW41cMrOyhz5X9K09YA-1; Mon, 08 Jun 2026 12:52:28 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 3600B180064A; Mon, 8 Jun 2026 16:52:27 +0000 (UTC) Received: from merkur.fritz.box (unknown [10.44.50.32]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id BA63619540CD; Mon, 8 Jun 2026 16:52:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780937552; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=kFatSLeHNba9Z+OqDy1gPE5uw+z+yLfNr64dou9P3L8=; b=hkQu55Ah0HGOTiUssOPYfT1s4RyxL5828ClUCulPsYwfGIYuHv1UEOndSQY8T3vGxPmRK8 qBLoVCD7zNYqBqYs8TbkZJFW9L1r3LEV9CMmK3RyI/89om1p4NdKGO95wKO6yF7yYvBNMb 3jN7wIZWZhLmgidaICBjbgj3RC+c6Ww= X-MC-Unique: JlSEW41cMrOyhz5X9K09YA-1 X-Mimecast-MFC-AGG-ID: JlSEW41cMrOyhz5X9K09YA_1780937547 From: Kevin Wolf To: qemu-block@nongnu.org Cc: kwolf@redhat.com, stefanha@redhat.com, qemu-devel@nongnu.org Subject: [PULL 8/8] qed: Don't try to flush during incoming migration Date: Mon, 8 Jun 2026 18:52:07 +0200 Message-ID: <20260608165207.307488-9-kwolf@redhat.com> In-Reply-To: <20260608165207.307488-1-kwolf@redhat.com> References: <20260608165207.307488-1-kwolf@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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=170.10.133.124; envelope-from=kwolf@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -24 X-Spam_score: -2.5 X-Spam_bar: -- X-Spam_report: (-2.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.445, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=unavailable 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 @redhat.com) X-ZM-MESSAGEID: 1780937609137154100 Content-Type: text/plain; charset="utf-8" From: Fabiano Rosas It's not possible to access the image file while there is an incoming migration in progress, the QEMU process doesn't hold any locks to the storage at this point so nodes are inactive. Attempting to flush leads to an assert at bdrv_co_write_req_prepare(): assert(!(bs->open_flags & BDRV_O_INACTIVE)) The issue is reproducible by running iotest 181 on a host under cpu load. The migration must coincide with the header already containing the QED_F_NEED_CHECK flag. The sequence of events is as follows, with the respective call stacks referenced below: During block device init, bdrv_qed_attach_aio_context() starts the 'need_check' timer. The timer will not fire during incoming migration as it uses QEMU_CLOCK_VIRTUAL (to avoid this very issue, as the code comment indicates). (0) However, there's still bdrv_qed_drain_begin() which uses the fact that the timer is live to decide whether to start the qed_need_check_timer_entry() directly. (1) The qed_need_check_timer_entry() eventually calls into qed_write_header() -> bdrv_co_pwrite() leading to the assert. (2) Skip creating the 'need_check' timer whenever the image is inactive. The stacks: (0) =3D=3D issues timer_mod =3D=3D #6 in qed_start_need_check_timer at ../block/qed.c:340 #7 in bdrv_qed_attach_aio_context at ../block/qed.c:373 #8 in bdrv_qed_do_open at ../block/qed.c:556 #9 in bdrv_qed_open_entry at ../block/qed.c:582 #10 in coroutine_trampoline at ../util/coroutine-ucontext.c:175 #0 in qemu_coroutine_switch<+120> at ../util/coroutine-ucontext.c:321 #1 in qemu_aio_coroutine_enter<+356> at ../util/qemu-coroutine.c:293 #2 in aio_co_enter<+179> at ../util/async.c:710 #3 in aio_co_wake<+53> at ../util/async.c:695 #4 in thread_pool_co_cb<+47> at ../util/thread-pool.c:283 #5 in thread_pool_completion_bh<+241> at ../util/thread-pool.c:202 #6 in aio_bh_call<+109> at ../util/async.c:173 #7 in aio_bh_poll<+299> at ../util/async.c:220 #8 in aio_poll<+690> at ../util/aio-posix.c:745 #9 in bdrv_qed_open<+392> at ../block/qed.c:607 #10 in bdrv_open_driver<+327> at ../block.c:1678 #11 in bdrv_open_common<+1619> at ../block.c:2008 #12 in bdrv_open_inherit<+2556> at ../block.c:4191 #13 in bdrv_open<+118> at ../block.c:4286 #14 in blk_new_open<+199> at ../block/block-backend.c:458 #15 in blockdev_init<+2011> at ../blockdev.c:612 #16 in drive_new<+3008> at ../blockdev.c:1008 #17 in drive_init_func<+51> at ../system/vl.c:662 #18 in qemu_opts_foreach<+227> at ../util/qemu-option.c:1148 #19 in configure_blockdev<+350> at ../system/vl.c:721 #20 in qemu_create_early_backends<+343> at ../system/vl.c:2076 #21 in qemu_init<+12483> at ../system/vl.c:3778 #22 in main<+46> at ../system/main.c:71 (1) =3D=3D sees timer_pending =3D=3D #6 in bdrv_qed_drain_begin at ../block/qed.c:391 #7 in bdrv_do_drained_begin at ../block/io.c:366 #8 in bdrv_do_drained_begin_quiesce at ../block/io.c:386 #9 in bdrv_child_cb_drained_begin at ../block.c:1207 #10 in bdrv_parent_drained_begin_single at ../block/io.c:133 #11 in bdrv_parent_drained_begin at ../block/io.c:64 #12 in bdrv_do_drained_begin at ../block/io.c:364 #13 in bdrv_drained_begin at ../block/io.c:393 #14 in blk_drain at ../block/block-backend.c:2101 #15 in blk_unref at ../block/block-backend.c:544 #16 in bdrv_open_inherit at ../block.c:4197 #17 in bdrv_open at ../block.c:4286 #18 in blk_new_open at ../block/block-backend.c:458 #19 in blockdev_init at ../blockdev.c:612 #20 in drive_new at ../blockdev.c:1008 #21 in drive_init_func at ../system/vl.c:662 #22 in qemu_opts_foreach at ../util/qemu-option.c:1148 #23 in configure_blockdev at ../system/vl.c:721 #24 in qemu_create_early_backends at ../system/vl.c:2076 #25 in qemu_init at ../system/vl.c:3778 #26 in main at ../system/main.c:71 (2) =3D=3D crashes =3D=3D #5 in __assert_fail (assertion=3D"!(bs->open_flags & BDRV_O_INACTIVE)", f= ile=3D"../block/io.c", line=3D1977 #6 in bdrv_co_write_req_prepare at ../block/io.c:1977 #7 in bdrv_aligned_pwritev at ../block/io.c:2099 #8 in bdrv_co_pwritev_part at ../block/io.c:2316 #9 in bdrv_co_pwritev at ../block/io.c:2233 #10 in bdrv_co_pwrite at ../include/block/block_int-io.h:77 #11 in qed_write_header at ../block/qed.c:128 #12 in qed_need_check_timer at ../block/qed.c:305 #13 in qed_need_check_timer_entry at ../block/qed.c:319 Note that this issue is not exactly the same as what's been reported in Gitlab, but given how easily this reproduces, I imagine it has to be happening in that setup as well. Link: https://gitlab.com/qemu-project/qemu/-/work_items/3515 Signed-off-by: Fabiano Rosas Message-ID: <20260603193813.2327596-1-farosas@suse.de> Reviewed-by: Stefan Hajnoczi Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/qed.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/block/qed.c b/block/qed.c index da23a83d623..0eccfa21c98 100644 --- a/block/qed.c +++ b/block/qed.c @@ -351,16 +351,22 @@ static void bdrv_qed_detach_aio_context(BlockDriverSt= ate *bs) { BDRVQEDState *s =3D bs->opaque; =20 - qed_cancel_need_check_timer(s); - timer_free(s->need_check_timer); - s->need_check_timer =3D NULL; + if (s->need_check_timer) { + qed_cancel_need_check_timer(s); + timer_free(s->need_check_timer); + s->need_check_timer =3D NULL; + } } =20 -static void bdrv_qed_attach_aio_context(BlockDriverState *bs, - AioContext *new_context) +static void GRAPH_RDLOCK bdrv_qed_attach_aio_context(BlockDriverState *bs, + AioContext *new_conte= xt) { BDRVQEDState *s =3D bs->opaque; =20 + if (bdrv_is_inactive(bs)) { + return; + } + s->need_check_timer =3D aio_timer_new(new_context, QEMU_CLOCK_VIRTUAL, SCALE_NS, qed_need_check_timer_cb, s); --=20 2.54.0