From nobody Tue Mar 3 04:53:02 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1771343848; cv=none; d=zohomail.com; s=zohoarc; b=TmsFaKrh8phVKJRme6Rth27WHqnzOMmpMov4A//SPBlhbeRk+POHvQduYApljGqOcEPEcdtrxRt4lUk0o0xCQ51L6NKYeMhQ5uZpu0cZtS5S/yXOerP0yVNJv0tn9ED51zX1HleW/57Nu1aQUv1aM7LRSr8A2NOjTzP41zSJ2jk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1771343848; h=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id:Cc; bh=k1YMYJ6jM7nFcaezcys+pgqNsASpVSpFD4zDomVEGLk=; b=GZhF2uS1JKYutyzjKG8Yg+EsJ5eoPSV04osK1k8b6KwjK3EZ5ETLXlF+H70Bt8YVHMX4KgeWDdwApdyx1leNPa19lUzUYxnuNmh7CXurt4R5rPm1UgNhktXdRrJiti4uBSGAGl5PhYy45FTFwclRiZkF2Xz0hDMsU1SFyKEpFOs= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1771343848924466.74886312174203; Tue, 17 Feb 2026 07:57:28 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 993) id 17882418FA; Tue, 17 Feb 2026 10:57:28 -0500 (EST) Received: from [172.19.199.9] (lists.libvirt.org [8.43.85.245]) by lists.libvirt.org (Postfix) with ESMTP id 4D11341A59; Tue, 17 Feb 2026 10:54:14 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 993) id 7CA703F95E; Tue, 17 Feb 2026 10:54:09 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id B84E1418F6 for ; Tue, 17 Feb 2026 10:53:02 -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-482--nIV6N0rNcOvHa82cpyGYw-1; Tue, 17 Feb 2026 10:53:01 -0500 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 35B4C1954B12 for ; Tue, 17 Feb 2026 15:53:00 +0000 (UTC) Received: from speedmetal.lan (unknown [10.45.242.39]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 821E31800590 for ; Tue, 17 Feb 2026 15:52:59 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-4.7 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HELO_MISC_IP,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_PASS autolearn=unavailable autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1771343582; 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=k1YMYJ6jM7nFcaezcys+pgqNsASpVSpFD4zDomVEGLk=; b=W2Epps/oF2DgsJ5/kQGo6i96AV0rIJ7zpe9xGo5zjhDzaLVG/YjpvOjn3Q7ysMjdBIwQKt DiAZLFgDGHqSllr7znPpnkHzuan8FTmJWR1iumgJfBffk3UufheTpTvDWj4h0EcCcW3Ga1 PptH2bxn7P4FdilO3k6JelMcgQzA50s= X-MC-Unique: -nIV6N0rNcOvHa82cpyGYw-1 X-Mimecast-MFC-AGG-ID: -nIV6N0rNcOvHa82cpyGYw_1771343580 To: devel@lists.libvirt.org Subject: [PATCH 5/6] qemu: driver: Merge 'qemuDomainRestoreInternal' and 'qemuDomainObjRestore' Date: Tue, 17 Feb 2026 16:52:50 +0100 Message-ID: <55dfbc629bf68d8cf5293ebaa0820a985784978d.1771343375.git.pkrempa@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: Z-g2nBdFh_SahGdTdCX5LNLSZdOg-EBIFQZMltiEKvQ_1771343580 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: QE7GSHLHXX45TUVMZ2MKYEEH3Y65EY47 X-Message-ID-Hash: QE7GSHLHXX45TUVMZ2MKYEEH3Y65EY47 X-MailFrom: pkrempa@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Peter Krempa via Devel Reply-To: Peter Krempa X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1771343851016158500 Content-Type: text/plain; charset="utf-8" From: Peter Krempa The two functions are for reverting a save image. They differ only on what domain object is used (new one vs existing one). Merge the code paths for existing VMs (for managed save restore) into 'qemuDomainRestoreInternal' and reuse it instead of 'qemuDomainObjRestore'. Signed-off-by: Peter Krempa --- src/qemu/qemu_driver.c | 222 +++++++++++++++++++---------------------- 1 file changed, 100 insertions(+), 122 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 7f08fd05e9..c2d810c013 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5760,19 +5760,50 @@ static int qemuNodeGetSecurityModel(virConnectPtr c= onn, return 0; } + +/** + * qemuDomainRestoreInternal: + * @conn: connection object + * @vmRestore: Domain object (optional; see below) + * @path: path to the save image file + * @unlink_corrupt: remove corrupted save image file @path + * @dxml: XML to replace definition in the save image (optional) + * @params: restore parameters + * @nparams: number of @params + * @flags: binary-OR of virDomainSaveRestoreFlags + * @ensureACL: callback for function checking ACL access (optional) + * @asyncJob: async job type + * + * Restores VM from save image at @path. + * + * If @vmRestore is non-NULL the VM object is reused and also the name and= UUID + * of the VM from the save image is checked against it. + * + * @dxml can be used to optionally override the XML from the save image. + * + * @ensureACL must be passed unless the access to the domain object was al= ready + * verified. + * + * Returns 0 on success; -1 on error. If @unlink_corrupt is true and the + * corrupted image was removed 1 is returned. + */ static int qemuDomainRestoreInternal(virConnectPtr conn, + virDomainObj *vmRestore, const char *path, + bool unlink_corrupt, const char *dxml, virTypedParameterPtr params, int nparams, unsigned int flags, - int (*ensureACL)(virConnectPtr, virDomainDef *)) + int (*ensureACL)(virConnectPtr, virDomainDef *), + virDomainAsyncJob asyncJob) { virQEMUDriver *driver =3D conn->privateData; qemuDomainObjPrivate *priv =3D NULL; g_autoptr(virDomainDef) def =3D NULL; virDomainObj *vm =3D NULL; + virDomainObj *vmNew =3D NULL; g_autofree char *xmlout =3D NULL; const char *newxml =3D dxml; int fd =3D -1; @@ -5792,8 +5823,21 @@ qemuDomainRestoreInternal(virConnectPtr conn, if (flags & VIR_DOMAIN_SAVE_RESET_NVRAM) reset_nvram =3D true; - if (qemuSaveImageGetMetadata(driver, NULL, path, ensureACL, conn, &def= , &data) < 0) + if (qemuSaveImageGetMetadata(driver, NULL, path, ensureACL, conn, &def= , &data) < 0) { + if (unlink_corrupt && + qemuSaveImageIsCorrupt(driver, path)) { + if (unlink(path) < 0) { + virReportSystemError(errno, + _("cannot remove corrupt file: %1$s"), + path); + } else { + virResetLastError(); + ret =3D 1; + } + } + goto cleanup; + } sparse =3D data->header.format =3D=3D QEMU_SAVE_FORMAT_SPARSE; if (!(restoreParams =3D qemuMigrationParamsForSave(params, nparams, sp= arse, @@ -5833,12 +5877,36 @@ qemuDomainRestoreInternal(virConnectPtr conn, def =3D tmp; } - if (!(vm =3D virDomainObjListAdd(driver->domains, &def, - driver->xmlopt, - VIR_DOMAIN_OBJ_LIST_ADD_LIVE | - VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE, - NULL))) - goto cleanup; + if (vmRestore) { + vm =3D vmRestore; + + if (STRNEQ(vm->def->name, def->name) || + memcmp(vm->def->uuid, def->uuid, VIR_UUID_BUFLEN)) { + char vm_uuidstr[VIR_UUID_STRING_BUFLEN]; + char def_uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(vm->def->uuid, vm_uuidstr); + virUUIDFormat(def->uuid, def_uuidstr); + virReportError(VIR_ERR_OPERATION_FAILED, + _("cannot restore domain '%1$s' uuid %2$s from = a file which belongs to domain '%3$s' uuid %4$s"), + vm->def->name, vm_uuidstr, + def->name, def_uuidstr); + goto cleanup; + } + + virDomainObjAssignDef(vm, &def, true, NULL); + } else { + if (!(vmNew =3D virDomainObjListAdd(driver->domains, &def, + driver->xmlopt, + VIR_DOMAIN_OBJ_LIST_ADD_LIVE | + VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LI= VE, + NULL))) + goto cleanup; + + vm =3D vmNew; + + if (qemuProcessBeginJob(vm, VIR_DOMAIN_JOB_OPERATION_RESTORE, flag= s) < 0) + goto cleanup; + } if (flags & VIR_DOMAIN_SAVE_RUNNING) data->header.was_running =3D 1; @@ -5850,13 +5918,11 @@ qemuDomainRestoreInternal(virConnectPtr conn, priv->hookRun =3D true; } - if (qemuProcessBeginJob(vm, VIR_DOMAIN_JOB_OPERATION_RESTORE, flags) <= 0) - goto cleanup; - ret =3D qemuSaveImageStartVM(conn, driver, vm, &fd, data, path, restor= eParams, - false, reset_nvram, VIR_ASYNC_JOB_START); + false, reset_nvram, asyncJob); - qemuProcessEndJob(vm); + if (vmNew) + qemuProcessEndJob(vmNew); cleanup: VIR_FORCE_CLOSE(fd); @@ -5864,9 +5930,9 @@ qemuDomainRestoreInternal(virConnectPtr conn, ret =3D -1; virFileWrapperFdFree(wrapperFd); virQEMUSaveDataFree(data); - if (vm && ret < 0) - qemuDomainRemoveInactive(vm, 0, false); - virDomainObjEndAPI(&vm); + if (vmNew && ret < 0) + qemuDomainRemoveInactive(vmNew, 0, false); + virDomainObjEndAPI(&vmNew); return ret; } @@ -5876,16 +5942,18 @@ qemuDomainRestoreFlags(virConnectPtr conn, const char *dxml, unsigned int flags) { - return qemuDomainRestoreInternal(conn, path, dxml, NULL, 0, flags, - virDomainRestoreFlagsEnsureACL); + return qemuDomainRestoreInternal(conn, NULL, path, false, dxml, NULL, = 0, + flags, virDomainRestoreFlagsEnsureACL, + VIR_ASYNC_JOB_START); } static int qemuDomainRestore(virConnectPtr conn, const char *path) { - return qemuDomainRestoreInternal(conn, path, NULL, NULL, 0, 0, - virDomainRestoreEnsureACL); + return qemuDomainRestoreInternal(conn, NULL, path, false, NULL, NULL, = 0, + 0, virDomainRestoreEnsureACL, + VIR_ASYNC_JOB_START); } static int @@ -5917,8 +5985,9 @@ qemuDomainRestoreParams(virConnectPtr conn, return -1; } - ret =3D qemuDomainRestoreInternal(conn, path, dxml, params, nparams, f= lags, - virDomainRestoreParamsEnsureACL); + ret =3D qemuDomainRestoreInternal(conn, NULL, path, false, dxml, param= s, nparams, + flags, virDomainRestoreParamsEnsureACL, + VIR_ASYNC_JOB_START); return ret; } @@ -6089,103 +6158,6 @@ qemuDomainManagedSaveDefineXML(virDomainPtr dom, co= nst char *dxml, return ret; } -/* Return 0 on success, 1 if incomplete saved image was silently unlinked, - * and -1 on failure with error raised. */ -static int -qemuDomainObjRestore(virConnectPtr conn, - virQEMUDriver *driver, - virDomainObj *vm, - const char *path, - bool start_paused, - bool bypass_cache, - bool reset_nvram, - virDomainAsyncJob asyncJob) -{ - g_autoptr(virDomainDef) def =3D NULL; - qemuDomainObjPrivate *priv =3D vm->privateData; - int fd =3D -1; - int ret =3D -1; - g_autofree char *xmlout =3D NULL; - virQEMUSaveData *data =3D NULL; - virFileWrapperFd *wrapperFd =3D NULL; - bool sparse =3D false; - g_autoptr(qemuMigrationParams) restoreParams =3D NULL; - - ret =3D qemuSaveImageGetMetadata(driver, NULL, path, NULL, NULL, &def,= &data); - if (ret < 0) { - if (qemuSaveImageIsCorrupt(driver, path)) { - if (unlink(path) < 0) { - virReportSystemError(errno, - _("cannot remove corrupt file: %1$s"), - path); - ret =3D -1; - } else { - virResetLastError(); - ret =3D 1; - } - } - goto cleanup; - } - - sparse =3D data->header.format =3D=3D QEMU_SAVE_FORMAT_SPARSE; - if (!(restoreParams =3D qemuMigrationParamsForSave(NULL, 0, sparse, - bypass_cache))) - return -1; - - fd =3D qemuSaveImageOpen(driver, path, bypass_cache, sparse, &wrapperF= d, false); - if (fd < 0) - goto cleanup; - - if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) { - int hookret; - - if ((hookret =3D virHookCall(VIR_HOOK_DRIVER_QEMU, def->name, - VIR_HOOK_QEMU_OP_RESTORE, - VIR_HOOK_SUBOP_BEGIN, - NULL, data->xml, &xmlout)) < 0) - goto cleanup; - - if (hookret =3D=3D 0 && !virStringIsEmpty(xmlout)) { - virDomainDef *tmp; - - VIR_DEBUG("Using hook-filtered domain XML: %s", xmlout); - - if (!(tmp =3D qemuSaveImageUpdateDef(driver, def, xmlout))) - goto cleanup; - - virDomainDefFree(def); - def =3D tmp; - priv->hookRun =3D true; - } - } - - if (STRNEQ(vm->def->name, def->name) || - memcmp(vm->def->uuid, def->uuid, VIR_UUID_BUFLEN)) { - char vm_uuidstr[VIR_UUID_STRING_BUFLEN]; - char def_uuidstr[VIR_UUID_STRING_BUFLEN]; - virUUIDFormat(vm->def->uuid, vm_uuidstr); - virUUIDFormat(def->uuid, def_uuidstr); - virReportError(VIR_ERR_OPERATION_FAILED, - _("cannot restore domain '%1$s' uuid %2$s from a fi= le which belongs to domain '%3$s' uuid %4$s"), - vm->def->name, vm_uuidstr, - def->name, def_uuidstr); - goto cleanup; - } - - virDomainObjAssignDef(vm, &def, true, NULL); - - ret =3D qemuSaveImageStartVM(conn, driver, vm, &fd, data, path, restor= eParams, - start_paused, reset_nvram, asyncJob); - - cleanup: - virQEMUSaveDataFree(data); - VIR_FORCE_CLOSE(fd); - if (virFileWrapperFdClose(wrapperFd) < 0) - ret =3D -1; - virFileWrapperFdFree(wrapperFd); - return ret; -} - static char *qemuDomainGetXMLDesc(virDomainPtr dom, @@ -6358,11 +6330,17 @@ qemuDomainObjStart(virConnectPtr conn, vm->hasManagedSave =3D false; } else { virDomainJobOperation op =3D vm->job->current->operation; + unsigned int restore_flags =3D 0; + vm->job->current->operation =3D VIR_DOMAIN_JOB_OPERATION_RESTO= RE; - ret =3D qemuDomainObjRestore(conn, driver, vm, managed_save, - start_paused, bypass_cache, - reset_nvram, asyncJob); + restore_flags |=3D start_paused ? VIR_DOMAIN_SAVE_PAUSED : 0; + restore_flags |=3D bypass_cache ? VIR_DOMAIN_SAVE_BYPASS_CACHE= : 0; + restore_flags |=3D reset_nvram ? VIR_DOMAIN_SAVE_RESET_NVRAM := 0; + + ret =3D qemuDomainRestoreInternal(conn, vm, managed_save, true= , NULL, NULL, 0, + restore_flags, NULL, + asyncJob); if (ret =3D=3D 0) { if (unlink(managed_save) < 0) --=20 2.53.0