From nobody Tue Feb 10 20:48:42 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=none dis=none) header.from=openvz.org 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 1648725593595963.8302979331761; Thu, 31 Mar 2022 04:19:53 -0700 (PDT) Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-626-Vah-c440MpKmr7_Btg97GA-1; Thu, 31 Mar 2022 07:19:48 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id B2F94180075B; Thu, 31 Mar 2022 11:19:46 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9CCE3400E42D; Thu, 31 Mar 2022 11:19:46 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (localhost [IPv6:::1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id DDE241947BBD; Thu, 31 Mar 2022 11:19:45 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 950FA1940345 for ; Thu, 31 Mar 2022 11:19:45 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id 783B4400E132; Thu, 31 Mar 2022 11:19:45 +0000 (UTC) Received: from mimecast-mx02.redhat.com (mimecast05.extmail.prod.ext.rdu2.redhat.com [10.11.55.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 73B4440D1B9B for ; Thu, 31 Mar 2022 11:19:45 +0000 (UTC) Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.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 53FF5805F46 for ; Thu, 31 Mar 2022 11:19:45 +0000 (UTC) Received: from mail-lf1-f54.google.com (mail-lf1-f54.google.com [209.85.167.54]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-608-3CBZ0cv5OfiF2E3_dr5Yyw-1; Thu, 31 Mar 2022 07:19:43 -0400 Received: by mail-lf1-f54.google.com with SMTP id bu29so40991942lfb.0 for ; Thu, 31 Mar 2022 04:19:43 -0700 (PDT) Received: from vzbook.. (broadband-90-154-71-96.ip.moscow.rt.ru. [90.154.71.96]) by smtp.gmail.com with ESMTPSA id b24-20020a196458000000b0044ab702b6acsm695653lfj.238.2022.03.31.04.19.40 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 31 Mar 2022 04:19:40 -0700 (PDT) X-MC-Unique: Vah-c440MpKmr7_Btg97GA-1 X-Original-To: libvir-list@listman.corp.redhat.com X-MC-Unique: 3CBZ0cv5OfiF2E3_dr5Yyw-1 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=LuMVXZxFvxI52RhGfU/tInpdoB0aJ6oBfZi4dl5yDmA=; b=UKw1ti3aUo//u8huuliS5j/ifkZ/lg0btVD7KLtylZf1/w6w1SQLJKY84kOdoKb5EI 2PtJW+xvNZijMNtGOjutmm8a5hxLQvubdzES/B93AjVwKfL9ydEyLRx+k5s4X4wsoUaX CLdEGIiV4nW3m/j3ok0ZXZLXfnrFLQ2s/QZSiGITfaUNszyf/EbbQqea384++ZG3J9sV AVd+SPZKdbcTtEYmwnuK2BvdSl2NvrO5YnmlzkKjO9XJ42x5scUeKrjCsZvHvdCirfiE bEJGubc/GnItWH0q+sXbYtKUYRphs7Pq57Jq6qPlhEzSOvF67qxB0i3TLDQ6mGVeOwP1 OWdg== X-Gm-Message-State: AOAM532fcC3ZxqNnNMu/wQahcothAB9AJSs0CGoA3lqNiCEA+PVEbo/1 oJ6l4oYwe35yVkSYHOETLUHBJ+l4bnByVA== X-Google-Smtp-Source: ABdhPJyH7KgdIzC4JCd6aatELC7y9UMNCmzICdrD0ZQLNOTEJVTKZYokhBzBxf+myi4XX3oRXrMsXQ== X-Received: by 2002:a05:6512:6d:b0:44a:42b7:e775 with SMTP id i13-20020a056512006d00b0044a42b7e775mr10622462lfo.33.1648725581108; Thu, 31 Mar 2022 04:19:41 -0700 (PDT) From: Nikolay Shirokovskiy To: libvir-list@redhat.com Subject: [PATCH 03/11] qemu: move snapshot related funcs from domain.c to snapshot.c Date: Thu, 31 Mar 2022 14:19:13 +0300 Message-Id: <20220331111921.450496-4-nikolay.shirokovskiy@openvz.org> In-Reply-To: <20220331111921.450496-1-nikolay.shirokovskiy@openvz.org> References: <20220331111921.450496-1-nikolay.shirokovskiy@openvz.org> 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.84 on 10.11.54.2 X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libvir-list-bounces@redhat.com Sender: "libvir-list" X-Scanned-By: MIMEDefang 2.84 on 10.11.54.2 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: 1648725595093100003 Content-Type: text/plain; charset="utf-8"; x-default="true" These functions mostly used from the qemu_snapshot.c and also semantically they belong to this source file. At the same time rename qemuDomainSnapshot* to qemuSnaphot*. Signed-off-by: Nikolay Shirokovskiy --- src/qemu/qemu_domain.c | 241 +---------------------------------- src/qemu/qemu_domain.h | 19 --- src/qemu/qemu_driver.c | 8 +- src/qemu/qemu_snapshot.c | 268 ++++++++++++++++++++++++++++++++++++--- src/qemu/qemu_snapshot.h | 10 ++ 5 files changed, 269 insertions(+), 277 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 18d403e099..56cf0c3f68 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -38,6 +38,7 @@ #include "qemu_checkpoint.h" #include "qemu_validate.h" #include "qemu_namespace.h" +#include "qemu_snapshot.h" #include "viralloc.h" #include "virlog.h" #include "virerror.h" @@ -64,7 +65,6 @@ #include "virsecret.h" #include "logging/log_manager.h" #include "locking/domain_lock.h" -#include "virdomainsnapshotobjlist.h" #include "virdomaincheckpointobjlist.h" #include "backup_conf.h" #include "virutil.h" @@ -7041,243 +7041,6 @@ qemuFindQemuImgBinary(virQEMUDriver *driver) return driver->qemuImgBinary; } =20 -int -qemuDomainSnapshotWriteMetadata(virDomainObj *vm, - virDomainMomentObj *snapshot, - virDomainXMLOption *xmlopt, - const char *snapshotDir) -{ - g_autofree char *newxml =3D NULL; - g_autofree char *snapDir =3D NULL; - g_autofree char *snapFile =3D NULL; - char uuidstr[VIR_UUID_STRING_BUFLEN]; - unsigned int flags =3D VIR_DOMAIN_SNAPSHOT_FORMAT_SECURE | - VIR_DOMAIN_SNAPSHOT_FORMAT_INTERNAL; - virDomainSnapshotDef *def =3D virDomainSnapshotObjGetDef(snapshot); - - if (virDomainSnapshotGetCurrent(vm->snapshots) =3D=3D snapshot) - flags |=3D VIR_DOMAIN_SNAPSHOT_FORMAT_CURRENT; - virUUIDFormat(vm->def->uuid, uuidstr); - newxml =3D virDomainSnapshotDefFormat(uuidstr, def, xmlopt, flags); - if (newxml =3D=3D NULL) - return -1; - - snapDir =3D g_strdup_printf("%s/%s", snapshotDir, vm->def->name); - if (g_mkdir_with_parents(snapDir, 0777) < 0) { - virReportSystemError(errno, _("cannot create snapshot directory '%= s'"), - snapDir); - return -1; - } - - snapFile =3D g_strdup_printf("%s/%s.xml", snapDir, def->parent.name); - - return virXMLSaveFile(snapFile, NULL, "snapshot-edit", newxml); -} - - -/* 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, - virDomainMomentObj *snap, - const char *op, - bool try_all, - 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", - 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 = '%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(driver, def, snap, - "-d", false, i); - } - virReportError(VIR_ERR_OPERATION_INVALID, - _("Disk device '%s' does not support snapshotti= ng"), - 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(driver, 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(virQEMUDriver *driver, - virDomainDef *def, - virDomainMomentObj *snap, - const char *op, - bool try_all) -{ - return qemuDomainSnapshotForEachQcow2Raw(driver, def, snap, - op, try_all, def->ndisks); -} - -/* Discard one snapshot (or its metadata), without reparenting any childre= n. */ -int -qemuDomainSnapshotDiscard(virQEMUDriver *driver, - virDomainObj *vm, - virDomainMomentObj *snap, - bool update_parent, - bool metadata_only) -{ - g_autofree char *snapFile =3D NULL; - qemuDomainObjPrivate *priv; - virDomainMomentObj *parentsnap =3D NULL; - g_autoptr(virQEMUDriverConfig) cfg =3D virQEMUDriverGetConfig(driver); - - if (!metadata_only) { - if (!virDomainObjIsActive(vm)) { - size_t i; - /* Ignore any skipped disks */ - - /* Prefer action on the disks in use at the time the snapshot = was - * created; but fall back to current definition if dealing wit= h a - * snapshot created prior to libvirt 0.9.5. */ - virDomainDef *def =3D snap->def->dom; - - if (!def) - def =3D vm->def; - - for (i =3D 0; i < def->ndisks; i++) { - if (virDomainDiskTranslateSourcePool(def->disks[i]) < 0) - return -1; - } - - if (qemuDomainSnapshotForEachQcow2(driver, def, snap, "-d", tr= ue) < 0) - return -1; - } else { - priv =3D vm->privateData; - qemuDomainObjEnterMonitor(driver, vm); - /* we continue on even in the face of error */ - qemuMonitorDeleteSnapshot(priv->mon, snap->def->name); - qemuDomainObjExitMonitor(vm); - } - } - - snapFile =3D g_strdup_printf("%s/%s/%s.xml", cfg->snapshotDir, vm->def= ->name, - snap->def->name); - - if (snap =3D=3D virDomainSnapshotGetCurrent(vm->snapshots)) { - virDomainSnapshotSetCurrent(vm->snapshots, NULL); - if (update_parent && snap->def->parent_name) { - parentsnap =3D virDomainSnapshotFindByName(vm->snapshots, - snap->def->parent_nam= e); - if (!parentsnap) { - VIR_WARN("missing parent snapshot matching name '%s'", - snap->def->parent_name); - } else { - virDomainSnapshotSetCurrent(vm->snapshots, parentsnap); - if (qemuDomainSnapshotWriteMetadata(vm, parentsnap, - driver->xmlopt, - cfg->snapshotDir) < 0)= { - VIR_WARN("failed to set parent snapshot '%s' as curren= t", - snap->def->parent_name); - virDomainSnapshotSetCurrent(vm->snapshots, NULL); - } - } - } - } - - if (unlink(snapFile) < 0) - VIR_WARN("Failed to unlink %s", snapFile); - if (update_parent) - virDomainMomentDropParent(snap); - virDomainSnapshotObjListRemove(vm->snapshots, snap); - - return 0; -} - -/* Hash iterator callback to discard multiple snapshots. */ -int qemuDomainMomentDiscardAll(void *payload, - const char *name G_GNUC_UNUSED, - void *data) -{ - virDomainMomentObj *moment =3D payload; - virQEMUMomentRemove *curr =3D data; - int err; - - if (!curr->found && curr->current =3D=3D moment) - curr->found =3D true; - err =3D curr->momentDiscard(curr->driver, curr->vm, moment, false, - curr->metadata_only); - if (err && !curr->err) - curr->err =3D err; - return 0; -} - -int -qemuDomainSnapshotDiscardAllMetadata(virQEMUDriver *driver, - virDomainObj *vm) -{ - virQEMUMomentRemove rem =3D { - .driver =3D driver, - .vm =3D vm, - .metadata_only =3D true, - .momentDiscard =3D qemuDomainSnapshotDiscard, - }; - - virDomainSnapshotForEach(vm->snapshots, qemuDomainMomentDiscardAll, &r= em); - virDomainSnapshotObjListRemoveAll(vm->snapshots); - - return rem.err; -} - =20 static void qemuDomainRemoveInactiveCommon(virQEMUDriver *driver, @@ -7288,7 +7051,7 @@ qemuDomainRemoveInactiveCommon(virQEMUDriver *driver, g_autofree char *chkDir =3D NULL; =20 /* Remove any snapshot metadata prior to removing the domain */ - if (qemuDomainSnapshotDiscardAllMetadata(driver, vm) < 0) { + if (qemuSnapshotDiscardAllMetadata(driver, vm) < 0) { VIR_WARN("unable to remove all snapshots for domain %s", vm->def->name); } else { diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index a41d8308e3..494a276212 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -633,22 +633,6 @@ int qemuDomainLogAppendMessage(virQEMUDriver *driver, =20 const char *qemuFindQemuImgBinary(virQEMUDriver *driver); =20 -int qemuDomainSnapshotWriteMetadata(virDomainObj *vm, - virDomainMomentObj *snapshot, - virDomainXMLOption *xmlopt, - const char *snapshotDir); - -int qemuDomainSnapshotForEachQcow2(virQEMUDriver *driver, - virDomainDef *def, - virDomainMomentObj *snap, - const char *op, - bool try_all); - -int qemuDomainSnapshotDiscard(virQEMUDriver *driver, - virDomainObj *vm, - virDomainMomentObj *snap, - bool update_current, - bool metadata_only); =20 typedef struct _virQEMUMomentRemove virQEMUMomentRemove; struct _virQEMUMomentRemove { @@ -666,9 +650,6 @@ int qemuDomainMomentDiscardAll(void *payload, const char *name, void *data); =20 -int qemuDomainSnapshotDiscardAllMetadata(virQEMUDriver *driver, - virDomainObj *vm); - void qemuDomainRemoveInactive(virQEMUDriver *driver, virDomainObj *vm); =20 diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 77012eb527..74bc2c7bf4 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6568,7 +6568,7 @@ qemuDomainUndefineFlags(virDomainPtr dom, nsnapshots); goto endjob; } - if (qemuDomainSnapshotDiscardAllMetadata(driver, vm) < 0) + if (qemuSnapshotDiscardAllMetadata(driver, vm) < 0) goto endjob; } if (!virDomainObjIsActive(vm) && @@ -19132,9 +19132,9 @@ qemuDomainSnapshotWriteMetadataIter(void *payload, virQEMUDriverConfig *cfg =3D virQEMUDriverGetConfig(data->driver); int ret; =20 - ret =3D qemuDomainSnapshotWriteMetadata(data->vm, payload, - data->driver->xmlopt, - cfg->snapshotDir); + ret =3D qemuSnapshotWriteMetadata(data->vm, payload, + data->driver->xmlopt, + cfg->snapshotDir); =20 virObjectUnref(cfg); return ret; diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index 5d622592c3..878a0abb34 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -49,6 +49,175 @@ VIR_LOG_INIT("qemu.qemu_snapshot"); =20 =20 +/* 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 +qemuSnapshotForEachQcow2Raw(virQEMUDriver *driver, + virDomainDef *def, + virDomainMomentObj *snap, + const char *op, + bool try_all, + 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", + 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 = '%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. */ + qemuSnapshotForEachQcow2Raw(driver, def, snap, "-d", false= , i); + } + virReportError(VIR_ERR_OPERATION_INVALID, + _("Disk device '%s' does not support snapshotti= ng"), + 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. */ + qemuSnapshotForEachQcow2Raw(driver, 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(virQEMUDriver *driver, + virDomainDef *def, + virDomainMomentObj *snap, + const char *op, + bool try_all) +{ + return qemuSnapshotForEachQcow2Raw(driver, def, snap, + op, try_all, def->ndisks); +} + + +/* Discard one snapshot (or its metadata), without reparenting any childre= n. */ +static int +qemuSnapshotDiscard(virQEMUDriver *driver, + virDomainObj *vm, + virDomainMomentObj *snap, + bool update_parent, + bool metadata_only) +{ + g_autofree char *snapFile =3D NULL; + qemuDomainObjPrivate *priv; + virDomainMomentObj *parentsnap =3D NULL; + g_autoptr(virQEMUDriverConfig) cfg =3D virQEMUDriverGetConfig(driver); + + if (!metadata_only) { + if (!virDomainObjIsActive(vm)) { + size_t i; + /* Ignore any skipped disks */ + + /* Prefer action on the disks in use at the time the snapshot = was + * created; but fall back to current definition if dealing wit= h a + * snapshot created prior to libvirt 0.9.5. */ + virDomainDef *def =3D snap->def->dom; + + if (!def) + def =3D vm->def; + + for (i =3D 0; i < def->ndisks; i++) { + if (virDomainDiskTranslateSourcePool(def->disks[i]) < 0) + return -1; + } + + if (qemuSnapshotForEachQcow2(driver, def, snap, "-d", true) < = 0) + return -1; + } else { + priv =3D vm->privateData; + qemuDomainObjEnterMonitor(driver, vm); + /* we continue on even in the face of error */ + qemuMonitorDeleteSnapshot(priv->mon, snap->def->name); + qemuDomainObjExitMonitor(vm); + } + } + + snapFile =3D g_strdup_printf("%s/%s/%s.xml", cfg->snapshotDir, vm->def= ->name, + snap->def->name); + + if (snap =3D=3D virDomainSnapshotGetCurrent(vm->snapshots)) { + virDomainSnapshotSetCurrent(vm->snapshots, NULL); + if (update_parent && snap->def->parent_name) { + parentsnap =3D virDomainSnapshotFindByName(vm->snapshots, + snap->def->parent_nam= e); + if (!parentsnap) { + VIR_WARN("missing parent snapshot matching name '%s'", + snap->def->parent_name); + } else { + virDomainSnapshotSetCurrent(vm->snapshots, parentsnap); + if (qemuSnapshotWriteMetadata(vm, parentsnap, + driver->xmlopt, + cfg->snapshotDir) < 0) { + VIR_WARN("failed to set parent snapshot '%s' as curren= t", + snap->def->parent_name); + virDomainSnapshotSetCurrent(vm->snapshots, NULL); + } + } + } + } + + if (unlink(snapFile) < 0) + VIR_WARN("Failed to unlink %s", snapFile); + if (update_parent) + virDomainMomentDropParent(snap); + virDomainSnapshotObjListRemove(vm->snapshots, snap); + + return 0; +} + + /** * qemuSnapshotSetCurrent: Set currently active snapshot * @@ -73,7 +242,7 @@ qemuSnapshotSetCurrent(virDomainObj *vm, * 'active' property */ if (oldcurrent && oldcurrent !=3D newcurrent) { - if (qemuDomainSnapshotWriteMetadata(vm, oldcurrent, driver->xmlopt= , cfg->snapshotDir) < 0) + if (qemuSnapshotWriteMetadata(vm, oldcurrent, driver->xmlopt, cfg-= >snapshotDir) < 0) VIR_WARN("failed to update old current snapshot"); } } @@ -167,7 +336,7 @@ qemuSnapshotCreateInactiveInternal(virQEMUDriver *drive= r, virDomainObj *vm, virDomainMomentObj *snap) { - return qemuDomainSnapshotForEachQcow2(driver, vm->def, snap, "-c", fal= se); + return qemuSnapshotForEachQcow2(driver, vm->def, snap, "-c", false); } =20 =20 @@ -1691,9 +1860,8 @@ qemuSnapshotCreateWriteMetadata(virDomainObj *vm, virQEMUDriver *driver, virQEMUDriverConfig *cfg) { - if (qemuDomainSnapshotWriteMetadata(vm, snap, - driver->xmlopt, - cfg->snapshotDir) < 0) { + if (qemuSnapshotWriteMetadata(vm, snap, driver->xmlopt, + cfg->snapshotDir) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("unable to save metadata for snapshot %s"), snap->def->name); @@ -2005,9 +2173,8 @@ qemuSnapshotRevertWriteMetadata(virDomainObj *vm, bool defined) { qemuSnapshotSetCurrent(vm, snap); - if (qemuDomainSnapshotWriteMetadata(vm, snap, - driver->xmlopt, - cfg->snapshotDir) < 0) { + if (qemuSnapshotWriteMetadata(vm, snap, driver->xmlopt, + cfg->snapshotDir) < 0) { virDomainSnapshotSetCurrent(vm->snapshots, NULL); return -1; } @@ -2146,7 +2313,7 @@ qemuSnapshotInternalRevertInactive(virQEMUDriver *dri= ver, } =20 /* Try all disks, but report failure if we skipped any. */ - if (qemuDomainSnapshotForEachQcow2(driver, def, snap, "-a", true) !=3D= 0) + if (qemuSnapshotForEachQcow2(driver, def, snap, "-a", true) !=3D 0) return -1; =20 return 0; @@ -2415,7 +2582,7 @@ qemuSnapshotDelete(virDomainObj *vm, rem.err =3D 0; rem.current =3D virDomainSnapshotGetCurrent(vm->snapshots); rem.found =3D false; - rem.momentDiscard =3D qemuDomainSnapshotDiscard; + rem.momentDiscard =3D qemuSnapshotDiscard; virDomainMomentForEachDescendant(snap, qemuDomainMomentDiscardAll, &rem); if (rem.err < 0) @@ -2424,9 +2591,8 @@ qemuSnapshotDelete(virDomainObj *vm, qemuSnapshotSetCurrent(vm, snap); =20 if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) { - if (qemuDomainSnapshotWriteMetadata(vm, snap, - driver->xmlopt, - cfg->snapshotDir) < 0)= { + if (qemuSnapshotWriteMetadata(vm, snap, driver->xmlopt, + cfg->snapshotDir) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to set snapshot '%s' as curre= nt"), snap->def->name); @@ -2441,7 +2607,7 @@ qemuSnapshotDelete(virDomainObj *vm, rep.vm =3D vm; rep.err =3D 0; rep.xmlopt =3D driver->xmlopt; - rep.writeMetadata =3D qemuDomainSnapshotWriteMetadata; + rep.writeMetadata =3D qemuSnapshotWriteMetadata; virDomainMomentForEachChild(snap, qemuSnapshotChildrenReparent, &rep); @@ -2454,7 +2620,7 @@ qemuSnapshotDelete(virDomainObj *vm, virDomainMomentDropChildren(snap); ret =3D 0; } else { - ret =3D qemuDomainSnapshotDiscard(driver, vm, snap, true, metadata= _only); + ret =3D qemuSnapshotDiscard(driver, vm, snap, true, metadata_only); } =20 endjob: @@ -2462,3 +2628,75 @@ qemuSnapshotDelete(virDomainObj *vm, =20 return ret; } + + +int +qemuSnapshotWriteMetadata(virDomainObj *vm, + virDomainMomentObj *snapshot, + virDomainXMLOption *xmlopt, + const char *snapshotDir) +{ + g_autofree char *newxml =3D NULL; + g_autofree char *snapDir =3D NULL; + g_autofree char *snapFile =3D NULL; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + unsigned int flags =3D VIR_DOMAIN_SNAPSHOT_FORMAT_SECURE | + VIR_DOMAIN_SNAPSHOT_FORMAT_INTERNAL; + virDomainSnapshotDef *def =3D virDomainSnapshotObjGetDef(snapshot); + + if (virDomainSnapshotGetCurrent(vm->snapshots) =3D=3D snapshot) + flags |=3D VIR_DOMAIN_SNAPSHOT_FORMAT_CURRENT; + virUUIDFormat(vm->def->uuid, uuidstr); + newxml =3D virDomainSnapshotDefFormat(uuidstr, def, xmlopt, flags); + if (newxml =3D=3D NULL) + return -1; + + snapDir =3D g_strdup_printf("%s/%s", snapshotDir, vm->def->name); + if (g_mkdir_with_parents(snapDir, 0777) < 0) { + virReportSystemError(errno, _("cannot create snapshot directory '%= s'"), + snapDir); + return -1; + } + + snapFile =3D g_strdup_printf("%s/%s.xml", snapDir, def->parent.name); + + return virXMLSaveFile(snapFile, NULL, "snapshot-edit", newxml); +} + + +/* Hash iterator callback to discard multiple snapshots. */ +int +qemuDomainMomentDiscardAll(void *payload, + const char *name G_GNUC_UNUSED, + void *data) +{ + virDomainMomentObj *moment =3D payload; + virQEMUMomentRemove *curr =3D data; + int err; + + if (!curr->found && curr->current =3D=3D moment) + curr->found =3D true; + err =3D curr->momentDiscard(curr->driver, curr->vm, moment, false, + curr->metadata_only); + if (err && !curr->err) + curr->err =3D err; + return 0; +} + + +int +qemuSnapshotDiscardAllMetadata(virQEMUDriver *driver, + virDomainObj *vm) +{ + virQEMUMomentRemove rem =3D { + .driver =3D driver, + .vm =3D vm, + .metadata_only =3D true, + .momentDiscard =3D qemuSnapshotDiscard, + }; + + virDomainSnapshotForEach(vm->snapshots, qemuDomainMomentDiscardAll, &r= em); + virDomainSnapshotObjListRemoveAll(vm->snapshots); + + return rem.err; +} diff --git a/src/qemu/qemu_snapshot.h b/src/qemu/qemu_snapshot.h index 0cc38c0039..016d18449a 100644 --- a/src/qemu/qemu_snapshot.h +++ b/src/qemu/qemu_snapshot.h @@ -81,3 +81,13 @@ qemuSnapshotDiskCreate(qemuSnapshotDiskContext *snapctxt= ); virDomainSnapshotDiskDef * qemuSnapshotGetTransientDiskDef(virDomainDiskDef *domdisk, const char *suffix); + +int +qemuSnapshotWriteMetadata(virDomainObj *vm, + virDomainMomentObj *snapshot, + virDomainXMLOption *xmlopt, + const char *snapshotDir); + +int +qemuSnapshotDiscardAllMetadata(virQEMUDriver *driver, + virDomainObj *vm); --=20 2.35.1