qemuDomainObjRestore is the only caller of qemuSaveImageOpen that requests an unlink of a corrupted save image. Provide a function to check for a corrupt image and move unlinking it to qemuDomainObjRestore. Signed-off-by: Jim Fehlig <jfehlig@xxxxxxxx> --- src/qemu/qemu_driver.c | 23 ++++++++++----- src/qemu/qemu_saveimage.c | 59 +++++++++++++++++++++------------------ src/qemu/qemu_saveimage.h | 8 ++++-- src/qemu/qemu_snapshot.c | 3 +- 4 files changed, 55 insertions(+), 38 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index da714f1975..2e80ce7921 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5777,7 +5777,7 @@ qemuDomainRestoreInternal(virConnectPtr conn, fd = qemuSaveImageOpen(driver, NULL, path, &def, &data, (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0, - &wrapperFd, false, false); + &wrapperFd, false); if (fd < 0) goto cleanup; @@ -5912,7 +5912,7 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path, virCheckFlags(VIR_DOMAIN_SAVE_IMAGE_XML_SECURE, NULL); fd = qemuSaveImageOpen(driver, NULL, path, &def, &data, - false, NULL, false, false); + false, NULL, false); if (fd < 0) goto cleanup; @@ -5949,7 +5949,7 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path, state = 0; fd = qemuSaveImageOpen(driver, NULL, path, &def, &data, - false, NULL, true, false); + false, NULL, true); if (fd < 0) goto cleanup; @@ -6030,7 +6030,7 @@ qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom, unsigned int flags) } if ((fd = qemuSaveImageOpen(driver, priv->qemuCaps, path, &def, &data, - false, NULL, false, false)) < 0) + false, NULL, false)) < 0) goto cleanup; ret = qemuDomainDefFormatXML(driver, priv->qemuCaps, def, flags); @@ -6094,10 +6094,19 @@ qemuDomainObjRestore(virConnectPtr conn, virFileWrapperFd *wrapperFd = NULL; fd = qemuSaveImageOpen(driver, NULL, path, &def, &data, - bypass_cache, &wrapperFd, false, true); + bypass_cache, &wrapperFd, false); if (fd < 0) { - if (fd == -3) - ret = 1; + if (qemuSaveImageIsCorrupt(driver, path)) { + if (unlink(path) < 0) { + virReportSystemError(errno, + _("cannot remove corrupt file: %1$s"), + path); + ret = -1; + } else { + virResetLastError(); + ret = 1; + } + } goto cleanup; } diff --git a/src/qemu/qemu_saveimage.c b/src/qemu/qemu_saveimage.c index 69617e07eb..385ac8a649 100644 --- a/src/qemu/qemu_saveimage.c +++ b/src/qemu/qemu_saveimage.c @@ -520,6 +520,35 @@ qemuSaveImageGetCompressionProgram(const char *imageFormat, return -1; } +/** + * qemuSaveImageIsCorrupt: + * @driver: qemu driver data + * @path: path of the save image + * + * Returns true if the save image file identified by @path does not exist or + * has a corrupt header. Returns false otherwise. + */ + +bool +qemuSaveImageIsCorrupt(virQEMUDriver *driver, const char *path) +{ + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + VIR_AUTOCLOSE fd = -1; + virQEMUSaveHeader header; + + if ((fd = qemuDomainOpenFile(cfg, NULL, path, O_RDONLY, NULL)) < 0) + return true; + + if (saferead(fd, &header, sizeof(header)) != sizeof(header)) + return true; + + if (memcmp(header.magic, QEMU_SAVE_MAGIC, sizeof(header.magic)) != 0 || + memcmp(header.magic, QEMU_SAVE_PARTIAL, sizeof(header.magic)) == 0) + return true; + + return false; +} + /** * qemuSaveImageOpen: @@ -531,11 +560,10 @@ qemuSaveImageGetCompressionProgram(const char *imageFormat, * @bypass_cache: bypass cache when opening the file * @wrapperFd: returns the file wrapper structure * @open_write: open the file for writing (for updates) - * @unlink_corrupt: remove the image file if it is corrupted * * 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 corrupt image was - * unlinked (no error raised). + * on success. On error returns -1 on most failures, -3 if a corrupt image was + * detected. */ int qemuSaveImageOpen(virQEMUDriver *driver, @@ -545,8 +573,7 @@ qemuSaveImageOpen(virQEMUDriver *driver, virQEMUSaveData **ret_data, bool bypass_cache, virFileWrapperFd **wrapperFd, - bool open_write, - bool unlink_corrupt) + bool open_write) { g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); VIR_AUTOCLOSE fd = -1; @@ -580,17 +607,6 @@ qemuSaveImageOpen(virQEMUDriver *driver, header = &data->header; if (saferead(fd, header, sizeof(*header)) != sizeof(*header)) { - if (unlink_corrupt) { - if (unlink(path) < 0) { - virReportSystemError(errno, - _("cannot remove corrupt file: %1$s"), - path); - return -1; - } else { - return -3; - } - } - virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to read qemu header")); return -1; @@ -598,17 +614,6 @@ qemuSaveImageOpen(virQEMUDriver *driver, if (memcmp(header->magic, QEMU_SAVE_MAGIC, sizeof(header->magic)) != 0) { if (memcmp(header->magic, QEMU_SAVE_PARTIAL, sizeof(header->magic)) == 0) { - if (unlink_corrupt) { - if (unlink(path) < 0) { - virReportSystemError(errno, - _("cannot remove corrupt file: %1$s"), - path); - return -1; - } else { - return -3; - } - } - virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("save image is incomplete")); return -1; diff --git a/src/qemu/qemu_saveimage.h b/src/qemu/qemu_saveimage.h index 0e58dd14b6..dc49f8463f 100644 --- a/src/qemu/qemu_saveimage.h +++ b/src/qemu/qemu_saveimage.h @@ -69,6 +69,11 @@ qemuSaveImageStartVM(virConnectPtr conn, virDomainAsyncJob asyncJob) ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5) ATTRIBUTE_NONNULL(6); +bool +qemuSaveImageIsCorrupt(virQEMUDriver *driver, + const char *path) + ATTRIBUTE_NONNULL(2); + int qemuSaveImageOpen(virQEMUDriver *driver, virQEMUCaps *qemuCaps, @@ -77,8 +82,7 @@ qemuSaveImageOpen(virQEMUDriver *driver, virQEMUSaveData **ret_data, bool bypass_cache, virFileWrapperFd **wrapperFd, - bool open_write, - bool unlink_corrupt) + bool open_write) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); int diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index 5273348aeb..b9c3983472 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -2379,8 +2379,7 @@ qemuSnapshotRevertExternalPrepare(virDomainObj *vm, memdata->path = snapdef->memorysnapshotfile; memdata->fd = qemuSaveImageOpen(driver, NULL, memdata->path, &savedef, &memdata->data, - false, NULL, - false, false); + false, NULL, false); if (memdata->fd < 0) return -1; -- 2.43.0