From nobody Thu Dec 26 19:45:16 2024 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=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1731660034057662.3023191688153; Fri, 15 Nov 2024 00:40:34 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 996) id E62391A1D; Fri, 15 Nov 2024 03:40:32 -0500 (EST) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 3506B19CD; Fri, 15 Nov 2024 03:39:43 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 996) id 6516F14A8; Fri, 15 Nov 2024 03:39:38 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id C016017AB for ; Fri, 15 Nov 2024 03:39:37 -0500 (EST) Received: from mx-prod-mc-02.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-260-d1nxipTDOvWVkaMnz2Ykgg-1; Fri, 15 Nov 2024 03:39:35 -0500 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-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id DDB021954128 for ; Fri, 15 Nov 2024 08:39:34 +0000 (UTC) Received: from speedmetal.lan (unknown [10.45.242.6]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id EEA1519560A3 for ; Fri, 15 Nov 2024 08:39:33 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1731659977; 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=phmaP87FOhVGU5MEd0kdbzyOe9KMkBQndpF/BKspUSs=; b=jD2F04fivnY6QOe3yXQUp+llmnXGLFzj+9yRyBgEt+VFFHQ6SIh6utaIGI4yEr0oGJeFeK osd2lE4doalth7fKSlh2/09oEwSuGlXHv+laieR4n+mzS6PYNMHoFqpRm959SrVK03VSCc IdJoqaYLNVPkyZSNQprRFIl+9muXmf0= X-MC-Unique: d1nxipTDOvWVkaMnz2Ykgg-1 X-Mimecast-MFC-AGG-ID: d1nxipTDOvWVkaMnz2Ykgg From: Peter Krempa To: devel@lists.libvirt.org Subject: [PATCH 1/9] qemu: Don't store path to qemu img Date: Fri, 15 Nov 2024 09:39:22 +0100 Message-ID: <3af7193e8fb6843d742e5ce542a114e6c3c26797.1731659896.git.pkrempa@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: Xoga6LMckhmE6lUUGcNWLFP8BRsg9T8pjjqWD4Z232w_1731659975 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: FK35YYYXO3LZEHIGBBDZKGTFBP5OIQGO X-Message-ID-Hash: FK35YYYXO3LZEHIGBBDZKGTFBP5OIQGO X-MailFrom: pkrempa@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1731660036250116600 Content-Type: text/plain; charset="utf-8" The 'virCommand' helpers already look up the full path to the binary in PATH if it's not specified. This means that the qemu driver doesn't have to lookup and store the path to 'qemu-img' in the conf object but rather can be cleaned up to use this new infrastructure. Signed-off-by: Peter Krempa Reviewed-by: Michal Privoznik --- src/qemu/qemu_conf.h | 3 --- src/qemu/qemu_domain.c | 20 +------------------- src/qemu/qemu_domain.h | 2 -- src/qemu/qemu_driver.c | 3 --- src/qemu/qemu_snapshot.c | 33 +++++++++------------------------ 5 files changed, 10 insertions(+), 51 deletions(-) diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index 157aba9e18..23a900193e 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -271,9 +271,6 @@ struct _virQEMUDriver { /* Immutable pointer, self-locking APIs */ virDomainObjList *domains; - /* Immutable pointer */ - char *qemuImgBinary; - /* Immutable pointer, lockless APIs. Pointless abstraction */ ebtablesContext *ebtables; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index c798ef37fd..e8e72e5091 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -5671,17 +5671,6 @@ qemuDomainLogAppendMessage(virQEMUDriver *driver, } -/* Locate an appropriate 'qemu-img' binary. */ -const char * -qemuFindQemuImgBinary(virQEMUDriver *driver) -{ - if (!driver->qemuImgBinary) - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("unable to find qemu-img")); - - return driver->qemuImgBinary; -} - int qemuDomainSnapshotWriteMetadata(virDomainObj *vm, virDomainMomentObj *snapshot, @@ -5727,18 +5716,11 @@ qemuDomainSnapshotForEachQcow2Raw(virQEMUDriver *dr= iver, int ndisks) { virDomainSnapshotDef *snapdef =3D virDomainSnapshotObjGetDef(snap); - const char *qemuimgbin; size_t i; bool skipped =3D false; - qemuimgbin =3D qemuFindQemuImgBinary(driver); - if (qemuimgbin =3D=3D NULL) { - /* qemuFindQemuImgBinary set the error */ - return -1; - } - for (i =3D 0; i < ndisks; i++) { - g_autoptr(virCommand) cmd =3D virCommandNewArgList(qemuimgbin, "sn= apshot", + g_autoptr(virCommand) cmd =3D virCommandNewArgList("qemu-img", "sn= apshot", op, snap->def->na= me, NULL); int format =3D virDomainDiskGetFormat(def->disks[i]); diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 1ae421e5f2..091b27823b 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -665,8 +665,6 @@ int qemuDomainLogAppendMessage(virQEMUDriver *driver, const char *fmt, ...) G_GNUC_PRINTF(3, 4); -const char *qemuFindQemuImgBinary(virQEMUDriver *driver); - int qemuDomainSnapshotWriteMetadata(virDomainObj *vm, virDomainMomentObj *snapshot, virDomainXMLOption *xmlopt, diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 72a9542c0b..90d55e53ec 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -679,8 +679,6 @@ qemuStateInitialize(bool privileged, virPidFileAcquire(cfg->stateDir, "driver", getpid())) < 0) goto error; - qemu_driver->qemuImgBinary =3D virFindFileInPath("qemu-img"); - if (!(qemu_driver->lockManager =3D virLockManagerPluginNew(cfg->lockManagerName ? cfg->lockManagerName : "nop", @@ -1065,7 +1063,6 @@ qemuStateCleanup(void) virCPUDefFree(qemu_driver->hostcpu); virObjectUnref(qemu_driver->caps); ebtablesContextFree(qemu_driver->ebtables); - VIR_FREE(qemu_driver->qemuImgBinary); virObjectUnref(qemu_driver->domains); virObjectUnref(qemu_driver->nbdkitCapsCache); diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index 795522da21..35c8d67d20 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -185,7 +185,6 @@ qemuSnapshotDomainDefUpdateDisk(virDomainDef *domdef, /** * qemuSnapshotCreateQcow2Files: - * @driver: QEMU driver * @def: domain definition * @snapdef: snapshot definition * @created: bitmap to store which disks were created @@ -196,20 +195,15 @@ qemuSnapshotDomainDefUpdateDisk(virDomainDef *domdef, * Returns 0 on success, -1 on error. */ static int -qemuSnapshotCreateQcow2Files(virQEMUDriver *driver, - virDomainDef *def, +qemuSnapshotCreateQcow2Files(virDomainDef *def, virDomainSnapshotDef *snapdef, virBitmap *created) { size_t i; - const char *qemuImgPath; g_auto(virBuffer) buf =3D VIR_BUFFER_INITIALIZER; virDomainSnapshotDiskDef *snapdisk =3D NULL; virDomainDiskDef *defdisk =3D NULL; - if (!(qemuImgPath =3D qemuFindQemuImgBinary(driver))) - return -1; - for (i =3D 0; i < snapdef->ndisks; i++) { g_autoptr(virCommand) cmd =3D NULL; snapdisk =3D &(snapdef->disks[i]); @@ -225,7 +219,7 @@ qemuSnapshotCreateQcow2Files(virQEMUDriver *driver, return -1; /* creates cmd line args: qemu-img create -f qcow2 -o */ - if (!(cmd =3D virCommandNewArgList(qemuImgPath, + if (!(cmd =3D virCommandNewArgList("qemu-img", "create", "-f", virStorageFileFormatTypeToString(= snapdisk->src->format), @@ -281,7 +275,7 @@ qemuSnapshotCreateInactiveExternal(virQEMUDriver *drive= r, /* If reuse is true, then qemuSnapshotPrepare already * ensured that the new files exist, and it was up to the user to * create them correctly. */ - if (!reuse && qemuSnapshotCreateQcow2Files(driver, vm->def, snapdef, c= reated) < 0) + if (!reuse && qemuSnapshotCreateQcow2Files(vm->def, snapdef, created) = < 0) goto cleanup; /* update disk definitions */ @@ -2300,7 +2294,6 @@ qemuSnapshotRevertExternalActive(virDomainObj *vm, /** * qemuSnapshotRevertExternalInactive: - * @vm: domain object * @tmpsnapdef: temporary snapshot definition * @domdef: offline domain definition * @@ -2310,17 +2303,15 @@ qemuSnapshotRevertExternalActive(virDomainObj *vm, * Returns 0 on success, -1 on error. */ static int -qemuSnapshotRevertExternalInactive(virDomainObj *vm, - virDomainSnapshotDef *tmpsnapdef, +qemuSnapshotRevertExternalInactive(virDomainSnapshotDef *tmpsnapdef, virDomainDef *domdef) { - virQEMUDriver *driver =3D QEMU_DOMAIN_PRIVATE(vm)->driver; g_autoptr(virBitmap) created =3D NULL; int ret =3D -1; created =3D virBitmapNew(tmpsnapdef->ndisks); - if (qemuSnapshotCreateQcow2Files(driver, domdef, tmpsnapdef, created) = < 0) + if (qemuSnapshotCreateQcow2Files(domdef, tmpsnapdef, created) < 0) goto cleanup; if (qemuSnapshotDomainDefUpdateDisk(domdef, tmpsnapdef, false) < 0) @@ -2613,7 +2604,7 @@ qemuSnapshotRevertInactive(virDomainObj *vm, return -1; } - if (qemuSnapshotRevertExternalInactive(vm, tmpsnapdef, + if (qemuSnapshotRevertExternalInactive(tmpsnapdef, *inactiveConfig) < 0) { return -1; } @@ -3443,22 +3434,16 @@ qemuSnapshotSetInvalid(virDomainObj *vm, static void -qemuSnapshotUpdateBackingStore(virDomainObj *vm, - qemuSnapshotDeleteExternalData *data) +qemuSnapshotUpdateBackingStore(qemuSnapshotDeleteExternalData *data) { GSList *cur =3D NULL; - const char *qemuImgPath; - virQEMUDriver *driver =3D QEMU_DOMAIN_PRIVATE(vm)->driver; - - if (!(qemuImgPath =3D qemuFindQemuImgBinary(driver))) - return; for (cur =3D data->disksWithBacking; cur; cur =3D g_slist_next(cur)) { struct _qemuSnapshotDisksWithBackingStoreData *backingData =3D cur= ->data; g_autoptr(virCommand) cmd =3D NULL; /* creates cmd line args: qemu-img create -f qcow2 -o */ - if (!(cmd =3D virCommandNewArgList(qemuImgPath, + if (!(cmd =3D virCommandNewArgList("qemu-img", "rebase", "-u", "-F", @@ -3565,7 +3550,7 @@ qemuSnapshotDiscardExternal(virDomainObj *vm, qemuBlockJobSyncEnd(vm, data->job, VIR_ASYNC_JOB_SNAPSHOT); - qemuSnapshotUpdateBackingStore(vm, data); + qemuSnapshotUpdateBackingStore(data); if (qemuSnapshotSetInvalid(vm, data->parentSnap, data->snapDisk, f= alse) < 0) goto error; --=20 2.47.0 From nobody Thu Dec 26 19:45:16 2024 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=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1731660064569192.29077566512444; Fri, 15 Nov 2024 00:41:04 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 996) id 87A4319A8; Fri, 15 Nov 2024 03:41:03 -0500 (EST) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id C52A71A1B; Fri, 15 Nov 2024 03:39:44 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 996) id 9F93818B2; Fri, 15 Nov 2024 03:39:39 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id ED5C114A8 for ; Fri, 15 Nov 2024 03:39:38 -0500 (EST) Received: from mx-prod-mc-02.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-609-86zX3IGXO4qP5eYJz0DVbQ-1; Fri, 15 Nov 2024 03:39:37 -0500 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-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 38D05195419F for ; Fri, 15 Nov 2024 08:39:36 +0000 (UTC) Received: from speedmetal.lan (unknown [10.45.242.6]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 68BD419560A3 for ; Fri, 15 Nov 2024 08:39:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-1.5 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1731659978; 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=hysli72Ym50FNTEGj8n2/Zn3YfqFGhvoiNl1q1dll+U=; b=bc7bIj0+UetD4QFFtAov7RRMcaiZ9KuY5EHl0k23o59BgaxBMNoH21wD0XoBLzzkugIWYw xrya3mhfzBUYTu5FaWZctF4+GJa3/sOE/tluDOEApKkuOgdrTDLbPi3r07awXfKBkU8DKu V1Kdvc6fXP29plpw99xxnBlMlP//mos= X-MC-Unique: 86zX3IGXO4qP5eYJz0DVbQ-1 X-Mimecast-MFC-AGG-ID: 86zX3IGXO4qP5eYJz0DVbQ From: Peter Krempa To: devel@lists.libvirt.org Subject: [PATCH 2/9] qemuDomainSnapshotForEachQcow2Raw: Remove 'driver' argument Date: Fri, 15 Nov 2024 09:39:23 +0100 Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: taH_WewjU2QZx58urB32yrlfAYNDYRIKcuIHiLJdOyU_1731659976 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: QOSOORTC73RQI7D4V67NWJSYO2N52OT5 X-Message-ID-Hash: QOSOORTC73RQI7D4V67NWJSYO2N52OT5 X-MailFrom: pkrempa@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1731660066399116600 Content-Type: text/plain; charset="utf-8" Now that it's unused except for the recursive call it can be dropped from all of the call tree. Signed-off-by: Peter Krempa Reviewed-by: Michal Privoznik --- src/qemu/qemu_domain.c | 15 +++++---------- src/qemu/qemu_domain.h | 3 +-- src/qemu/qemu_snapshot.c | 28 +++++++++++----------------- 3 files changed, 17 insertions(+), 29 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index e8e72e5091..5fdd7f9fc0 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -5708,8 +5708,7 @@ qemuDomainSnapshotWriteMetadata(virDomainObj *vm, /* The domain is expected to be locked and inactive. Return -1 on normal * failure, 1 if we skipped a disk due to try_all. */ static int -qemuDomainSnapshotForEachQcow2Raw(virQEMUDriver *driver, - virDomainDef *def, +qemuDomainSnapshotForEachQcow2Raw(virDomainDef *def, virDomainMomentObj *snap, const char *op, bool try_all, @@ -5748,8 +5747,7 @@ qemuDomainSnapshotForEachQcow2Raw(virQEMUDriver *driv= er, } else if (STREQ(op, "-c") && i) { /* We must roll back partial creation by deleting * all earlier snapshots. */ - qemuDomainSnapshotForEachQcow2Raw(driver, def, snap, - "-d", false, i); + qemuDomainSnapshotForEachQcow2Raw(def, snap, "-d", false, = i); } virReportError(VIR_ERR_OPERATION_INVALID, _("Disk device '%1$s' does not support snapshot= ting"), @@ -5768,8 +5766,7 @@ qemuDomainSnapshotForEachQcow2Raw(virQEMUDriver *driv= er, } else if (STREQ(op, "-c") && i) { /* We must roll back partial creation by deleting * all earlier snapshots. */ - qemuDomainSnapshotForEachQcow2Raw(driver, def, snap, - "-d", false, i); + qemuDomainSnapshotForEachQcow2Raw(def, snap, "-d", false, = i); } return -1; } @@ -5781,14 +5778,12 @@ qemuDomainSnapshotForEachQcow2Raw(virQEMUDriver *dr= iver, /* The domain is expected to be locked and inactive. Return -1 on normal * failure, 1 if we skipped a disk due to try_all. */ int -qemuDomainSnapshotForEachQcow2(virQEMUDriver *driver, - virDomainDef *def, +qemuDomainSnapshotForEachQcow2(virDomainDef *def, virDomainMomentObj *snap, const char *op, bool try_all) { - return qemuDomainSnapshotForEachQcow2Raw(driver, def, snap, - op, try_all, def->ndisks); + return qemuDomainSnapshotForEachQcow2Raw(def, snap, op, try_all, def->= ndisks); } /* Hash iterator callback to discard multiple snapshots. */ diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 091b27823b..ad0f4341c0 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -670,8 +670,7 @@ int qemuDomainSnapshotWriteMetadata(virDomainObj *vm, virDomainXMLOption *xmlopt, const char *snapshotDir); -int qemuDomainSnapshotForEachQcow2(virQEMUDriver *driver, - virDomainDef *def, +int qemuDomainSnapshotForEachQcow2(virDomainDef *def, virDomainMomentObj *snap, const char *op, bool try_all); diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index 35c8d67d20..f1d5103abe 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -251,11 +251,10 @@ qemuSnapshotCreateQcow2Files(virDomainDef *def, /* The domain is expected to be locked and inactive. */ static int -qemuSnapshotCreateInactiveInternal(virQEMUDriver *driver, - virDomainObj *vm, +qemuSnapshotCreateInactiveInternal(virDomainObj *vm, virDomainMomentObj *snap) { - return qemuDomainSnapshotForEachQcow2(driver, vm->def, snap, "-c", fal= se); + return qemuDomainSnapshotForEachQcow2(vm->def, snap, "-c", false); } @@ -1935,7 +1934,7 @@ qemuSnapshotCreate(virDomainObj *vm, if (qemuSnapshotCreateInactiveExternal(driver, vm, snap, reuse= ) < 0) goto error; } else { - if (qemuSnapshotCreateInactiveInternal(driver, vm, snap) < 0) + if (qemuSnapshotCreateInactiveInternal(vm, snap) < 0) goto error; } } @@ -2533,8 +2532,7 @@ qemuSnapshotRevertActive(virDomainObj *vm, /* The domain is expected to be locked and inactive. */ static int -qemuSnapshotInternalRevertInactive(virQEMUDriver *driver, - virDomainObj *vm, +qemuSnapshotInternalRevertInactive(virDomainObj *vm, virDomainMomentObj *snap) { size_t i; @@ -2553,7 +2551,7 @@ qemuSnapshotInternalRevertInactive(virQEMUDriver *dri= ver, } /* Try all disks, but report failure if we skipped any. */ - if (qemuDomainSnapshotForEachQcow2(driver, def, snap, "-a", true) !=3D= 0) + if (qemuDomainSnapshotForEachQcow2(def, snap, "-a", true) !=3D 0) return -1; return 0; @@ -2611,7 +2609,7 @@ qemuSnapshotRevertInactive(virDomainObj *vm, qemuSnapshotRevertExternalFinish(vm, tmpsnapdef, snap); } else { - if (qemuSnapshotInternalRevertInactive(driver, vm, snap) < 0) { + if (qemuSnapshotInternalRevertInactive(vm, snap) < 0) { qemuDomainRemoveInactive(driver, vm, 0, false); return -1; } @@ -3893,8 +3891,7 @@ qemuSnapshotDiscardActiveInternal(virDomainObj *vm, /* Discard one snapshot (or its metadata), without reparenting any childre= n. */ static int -qemuSnapshotDiscardImpl(virQEMUDriver *driver, - virDomainObj *vm, +qemuSnapshotDiscardImpl(virDomainObj *vm, virDomainMomentObj *snap, GSList *externalData, bool update_parent, @@ -3922,7 +3919,7 @@ qemuSnapshotDiscardImpl(virQEMUDriver *driver, if (qemuSnapshotDiscardExternal(vm, snap, externalData) < = 0) return -1; } else { - if (qemuDomainSnapshotForEachQcow2(driver, def, snap, "-d"= , true) < 0) + if (qemuDomainSnapshotForEachQcow2(def, snap, "-d", true) = < 0) return -1; } } else { @@ -3961,13 +3958,13 @@ qemuSnapshotDiscardImpl(virQEMUDriver *driver, static int -qemuSnapshotDiscard(virQEMUDriver *driver, +qemuSnapshotDiscard(virQEMUDriver *driver G_GNUC_UNUSED, virDomainObj *vm, virDomainMomentObj *snap, bool update_parent, bool metadata_only) { - return qemuSnapshotDiscardImpl(driver, vm, snap, NULL, update_parent, = metadata_only); + return qemuSnapshotDiscardImpl(vm, snap, NULL, update_parent, metadata= _only); } @@ -3995,10 +3992,7 @@ qemuSnapshotDeleteSingle(virDomainObj *vm, GSList *externalData, bool metadata_only) { - qemuDomainObjPrivate *priv =3D vm->privateData; - virQEMUDriver *driver =3D priv->driver; - - return qemuSnapshotDiscardImpl(driver, vm, snap, externalData, true, m= etadata_only); + return qemuSnapshotDiscardImpl(vm, snap, externalData, true, metadata_= only); } --=20 2.47.0 From nobody Thu Dec 26 19:45:16 2024 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=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1731660102073708.9900343141742; Fri, 15 Nov 2024 00:41:42 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 996) id 08E0019FF; Fri, 15 Nov 2024 03:41:41 -0500 (EST) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id D6DDB1A2F; Fri, 15 Nov 2024 03:39:50 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 996) id 2BD7C19AF; Fri, 15 Nov 2024 03:39:46 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 81AD01990 for ; Fri, 15 Nov 2024 03:39:40 -0500 (EST) Received: from mx-prod-mc-04.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-387-7l6U0-WTOHSuFnJyaJRdpQ-1; Fri, 15 Nov 2024 03:39:38 -0500 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-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8CB771955D4D for ; Fri, 15 Nov 2024 08:39:37 +0000 (UTC) Received: from speedmetal.lan (unknown [10.45.242.6]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id B62461953880 for ; Fri, 15 Nov 2024 08:39:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-1.5 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1731659980; 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=O2ho2lCpkNnj7lWfNZt7eKaouSYcxm5I5JxxCFSG8eA=; b=K9fFtu0yO96JgzVNLolrCby9QtAdcV+QsIwuTO9K0i7zGwlUlG/zySYaLuHeL5bajFLiA+ AKPdiSzpYmua3Sy+CXkUSV4AOP7OJLuo3SfEe1ZGTbqPDNhZIXRV+aOPBdDlNgzdsECd0l X0q5HKChwKu+SS49bCuowXFPhbQPLAc= X-MC-Unique: 7l6U0-WTOHSuFnJyaJRdpQ-1 X-Mimecast-MFC-AGG-ID: 7l6U0-WTOHSuFnJyaJRdpQ From: Peter Krempa To: devel@lists.libvirt.org Subject: [PATCH 3/9] qemu: Move 'qemuDomainSnapshotForEachQcow2(Raw)' to qemu_snapshot.c Date: Fri, 15 Nov 2024 09:39:24 +0100 Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: gMuKtl9iYwoji3GPws5DJRClKPoQzzkUkSe5-R8cno4_1731659977 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: 3PJK25KSYVGNGF2PRMWFZLCFILSSQE2N X-Message-ID-Hash: 3PJK25KSYVGNGF2PRMWFZLCFILSSQE2N X-MailFrom: pkrempa@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1731660102487116600 Content-Type: text/plain; charset="utf-8" The functions are exclusively used in the snapshot module. Move and rename them: qemuDomainSnapshotForEachQcow2Raw -> qemuSnapshotForEachQcow2Internal qemuDomainSnapshotForEachQcow2 -> qemuSnapshotForEachQcow2 Signed-off-by: Peter Krempa Reviewed-by: Michal Privoznik --- src/qemu/qemu_domain.c | 81 ------------------------------------ src/qemu/qemu_domain.h | 5 --- src/qemu/qemu_snapshot.c | 89 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 86 insertions(+), 89 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 5fdd7f9fc0..4c0bfcd172 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -5705,87 +5705,6 @@ qemuDomainSnapshotWriteMetadata(virDomainObj *vm, } -/* The domain is expected to be locked and inactive. Return -1 on normal - * failure, 1 if we skipped a disk due to try_all. */ -static int -qemuDomainSnapshotForEachQcow2Raw(virDomainDef *def, - virDomainMomentObj *snap, - const char *op, - bool try_all, - int ndisks) -{ - virDomainSnapshotDef *snapdef =3D virDomainSnapshotObjGetDef(snap); - size_t i; - bool skipped =3D false; - - for (i =3D 0; i < ndisks; i++) { - g_autoptr(virCommand) cmd =3D virCommandNewArgList("qemu-img", "sn= apshot", - op, snap->def->na= me, NULL); - int format =3D virDomainDiskGetFormat(def->disks[i]); - - /* FIXME: we also need to handle LVM here */ - if (def->disks[i]->device !=3D VIR_DOMAIN_DISK_DEVICE_DISK || - snapdef->disks[i].snapshot !=3D VIR_DOMAIN_SNAPSHOT_LOCATION_I= NTERNAL) - continue; - - if (!virStorageSourceIsLocalStorage(def->disks[i]->src)) { - virReportError(VIR_ERR_OPERATION_INVALID, - _("can't manipulate inactive snapshots of disk = '%1$s'"), - def->disks[i]->dst); - return -1; - } - - if (format > 0 && format !=3D VIR_STORAGE_FILE_QCOW2) { - if (try_all) { - /* Continue on even in the face of error, since other - * disks in this VM may have the same snapshot name. - */ - VIR_WARN("skipping snapshot action on %s", - def->disks[i]->dst); - skipped =3D true; - continue; - } else if (STREQ(op, "-c") && i) { - /* We must roll back partial creation by deleting - * all earlier snapshots. */ - qemuDomainSnapshotForEachQcow2Raw(def, snap, "-d", false, = i); - } - virReportError(VIR_ERR_OPERATION_INVALID, - _("Disk device '%1$s' does not support snapshot= ting"), - def->disks[i]->dst); - return -1; - } - - virCommandAddArg(cmd, virDomainDiskGetSource(def->disks[i])); - - if (virCommandRun(cmd, NULL) < 0) { - if (try_all) { - VIR_WARN("skipping snapshot action on %s", - def->disks[i]->dst); - skipped =3D true; - continue; - } else if (STREQ(op, "-c") && i) { - /* We must roll back partial creation by deleting - * all earlier snapshots. */ - qemuDomainSnapshotForEachQcow2Raw(def, snap, "-d", false, = i); - } - return -1; - } - } - - return skipped ? 1 : 0; -} - -/* The domain is expected to be locked and inactive. Return -1 on normal - * failure, 1 if we skipped a disk due to try_all. */ -int -qemuDomainSnapshotForEachQcow2(virDomainDef *def, - virDomainMomentObj *snap, - const char *op, - bool try_all) -{ - return qemuDomainSnapshotForEachQcow2Raw(def, snap, op, try_all, def->= ndisks); -} - /* Hash iterator callback to discard multiple snapshots. */ int qemuDomainMomentDiscardAll(void *payload, const char *name G_GNUC_UNUSED, diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index ad0f4341c0..e810f79599 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -670,11 +670,6 @@ int qemuDomainSnapshotWriteMetadata(virDomainObj *vm, virDomainXMLOption *xmlopt, const char *snapshotDir); -int qemuDomainSnapshotForEachQcow2(virDomainDef *def, - virDomainMomentObj *snap, - const char *op, - bool try_all); - typedef struct _virQEMUMomentRemove virQEMUMomentRemove; struct _virQEMUMomentRemove { virQEMUDriver *driver; diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index f1d5103abe..222afe62e1 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -249,12 +249,95 @@ qemuSnapshotCreateQcow2Files(virDomainDef *def, } +/* The domain is expected to be locked and inactive. Return -1 on normal + * failure, 1 if we skipped a disk due to try_all. */ +static int +qemuSnapshotForEachQcow2Internal(virDomainDef *def, + virDomainMomentObj *snap, + const char *op, + bool try_all, + int ndisks) +{ + virDomainSnapshotDef *snapdef =3D virDomainSnapshotObjGetDef(snap); + size_t i; + bool skipped =3D false; + + for (i =3D 0; i < ndisks; i++) { + g_autoptr(virCommand) cmd =3D virCommandNewArgList("qemu-img", "sn= apshot", + op, snap->def->na= me, NULL); + int format =3D virDomainDiskGetFormat(def->disks[i]); + + /* FIXME: we also need to handle LVM here */ + if (def->disks[i]->device !=3D VIR_DOMAIN_DISK_DEVICE_DISK || + snapdef->disks[i].snapshot !=3D VIR_DOMAIN_SNAPSHOT_LOCATION_I= NTERNAL) + continue; + + if (!virStorageSourceIsLocalStorage(def->disks[i]->src)) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("can't manipulate inactive snapshots of disk = '%1$s'"), + def->disks[i]->dst); + return -1; + } + + if (format > 0 && format !=3D VIR_STORAGE_FILE_QCOW2) { + if (try_all) { + /* Continue on even in the face of error, since other + * disks in this VM may have the same snapshot name. + */ + VIR_WARN("skipping snapshot action on %s", + def->disks[i]->dst); + skipped =3D true; + continue; + } else if (STREQ(op, "-c") && i) { + /* We must roll back partial creation by deleting + * all earlier snapshots. */ + qemuSnapshotForEachQcow2Internal(def, snap, "-d", false, i= ); + } + virReportError(VIR_ERR_OPERATION_INVALID, + _("Disk device '%1$s' does not support snapshot= ting"), + def->disks[i]->dst); + return -1; + } + + virCommandAddArg(cmd, virDomainDiskGetSource(def->disks[i])); + + if (virCommandRun(cmd, NULL) < 0) { + if (try_all) { + VIR_WARN("skipping snapshot action on %s", + def->disks[i]->dst); + skipped =3D true; + continue; + } else if (STREQ(op, "-c") && i) { + /* We must roll back partial creation by deleting + * all earlier snapshots. */ + qemuSnapshotForEachQcow2Internal(def, snap, "-d", false, i= ); + } + return -1; + } + } + + return skipped ? 1 : 0; +} + + +/* The domain is expected to be locked and inactive. Return -1 on normal + * failure, 1 if we skipped a disk due to try_all. */ +static int +qemuSnapshotForEachQcow2(virDomainDef *def, + virDomainMomentObj *snap, + const char *op, + bool try_all) +{ + return qemuSnapshotForEachQcow2Internal(def, snap, op, try_all, def->n= disks); +} + + /* The domain is expected to be locked and inactive. */ static int qemuSnapshotCreateInactiveInternal(virDomainObj *vm, virDomainMomentObj *snap) { - return qemuDomainSnapshotForEachQcow2(vm->def, snap, "-c", false); + return qemuSnapshotForEachQcow2(vm->def, snap, "-c", false); } @@ -2551,7 +2634,7 @@ qemuSnapshotInternalRevertInactive(virDomainObj *vm, } /* Try all disks, but report failure if we skipped any. */ - if (qemuDomainSnapshotForEachQcow2(def, snap, "-a", true) !=3D 0) + if (qemuSnapshotForEachQcow2(def, snap, "-a", true) !=3D 0) return -1; return 0; @@ -3919,7 +4002,7 @@ qemuSnapshotDiscardImpl(virDomainObj *vm, if (qemuSnapshotDiscardExternal(vm, snap, externalData) < = 0) return -1; } else { - if (qemuDomainSnapshotForEachQcow2(def, snap, "-d", true) = < 0) + if (qemuSnapshotForEachQcow2(def, snap, "-d", true) < 0) return -1; } } else { --=20 2.47.0 From nobody Thu Dec 26 19:45:16 2024 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=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1731660131672614.8418700601253; Fri, 15 Nov 2024 00:42:11 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 996) id 98DA31A69; Fri, 15 Nov 2024 03:42:10 -0500 (EST) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 9F8A51A09; Fri, 15 Nov 2024 03:39:54 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 996) id 4A12A19E7; Fri, 15 Nov 2024 03:39:50 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 5AAFF19D1 for ; Fri, 15 Nov 2024 03:39:41 -0500 (EST) Received: from mx-prod-mc-04.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-592-5B1WyJh_NWy5t8vmt2pfjg-1; Fri, 15 Nov 2024 03:39:39 -0500 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-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D5B8A1955DC3 for ; Fri, 15 Nov 2024 08:39:38 +0000 (UTC) Received: from speedmetal.lan (unknown [10.45.242.6]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 0FCC719560A3 for ; Fri, 15 Nov 2024 08:39:37 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1731659981; 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=273pm2D1U4jG82Ep7oq1+Sdt+A+LYSLOkALx3bSkUMY=; b=bLVKDlcVU+FGZhLt1azupt67QP9kAWdoWZT3xpgyGDSt9mZ0YCyCEULRP4J72SBgUIBwIq ol4DCHKjE9dJ9+MlhFdgaRwVxAuLVx7f4u8WVhnFUxPkCajf0rVpcSvKrkUhxuHHPjs0Y1 Mu9sZtDkaZ2de/XEC4aYZlcVQ21Uzo0= X-MC-Unique: 5B1WyJh_NWy5t8vmt2pfjg-1 X-Mimecast-MFC-AGG-ID: 5B1WyJh_NWy5t8vmt2pfjg From: Peter Krempa To: devel@lists.libvirt.org Subject: [PATCH 4/9] qemuSnapshotForEachQcow2: Refactor Date: Fri, 15 Nov 2024 09:39:25 +0100 Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: f2KSlnVE4jXfZrkFBMKRAFuBGlq_vInL_z6XY6rJi4Y_1731659979 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: HU3TRR55M3YJTLJQ7FDLB6WWKPUN5HFD X-Message-ID-Hash: HU3TRR55M3YJTLJQ7FDLB6WWKPUN5HFD X-MailFrom: pkrempa@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1731660132645116600 Content-Type: text/plain; charset="utf-8" Refactor the function to avoid recursive call to rollback and simplify calling parameters. To achieve that most of the fatal checks are extracted into a dedicated loop that runs before modifying the disk state thus removing the need to rollback altoghether. Since rollback is still necessary when creation of the snapshot fails half-way through the rollback is extracted to handle only that scenario. Additionally callers would only pass the old 'try_all' argument as true on all non-creation ("-c") modes. This means that we can infer it from the operation instead of passing it as an extra argument. This refactor will also make it much simpler to implement handling of the NVRAM pflash backing file (in case it's qcow2) for internal snapshots. Signed-off-by: Peter Krempa Reviewed-by: Michal Privoznik --- src/qemu/qemu_snapshot.c | 141 ++++++++++++++++++++++++--------------- 1 file changed, 88 insertions(+), 53 deletions(-) diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index 222afe62e1..f560cf270c 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -249,86 +249,121 @@ qemuSnapshotCreateQcow2Files(virDomainDef *def, } -/* The domain is expected to be locked and inactive. Return -1 on normal - * failure, 1 if we skipped a disk due to try_all. */ static int -qemuSnapshotForEachQcow2Internal(virDomainDef *def, - virDomainMomentObj *snap, - const char *op, - bool try_all, - int ndisks) +qemuSnapshotForEachQcow2One(virStorageSource *src, + const char *op, + const char *snapname) +{ + g_autoptr(virCommand) cmd =3D NULL; + + cmd =3D virCommandNewArgList("qemu-img", "snapshot", + op, snapname, src->path, NULL); + + if (virCommandRun(cmd, NULL) < 0) + return -1; + + return 0; +} + + +/** + * qemuSnapshotForEachQcow2: + * + * @def: domain definition + * @snap: snapshot object + * @op: 'qemu-img snapshot' operation flag, one of "-c", "-d", "-a" + * + * Applies the selected 'qemu-img snapshot' operation @op on all relevant = QCOW2 + * images of @def. In case when @op is "-c" (create) any failure is fatal = and + * rolled back. Otherwise the selected operation @op is applied on all ima= ges + * regardless of failure. + * + * Returns: -1 on errror; 0 on complete success; 1 on partial success in + * permissive modes. + */ +static int +qemuSnapshotForEachQcow2(virDomainDef *def, + virDomainMomentObj *snap, + const char *op) { virDomainSnapshotDef *snapdef =3D virDomainSnapshotObjGetDef(snap); size_t i; bool skipped =3D false; + bool create =3D STREQ(op, "-c"); + size_t nrollback =3D -1; + virErrorPtr orig_err; - for (i =3D 0; i < ndisks; i++) { - g_autoptr(virCommand) cmd =3D virCommandNewArgList("qemu-img", "sn= apshot", - op, snap->def->na= me, NULL); - int format =3D virDomainDiskGetFormat(def->disks[i]); + /* pre-checks */ + for (i =3D 0; i < def->ndisks; i++) { + virDomainDiskDef *disk =3D def->disks[i]; - /* FIXME: we also need to handle LVM here */ if (def->disks[i]->device !=3D VIR_DOMAIN_DISK_DEVICE_DISK || snapdef->disks[i].snapshot !=3D VIR_DOMAIN_SNAPSHOT_LOCATION_I= NTERNAL) continue; - if (!virStorageSourceIsLocalStorage(def->disks[i]->src)) { + if (!virStorageSourceIsLocalStorage(disk->src)) { virReportError(VIR_ERR_OPERATION_INVALID, _("can't manipulate inactive snapshots of disk = '%1$s'"), - def->disks[i]->dst); + disk->dst); return -1; } - if (format > 0 && format !=3D VIR_STORAGE_FILE_QCOW2) { - if (try_all) { - /* Continue on even in the face of error, since other - * disks in this VM may have the same snapshot name. - */ - VIR_WARN("skipping snapshot action on %s", - def->disks[i]->dst); - skipped =3D true; - continue; - } else if (STREQ(op, "-c") && i) { - /* We must roll back partial creation by deleting - * all earlier snapshots. */ - qemuSnapshotForEachQcow2Internal(def, snap, "-d", false, i= ); - } + if (create && + disk->src->format > VIR_STORAGE_FILE_NONE && + disk->src->format !=3D VIR_STORAGE_FILE_QCOW2) { virReportError(VIR_ERR_OPERATION_INVALID, _("Disk device '%1$s' does not support snapshot= ting"), - def->disks[i]->dst); + disk->dst); return -1; } + } + + for (i =3D 0; i < def->ndisks; i++) { + virDomainDiskDef *disk =3D def->disks[i]; + + if (def->disks[i]->device !=3D VIR_DOMAIN_DISK_DEVICE_DISK || + snapdef->disks[i].snapshot !=3D VIR_DOMAIN_SNAPSHOT_LOCATION_I= NTERNAL) + continue; - virCommandAddArg(cmd, virDomainDiskGetSource(def->disks[i])); + if (disk->src->format > VIR_STORAGE_FILE_NONE && + disk->src->format !=3D VIR_STORAGE_FILE_QCOW2) { + VIR_WARN("skipping 'qemu-img snapshot %s' action on non-qcow2 = disk '%s'", + op, disk->dst); + skipped =3D true; + continue; + } - if (virCommandRun(cmd, NULL) < 0) { - if (try_all) { - VIR_WARN("skipping snapshot action on %s", - def->disks[i]->dst); + if (qemuSnapshotForEachQcow2One(disk->src, op, snap->def->name) < = 0) { + if (create) { + nrollback =3D i; + virErrorPreserveLast(&orig_err); + goto rollback; + } else { + VIR_WARN("failed 'qemu-img snapshot %s' action on '%s'", + op, disk->dst); skipped =3D true; - continue; - } else if (STREQ(op, "-c") && i) { - /* We must roll back partial creation by deleting - * all earlier snapshots. */ - qemuSnapshotForEachQcow2Internal(def, snap, "-d", false, i= ); + virResetLastError(); } - return -1; } } return skipped ? 1 : 0; -} + rollback: + for (i =3D 0; i < nrollback; i++) { + virDomainDiskDef *disk =3D def->disks[i]; -/* The domain is expected to be locked and inactive. Return -1 on normal - * failure, 1 if we skipped a disk due to try_all. */ -static int -qemuSnapshotForEachQcow2(virDomainDef *def, - virDomainMomentObj *snap, - const char *op, - bool try_all) -{ - return qemuSnapshotForEachQcow2Internal(def, snap, op, try_all, def->n= disks); + if (def->disks[i]->device !=3D VIR_DOMAIN_DISK_DEVICE_DISK || + snapdef->disks[i].snapshot !=3D VIR_DOMAIN_SNAPSHOT_LOCATION_I= NTERNAL || + (disk->src->format > VIR_STORAGE_FILE_NONE && + disk->src->format !=3D VIR_STORAGE_FILE_QCOW2)) + continue; + + ignore_value(qemuSnapshotForEachQcow2One(disk->src, "-d", snap->de= f->name)); + } + + virErrorRestore(&orig_err); + return -1; } @@ -337,7 +372,7 @@ static int qemuSnapshotCreateInactiveInternal(virDomainObj *vm, virDomainMomentObj *snap) { - return qemuSnapshotForEachQcow2(vm->def, snap, "-c", false); + return qemuSnapshotForEachQcow2(vm->def, snap, "-c"); } @@ -2634,7 +2669,7 @@ qemuSnapshotInternalRevertInactive(virDomainObj *vm, } /* Try all disks, but report failure if we skipped any. */ - if (qemuSnapshotForEachQcow2(def, snap, "-a", true) !=3D 0) + if (qemuSnapshotForEachQcow2(def, snap, "-a") !=3D 0) return -1; return 0; @@ -4002,7 +4037,7 @@ qemuSnapshotDiscardImpl(virDomainObj *vm, if (qemuSnapshotDiscardExternal(vm, snap, externalData) < = 0) return -1; } else { - if (qemuSnapshotForEachQcow2(def, snap, "-d", true) < 0) + if (qemuSnapshotForEachQcow2(def, snap, "-d") < 0) return -1; } } else { --=20 2.47.0 From nobody Thu Dec 26 19:45:16 2024 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=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1731660150309216.9913618342215; Fri, 15 Nov 2024 00:42:30 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 996) id 3DBB119AE; Fri, 15 Nov 2024 03:42:29 -0500 (EST) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 513D219F9; Fri, 15 Nov 2024 03:39:59 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 996) id 6A6A118F9; Fri, 15 Nov 2024 03:39:55 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 847D318F9 for ; Fri, 15 Nov 2024 03:39:43 -0500 (EST) 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-437-m-W4eASLMhK43KMwaJM21A-1; Fri, 15 Nov 2024 03:39:40 -0500 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 352AE1956048 for ; Fri, 15 Nov 2024 08:39:40 +0000 (UTC) Received: from speedmetal.lan (unknown [10.45.242.6]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 5E9B219560A3 for ; Fri, 15 Nov 2024 08:39:39 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-1.5 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1731659983; 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=e3TSRdZ9g+PoRenQAek2//jZSze3fSIljrb0q87nRsU=; b=ehZXP7LCcuUMWPtbFjePaascxgc1wyqpifa69aEAwMHcag2FK+iz+wglrCXjvR4sW4zlI5 HytRFaePjVQdkw+GXorTacV1XSmK8b3pktOESB1GaaYIixdjip/b5psjLPw9lsAA2WRhI5 d0Jz7Mt45dkW7YVvR7zh3HfVwtcgtzk= X-MC-Unique: m-W4eASLMhK43KMwaJM21A-1 X-Mimecast-MFC-AGG-ID: m-W4eASLMhK43KMwaJM21A From: Peter Krempa To: devel@lists.libvirt.org Subject: [PATCH 5/9] qemuSnapshotForEachQcow2: Handle also NVRAM image for internal snapshots Date: Fri, 15 Nov 2024 09:39:26 +0100 Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 5S9e8cg_YIWp3jK77AEQPZyM7skjZnSHXn_NnvvFwCk_1731659980 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: 6Z6K37O2YNJSMKNY3CIZV7HK5PSMH2OE X-Message-ID-Hash: 6Z6K37O2YNJSMKNY3CIZV7HK5PSMH2OE X-MailFrom: pkrempa@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1731660150535116600 Content-Type: text/plain; charset="utf-8" The live VM snapshot code already does handle the NVRAM image when it's in use, so we should also handle it when modifying/creating the snapshots via qemu-img when inactive. Add the handling to qemuSnapshotForEachQcow2 which is used for all inactive operations. Signed-off-by: Peter Krempa Reviewed-by: Michal Privoznik --- src/qemu/qemu_snapshot.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index f560cf270c..4a17935627 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -347,6 +347,26 @@ qemuSnapshotForEachQcow2(virDomainDef *def, } } + if (def->os.loader && def->os.loader->nvram) { + virStorageSource *nvram =3D def->os.loader->nvram; + + if (virStorageSourceIsLocalStorage(nvram) && + nvram->format =3D=3D VIR_STORAGE_FILE_QCOW2) { + if (qemuSnapshotForEachQcow2One(nvram, op, snap->def->name) < = 0) { + if (create) { + nrollback =3D def->ndisks; + virErrorPreserveLast(&orig_err); + goto rollback; + } else { + VIR_WARN("failed 'qemu-img snapshot %s' action on NVRA= M image", + op); + skipped =3D true; + virResetLastError(); + } + } + } + } + return skipped ? 1 : 0; rollback: --=20 2.47.0 From nobody Thu Dec 26 19:45:16 2024 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=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1731660173406857.5754442001318; Fri, 15 Nov 2024 00:42:53 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 996) id 2B74B13E0; Fri, 15 Nov 2024 03:42:52 -0500 (EST) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 1CBDA1A38; Fri, 15 Nov 2024 03:40:02 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 996) id C78DF1A01; Fri, 15 Nov 2024 03:39:56 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 4DB221A02 for ; Fri, 15 Nov 2024 03:39:44 -0500 (EST) 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-17-BbcOk2QuNfqd9DZYB6YRsg-1; Fri, 15 Nov 2024 03:39:42 -0500 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 7E0CA1955EB3 for ; Fri, 15 Nov 2024 08:39:41 +0000 (UTC) Received: from speedmetal.lan (unknown [10.45.242.6]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id AD35419560A3 for ; Fri, 15 Nov 2024 08:39:40 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-1.5 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1731659984; 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=uK0va/UUXJd4zNHiiHmjeGYP++RbZK4Lf14rfa8wwKg=; b=CbrvWEbP1oEenu/uD7SLpoLBOLlO/ibh0Vz4hDXKuoaPV3XrXdgb0yd3QZUfQEHtbhO13/ vRZuwvJz+0dE+gi0SJzWYynTnagMNnYCkgaM25dlXb/U9BpPcjG2BE+ML6+uZ86amHXcvY 2hXhyigPwaem8go9aYvczVPpPTCy9KI= X-MC-Unique: BbcOk2QuNfqd9DZYB6YRsg-1 X-Mimecast-MFC-AGG-ID: BbcOk2QuNfqd9DZYB6YRsg From: Peter Krempa To: devel@lists.libvirt.org Subject: [PATCH 6/9] qemu: monitor: Add monitor infrastructure for 'snapshot-load' QMP command Date: Fri, 15 Nov 2024 09:39:27 +0100 Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: zuP8R-23kbQ2VQaHmKvsRnVqGfo-Up_UN1sF3ylfMWU_1731659981 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: HWUKKGZB2FFY2XIJGGXWAXWFOJNHM2HO X-Message-ID-Hash: HWUKKGZB2FFY2XIJGGXWAXWFOJNHM2HO X-MailFrom: pkrempa@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1731660174779116600 Content-Type: text/plain; charset="utf-8" Libvirt currently loads snapshots via the '-loadvm' commandline option but that uses the same logic as the 'loadvm' text monitor command used to pick the disk image with the 'vmstate' section. Since libvirt now implements our own logic to pick the 'vmstate' device it can happen that we pick a different than qemu and thus qemu would fail to load the snapshot. This happens currently on VMs with UEFI firmware with NVRAM image in qcow2 format. To fix this libvirt will need to use the 'snapshot-load' QMP command instead of relying on '-savevm'. Implement the monitor bits for 'snapshot-load'. Signed-off-by: Peter Krempa Reviewed-by: Michal Privoznik --- src/qemu/qemu_monitor.c | 16 ++++++++++++++++ src/qemu/qemu_monitor.h | 7 +++++++ src/qemu/qemu_monitor_json.c | 31 +++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 7 +++++++ 4 files changed, 61 insertions(+) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index fd888e2468..73f37d26eb 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2780,6 +2780,22 @@ qemuMonitorSnapshotSave(qemuMonitor *mon, } +int +qemuMonitorSnapshotLoad(qemuMonitor *mon, + const char *jobname, + const char *snapshotname, + const char *vmstate_disk, + const char **disks) +{ + VIR_DEBUG("jobname=3D'%s', snapshotname=3D'%s', vmstate_disk=3D'%s'", + jobname, snapshotname, vmstate_disk); + + QEMU_CHECK_MONITOR(mon); + + return qemuMonitorJSONSnapshotLoad(mon, jobname, snapshotname, vmstate= _disk, disks); +} + + int qemuMonitorSnapshotDelete(qemuMonitor *mon, const char *jobname, diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 035c9a7e3c..aded771315 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1626,6 +1626,13 @@ qemuMonitorSnapshotSave(qemuMonitor *mon, const char *vmstate_disk, const char **disks); +int +qemuMonitorSnapshotLoad(qemuMonitor *mon, + const char *jobname, + const char *snapshotname, + const char *vmstate_disk, + const char **disks); + int qemuMonitorSnapshotDelete(qemuMonitor *mon, const char *jobname, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index c594b33106..b3924461a9 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -8754,6 +8754,37 @@ qemuMonitorJSONSnapshotSave(qemuMonitor *mon, } +int +qemuMonitorJSONSnapshotLoad(qemuMonitor *mon, + const char *jobname, + const char *snapshotname, + const char *vmstate_disk, + const char **disks) +{ + g_autoptr(virJSONValue) cmd =3D NULL; + g_autoptr(virJSONValue) reply =3D NULL; + g_autoptr(virJSONValue) devices =3D virJSONValueNewArray(); + + for (; *disks; disks++) { + if (virJSONValueArrayAppendString(devices, *disks) < 0) + return -1; + } + + if (!(cmd =3D qemuMonitorJSONMakeCommand("snapshot-load", + "s:job-id", jobname, + "s:tag", snapshotname, + "s:vmstate", vmstate_disk, + "a:devices", &devices, + NULL))) + return -1; + + if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) + return -1; + + return qemuMonitorJSONCheckError(cmd, reply); +} + + int qemuMonitorJSONSnapshotDelete(qemuMonitor *mon, const char *jobname, diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index ab3c2cb7c8..0214e9e9ff 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -804,6 +804,13 @@ qemuMonitorJSONSnapshotSave(qemuMonitor *mon, const char *vmstate_disk, const char **disks); +int +qemuMonitorJSONSnapshotLoad(qemuMonitor *mon, + const char *jobname, + const char *snapshotname, + const char *vmstate_disk, + const char **disks); + int qemuMonitorJSONSnapshotDelete(qemuMonitor *mon, const char *jobname, --=20 2.47.0 From nobody Thu Dec 26 19:45:16 2024 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=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1731660198979604.0770718569398; Fri, 15 Nov 2024 00:43:18 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 996) id DDC3718F9; Fri, 15 Nov 2024 03:43:17 -0500 (EST) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 791FF17D9; Fri, 15 Nov 2024 03:40:05 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 996) id 84CEB19E0; Fri, 15 Nov 2024 03:39:57 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id C8CEE19B3 for ; Fri, 15 Nov 2024 03:39:46 -0500 (EST) 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-556-TmR-JF4FMISJRqzdfwfcJg-1; Fri, 15 Nov 2024 03:39:44 -0500 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 218281954AFB for ; Fri, 15 Nov 2024 08:39:43 +0000 (UTC) Received: from speedmetal.lan (unknown [10.45.242.6]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 0C3CD195388E for ; Fri, 15 Nov 2024 08:39:41 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1731659986; 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=9Ma7vC7r27I/1rm4ROc02D1upTaIMi5+XHw3SXQAQmM=; b=RiTWNyZTWcowaeDQWcRztj3JbGupgsfZ8LFcq3y/94RLpGL6a2bzGB1mSBAk9EKdz4unqF QYYAL3sqcYAeEjh70hhqORfWUB3Zg8la3w7MPeRspA1KGUW4ZdHkB24MZHDqAcBi/lVwEh r8UJ1k3rT7fnGze+Zgb3d4/mjzqj5Nk= X-MC-Unique: TmR-JF4FMISJRqzdfwfcJg-1 X-Mimecast-MFC-AGG-ID: TmR-JF4FMISJRqzdfwfcJg From: Peter Krempa To: devel@lists.libvirt.org Subject: [PATCH 7/9] qemu: Add enum entries for 'snapshot-load' qemu job Date: Fri, 15 Nov 2024 09:39:28 +0100 Message-ID: <7c665022dc9fe7afdace3809a3a183bb03eca3f1.1731659896.git.pkrempa@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: rB2aZvMSvGVPmA09Uv4J9-77ySdMmrfT221F9N747rg_1731659983 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: VXT7Y2ZRNTBADQELV7JZVTSC3GPAS2J7 X-Message-ID-Hash: VXT7Y2ZRNTBADQELV7JZVTSC3GPAS2J7 X-MailFrom: pkrempa@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1731660200886116600 Content-Type: text/plain; charset="utf-8" The internal snapshot code will use the 'snapshot-load' command so we need to add the corresponding job type. Signed-off-by: Peter Krempa Reviewed-by: Michal Privoznik --- src/qemu/qemu_block.c | 1 + src/qemu/qemu_blockjob.c | 2 ++ src/qemu/qemu_blockjob.h | 1 + src/qemu/qemu_domain.c | 2 ++ 4 files changed, 6 insertions(+) diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index 692b4d350e..3c1305ec84 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -3777,6 +3777,7 @@ qemuBlockPivot(virDomainObj *vm, case QEMU_BLOCKJOB_TYPE_CREATE: case QEMU_BLOCKJOB_TYPE_SNAPSHOT_SAVE: case QEMU_BLOCKJOB_TYPE_SNAPSHOT_DELETE: + case QEMU_BLOCKJOB_TYPE_SNAPSHOT_LOAD: case QEMU_BLOCKJOB_TYPE_BROKEN: virReportError(VIR_ERR_OPERATION_INVALID, _("job type '%1$s' does not support pivot"), diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c index 6e53603fba..c35321790e 100644 --- a/src/qemu/qemu_blockjob.c +++ b/src/qemu/qemu_blockjob.c @@ -70,6 +70,7 @@ VIR_ENUM_IMPL(qemuBlockjob, "create", "snapshot-save", "snapshot-delete", + "snapshot-load", "broken"); static virClass *qemuBlockJobDataClass; @@ -1459,6 +1460,7 @@ qemuBlockJobEventProcessConcludedTransition(qemuBlock= JobData *job, case QEMU_BLOCKJOB_TYPE_SNAPSHOT_SAVE: case QEMU_BLOCKJOB_TYPE_SNAPSHOT_DELETE: + case QEMU_BLOCKJOB_TYPE_SNAPSHOT_LOAD: /* The internal snapshot jobs don't need any extra handling */ break; diff --git a/src/qemu/qemu_blockjob.h b/src/qemu/qemu_blockjob.h index 6620e08c47..572a838676 100644 --- a/src/qemu/qemu_blockjob.h +++ b/src/qemu/qemu_blockjob.h @@ -67,6 +67,7 @@ typedef enum { QEMU_BLOCKJOB_TYPE_CREATE, QEMU_BLOCKJOB_TYPE_SNAPSHOT_SAVE, QEMU_BLOCKJOB_TYPE_SNAPSHOT_DELETE, + QEMU_BLOCKJOB_TYPE_SNAPSHOT_LOAD, QEMU_BLOCKJOB_TYPE_BROKEN, QEMU_BLOCKJOB_TYPE_LAST } qemuBlockJobType; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 4c0bfcd172..dfbf3dd9f0 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -2478,6 +2478,7 @@ qemuDomainObjPrivateXMLFormatBlockjobIterator(void *p= ayload, case QEMU_BLOCKJOB_TYPE_SNAPSHOT_SAVE: case QEMU_BLOCKJOB_TYPE_SNAPSHOT_DELETE: + case QEMU_BLOCKJOB_TYPE_SNAPSHOT_LOAD: /* No private data for internal snapshot jobs */ break; @@ -3035,6 +3036,7 @@ qemuDomainObjPrivateXMLParseBlockjobDataSpecific(qemu= BlockJobData *job, case QEMU_BLOCKJOB_TYPE_SNAPSHOT_SAVE: case QEMU_BLOCKJOB_TYPE_SNAPSHOT_DELETE: + case QEMU_BLOCKJOB_TYPE_SNAPSHOT_LOAD: /* No extra data for internal snapshot jobs. */ break; --=20 2.47.0 From nobody Thu Dec 26 19:45:16 2024 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=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1731660222090224.21300643720883; Fri, 15 Nov 2024 00:43:42 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 996) id 06ACA1A10; Fri, 15 Nov 2024 03:43:40 -0500 (EST) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id E710A1A57; Fri, 15 Nov 2024 03:40:07 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 996) id 61D3A1986; Fri, 15 Nov 2024 03:39:59 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id CEE341A2A for ; Fri, 15 Nov 2024 03:39:47 -0500 (EST) Received: from mx-prod-mc-04.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-685-JvynmYsKNpOY8L4Xs8c60g-1; Fri, 15 Nov 2024 03:39:45 -0500 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-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5270719792E1 for ; Fri, 15 Nov 2024 08:39:44 +0000 (UTC) Received: from speedmetal.lan (unknown [10.45.242.6]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 8370F1953880 for ; Fri, 15 Nov 2024 08:39:43 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-1.5 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1731659987; 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=dWgZjK5C3KQ4Mx1+vuU3CM4lF+35ZJ4oRE86Ftv1aAI=; b=QpQdeg3hqlAO6dDndVJPA61+Q++LWYqV5Daby7nkRmW88tzI54nVCze4nOP7MUSOSBKfp3 d+fRD8t4b2nV80rLADBiq1K/oKWfzeXe8MBRxpUZy2rSn8lalODpL7FGnUeDsKYRm5d6fJ oPAi7oHZZYmTlRJQVA9lPmn23F5mVwQ= X-MC-Unique: JvynmYsKNpOY8L4Xs8c60g-1 X-Mimecast-MFC-AGG-ID: JvynmYsKNpOY8L4Xs8c60g From: Peter Krempa To: devel@lists.libvirt.org Subject: [PATCH 8/9] qemu: monitor: Extract vmstate presence for internal snapshots in qemuBlockGetNamedNodeData Date: Fri, 15 Nov 2024 09:39:29 +0100 Message-ID: <3654389f1c98b1936e58cc02c364f15de93dc596.1731659896.git.pkrempa@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 4S-3DgQIUYDxwUXyxbH4vvXVbOOboxpi6Zd-df4pY0A_1731659985 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: XO6UCFPIL6JDUVP4ESX7ZCRCWUTUGPNX X-Message-ID-Hash: XO6UCFPIL6JDUVP4ESX7ZCRCWUTUGPNX X-MailFrom: pkrempa@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1731660223052116600 Content-Type: text/plain; charset="utf-8" Refactor the parts of qemuBlockGetNamedNodeData which fetch the names of internal snapshots present in the on-disk state of QCOW2 images to also extract the presence of the 'vmstate' section. This requires conversion of the snapshot list to a hash table as we always know the name of the snapshot that we're looking for, and the hash table allows also storing of additional data which we'll use to store the presence of the 'vmstate'. Signed-off-by: Peter Krempa Reviewed-by: Michal Privoznik --- src/qemu/qemu_monitor.h | 12 ++++++++++-- src/qemu/qemu_monitor_json.c | 18 ++++++++++++++---- src/qemu/qemu_snapshot.c | 6 ++---- tests/qemublocktest.c | 14 +++++++++++--- .../bitmap/snapshots-internal.out | 2 +- 5 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index aded771315..89a59dfd27 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -701,6 +701,13 @@ struct _qemuBlockNamedNodeDataBitmap { unsigned long long granularity; }; + +typedef struct _qemuBlockNamedNodeDataSnapshot qemuBlockNamedNodeDataSnaps= hot; +struct _qemuBlockNamedNodeDataSnapshot { + bool vmstate; +}; + + typedef struct _qemuBlockNamedNodeData qemuBlockNamedNodeData; struct _qemuBlockNamedNodeData { unsigned long long capacity; @@ -709,8 +716,9 @@ struct _qemuBlockNamedNodeData { qemuBlockNamedNodeDataBitmap **bitmaps; size_t nbitmaps; - /* NULL terminated string list of internal snapshot names */ - char **snapshots; + /* hash table indexed by snapshot name containing data about snapshots + * (qemuBlockNamedNodeDataSnapshot) */ + GHashTable *snapshots; /* the cluster size of the image is valid only when > 0 */ unsigned long long clusterSize; diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index b3924461a9..1b4288b744 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2569,7 +2569,7 @@ qemuMonitorJSONBlockNamedNodeDataFree(qemuBlockNamedN= odeData *data) for (i =3D 0; i < data->nbitmaps; i++) qemuMonitorJSONBlockNamedNodeDataBitmapFree(data->bitmaps[i]); - g_strfreev(data->snapshots); + g_clear_pointer(&data->snapshots, g_hash_table_unref); g_free(data->bitmaps); g_free(data); } @@ -2658,19 +2658,29 @@ qemuMonitorJSONBlockGetNamedNodeDataWorker(size_t p= os G_GNUC_UNUSED, if ((snapshots =3D virJSONValueObjectGetArray(img, "snapshots"))) { size_t nsnapshots =3D virJSONValueArraySize(snapshots); - size_t nsnapnames =3D 0; size_t i; - ent->snapshots =3D g_new0(char *, nsnapshots + 1); + ent->snapshots =3D virHashNew(g_free); for (i =3D 0; i < nsnapshots; i++) { virJSONValue *snapshot =3D virJSONValueArrayGet(snapshots, i); const char *name =3D virJSONValueObjectGetString(snapshot, "na= me"); + unsigned long long vmstate_size =3D 0; + qemuBlockNamedNodeDataSnapshot *snd; if (!name) continue; - ent->snapshots[nsnapnames++] =3D g_strdup(name); + ignore_value(virJSONValueObjectGetNumberUlong(snapshot, + "vm-state-size", + &vmstate_size)); + + snd =3D g_new0(qemuBlockNamedNodeDataSnapshot, 1); + + if (vmstate_size > 0) + snd->vmstate =3D true; + + g_hash_table_insert(ent->snapshots, g_strdup(name), snd); } } diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index 4a17935627..aab06a09c6 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -3897,8 +3897,7 @@ qemuSnapshotActiveInternalDeleteGetDevices(virDomainO= bj *vm, continue; /* there might be no snapshot for given disk with given name */ - if (!d->snapshots || - !g_strv_contains((const char **) d->snapshots, snapname)) + if (!virHashHasEntry(d->snapshots, snapname)) continue; devices[ndevs++] =3D g_strdup(format_nodename); @@ -3913,8 +3912,7 @@ qemuSnapshotActiveInternalDeleteGetDevices(virDomainO= bj *vm, if ((format_nodename =3D qemuBlockStorageSourceGetFormatNodename(v= m->def->os.loader->nvram)) && (d =3D virHashLookup(blockNamedNodeData, format_nodename)) && - d->snapshots && - g_strv_contains((const char **) d->snapshots, snapname)) { + virHashHasEntry(d->snapshots, snapname)) { devices[ndevs++] =3D g_strdup(format_nodename); } } diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c index ac4d87b527..be3e421ac0 100644 --- a/tests/qemublocktest.c +++ b/tests/qemublocktest.c @@ -598,12 +598,20 @@ testQemuDetectBitmapsWorker(GHashTable *nodedata, } if (data->snapshots) { - char **sn; + g_autofree virHashKeyValuePair *snaps =3D virHashGetItems(data->sn= apshots, NULL, true); + virHashKeyValuePair *n; virBufferAddLit(buf, "internal snapshots:"); - for (sn =3D data->snapshots; *sn; sn++) - virBufferAsprintf(buf, " '%s'", *sn); + for (n =3D snaps; n->key; n++) { + const qemuBlockNamedNodeDataSnapshot *d =3D n->value; + const char *vms =3D ""; + + if (d->vmstate) + vms =3D "(*)"; + + virBufferAsprintf(buf, " '%s'%s", (const char *) n->key, vms); + } } virBufferAdjustIndent(buf, -1); diff --git a/tests/qemublocktestdata/bitmap/snapshots-internal.out b/tests/= qemublocktestdata/bitmap/snapshots-internal.out index f2fb0a1dcc..dbb3cfded4 100644 --- a/tests/qemublocktestdata/bitmap/snapshots-internal.out +++ b/tests/qemublocktestdata/bitmap/snapshots-internal.out @@ -1,2 +1,2 @@ libvirt-1-format: - internal snapshots: '1727868651' '1727872064' + internal snapshots: '1727868651'(*) '1727872064'(*) --=20 2.47.0 From nobody Thu Dec 26 19:45:16 2024 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=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1731660253894286.7178635427092; Fri, 15 Nov 2024 00:44:13 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 996) id CD6B71828; Fri, 15 Nov 2024 03:44:12 -0500 (EST) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 62E5A1A60; Fri, 15 Nov 2024 03:40:09 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 996) id 8339119E1; Fri, 15 Nov 2024 03:40:03 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 141E617BE for ; Fri, 15 Nov 2024 03:39:49 -0500 (EST) Received: from mx-prod-mc-02.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-674-1_4KtNAGN2eyyNffyGfQQQ-1; Fri, 15 Nov 2024 03:39:46 -0500 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-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id A6E691944EAE for ; Fri, 15 Nov 2024 08:39:45 +0000 (UTC) Received: from speedmetal.lan (unknown [10.45.242.6]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id D2C7C1953880 for ; Fri, 15 Nov 2024 08:39:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1731659988; 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=UOMKOgUQsTreemoXppJb/jfU3jo4ncWchH33+RYh1ws=; b=K85zQ2hegl+RLhTXiaWpu4OK9Gl6h7oC2xlrp9E3Jh1dcwVs/iOIqOOYVAwPdZ+hygrqjo BoE1lzPirPDQb47SdshbOBFmW7uGCSdkAeWBt0L8xSsPucUE4tFLPjdxiZ8kPo3uz4UFVy pBlK3FQoiWbHaN0EaibwKWl44no6jqQ= X-MC-Unique: 1_4KtNAGN2eyyNffyGfQQQ-1 X-Mimecast-MFC-AGG-ID: 1_4KtNAGN2eyyNffyGfQQQ From: Peter Krempa To: devel@lists.libvirt.org Subject: [PATCH 9/9] qemu: Avoid use of '-loadvm' commandline argument for internal snapshot reversion Date: Fri, 15 Nov 2024 09:39:30 +0100 Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: jkD8_tgyZ-nPQA60EC6u0TV4-EMClcH-OWkB0wkNLns_1731659985 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: EK655I4LD5J5UKRNJUOPM2Q6AXV4SP6B X-Message-ID-Hash: EK655I4LD5J5UKRNJUOPM2Q6AXV4SP6B X-MailFrom: pkrempa@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1731660255226116600 Content-Type: text/plain; charset="utf-8" The '-loadvm' commandline parameter has exactly the same semantics as the HMP 'loadvm' command. This includes the selection of which block device is considered to contain the 'vmstate' section. Since libvirt recently switched to the new QMP commands which allow a free selection of where the 'vmstate' is placed, snapshot reversion will no longer work if libvirt's algorithm disagrees with qemu's. This is the case when the VM has UEFI NVRAM image, in qcow2 format, present. To solve this we'll use the QMP counterpart 'snapshot-load' to load the snapshot instead of using '-loadvm'. We'll do this before resuming processors after startup of qemu and thus the behaviour is identical to what we had before. The logic for selecting the images now checks both the snapshot metadata and the VM definition. In case images not covered by the snapshot definition do have the snapshot it's included in the reversion, but it's fatal if the snapshot is not present in a disk covered in snapshot metadata. The vmstate is selected based on where it's present as libvirt doesn't store this information. Signed-off-by: Peter Krempa Reviewed-by: Michal Privoznik --- src/qemu/qemu_command.c | 5 +- src/qemu/qemu_process.c | 7 ++ src/qemu/qemu_snapshot.c | 232 +++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_snapshot.h | 5 + 4 files changed, 248 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 696f891b47..f4430275dc 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -10567,7 +10567,10 @@ qemuBuildCommandLine(virDomainObj *vm, if (qemuBuildSecCommandLine(vm, cmd, def->sec) < 0) return NULL; - if (snapshot) + /* Internal snapshot reversion happens via QMP command after startup if + * supported */ + if (snapshot && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_SNAPSHOT_INTERNAL_QMP)) virCommandAddArgList(cmd, "-loadvm", snapshot->def->name, NULL); if (def->namespaceData) { diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 0815bffe3c..1fda8bdd65 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -7944,6 +7944,13 @@ qemuProcessLaunch(virConnectPtr conn, qemuDomainVcpuPersistOrder(vm->def); + if (snapshot && + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SNAPSHOT_INTERNAL_QMP)) { + VIR_DEBUG("reverting internal snapshot via QMP"); + if (qemuSnapshotInternalRevert(vm, snapshot, asyncJob) < 0) + goto cleanup; + } + VIR_DEBUG("Verifying and updating provided guest CPU"); if (qemuProcessUpdateAndVerifyCPU(vm, asyncJob) < 0) goto cleanup; diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index aab06a09c6..5b3aadcbf0 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -4361,3 +4361,235 @@ qemuSnapshotDelete(virDomainObj *vm, return ret; } + + +static char ** +qemuSnapshotInternalRevertGetDevices(virDomainObj *vm, + virDomainSnapshotDef *snapdef, + char **vmstate, + virDomainAsyncJob asyncJob) + +{ + g_autoptr(GHashTable) blockNamedNodeData =3D NULL; + const char *snapname =3D snapdef->parent.name; + g_auto(GStrv) devices =3D g_new0(char *, vm->def->ndisks + 2); + size_t ndevs =3D 0; + size_t i =3D 0; + const char *vmstate_candidate =3D NULL; + g_autoptr(GHashTable) snapdisks =3D virHashNew(NULL); + /* following variables add debug information */ + g_auto(virBuffer) errExtraSnap =3D VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) errSnapWithoutMetadata =3D VIR_BUFFER_INITIALIZER; + + if (!(blockNamedNodeData =3D qemuBlockGetNamedNodeData(vm, asyncJob))) + return NULL; + + /* Look up snapshot data from the snapshot object config itself */ + for (i =3D 0; i < snapdef->ndisks; i++) { + virDomainSnapshotDiskDef *snapdisk =3D snapdef->disks + i; + virDomainDiskDef *domdisk =3D virDomainDiskByTarget(vm->def, snapd= isk->name); + const char *format_nodename; + qemuBlockNamedNodeData *d =3D NULL; + qemuBlockNamedNodeDataSnapshot *sn =3D NULL; + + if (!domdisk) { + /* This can happen only if the snapshot metadata doesn't match= the + * domain XML stored in the snapshot */ + virReportError(VIR_ERR_INTERNAL_ERROR, + _("VM doesn't have disk '%1$s' referenced by sn= apshot '%2$s'"), + snapdisk->name, snapname); + return NULL; + } + + /* later we'll check if all disks from the VM definition XML were = considered */ + g_hash_table_insert(snapdisks, g_strdup(snapdisk->name), NULL); + + format_nodename =3D qemuBlockStorageSourceGetFormatNodename(domdis= k->src); + + /* Internal snapshots require image format which supports them, th= us + * this effectively rejects any raw images */ + if (format_nodename) + d =3D g_hash_table_lookup(blockNamedNodeData, format_nodename); + + if (d && d->snapshots) + sn =3D g_hash_table_lookup(d->snapshots, snapname); + + if (sn) { + if (sn->vmstate) { + if (vmstate_candidate) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("two disks images contain vm state se= ction for internal snapshot '%1$s'"), + snapname); + return NULL; + } + vmstate_candidate =3D format_nodename; + } + + devices[ndevs++] =3D g_strdup(format_nodename); + } + + switch (snapdisk->snapshot) { + case VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL: + if (!sn) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("image of disk '%1$s' does not have inter= nal snapshot '%2$s'"), + snapdisk->name, snapname); + return NULL; + } + + break; + + case VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL: + case VIR_DOMAIN_SNAPSHOT_LOCATION_MANUAL: + case VIR_DOMAIN_SNAPSHOT_LOCATION_NO: + case VIR_DOMAIN_SNAPSHOT_LOCATION_DEFAULT: + case VIR_DOMAIN_SNAPSHOT_LOCATION_LAST: + if (sn) { + /* Unexpected internal snapshot present in image even if t= he + * snapshot metadata claims otherwise */ + virBufferAsprintf(&errExtraSnap, "%s ", snapdisk->name); + } + break; + } + } + + /* check if all VM disks were covered */ + for (i =3D 0; i < vm->def->ndisks; i++) { + virDomainDiskDef *domdisk =3D vm->def->disks[i]; + const char *format_nodename; + qemuBlockNamedNodeData *d =3D NULL; + qemuBlockNamedNodeDataSnapshot *sn =3D NULL; + + if (g_hash_table_contains(snapdisks, domdisk->dst)) + continue; + + format_nodename =3D qemuBlockStorageSourceGetFormatNodename(domdis= k->src); + + if (format_nodename) + d =3D g_hash_table_lookup(blockNamedNodeData, format_nodename); + + if (d && d->snapshots) + sn =3D g_hash_table_lookup(d->snapshots, snapname); + + if (sn) { + virBufferAsprintf(&errSnapWithoutMetadata, "%s ", domdisk->dst= ); + + if (sn->vmstate) { + if (vmstate_candidate) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("two disks images contain vm state se= ction for internal snapshot '%1$s'"), + snapname); + return NULL; + } + vmstate_candidate =3D format_nodename; + } + + devices[ndevs++] =3D g_strdup(format_nodename); + } + } + + /* pflash */ + if (vm->def->os.loader && + vm->def->os.loader->nvram && + vm->def->os.loader->nvram->format =3D=3D VIR_STORAGE_FILE_QCOW2) { + const char *format_nodename; + qemuBlockNamedNodeData *d =3D NULL; + qemuBlockNamedNodeDataSnapshot *sn =3D NULL; + + if ((format_nodename =3D qemuBlockStorageSourceGetFormatNodename(v= m->def->os.loader->nvram)) && + (d =3D virHashLookup(blockNamedNodeData, format_nodename)) && + d->snapshots && + (sn =3D g_hash_table_lookup(d->snapshots, snapname))) { + if (sn->vmstate) { + if (vmstate_candidate) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("two disks images contain vm state se= ction for internal snapshot '%1$s'"), + snapname); + return NULL; + } + + vmstate_candidate =3D format_nodename; + } + + devices[ndevs++] =3D g_strdup(format_nodename); + } + } + + if (virBufferUse(&errExtraSnap) > 0 || + virBufferUse(&errSnapWithoutMetadata) > 0) { + VIR_WARN("inconsistent internal snapshot state (reversion): VM=3D'= %s' snapshot=3D'%s' no-snapshot=3D'%s' no-metadata=3D'%s'", + vm->def->name, snapname, + virBufferCurrentContent(&errExtraSnap), + virBufferCurrentContent(&errSnapWithoutMetadata)); + } + + *vmstate =3D g_strdup(vmstate_candidate); + return g_steal_pointer(&devices); +} + + +int +qemuSnapshotInternalRevert(virDomainObj *vm, + virDomainMomentObj *snapshot, + virDomainAsyncJob asyncJob) +{ + virDomainSnapshotDef *snapdef =3D virDomainSnapshotObjGetDef(snapshot); + g_autofree char *jobname =3D g_strdup_printf("internal-snapshot-load-%= s", snapdef->parent.name); + qemuBlockJobData *job =3D NULL; + g_auto(GStrv) devices =3D NULL; + g_autofree char *vmstate =3D NULL; + int rc =3D 0; + int ret =3D -1; + + if (!(devices =3D qemuSnapshotInternalRevertGetDevices(vm, snapdef, &v= mstate, asyncJob))) + return -1; + + if (!vmstate) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("missing vmstate section when reverting active in= ternal snapshot '%1$s'"), + snapshot->def->name); + return -1; + } + + if (!(job =3D qemuBlockJobDiskNew(vm, NULL, QEMU_BLOCKJOB_TYPE_SNAPSHO= T_LOAD, + jobname))) + return -1; + + qemuBlockJobSyncBegin(job); + + if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0) + goto cleanup; + + rc =3D qemuMonitorSnapshotLoad(qemuDomainGetMonitor(vm), jobname, snap= def->parent.name, + vmstate, (const char **) devices); + qemuDomainObjExitMonitor(vm); + + if (rc < 0) + goto cleanup; + + qemuBlockJobStarted(job, vm); + + while (true) { + qemuBlockJobUpdate(vm, job, asyncJob); + + if (job->state =3D=3D VIR_DOMAIN_BLOCK_JOB_FAILED) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("load of internal snapshot '%1$s' job failed:= %2$s"), + snapdef->parent.name, NULLSTR(job->errmsg)); + goto cleanup; + } + + if (job->state =3D=3D VIR_DOMAIN_BLOCK_JOB_COMPLETED) + break; + + if (qemuDomainObjWait(vm) < 0) + goto cleanup; + } + + ret =3D 0; + + cleanup: + qemuBlockJobStartupFinalize(vm, job); + + return ret; +} diff --git a/src/qemu/qemu_snapshot.h b/src/qemu/qemu_snapshot.h index 38437a2fd7..f38c2acfb3 100644 --- a/src/qemu/qemu_snapshot.h +++ b/src/qemu/qemu_snapshot.h @@ -84,3 +84,8 @@ qemuSnapshotDiskCreate(qemuSnapshotDiskContext *snapctxt); virDomainSnapshotDiskDef * qemuSnapshotGetTransientDiskDef(virDomainDiskDef *domdisk, const char *suffix); + +int +qemuSnapshotInternalRevert(virDomainObj *vm, + virDomainMomentObj *snapshot, + virDomainAsyncJob asyncJob); --=20 2.47.0