From nobody Mon Feb 2 07:30:15 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1769622813; cv=none; d=zohomail.com; s=zohoarc; b=GT6G6ds0gTEjYreGlX29OIUqchBuVbruJEe7q76b7SKvkDX6Wxti5ReKW60fjZQoCvFlyeopFtOA8OHSUDKWKqvwNHX8Qw9w2NtqEmDkZbzNhz+B1zGBT+/95y5ZHeAUNyHg7U6pzjdUn/pHs/BDOdYIU0j8rw55RLa/lzU2ODI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769622813; h=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id:Cc; bh=64oMHWxRqmI0V2E9H3iBQNYe2t1vGQCEd3mHTCwb1U0=; b=g7WmMXKn+wmTXSZEeWavNKYYO1seNmT9lZLjmQnV4xgkfVY5271uGj9WZbyUpmDmn+0+akRlZI2nZOv2eIS3oPot9a3+WQftRZa0DerDTozmeR9dA5hFJT8FHoDZWvHfKYhhDHa9NAghGdyphVqJKfApONfx6yRkJPsEPwPz9rU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 176962281377613.299038143979374; Wed, 28 Jan 2026 09:53:33 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 993) id E932041A4A; Wed, 28 Jan 2026 12:53:32 -0500 (EST) Received: from [172.19.199.3] (lists.libvirt.org [8.43.85.245]) by lists.libvirt.org (Postfix) with ESMTP id 2C27E43E6E; Wed, 28 Jan 2026 12:50:22 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 993) id EC5BC418CA; Wed, 28 Jan 2026 12:50:11 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 55CA941AAD for ; Wed, 28 Jan 2026 12:49:43 -0500 (EST) 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-344-uWkGFLyxOTCNZfb0cABXKQ-1; Wed, 28 Jan 2026 12:49:41 -0500 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (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 BE525180035C for ; Wed, 28 Jan 2026 17:49:40 +0000 (UTC) Received: from speedmetal.lan (unknown [10.45.242.3]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id ED53F1958DC1 for ; Wed, 28 Jan 2026 17:49:39 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-5.0 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_PASS autolearn=unavailable autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1769622583; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=64oMHWxRqmI0V2E9H3iBQNYe2t1vGQCEd3mHTCwb1U0=; b=EMwc+PAqte3tluVwUvsIzDZFha4G4kA+xlaRU0J/bAHiS5mTjtM85ZCUE0yGRDpA6lPSJ2 ih1RWWbYI4glapLl+ncQ5Xn2VOlYSPeZ1sWXLylOZ7iCLmUniZLx6bi51NUBoS3WyaKePT xfGzSDEmhuxgrFsomyo7Es/KbB/Gy6s= X-MC-Unique: uWkGFLyxOTCNZfb0cABXKQ-1 X-Mimecast-MFC-AGG-ID: uWkGFLyxOTCNZfb0cABXKQ_1769622580 To: devel@lists.libvirt.org Subject: [PATCH 2/5] qemu: monitor: Detect list of bitmaps from 'qcow2' format specific data Date: Wed, 28 Jan 2026 18:49:33 +0100 Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: H36eZBUL0vlG6dikIO6k_J-0gPENsachF0EW4B6T2gE_1769622580 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: JU4WBNBZB5H4H2FDR6SBKKWVZ34B4JW6 X-Message-ID-Hash: JU4WBNBZB5H4H2FDR6SBKKWVZ34B4JW6 X-MailFrom: pkrempa@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Peter Krempa via Devel Reply-To: Peter Krempa X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1769622816233158500 Content-Type: text/plain; charset="utf-8" From: Peter Krempa We currently probe dirty block tracking bitmaps by looking at the loaded ones ('dirty-bitmaps'). Unfortunately those may not yet be populated on incoming migration when the image was not yet activated, but we need to know which ones are stored in the image so that we don't migrate those explicitly, which would fail. Load the list of bitmaps in a qcow2 image from the format specific data, which is already loaded at that point. Signed-off-by: Peter Krempa --- src/qemu/qemu_monitor.h | 4 ++++ src/qemu/qemu_monitor_json.c | 17 +++++++++++++++++ tests/qemublocktest.c | 11 +++++++++++ tests/qemublocktestdata/bitmap/snapshots.out | 5 +++++ tests/qemublocktestdata/bitmap/synthetic.out | 4 ++++ 5 files changed, 41 insertions(+) diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index d096f474c1..041aa7bc12 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -893,8 +893,12 @@ struct _qemuBlockNamedNodeData { unsigned long long capacity; unsigned long long physical; + /* Information about change block tracking bitmaps which are active an= d loaded */ qemuBlockNamedNodeDataBitmap **bitmaps; size_t nbitmaps; + /* With qcow2 we have also a separate list of bitmaps present in the i= mage + * but not yet activated, which happens when starting qemu during migr= ation */ + char **qcow2bitmaps; /* hash table indexed by snapshot name containing data about snapshots * (qemuBlockNamedNodeDataSnapshot) */ diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index a602b1e65b..f345741207 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2730,6 +2730,7 @@ qemuMonitorJSONBlockNamedNodeDataFree(qemuBlockNamedN= odeData *data) qemuMonitorJSONBlockNamedNodeDataBitmapFree(data->bitmaps[i]); g_clear_pointer(&data->snapshots, g_hash_table_unref); g_free(data->bitmaps); + g_strfreev(data->qcow2bitmaps); g_free(data); } G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuBlockNamedNodeData, qemuMonitorJSONBlock= NamedNodeDataFree); @@ -2854,6 +2855,9 @@ qemuMonitorJSONBlockGetNamedNodeDataWorker(size_t pos= G_GNUC_UNUSED, virJSONValue *qcow2props =3D virJSONValueObjectGetObject(format_sp= ecific, "data"); if (qcow2props) { + virJSONValue *bmp; + size_t nbmp; + if (STREQ_NULLABLE(virJSONValueObjectGetString(qcow2props, "co= mpat"), "0.10")) ent->qcow2v2 =3D true; @@ -2862,6 +2866,19 @@ qemuMonitorJSONBlockGetNamedNodeDataWorker(size_t po= s G_GNUC_UNUSED, ignore_value(virJSONValueObjectGetBoolean(qcow2props, "data-fi= le-raw", &ent->qcow2dataFileR= aw)); + + if ((bmp =3D virJSONValueObjectGetArray(qcow2props, "bitmaps")= ) && + ((nbmp =3D virJSONValueArraySize(bmp)) > 0)) { + size_t i; + + ent->qcow2bitmaps =3D g_new0(char *, nbmp + 1); + + for (i =3D 0; i < nbmp; i++) { + virJSONValue *b =3D virJSONValueArrayGet(bmp, i); + + ent->qcow2bitmaps[i] =3D g_strdup(virJSONValueObjectGe= tString(b, "name")); + } + } } } diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c index 51d9268cdd..18ec90edf5 100644 --- a/tests/qemublocktest.c +++ b/tests/qemublocktest.c @@ -600,6 +600,17 @@ testQemuDetectBitmapsWorker(void *payload, bitmap->granularity, bitmap->dirtybytes); } + if (data->qcow2bitmaps) { + char **b; + + virBufferAddLit(buf, "qcow2 bitmaps:"); + + for (b =3D data->qcow2bitmaps; *b; b++) + virBufferAsprintf(buf, " %s", *b); + + virBufferAddLit(buf, "\n"); + } + if (data->snapshots) { g_autofree virHashKeyValuePair *snaps =3D virHashGetItems(data->sn= apshots, NULL, true); virHashKeyValuePair *n; diff --git a/tests/qemublocktestdata/bitmap/snapshots.out b/tests/qemublock= testdata/bitmap/snapshots.out index 29c586be7e..dedd77465c 100644 --- a/tests/qemublocktestdata/bitmap/snapshots.out +++ b/tests/qemublocktestdata/bitmap/snapshots.out @@ -4,21 +4,26 @@ libvirt-1-format: b: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0 c: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0 current: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0 + qcow2 bitmaps: current c b a d libvirt-1-storage: libvirt-2-format: c: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0 b: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0 a: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0 d: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0 + qcow2 bitmaps: d a b c libvirt-2-storage: libvirt-3-format: a: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0 b: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0 c: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0 + qcow2 bitmaps: c b a libvirt-3-storage: libvirt-4-format: a: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0 + qcow2 bitmaps: a libvirt-4-storage: libvirt-5-format: a: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0 + qcow2 bitmaps: a libvirt-5-storage: diff --git a/tests/qemublocktestdata/bitmap/synthetic.out b/tests/qemublock= testdata/bitmap/synthetic.out index 2f4ae2b217..0a47a90107 100644 --- a/tests/qemublocktestdata/bitmap/synthetic.out +++ b/tests/qemublocktestdata/bitmap/synthetic.out @@ -6,17 +6,21 @@ libvirt-1-format: top-inactive: record:0 busy:0 persist:1 inconsist:0 gran:65536 dirty:0 top-transient: record:1 busy:0 persist:0 inconsist:0 gran:65536 dirty:0 top-transient-inactive: record:0 busy:0 persist:0 inconsist:0 gran:65536 = dirty:0 + qcow2 bitmaps: current libvirt-1-storage: libvirt-2-format: d: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0 + qcow2 bitmaps: d libvirt-2-storage: libvirt-3-format: b: record:1 busy:0 persist:0 inconsist:0 gran:65536 dirty:0 c: record:0 busy:0 persist:1 inconsist:0 gran:65536 dirty:0 d: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0 + qcow2 bitmaps: c b libvirt-3-storage: libvirt-4-format: libvirt-4-storage: libvirt-5-format: a: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0 + qcow2 bitmaps: a libvirt-5-storage: --=20 2.52.0