use this data type to encapsulate the pathname,
file descriptor, wrapper, and need to unlink.
Adapt qemuSaveImageCreate and qemuSaveImageOpen to use a
virQEMUSaveFd instead of a plain file descriptor.
This makes management of wrapper, need_unlink etc
much easier.
Signed-off-by: Claudio Fontana <cfontana(a)suse.de>
---
src/qemu/qemu_driver.c | 100 +++++++++------
src/qemu/qemu_saveimage.c | 259 ++++++++++++++++++++++----------------
src/qemu/qemu_saveimage.h | 27 +++-
3 files changed, 235 insertions(+), 151 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 9f5ae687e8..914be2e703 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5824,12 +5824,13 @@ qemuDomainRestoreInternal(virConnectPtr conn,
virDomainObj *vm = NULL;
g_autofree char *xmlout = NULL;
const char *newxml = dxml;
- int fd = -1;
int ret = -1;
virQEMUSaveData *data = NULL;
- virFileWrapperFd *wrapperFd = NULL;
+ virQEMUSaveFd saveFd = QEMU_SAVEFD_INVALID;
bool hook_taint = false;
bool reset_nvram = false;
+ g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
+ int oflags = O_RDONLY;
virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
VIR_DOMAIN_SAVE_RUNNING |
@@ -5840,10 +5841,18 @@ qemuDomainRestoreInternal(virConnectPtr conn,
if (flags & VIR_DOMAIN_SAVE_RESET_NVRAM)
reset_nvram = true;
- fd = qemuSaveImageOpen(driver, NULL, path, &def, &data,
- (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0,
- &wrapperFd, false, false);
- if (fd < 0)
+ if (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) {
+ if (virFileDirectFdFlag() < 0) {
+ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+ _("bypass cache unsupported by this system"));
+ return -1;
+ }
+ oflags |= O_DIRECT;
+ }
+ if (virQEMUSaveFdInit(&saveFd, path, 0, oflags, cfg) < 0)
+ return -1;
+
+ if (qemuSaveImageOpen(driver, NULL, &def, &data, false, &saveFd) < 0)
goto cleanup;
if (virDomainRestoreFlagsEnsureACL(conn, def) < 0)
@@ -5897,16 +5906,13 @@ qemuDomainRestoreInternal(virConnectPtr conn,
flags) < 0)
goto cleanup;
- ret = qemuSaveImageStartVM(conn, driver, vm, &fd, data, path,
+ ret = qemuSaveImageStartVM(conn, driver, vm, &saveFd.fd, data, path,
false, reset_nvram, VIR_ASYNC_JOB_START);
qemuProcessEndJob(vm);
cleanup:
- VIR_FORCE_CLOSE(fd);
- if (virFileWrapperFdClose(wrapperFd) < 0)
- ret = -1;
- virFileWrapperFdFree(wrapperFd);
+ ret = virQEMUSaveFdFini(&saveFd, vm, ret);
virQEMUSaveDataFree(data);
if (vm && ret < 0)
qemuDomainRemoveInactive(driver, vm);
@@ -5965,15 +5971,16 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char
*path,
virQEMUDriver *driver = conn->privateData;
char *ret = NULL;
g_autoptr(virDomainDef) def = NULL;
- int fd = -1;
virQEMUSaveData *data = NULL;
+ g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
+ virQEMUSaveFd saveFd = QEMU_SAVEFD_INVALID;
virCheckFlags(VIR_DOMAIN_SAVE_IMAGE_XML_SECURE, NULL);
- fd = qemuSaveImageOpen(driver, NULL, path, &def, &data,
- false, NULL, false, false);
+ if (virQEMUSaveFdInit(&saveFd, path, 0, O_RDONLY, cfg) < 0)
+ return NULL;
- if (fd < 0)
+ if (qemuSaveImageOpen(driver, NULL, &def, &data, false, &saveFd) < 0)
goto cleanup;
if (virDomainSaveImageGetXMLDescEnsureACL(conn, def) < 0)
@@ -5983,7 +5990,8 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path,
cleanup:
virQEMUSaveDataFree(data);
- VIR_FORCE_CLOSE(fd);
+ if (virQEMUSaveFdFini(&saveFd, NULL, ret ? 0 : -1) < 0)
+ ret = NULL;
return ret;
}
@@ -5995,22 +6003,23 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char
*path,
int ret = -1;
g_autoptr(virDomainDef) def = NULL;
g_autoptr(virDomainDef) newdef = NULL;
- int fd = -1;
virQEMUSaveData *data = NULL;
+ virQEMUSaveFd saveFd = QEMU_SAVEFD_INVALID;
+ g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
int state = -1;
virCheckFlags(VIR_DOMAIN_SAVE_RUNNING |
VIR_DOMAIN_SAVE_PAUSED, -1);
+ if (virQEMUSaveFdInit(&saveFd, path, 0, O_RDWR, cfg) < 0)
+ return -1;
+
if (flags & VIR_DOMAIN_SAVE_RUNNING)
state = 1;
else if (flags & VIR_DOMAIN_SAVE_PAUSED)
state = 0;
- fd = qemuSaveImageOpen(driver, NULL, path, &def, &data,
- false, NULL, true, false);
-
- if (fd < 0)
+ if (qemuSaveImageOpen(driver, NULL, &def, &data, false, &saveFd) < 0)
goto cleanup;
if (virDomainSaveImageDefineXMLEnsureACL(conn, def) < 0)
@@ -6037,15 +6046,15 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char
*path,
VIR_DOMAIN_XML_MIGRATABLE)))
goto cleanup;
- if (lseek(fd, 0, SEEK_SET) != 0) {
+ if (lseek(saveFd.fd, 0, SEEK_SET) != 0) {
virReportSystemError(errno, _("cannot seek in '%s'"), path);
goto cleanup;
}
- if (virQEMUSaveDataWrite(data, fd, path) < 0)
+ if (virQEMUSaveDataWrite(data, saveFd.fd, path) < 0)
goto cleanup;
- if (VIR_CLOSE(fd) < 0) {
+ if (virQEMUSaveFdClose(&saveFd, NULL) < 0) {
virReportSystemError(errno, _("failed to write header data to
'%s'"), path);
goto cleanup;
}
@@ -6053,8 +6062,8 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path,
ret = 0;
cleanup:
- VIR_FORCE_CLOSE(fd);
virQEMUSaveDataFree(data);
+ ret = virQEMUSaveFdFini(&saveFd, NULL, ret);
return ret;
}
@@ -6066,8 +6075,9 @@ qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom, unsigned int
flags)
g_autofree char *path = NULL;
char *ret = NULL;
g_autoptr(virDomainDef) def = NULL;
- int fd = -1;
virQEMUSaveData *data = NULL;
+ virQEMUSaveFd saveFd = QEMU_SAVEFD_INVALID;
+ g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
qemuDomainObjPrivate *priv;
virCheckFlags(VIR_DOMAIN_SAVE_IMAGE_XML_SECURE, NULL);
@@ -6089,15 +6099,19 @@ qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom, unsigned int
flags)
goto cleanup;
}
- if ((fd = qemuSaveImageOpen(driver, priv->qemuCaps, path, &def, &data,
- false, NULL, false, false)) < 0)
+ if (virQEMUSaveFdInit(&saveFd, path, 0, O_RDONLY, cfg) < 0)
+ goto cleanup;
+
+ if (qemuSaveImageOpen(driver, priv->qemuCaps, &def, &data, false,
+ &saveFd) < 0)
goto cleanup;
ret = qemuDomainDefFormatXML(driver, priv->qemuCaps, def, flags);
cleanup:
virQEMUSaveDataFree(data);
- VIR_FORCE_CLOSE(fd);
+ if (virQEMUSaveFdFini(&saveFd, vm, ret ? 0 : -1) < 0)
+ ret = NULL;
virDomainObjEndAPI(&vm);
return ret;
}
@@ -6148,16 +6162,25 @@ qemuDomainObjRestore(virConnectPtr conn,
{
g_autoptr(virDomainDef) def = NULL;
qemuDomainObjPrivate *priv = vm->privateData;
- int fd = -1;
int ret = -1;
g_autofree char *xmlout = NULL;
virQEMUSaveData *data = NULL;
- virFileWrapperFd *wrapperFd = NULL;
+ virQEMUSaveFd saveFd = QEMU_SAVEFD_INVALID;
+ int oflags = O_RDONLY;
+ g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
- fd = qemuSaveImageOpen(driver, NULL, path, &def, &data,
- bypass_cache, &wrapperFd, false, true);
- if (fd < 0) {
- if (fd == -3)
+ if (bypass_cache) {
+ if (virFileDirectFdFlag() < 0) {
+ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+ _("bypass cache unsupported by this system"));
+ return -1;
+ }
+ oflags |= O_DIRECT;
+ }
+
+ ret = qemuSaveImageOpen(driver, NULL, &def, &data, true, &saveFd);
+ if (ret < 0) {
+ if (ret == -3)
ret = 1;
goto cleanup;
}
@@ -6201,15 +6224,12 @@ qemuDomainObjRestore(virConnectPtr conn,
virDomainObjAssignDef(vm, &def, true, NULL);
- ret = qemuSaveImageStartVM(conn, driver, vm, &fd, data, path,
+ ret = qemuSaveImageStartVM(conn, driver, vm, &saveFd.fd, data, path,
start_paused, reset_nvram, asyncJob);
cleanup:
virQEMUSaveDataFree(data);
- VIR_FORCE_CLOSE(fd);
- if (virFileWrapperFdClose(wrapperFd) < 0)
- ret = -1;
- virFileWrapperFdFree(wrapperFd);
+ ret = virQEMUSaveFdFini(&saveFd, vm, ret);
return ret;
}
diff --git a/src/qemu/qemu_saveimage.c b/src/qemu/qemu_saveimage.c
index 6e7f067be2..6af256aabe 100644
--- a/src/qemu/qemu_saveimage.c
+++ b/src/qemu/qemu_saveimage.c
@@ -248,6 +248,123 @@ qemuSaveImageGetCompressionCommand(virQEMUSaveFormat compression)
return ret;
}
+/*
+ * virQEMUSaveFdInit: initialize a virQEMUSaveFd
+ *
+ * @saveFd: the structure to initialize
+ * @base: the main file name
+ * @idx: 0 for the main file, >0 for multifd channels.
+ * @oflags the file descriptor open flags
+ * @cfg: the driver config
+ *
+ * Returns -1 on error, 0 on success,
+ * and in both cases virQEMUSaveFdFini must be called to free resources.
+ */
+int virQEMUSaveFdInit(virQEMUSaveFd *saveFd, const char *base, int idx,
+ int oflags, virQEMUDriverConfig *cfg)
+{
+ unsigned int wrapperFlags = VIR_FILE_WRAPPER_NON_BLOCKING;
+ bool isCreat = oflags & O_CREAT;
+ bool isDirect = O_DIRECT && (oflags & O_DIRECT);
+
+ if (isDirect)
+ wrapperFlags |= VIR_FILE_WRAPPER_BYPASS_CACHE;
+ if (idx > 0) {
+ saveFd->path = g_strdup_printf("%s.%d", base, idx);
+ } else {
+ saveFd->path = g_strdup(base);
+ }
+ saveFd->wrapper = NULL;
+ if (isCreat) {
+ saveFd->fd = virQEMUFileOpenAs(cfg->user, cfg->group, false,
saveFd->path,
+ oflags, &saveFd->need_unlink);
+ } else {
+ saveFd->fd = qemuDomainOpenFile(cfg, NULL, saveFd->path, oflags, NULL);
+ }
+ if (saveFd->fd < 0)
+ return -1;
+ /*
+ * no wrapper required for the multifd channels.
+ * For O_CREAT, we always add the wrapper for the main file.
+ * For !O_CREAT, we only add the wrapper if using O_DIRECT.
+ */
+ if (idx == 0 && (isDirect || isCreat)) {
+ saveFd->wrapper = virFileWrapperFdNew(&saveFd->fd, saveFd->path,
wrapperFlags);
+ if (!saveFd->wrapper)
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * virQEMUSaveFdClose: close a virQEMUSaveFd descriptor with normal close.
+ *
+ * @saveFd: the saveFd structure with the file descriptors to close.
+ * @vm: the virDomainObj (necessary to release lock), or NULL.
+ *
+ * If saveFd is NULL, the function will return success.
+ *
+ * Returns -1 on error, 0 on success.
+ */
+int virQEMUSaveFdClose(virQEMUSaveFd *saveFd, virDomainObj *vm)
+{
+ if (!saveFd)
+ return 0;
+
+ if (VIR_CLOSE(saveFd->fd) < 0) {
+ virReportSystemError(errno, _("unable to close %s"), saveFd->path);
+ return -1;
+ }
+ if (vm) {
+ if (qemuDomainFileWrapperFDClose(vm, saveFd->wrapper) < 0)
+ return -1;
+ } else {
+ if (virFileWrapperFdClose(saveFd->wrapper) < 0)
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * virQEMUSaveFdFini: finalize a virQEMUSaveFd
+ *
+ * @saveFd: the saveFd structure containing the resources to free.
+ * @vm: the virDomainObj (necessary to release lock for long close ops), or NULL.
+ * @ret: the current operation result (< 0 is failure)
+ *
+ * If saveFd is NULL, the return value will be unchanged.
+ *
+ * Returns ret, or -1 if an error is detected.
+ */
+int virQEMUSaveFdFini(virQEMUSaveFd *saveFd, virDomainObj *vm, int ret)
+{
+ if (!saveFd)
+ return ret;
+ VIR_FORCE_CLOSE(saveFd->fd);
+ if (vm) {
+ if (qemuDomainFileWrapperFDClose(vm, saveFd->wrapper) < 0)
+ ret = -1;
+ } else {
+ if (virFileWrapperFdClose(saveFd->wrapper) < 0)
+ ret = -1;
+ }
+
+ if (ret < 0 && saveFd->need_unlink && saveFd->path) {
+ if (unlink(saveFd->path) < 0) {
+ virReportSystemError(errno, _("cannot remove file: %s"),
+ saveFd->path);
+ }
+ }
+ if (saveFd->wrapper) {
+ virFileWrapperFdFree(saveFd->wrapper);
+ saveFd->wrapper = NULL;
+ }
+
+ g_free(saveFd->path);
+ saveFd->path = NULL;
+ return ret;
+}
+
/* Helper function to execute a migration to file with a correct save header
* the caller needs to make sure that the processors are stopped and do all other
@@ -263,42 +380,34 @@ qemuSaveImageCreate(virQEMUDriver *driver,
virDomainAsyncJob asyncJob)
{
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
- bool needUnlink = false;
+ virQEMUSaveFd saveFd = QEMU_SAVEFD_INVALID;
+ unsigned int oflags = O_WRONLY | O_TRUNC | O_CREAT;
int ret = -1;
- int fd = -1;
- int directFlag = 0;
- virFileWrapperFd *wrapperFd = NULL;
- unsigned int wrapperFlags = VIR_FILE_WRAPPER_NON_BLOCKING;
-
nconn = nconn; /* unused */
- /* Obtain the file handle. */
- if ((flags & VIR_DOMAIN_SAVE_BYPASS_CACHE)) {
- wrapperFlags |= VIR_FILE_WRAPPER_BYPASS_CACHE;
- directFlag = virFileDirectFdFlag();
- if (directFlag < 0) {
+
+ if (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) {
+ if (virFileDirectFdFlag() < 0) {
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
_("bypass cache unsupported by this system"));
- goto cleanup;
+ return -1;
}
+ oflags |= O_DIRECT;
}
- fd = virQEMUFileOpenAs(cfg->user, cfg->group, false, path,
- O_WRONLY | O_TRUNC | O_CREAT | directFlag,
- &needUnlink);
- if (fd < 0)
+ if (virQEMUSaveFdInit(&saveFd, path, 0, oflags, cfg) < 0) {
goto cleanup;
-
- if (qemuSecuritySetImageFDLabel(driver->securityManager, vm->def, fd) < 0)
+ }
+ if (qemuSecuritySetImageFDLabel(driver->securityManager, vm->def, saveFd.fd)
< 0)
goto cleanup;
- if (!(wrapperFd = virFileWrapperFdNew(&fd, path, wrapperFlags)))
+ if (virQEMUSaveDataWrite(data, saveFd.fd, saveFd.path) < 0)
goto cleanup;
- if (virQEMUSaveDataWrite(data, fd, path) < 0)
- goto cleanup;
/* Perform the migration */
- if (qemuMigrationSrcToFile(driver, vm, fd, compressor, asyncJob) < 0)
+ if (qemuMigrationSrcToFile(driver, vm, saveFd.fd, compressor, asyncJob) < 0)
+ goto cleanup;
+ if (virQEMUSaveFdClose(&saveFd, vm) < 0)
goto cleanup;
/* Touch up file header to mark image complete. */
@@ -307,29 +416,17 @@ qemuSaveImageCreate(virQEMUDriver *driver,
* up to seek backwards on wrapperFd. The reopened fd will
* trigger a single page of file system cache pollution, but
* that's acceptable. */
- if (VIR_CLOSE(fd) < 0) {
- virReportSystemError(errno, _("unable to close %s"), path);
- goto cleanup;
- }
- if (qemuDomainFileWrapperFDClose(vm, wrapperFd) < 0)
- goto cleanup;
-
- if ((fd = qemuDomainOpenFile(cfg, vm->def, path, O_WRONLY, NULL)) < 0 ||
- virQEMUSaveDataFinish(data, &fd, path) < 0)
+ if ((saveFd.fd = qemuDomainOpenFile(cfg, vm->def, saveFd.path, O_WRONLY, NULL))
< 0 ||
+ virQEMUSaveDataFinish(data, &saveFd.fd, saveFd.path) < 0)
goto cleanup;
ret = 0;
- cleanup:
- VIR_FORCE_CLOSE(fd);
- if (qemuDomainFileWrapperFDClose(vm, wrapperFd) < 0)
- ret = -1;
- virFileWrapperFdFree(wrapperFd);
- if (ret < 0 && needUnlink)
- unlink(path);
+ cleanup:
+ ret = virQEMUSaveFdFini(&saveFd, vm, ret);
return ret;
}
@@ -422,94 +519,49 @@ qemuSaveImageGetCompressionProgram(const char *imageFormat,
* @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
- * @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
+ * @unlink_corrupt: mark the image file for removal if it is corrupted
+ * @saveFd: the save file
*
- * 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).
+ * Returns 0 on success or -1 on failure.
+ * On success, the appropriate fields are filled.
*/
int
qemuSaveImageOpen(virQEMUDriver *driver,
virQEMUCaps *qemuCaps,
- const char *path,
virDomainDef **ret_def,
virQEMUSaveData **ret_data,
- bool bypass_cache,
- virFileWrapperFd **wrapperFd,
- bool open_write,
- bool unlink_corrupt)
+ bool unlink_corrupt,
+ virQEMUSaveFd *saveFd)
{
- g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
- VIR_AUTOCLOSE fd = -1;
- int ret = -1;
g_autoptr(virQEMUSaveData) data = NULL;
virQEMUSaveHeader *header;
g_autoptr(virDomainDef) def = NULL;
- int oflags = open_write ? O_RDWR : O_RDONLY;
size_t xml_len;
size_t cookie_len;
- if (bypass_cache) {
- int directFlag = virFileDirectFdFlag();
- if (directFlag < 0) {
- virReportError(VIR_ERR_OPERATION_FAILED, "%s",
- _("bypass cache unsupported by this system"));
- return -1;
- }
- oflags |= directFlag;
- }
-
- if ((fd = qemuDomainOpenFile(cfg, NULL, path, oflags, NULL)) < 0)
- return -1;
-
- if (bypass_cache &&
- !(*wrapperFd = virFileWrapperFdNew(&fd, path,
- VIR_FILE_WRAPPER_BYPASS_CACHE)))
- return -1;
data = g_new0(virQEMUSaveData, 1);
header = &data->header;
- if (saferead(fd, header, sizeof(*header)) != sizeof(*header)) {
- if (unlink_corrupt) {
- if (unlink(path) < 0) {
- virReportSystemError(errno,
- _("cannot remove corrupt file: %s"),
- path);
- return -1;
- } else {
- return -3;
- }
- }
-
+ if (saferead(saveFd->fd, header, sizeof(*header)) != sizeof(*header)) {
virReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("failed to read qemu header"));
+ if (unlink_corrupt) {
+ saveFd->need_unlink = true;
+ }
return -1;
}
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: %s"),
- path);
- return -1;
- } else {
- return -3;
- }
- }
-
+ if (memcmp(header->magic, QEMU_SAVE_PARTIAL, sizeof(header->magic)) == 0)
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
_("save image is incomplete"));
- return -1;
+ else
+ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+ _("image magic is incorrect"));
+ if (unlink_corrupt) {
+ saveFd->need_unlink = true;
}
-
- virReportError(VIR_ERR_OPERATION_FAILED, "%s",
- _("image magic is incorrect"));
return -1;
}
@@ -540,7 +592,7 @@ qemuSaveImageOpen(virQEMUDriver *driver,
data->xml = g_new0(char, xml_len);
- if (saferead(fd, data->xml, xml_len) != xml_len) {
+ if (saferead(saveFd->fd, data->xml, xml_len) != xml_len) {
virReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("failed to read domain XML"));
return -1;
@@ -549,7 +601,7 @@ qemuSaveImageOpen(virQEMUDriver *driver,
if (cookie_len > 0) {
data->cookie = g_new0(char, cookie_len);
- if (saferead(fd, data->cookie, cookie_len) != cookie_len) {
+ if (saferead(saveFd->fd, data->cookie, cookie_len) != cookie_len) {
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
_("failed to read cookie"));
return -1;
@@ -565,10 +617,7 @@ qemuSaveImageOpen(virQEMUDriver *driver,
*ret_def = g_steal_pointer(&def);
*ret_data = g_steal_pointer(&data);
- ret = fd;
- fd = -1;
-
- return ret;
+ return 0;
}
int
diff --git a/src/qemu/qemu_saveimage.h b/src/qemu/qemu_saveimage.h
index b3d5c02fd6..5dc63f3661 100644
--- a/src/qemu/qemu_saveimage.h
+++ b/src/qemu/qemu_saveimage.h
@@ -54,6 +54,24 @@ struct _virQEMUSaveData {
};
+typedef struct _virQEMUSaveFd virQEMUSaveFd;
+struct _virQEMUSaveFd {
+ char *path;
+ int fd;
+ bool need_unlink;
+ virFileWrapperFd *wrapper;
+};
+
+#define QEMU_SAVEFD_INVALID (virQEMUSaveFd) { .path = NULL, .fd = -1, .need_unlink =
false, .wrapper = NULL }
+
+int virQEMUSaveFdInit(virQEMUSaveFd *saveFd, const char *base, int idx,
+ int oflags, virQEMUDriverConfig *cfg)
+ ATTRIBUTE_NONNULL(5);
+
+int virQEMUSaveFdClose(virQEMUSaveFd *saveFd, virDomainObj *vm);
+
+int virQEMUSaveFdFini(virQEMUSaveFd *saveFd, virDomainObj *vm, int ret);
+
virDomainDef *
qemuSaveImageUpdateDef(virQEMUDriver *driver,
virDomainDef *def,
@@ -74,14 +92,11 @@ qemuSaveImageStartVM(virConnectPtr conn,
int
qemuSaveImageOpen(virQEMUDriver *driver,
virQEMUCaps *qemuCaps,
- const char *path,
virDomainDef **ret_def,
virQEMUSaveData **ret_data,
- bool bypass_cache,
- virFileWrapperFd **wrapperFd,
- bool open_write,
- bool unlink_corrupt)
- ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
+ bool unlink_corrupt,
+ virQEMUSaveFd *saveFd)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(6);
int
qemuSaveImageGetCompressionProgram(const char *imageFormat,
--
2.34.1