From nobody Tue Sep 9 23:43:09 2025 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=1738290772; cv=none; d=zohomail.com; s=zohoarc; b=A6Hj5fUX053Zldi9TqUGUTxqf0lPyguyIV5zPEvnFPw+8rCoyV4Azugit2CDu0NUy64ClmXomAYeVFRvyBhZxQeDH78dvK9U26m0ojuhDPg/2gxPSrxZ6vrpSYIwbfVv5UbZIO/yBlaP0Jerz7sExS5yxcUeRRCGB269O/2zJAc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1738290772; h=Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post: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=q0mwgibkfIF3TYNUOvoY92m+bSFxCco7AZ1JCCcZMpg=; b=BfVYQFe6UlEbKNHId4JP5pfE1mI7BiDUAN5qoZ1mU1DrLQalo5uUWaZvjU+CEzP5+EU1FDGj38dhjAwwU2O0lXDjRagClQbbAUdssYGNW2QUthEJemHwgY9olDiXU5EASOq0+IBDNCgwwUnqEf4qE59A2P4w1T/Er11vvzek6s4= 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 1738290772595496.48561209347577; Thu, 30 Jan 2025 18:32:52 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 996) id EAAA81D87; Thu, 30 Jan 2025 21:32:51 -0500 (EST) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 178FA1D7C; Thu, 30 Jan 2025 21:31:23 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 996) id 2668B1CD0; Thu, 30 Jan 2025 21:31:18 -0500 (EST) Received: from mail-ed1-f41.google.com (mail-ed1-f41.google.com [209.85.208.41]) (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 200591CCF for ; Thu, 30 Jan 2025 21:31:17 -0500 (EST) Received: by mail-ed1-f41.google.com with SMTP id 4fb4d7f45d1cf-5dc82e38c10so383709a12.3 for ; Thu, 30 Jan 2025 18:31:17 -0800 (PST) Received: from localhost (205-201-32-8.scinternet.net. [205.201.32.8]) by smtp.gmail.com with UTF8SMTPSA id d2e1a72fcca58-72fe631bea6sm2168055b3a.22.2025.01.30.18.31.15 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Jan 2025 18:31:15 -0800 (PST) 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, 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=suse.com; s=google; t=1738290676; x=1738895476; darn=lists.libvirt.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=FOGFz0R89I+3XlhdqrkY22tFKN4smXuqaSck1w1ygKU=; b=YuxCqOax2BeMmI8pm3VwHLbiU3hnxmZIV4hqhULkHcK20a5bXzz7xXJEPtjDpstST1 3DrmAUc85RFfSV9dycI1fWz04GZYCm3L3Y705u9NDo/7PP1duE2MSVAi6J49Nf5tBxpW 7pVuAsN2miKOLcnB0UIQXyPk0GZ9l+YwTQ1vbfTzTijdndXpQRiFMmlNzb5z4OqZDP/b qheit5czpvqDFyCtakucHHVNYH/4UUU32zegzEYcyqY8X1l6t0H7B9NkbMsJSXGSFY5W rKH5yE1ayN+E4nMBLDoE0AApW3DrLwG3smvD1TCCOAel7BW2b6IDyGnNCsgYSisp1S/D Rxbw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738290676; x=1738895476; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=FOGFz0R89I+3XlhdqrkY22tFKN4smXuqaSck1w1ygKU=; b=STNzvAyILXQl/p5zUasDQ4U+5gqZqbU/bnUxIy7YuRLft1AD2HeIoKOMtelwcBnDOj XmFLbsmStEpkwG1ni9AVIQlPJgeKCY0pxw3swj1VNOYPCJ1dhhSj8qUdd8ZrBTPEsnBC G+ivCXuI5fwWKz8BjSc5CrOT36JxZp6jIqwYOOtK/hzeFuGKCbGeX+DMd7EOHO/NxtfL vlI3OTw2eFxmJCUg9OG/MoHV29lpqYmdu5GEWGIL2n7y8MhYJfdSzwrUttCeboB9Aj7Q 8CjdSP/Z1Bf9flKaI7Z/wioEqgvJ2ywNepYjtrGRmwSYZk+4Dk5GU3l7bQBdMpM8a3T1 YAPw== X-Gm-Message-State: AOJu0YzUh614leFT59CUHaoslcj0Uofzrs3b3C9ytFPdVlDdXD0nnaqd giSwa5ph0QwWqZvNZzfvxLABPYnbJwyTIE09MwkEI47TTOtJWkUCIVkQ1nFsRzrbb3Ets2HSAhP D X-Gm-Gg: ASbGncuHMp1816vZgO/dt1VdrLE9VNqAnaG4whFpzV9j62m4BvOz0PlRA8a2be7smYe TVouQAIOYiWm2KJshdpaAHWXw/C96uYmPWggT3Q8Uy+HNfNGh20xN4H9yk3SkHbAbPHyTHvZW7R QqoZUTlb6CqxdXTgVigwXevHBIqBPm2+60SZfi1iPbSDqUBKsHsf5hpDEvkSL3OHMguBaFOzOWW GAlMvVr3ZkGwJ+v8JndiYZaPZi1ebBHx8cZs0zxatamgLDoIZUpAdOSHrH1Zq2rkVVsHhqLBitR eH65MEGp/imPvrE2lb10OSUwbEmhDJrw1w== X-Google-Smtp-Source: AGHT+IGGUNonyzsGVmFex1WJezgOzuRRqaiEpB4a93rE6bhrlxSa64yFtjxblG6y7DF8/CKkclS4fA== X-Received: by 2002:a17:907:72c1:b0:ab6:b9a6:a9e6 with SMTP id a640c23a62f3a-ab6cfdd6d90mr1047632266b.46.1738290675956; Thu, 30 Jan 2025 18:31:15 -0800 (PST) To: devel@lists.libvirt.org Subject: [PATCH V2 2/3] qemu: Decompose qemuSaveImageOpen Date: Thu, 30 Jan 2025 19:29:03 -0700 Message-ID: <20250131023110.20024-3-jfehlig@suse.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250131023110.20024-1-jfehlig@suse.com> References: <20250131023110.20024-1-jfehlig@suse.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Message-ID-Hash: JKJA2J2POUUKZHNUNLMFYFSXX53DAASR X-Message-ID-Hash: JKJA2J2POUUKZHNUNLMFYFSXX53DAASR X-MailFrom: jfehlig@suse.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: From: Jim Fehlig via Devel Reply-To: Jim Fehlig X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1738290774129019000 Content-Type: text/plain; charset="utf-8" Split the reading of libvirt's save image metadata from the opening of the fd that will be passed to QEMU. This allows improved error handling and provides more flexibility users of qemu_saveimage. Signed-off-by: Jim Fehlig --- src/qemu/qemu_driver.c | 31 +++--- src/qemu/qemu_saveimage.c | 207 +++++++++++++++++++++++--------------- src/qemu/qemu_saveimage.h | 13 ++- src/qemu/qemu_snapshot.c | 8 +- 4 files changed, 153 insertions(+), 106 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 2e80ce7921..f326937585 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5775,7 +5775,10 @@ qemuDomainRestoreInternal(virConnectPtr conn, if (flags & VIR_DOMAIN_SAVE_RESET_NVRAM) reset_nvram =3D true; =20 - fd =3D qemuSaveImageOpen(driver, NULL, path, &def, &data, + if (qemuSaveImageGetMetadata(driver, NULL, path, &def, &data) < 0) + goto cleanup; + + fd =3D qemuSaveImageOpen(driver, path, (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) !=3D 0, &wrapperFd, false); if (fd < 0) @@ -5906,15 +5909,11 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, c= onst char *path, virQEMUDriver *driver =3D conn->privateData; char *ret =3D NULL; g_autoptr(virDomainDef) def =3D NULL; - int fd =3D -1; virQEMUSaveData *data =3D NULL; =20 virCheckFlags(VIR_DOMAIN_SAVE_IMAGE_XML_SECURE, NULL); =20 - fd =3D qemuSaveImageOpen(driver, NULL, path, &def, &data, - false, NULL, false); - - if (fd < 0) + if (qemuSaveImageGetMetadata(driver, NULL, path, &def, &data) < 0) goto cleanup; =20 if (virDomainSaveImageGetXMLDescEnsureACL(conn, def) < 0) @@ -5924,7 +5923,6 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, con= st char *path, =20 cleanup: virQEMUSaveDataFree(data); - VIR_FORCE_CLOSE(fd); return ret; } =20 @@ -5948,9 +5946,10 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, con= st char *path, else if (flags & VIR_DOMAIN_SAVE_PAUSED) state =3D 0; =20 - fd =3D qemuSaveImageOpen(driver, NULL, path, &def, &data, - false, NULL, true); + if (qemuSaveImageGetMetadata(driver, NULL, path, &def, &data) < 0) + goto cleanup; =20 + fd =3D qemuSaveImageOpen(driver, path, 0, NULL, false); if (fd < 0) goto cleanup; =20 @@ -6007,7 +6006,6 @@ qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom, uns= igned int flags) g_autofree char *path =3D NULL; char *ret =3D NULL; g_autoptr(virDomainDef) def =3D NULL; - int fd =3D -1; virQEMUSaveData *data =3D NULL; qemuDomainObjPrivate *priv; =20 @@ -6029,15 +6027,13 @@ qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom, u= nsigned int flags) goto cleanup; } =20 - if ((fd =3D qemuSaveImageOpen(driver, priv->qemuCaps, path, &def, &dat= a, - false, NULL, false)) < 0) + if (qemuSaveImageGetMetadata(driver, priv->qemuCaps, path, &def, &data= ) < 0) goto cleanup; =20 ret =3D qemuDomainDefFormatXML(driver, priv->qemuCaps, def, flags); =20 cleanup: virQEMUSaveDataFree(data); - VIR_FORCE_CLOSE(fd); virDomainObjEndAPI(&vm); return ret; } @@ -6093,9 +6089,8 @@ qemuDomainObjRestore(virConnectPtr conn, virQEMUSaveData *data =3D NULL; virFileWrapperFd *wrapperFd =3D NULL; =20 - fd =3D qemuSaveImageOpen(driver, NULL, path, &def, &data, - bypass_cache, &wrapperFd, false); - if (fd < 0) { + ret =3D qemuSaveImageGetMetadata(driver, NULL, path, &def, &data); + if (ret < 0) { if (qemuSaveImageIsCorrupt(driver, path)) { if (unlink(path) < 0) { virReportSystemError(errno, @@ -6110,6 +6105,10 @@ qemuDomainObjRestore(virConnectPtr conn, goto cleanup; } =20 + fd =3D qemuSaveImageOpen(driver, path, bypass_cache, &wrapperFd, false= ); + if (fd < 0) + goto cleanup; + if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) { int hookret; =20 diff --git a/src/qemu/qemu_saveimage.c b/src/qemu/qemu_saveimage.c index 385ac8a649..8315171b78 100644 --- a/src/qemu/qemu_saveimage.c +++ b/src/qemu/qemu_saveimage.c @@ -249,6 +249,84 @@ qemuSaveImageGetCompressionCommand(virQEMUSaveFormat f= ormat) } =20 =20 +static int +qemuSaveImageReadHeader(int fd, virQEMUSaveData **ret_data) +{ + g_autoptr(virQEMUSaveData) data =3D NULL; + virQEMUSaveHeader *header; + size_t xml_len; + size_t cookie_len; + + data =3D g_new0(virQEMUSaveData, 1); + header =3D &data->header; + if (saferead(fd, header, sizeof(*header)) !=3D sizeof(*header)) { + virReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("failed to read qemu header")); + return -1; + } + + if (memcmp(header->magic, QEMU_SAVE_MAGIC, sizeof(header->magic)) !=3D= 0) { + if (memcmp(header->magic, QEMU_SAVE_PARTIAL, sizeof(header->magic)= ) =3D=3D 0) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("save image is incomplete")); + return -1; + } + + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("image magic is incorrect")); + return -1; + } + + if (header->version > QEMU_SAVE_VERSION) { + /* convert endianness and try again */ + qemuSaveImageBswapHeader(header); + } + + if (header->version > QEMU_SAVE_VERSION) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("image version is not supported (%1$d > %2$d)"), + header->version, QEMU_SAVE_VERSION); + return -1; + } + + if (header->data_len <=3D 0) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("invalid header data length: %1$d"), header->data= _len); + return -1; + } + + if (header->cookieOffset) + xml_len =3D header->cookieOffset; + else + xml_len =3D header->data_len; + + cookie_len =3D header->data_len - xml_len; + + data->xml =3D g_new0(char, xml_len); + + if (saferead(fd, data->xml, xml_len) !=3D xml_len) { + virReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("failed to read domain XML")); + return -1; + } + + if (cookie_len > 0) { + data->cookie =3D g_new0(char, cookie_len); + + if (saferead(fd, data->cookie, cookie_len) !=3D cookie_len) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("failed to read cookie")); + return -1; + } + } + + if (ret_data) + *ret_data =3D g_steal_pointer(&data); + + return 0; +} + + /** * qemuSaveImageDecompressionStart: * @data: data from memory state file @@ -520,6 +598,7 @@ qemuSaveImageGetCompressionProgram(const char *imageFor= mat, return -1; } =20 + /** * qemuSaveImageIsCorrupt: * @driver: qemu driver data @@ -551,26 +630,61 @@ qemuSaveImageIsCorrupt(virQEMUDriver *driver, const c= har *path) =20 =20 /** - * qemuSaveImageOpen: + * qemuSaveImageGetMetadata: * @driver: qemu driver data * @qemuCaps: pointer to qemuCaps if the domain is running or NULL * @path: path of the save image * @ret_def: returns domain definition created from the XML stored in the = image * @ret_data: returns structure filled with data from the image header + * + * Open the save image file, read libvirt's save image metadata, and popul= ate + * the @ret_def and @ret_data structures. Returns 0 on success and -1 on f= ailure. + */ +int +qemuSaveImageGetMetadata(virQEMUDriver *driver, + virQEMUCaps *qemuCaps, + const char *path, + virDomainDef **ret_def, + virQEMUSaveData **ret_data) +{ + g_autoptr(virQEMUDriverConfig) cfg =3D virQEMUDriverGetConfig(driver); + VIR_AUTOCLOSE fd =3D -1; + virQEMUSaveData *data; + g_autoptr(virDomainDef) def =3D NULL; + int rc; + + if ((fd =3D qemuDomainOpenFile(cfg, NULL, path, O_RDONLY, NULL)) < 0) + return -1; + + if ((rc =3D qemuSaveImageReadHeader(fd, ret_data)) < 0) + return rc; + + data =3D *ret_data; + /* Create a domain from this XML */ + if (!(def =3D virDomainDefParseString(data->xml, driver->xmlopt, qemuC= aps, + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE= ))) + return -1; + + *ret_def =3D g_steal_pointer(&def); + + return 0; +} + + +/** + * qemuSaveImageOpen: + * @driver: qemu driver data + * @path: path of the save image * @bypass_cache: bypass cache when opening the file * @wrapperFd: returns the file wrapper structure * @open_write: open the file for writing (for updates) * - * Returns the opened fd of the save image file and fills the appropriate = fields - * on success. On error returns -1 on most failures, -3 if a corrupt image= was - * detected. + * Returns the opened fd of the save image file on success, -1 on failure. */ int qemuSaveImageOpen(virQEMUDriver *driver, - virQEMUCaps *qemuCaps, const char *path, - virDomainDef **ret_def, - virQEMUSaveData **ret_data, bool bypass_cache, virFileWrapperFd **wrapperFd, bool open_write) @@ -578,12 +692,7 @@ qemuSaveImageOpen(virQEMUDriver *driver, g_autoptr(virQEMUDriverConfig) cfg =3D virQEMUDriverGetConfig(driver); VIR_AUTOCLOSE fd =3D -1; int ret =3D -1; - g_autoptr(virQEMUSaveData) data =3D NULL; - virQEMUSaveHeader *header; - g_autoptr(virDomainDef) def =3D NULL; int oflags =3D open_write ? O_RDWR : O_RDONLY; - size_t xml_len; - size_t cookie_len; =20 if (bypass_cache) { int directFlag =3D virFileDirectFdFlag(); @@ -603,78 +712,10 @@ qemuSaveImageOpen(virQEMUDriver *driver, VIR_FILE_WRAPPER_BYPASS_CACHE))) return -1; =20 - data =3D g_new0(virQEMUSaveData, 1); - - header =3D &data->header; - if (saferead(fd, header, sizeof(*header)) !=3D sizeof(*header)) { - virReportError(VIR_ERR_OPERATION_FAILED, - "%s", _("failed to read qemu header")); + /* Read the header to position the file pointer for QEMU. Unfortunatel= y we + * can't use lseek with virFileWrapperFD. */ + if (qemuSaveImageReadHeader(fd, NULL) < 0) return -1; - } - - if (memcmp(header->magic, QEMU_SAVE_MAGIC, sizeof(header->magic)) !=3D= 0) { - if (memcmp(header->magic, QEMU_SAVE_PARTIAL, sizeof(header->magic)= ) =3D=3D 0) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("save image is incomplete")); - return -1; - } - - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("image magic is incorrect")); - return -1; - } - - if (header->version > QEMU_SAVE_VERSION) { - /* convert endianness and try again */ - qemuSaveImageBswapHeader(header); - } - - if (header->version > QEMU_SAVE_VERSION) { - virReportError(VIR_ERR_OPERATION_FAILED, - _("image version is not supported (%1$d > %2$d)"), - header->version, QEMU_SAVE_VERSION); - return -1; - } - - if (header->data_len <=3D 0) { - virReportError(VIR_ERR_OPERATION_FAILED, - _("invalid header data length: %1$d"), header->data= _len); - return -1; - } - - if (header->cookieOffset) - xml_len =3D header->cookieOffset; - else - xml_len =3D header->data_len; - - cookie_len =3D header->data_len - xml_len; - - data->xml =3D g_new0(char, xml_len); - - if (saferead(fd, data->xml, xml_len) !=3D xml_len) { - virReportError(VIR_ERR_OPERATION_FAILED, - "%s", _("failed to read domain XML")); - return -1; - } - - if (cookie_len > 0) { - data->cookie =3D g_new0(char, cookie_len); - - if (saferead(fd, data->cookie, cookie_len) !=3D cookie_len) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("failed to read cookie")); - return -1; - } - } - - /* Create a domain from this XML */ - if (!(def =3D virDomainDefParseString(data->xml, driver->xmlopt, qemuC= aps, - VIR_DOMAIN_DEF_PARSE_INACTIVE | - VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE= ))) - return -1; - - *ret_def =3D g_steal_pointer(&def); - *ret_data =3D g_steal_pointer(&data); =20 ret =3D fd; fd =3D -1; diff --git a/src/qemu/qemu_saveimage.h b/src/qemu/qemu_saveimage.h index dc49f8463f..53ae222467 100644 --- a/src/qemu/qemu_saveimage.h +++ b/src/qemu/qemu_saveimage.h @@ -74,16 +74,21 @@ qemuSaveImageIsCorrupt(virQEMUDriver *driver, const char *path) ATTRIBUTE_NONNULL(2); =20 +int +qemuSaveImageGetMetadata(virQEMUDriver *driver, + virQEMUCaps *qemuCaps, + const char *path, + virDomainDef **ret_def, + virQEMUSaveData **ret_data) + ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5); + int qemuSaveImageOpen(virQEMUDriver *driver, - virQEMUCaps *qemuCaps, const char *path, - virDomainDef **ret_def, - virQEMUSaveData **ret_data, bool bypass_cache, virFileWrapperFd **wrapperFd, bool open_write) - ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); + ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4); =20 int qemuSaveImageGetCompressionProgram(const char *imageFormat, diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index b9c3983472..7ce018b026 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -2377,10 +2377,12 @@ qemuSnapshotRevertExternalPrepare(virDomainObj *vm, g_autoptr(virDomainDef) savedef =3D NULL; =20 memdata->path =3D snapdef->memorysnapshotfile; - memdata->fd =3D qemuSaveImageOpen(driver, NULL, memdata->path, - &savedef, &memdata->data, + if (qemuSaveImageGetMetadata(driver, NULL, memdata->path, &savedef, + &memdata->data) < 0) + return -1; + + memdata->fd =3D qemuSaveImageOpen(driver, memdata->path, false, NULL, false); - if (memdata->fd < 0) return -1; =20 --=20 2.43.0