From nobody Mon Feb 9 07:12:24 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=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 1727963371218462.3845911392863; Thu, 3 Oct 2024 06:49:31 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 2809F15F9; Thu, 3 Oct 2024 09:49:30 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id EB1D414F3; Thu, 3 Oct 2024 09:47:11 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 4B0EB14CA; Thu, 3 Oct 2024 09:47:06 -0400 (EDT) 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 1916EA2C for ; Thu, 3 Oct 2024 09:46:53 -0400 (EDT) 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-681-0gSA_W9pPiK3DcnMFVuxsw-1; Thu, 03 Oct 2024 09:46:51 -0400 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 95C601955D92; Thu, 3 Oct 2024 13:46:50 +0000 (UTC) Received: from speedmetal.redhat.com (unknown [10.45.242.12]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 273FB19560A2; Thu, 3 Oct 2024 13:46:48 +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.5 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=1727963212; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=j/PC49cASH5oVwAAt0iSc7K12jZ/HlffDzGJ596cTqU=; b=fobPUXhgTWEPBjGJvfrlWPJJLgLg/tMADF7ptk1Bvg/xAQC6XhGBsR0EE8HnlwdhkwyVYK y39jbjsNj22yvdw4adia5GoqtzYAp2BK3jE+YpBK0QTd4mC0hlWkMEzfKGkBuiQJv9BX4H i7bxzLrf5X+zbDKpqDww+Jipi4s8eLU= X-MC-Unique: 0gSA_W9pPiK3DcnMFVuxsw-1 From: Peter Krempa To: devel@lists.libvirt.org Subject: [PATCH v3 06/10] qemu snapshot: use QMP snapshot-save for internal snapshots creation Date: Thu, 3 Oct 2024 15:46:32 +0200 Message-ID: <3b844b91b9ad862021f94629f1f462e4ef9ae6c6.1727962906.git.pkrempa@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: PKOLAVIDHGWRIIN6XC23SDHX2DDYNITU X-Message-ID-Hash: PKOLAVIDHGWRIIN6XC23SDHX2DDYNITU 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 CC: nikolai.barybin@virtuozzo.com, den@openvz.org 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: 1727963371825116600 Content-Type: text/plain; charset="utf-8" From: Nikolai Barybin via Devel The usage of HMP commands are highly discouraged by qemu. Moreover, current snapshot creation routine does not provide flexibility in choosing target device for VM state snapshot. This patch makes use of QMP commands snapshot-save and by default chooses first writable non-shared qcow2 disk (if present) as target for VM state. Signed-off-by: Nikolai Barybin Signed-off-by: Peter Krempa --- src/qemu/qemu_snapshot.c | 124 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 116 insertions(+), 8 deletions(-) diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index f5260c4a22..d4602d386f 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -309,6 +309,99 @@ qemuSnapshotCreateInactiveExternal(virQEMUDriver *driv= er, } +static char ** +qemuSnapshotActiveInternalCreateGetDevices(virDomainObj *vm, + virDomainSnapshotDef *snapdef) +{ + g_auto(GStrv) devices =3D g_new0(char *, vm->def->ndisks + 2); + size_t ndevs =3D 0; + size_t i =3D 0; + + /* This relies on @snapdef being aligned and validated via + * virDomainSnapshotAlignDisks() and qemuSnapshotPrepare(), which also + * ensures that all disks are backed by qcow2. */ + for (i =3D 0; i < snapdef->ndisks; i++) { + virDomainSnapshotDiskDef *snapdisk =3D snapdef->disks + i; + virDomainDiskDef *domdisk =3D vm->def->disks[i]; + + switch (snapdisk->snapshot) { + case VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL: + devices[ndevs++] =3D g_strdup(qemuBlockStorageSourceGetFormatN= odename(domdisk->src)); + 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: + continue; + } + } + + if (vm->def->os.loader && + vm->def->os.loader->nvram && + vm->def->os.loader->nvram->format =3D=3D VIR_STORAGE_FILE_QCOW2) { + devices[ndevs++] =3D g_strdup(qemuBlockStorageSourceGetFormatNoden= ame(vm->def->os.loader->nvram)); + } + + return g_steal_pointer(&devices); +} + + +static int +qemuSnapshotCreateActiveInternalDone(virDomainObj *vm, + qemuBlockJobData *job) +{ + qemuBlockJobUpdate(vm, job, VIR_ASYNC_JOB_SNAPSHOT); + + if (job->state =3D=3D VIR_DOMAIN_BLOCK_JOB_FAILED) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("snapshot-save job failed: %1$s"), NULLSTR(job->e= rrmsg)); + return -1; + } + + return job->state =3D=3D VIR_DOMAIN_BLOCK_JOB_COMPLETED ? 1 : 0; +} + + +static qemuBlockJobData * +qemuSnapshotCreateActiveInternalStart(virDomainObj *vm, + virDomainSnapshotDef *snapdef) +{ + g_autofree char *jobname =3D g_strdup_printf("internal-snapshot-save-%= s", snapdef->parent.name); + qemuBlockJobData *job =3D NULL; + g_auto(GStrv) devices =3D NULL; + int rc =3D 0; + + if (!(devices =3D qemuSnapshotActiveInternalCreateGetDevices(vm, snapd= ef))) + return NULL; + + if (!(job =3D qemuBlockJobDiskNew(vm, NULL, QEMU_BLOCKJOB_TYPE_SNAPSHO= T_SAVE, + jobname))) + return NULL; + + qemuBlockJobSyncBegin(job); + + if (qemuDomainObjEnterMonitorAsync(vm, VIR_ASYNC_JOB_SNAPSHOT) < 0) + goto error; + + rc =3D qemuMonitorSnapshotSave(qemuDomainGetMonitor(vm), jobname, snap= def->parent.name, + devices[0], (const char **) devices); + qemuDomainObjExitMonitor(vm); + + if (rc < 0) + goto error; + + qemuBlockJobStarted(job, vm); + + return job; + + error: + qemuBlockJobStartupFinalize(vm, job); + return NULL; +} + + /* The domain is expected to be locked and active. */ static int qemuSnapshotCreateActiveInternal(virQEMUDriver *driver, @@ -321,6 +414,7 @@ qemuSnapshotCreateActiveInternal(virQEMUDriver *driver, bool resume =3D false; virDomainSnapshotDef *snapdef =3D virDomainSnapshotObjGetDef(snap); int ret =3D -1; + int rv =3D 0; if (!qemuMigrationSrcIsAllowed(vm, false, VIR_ASYNC_JOB_SNAPSHOT, 0)) goto cleanup; @@ -342,15 +436,29 @@ qemuSnapshotCreateActiveInternal(virQEMUDriver *drive= r, } } - if (qemuDomainObjEnterMonitorAsync(vm, VIR_ASYNC_JOB_SNAPSHOT) < 0) { - resume =3D false; - goto cleanup; - } + if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SNAPSHOT_INTERNAL_QMP)) { + g_autoptr(qemuBlockJobData) job =3D NULL; - ret =3D qemuMonitorCreateSnapshot(priv->mon, snap->def->name); - qemuDomainObjExitMonitor(vm); - if (ret < 0) - goto cleanup; + if (!(job =3D qemuSnapshotCreateActiveInternalStart(vm, snapdef))) + goto cleanup; + + while ((rv =3D qemuSnapshotCreateActiveInternalDone(vm, job)) !=3D= 1) { + if (rv < 0 || qemuDomainObjWait(vm) < 0) + goto cleanup; + } + + ret =3D 0; + } else { + if (qemuDomainObjEnterMonitorAsync(vm, VIR_ASYNC_JOB_SNAPSHOT) < 0= ) { + resume =3D false; + goto cleanup; + } + + ret =3D qemuMonitorCreateSnapshot(priv->mon, snap->def->name); + qemuDomainObjExitMonitor(vm); + if (ret < 0) + goto cleanup; + } if (!(snapdef->cookie =3D (virObject *) qemuDomainSaveCookieNew(vm))) goto cleanup; --=20 2.46.0