qemu: Move unlinking corrupt save image file to caller

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@suse.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Jim Fehlig via Devel 2025-01-30 19:29:02 -07:00 committed by Michal Privoznik
parent 18f0160994
commit 50d65b94ef
4 changed files with 55 additions and 38 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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;