From nobody Mon Feb 9 12:26:21 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) client-ip=170.10.133.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail(p=quarantine dis=quarantine) header.from=virtuozzo.com Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by mx.zohomail.com with SMTPS id 1636622203398245.167409471047; Thu, 11 Nov 2021 01:16:43 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-100-F0oao-g-PO65u2NTtmk4Jg-1; Thu, 11 Nov 2021 04:16:38 -0500 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 45E78804148; Thu, 11 Nov 2021 09:16:34 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 2688960CCC; Thu, 11 Nov 2021 09:16:34 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id EDAC21819AC1; Thu, 11 Nov 2021 09:16:33 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 1AB9C9fo027498 for ; Thu, 11 Nov 2021 04:12:09 -0500 Received: by smtp.corp.redhat.com (Postfix) id 929AE51E3; Thu, 11 Nov 2021 09:12:08 +0000 (UTC) Received: from mimecast-mx02.redhat.com (mimecast02.extmail.prod.ext.rdu2.redhat.com [10.11.55.18]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8D1E751E2 for ; Thu, 11 Nov 2021 09:12:08 +0000 (UTC) Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [207.211.31.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 73BA3801212 for ; Thu, 11 Nov 2021 09:12:08 +0000 (UTC) Received: from relay.sw.ru (relay.sw.ru [185.231.240.75]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-419-0YhCx8icOaCrxghtV7wC0A-1; Thu, 11 Nov 2021 04:12:06 -0500 Received: from [10.28.15.237] (helo=vz8.sw.ru) by relay.sw.ru with esmtp (Exim 4.94.2) (envelope-from ) id 1ml5sB-008xIO-Sd for libvir-list@redhat.com; Thu, 11 Nov 2021 11:55:55 +0300 X-MC-Unique: F0oao-g-PO65u2NTtmk4Jg-1 X-MC-Unique: 0YhCx8icOaCrxghtV7wC0A-1 From: Nikolay Shirokovskiy To: libvir-list@redhat.com Subject: [PATCH 8/9] qemu: support instant snapshots Date: Thu, 11 Nov 2021 11:55:53 +0300 Message-Id: <20211111085554.14685-9-nshirokovskiy@virtuozzo.com> In-Reply-To: <20211111085554.14685-1-nshirokovskiy@virtuozzo.com> References: <20211111085554.14685-1-nshirokovskiy@virtuozzo.com> MIME-Version: 1.0 X-Mimecast-Impersonation-Protect: Policy=CLT - Impersonation Protection Definition; Similar Internal Domain=false; Similar Monitored External Domain=false; Custom External Domain=false; Mimecast External Domain=false; Newly Observed Domain=false; Internal User Name=false; Custom Display Name List=false; Reply-to Address Mismatch=false; Targeted Threat Dictionary=false; Mimecast Threat Dictionary=false; Custom Threat Dictionary=false X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1636622204319100001 Content-Type: text/plain; charset="utf-8" Usual snapshot with memory of a running domain with first saves domain memory to disk and then make a disk snapshot. As result we get snapshot at moment in time much later then client asked for snapshot if domain memory is large. So basically you need to wait several minutes or even several tens of minutes before making guest unsafe changes. This patch adds instant mode to snapshot with memory of a running domain. In this mode snapshot is done almost at the moment of client request. It does not depends of domain memory size. So client can proceed with unsafe changes immediately (We need an event to notify client though as snapshot API itself is still synchronous and API will finish when domain memory will be stored to disk). I dared to call this snapshot mode instant instead of background as it named in QEMU. IMHO in case of libvirt API name background be confused with asynchronous snapshot API which is not true. Instant mode basically just stops guest CPUs, makes disks snapshot and then start QEMU's background memory snapshot. Background here means if guest writes some region in memory then this memory first is written to disk so that eventually domain memory written to disk corresponds to moment of starting background snapshot. Note that background snapshot starts guest CPUs right after snapshot start and do not stop CPUs after snapshot is finished unlikely to usual memory snapshots or migration. Nevertheless qemuSnapshotCreateActiveExternal calls qemuProcessStartCPUs in instant mode in order to lock domain images and other tasks we do not do in resume handler. Signed-off-by: Nikolay Shirokovskiy --- include/libvirt/libvirt-domain-snapshot.h | 2 + src/qemu/qemu_snapshot.c | 68 ++++++++++++++++++----- 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/include/libvirt/libvirt-domain-snapshot.h b/include/libvirt/li= bvirt-domain-snapshot.h index 90673ed0fb..2661ba2556 100644 --- a/include/libvirt/libvirt-domain-snapshot.h +++ b/include/libvirt/libvirt-domain-snapshot.h @@ -73,6 +73,8 @@ typedef enum { running */ VIR_DOMAIN_SNAPSHOT_CREATE_VALIDATE =3D (1 << 9), /* validate the X= ML against the sche= ma */ + VIR_DOMAIN_SNAPSHOT_CREATE_INSTANT =3D (1 << 10),/* snapshot at th= e moment + of call */ } virDomainSnapshotCreateFlags; =20 /* Take a snapshot of the current VM state */ diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index b521634f2a..14c4a64d52 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -1398,6 +1398,7 @@ qemuSnapshotCreateActiveExternal(virQEMUDriver *drive= r, { virObjectEvent *event; bool resume =3D false; + bool instant =3D false; int ret =3D -1; qemuDomainObjPrivate *priv =3D vm->privateData; virDomainSnapshotDef *snapdef =3D virDomainSnapshotObjGetDef(snap); @@ -1442,13 +1443,25 @@ qemuSnapshotCreateActiveExternal(virQEMUDriver *dri= ver, if (virDomainObjGetState(vm, NULL) =3D=3D VIR_DOMAIN_PMSUSPENDED) { pmsuspended =3D true; } else if (virDomainObjGetState(vm, NULL) =3D=3D VIR_DOMAIN_RUNNING) { + if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_INSTANT) { + if (!qemuMigrationCapsGet(vm, QEMU_MIGRATION_CAP_BACKGROUND_SN= APSHOT)) { + virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", + _("Migration option 'background-snapshot'" + " is not supported by QEMU binary")); + goto cleanup; + } + + instant =3D true; + } + /* For full system external snapshots (those with memory), the gue= st * must pause (either by libvirt up front, or by qemu after * _LIVE converges). */ if (memory) resume =3D true; =20 - if (memory && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_LIVE)) { + if (memory && + (!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_LIVE) || instant)) { if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SNAPSHOT, QEMU_ASYNC_JOB_SNAPSHOT) < 0) goto cleanup; @@ -1472,21 +1485,39 @@ qemuSnapshotCreateActiveExternal(virQEMUDriver *dri= ver, if (memory) { memory_existing =3D virFileExists(snapdef->memorysnapshotfile); =20 - if (qemuSnapshotSaveMemory(driver, vm, snapdef, resume, false, cfg= ) < 0) - goto cleanup; + if (instant) { + if ((ret =3D qemuSnapshotCreateActiveExternalDisks(vm, snap, + blockNamedNod= eData, flags, + QEMU_ASYNC_JO= B_SNAPSHOT)) < 0) + goto cleanup; =20 - /* the memory image was created, remove it on errors */ - if (!memory_existing) - memory_unlink =3D true; + if (qemuSnapshotSaveMemory(driver, vm, snapdef, resume, true, = cfg) < 0) + goto cleanup; =20 - } + /* the memory image was created, remove it on errors */ + if (!memory_existing) + memory_unlink =3D true; + } else { + if (qemuSnapshotSaveMemory(driver, vm, snapdef, resume, false,= cfg) < 0) + goto cleanup; =20 - /* the domain is now paused if a memory snapshot was requested */ + /* the memory image was created, remove it on errors */ + if (!memory_existing) + memory_unlink =3D true; =20 - if ((ret =3D qemuSnapshotCreateActiveExternalDisks(vm, snap, - blockNamedNodeData, f= lags, - QEMU_ASYNC_JOB_SNAPSH= OT)) < 0) - goto cleanup; + /* the domain is now paused if a memory snapshot was requested= */ + if ((ret =3D qemuSnapshotCreateActiveExternalDisks(vm, snap, + blockNamedNod= eData, flags, + QEMU_ASYNC_JO= B_SNAPSHOT)) < 0) + goto cleanup; + } + } else { + /* the domain is now paused if a memory snapshot was requested */ + if ((ret =3D qemuSnapshotCreateActiveExternalDisks(vm, snap, + blockNamedNodeDat= a, flags, + QEMU_ASYNC_JOB_SN= APSHOT)) < 0) + goto cleanup; + } =20 /* the snapshot is complete now */ if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT) { @@ -1575,7 +1606,8 @@ qemuSnapshotCreateXML(virDomainPtr domain, VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE | VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC | VIR_DOMAIN_SNAPSHOT_CREATE_LIVE | - VIR_DOMAIN_SNAPSHOT_CREATE_VALIDATE, NULL); + VIR_DOMAIN_SNAPSHOT_CREATE_VALIDATE | + VIR_DOMAIN_SNAPSHOT_CREATE_INSTANT, NULL); =20 VIR_REQUIRE_FLAG_RET(VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE, VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY, @@ -1584,6 +1616,16 @@ qemuSnapshotCreateXML(virDomainPtr domain, VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE, NULL); =20 + VIR_EXCLUSIVE_FLAGS_RET(VIR_DOMAIN_SNAPSHOT_CREATE_INSTANT, + VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY, + NULL); + VIR_EXCLUSIVE_FLAGS_RET(VIR_DOMAIN_SNAPSHOT_CREATE_INSTANT, + VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE, + NULL); + VIR_REQUIRE_FLAG_RET(VIR_DOMAIN_SNAPSHOT_CREATE_INSTANT, + VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, + NULL); + if ((redefine && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)) || (flags & VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA)) update_current =3D false; --=20 2.27.0