add APIs to Create, Close and Free MultiFD files to associate with
multifd channels. Adapt virQEMUSaveFdInit to consider multifd.
Signed-off-by: Claudio Fontana <cfontana(a)suse.de>
---
src/qemu/qemu_driver.c | 10 ++--
src/qemu/qemu_saveimage.c | 117 +++++++++++++++++++++++++++++++++++---
src/qemu/qemu_saveimage.h | 17 +++++-
3 files changed, 129 insertions(+), 15 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index d071df1c81..a03ead960b 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5869,7 +5869,7 @@ qemuDomainRestoreInternal(virConnectPtr conn,
}
oflags |= O_DIRECT;
}
- if (virQEMUSaveFdInit(&saveFd, path, oflags, cfg) < 0)
+ if (virQEMUSaveFdInit(&saveFd, path, 0, oflags, cfg, false) < 0)
return -1;
if (qemuSaveImageOpen(driver, NULL, &def, &data, false, &saveFd) < 0)
goto cleanup;
@@ -6003,7 +6003,7 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path,
virCheckFlags(VIR_DOMAIN_SAVE_IMAGE_XML_SECURE, NULL);
- if (virQEMUSaveFdInit(&saveFd, path, O_RDONLY, cfg) < 0)
+ if (virQEMUSaveFdInit(&saveFd, path, 0, O_RDONLY, cfg, false) < 0)
return NULL;
if (qemuSaveImageOpen(driver, NULL, &def, &data, false, &saveFd) < 0)
goto cleanup;
@@ -6041,7 +6041,7 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path,
else if (flags & VIR_DOMAIN_SAVE_PAUSED)
state = 0;
- if (virQEMUSaveFdInit(&saveFd, path, O_RDWR, cfg) < 0)
+ if (virQEMUSaveFdInit(&saveFd, path, 0, O_RDWR, cfg, false) < 0)
return -1;
if (qemuSaveImageOpen(driver, NULL, &def, &data, false, &saveFd) < 0)
goto cleanup;
@@ -6122,7 +6122,7 @@ qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom, unsigned int
flags)
goto cleanup;
}
- if (virQEMUSaveFdInit(&saveFd, path, O_RDONLY, cfg) < 0)
+ if (virQEMUSaveFdInit(&saveFd, path, 0, O_RDONLY, cfg, false) < 0)
goto cleanup;
if (qemuSaveImageOpen(driver, priv->qemuCaps, &def, &data, false,
&saveFd) < 0)
@@ -6198,7 +6198,7 @@ qemuDomainObjRestore(virConnectPtr conn,
}
oflags |= O_DIRECT;
}
- if (virQEMUSaveFdInit(&saveFd, path, oflags, cfg) < 0)
+ if (virQEMUSaveFdInit(&saveFd, path, 0, oflags, cfg, false) < 0)
goto cleanup;
ret = qemuSaveImageOpen(driver, NULL, &def, &data, true, &saveFd);
if (ret < 0) {
diff --git a/src/qemu/qemu_saveimage.c b/src/qemu/qemu_saveimage.c
index ca6eccd7b5..5c35c39d83 100644
--- a/src/qemu/qemu_saveimage.c
+++ b/src/qemu/qemu_saveimage.c
@@ -400,15 +400,17 @@ qemuSaveImageGetCompressionCommand(virQEMUSaveFormat compression)
* virQEMUSaveFdInit: initialize a virQEMUSaveFd
*
* @saveFd: the structure to initialize
- * @base: the file name
+ * @base: the main file name
+ * @idx: 0 for the main file, > 0 for the multifd channels.
* @oflags the file descriptor open flags
* @cfg: the driver config
+ * @parallel: whether parallel save is enabled
*
* 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 oflags, virQEMUDriverConfig *cfg)
+int virQEMUSaveFdInit(virQEMUSaveFd *saveFd, const char *base, int idx,
+ int oflags, virQEMUDriverConfig *cfg, bool parallel)
{
unsigned int wrapperFlags = VIR_FILE_WRAPPER_NON_BLOCKING;
bool isCreat = oflags & O_CREAT;
@@ -416,8 +418,11 @@ int virQEMUSaveFdInit(virQEMUSaveFd *saveFd, const char *base,
if (isDirect)
wrapperFlags |= VIR_FILE_WRAPPER_BYPASS_CACHE;
-
- saveFd->path = g_strdup(base);
+ 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,
@@ -428,10 +433,11 @@ int virQEMUSaveFdInit(virQEMUSaveFd *saveFd, const char *base,
if (saveFd->fd < 0)
return -1;
/*
+ * iohelper Wrapper is never required for multifd parallel save.
* For O_CREAT, we always add the wrapper,
* and for !O_CREAT, we only add the wrapper if using O_DIRECT.
*/
- if (isDirect || isCreat) {
+ if (!parallel && (isDirect || isCreat)) {
saveFd->wrapper = virFileWrapperFdNew(&saveFd->fd, saveFd->path,
wrapperFlags);
if (!saveFd->wrapper)
return -1;
@@ -508,6 +514,103 @@ int virQEMUSaveFdFini(virQEMUSaveFd *saveFd, virDomainObj *vm, int
ret)
return ret;
}
+/*
+ * qemuSaveImageFreeMultiFd: free all multifd virQEMUSaveFds.
+ * @multiFd: the array of saveFds
+ * @vm: the virDomainObj, to release lock
+ * @nconn: number of multifd channels
+ * @ret: the current operation result (< 0 is failure)
+ *
+ * If multiFd is NULL, the return value will be unchanged.
+ *
+ * Returns ret, or -1 if an error is detected.
+ */
+int qemuSaveImageFreeMultiFd(virQEMUSaveFd *multiFd, virDomainObj *vm, int nconn, int
ret)
+{
+ int idx;
+
+ if (!multiFd)
+ return ret;
+
+ for (idx = 0; idx < nconn; idx++) {
+ ret = virQEMUSaveFdFini(&multiFd[idx], vm, ret);
+ }
+ /*
+ * do it again to unlink all in the error case,
+ * if error happened in the middle of previous loop.
+ */
+ for (idx = 0; idx < nconn; idx++) {
+ ret = virQEMUSaveFdFini(&multiFd[idx], vm, ret);
+ }
+ g_free(multiFd);
+ return ret;
+}
+
+/*
+ * qemuSaveImageCloseMultiFd: perform normal close on all multifd virQEMUSaveFds.
+ *
+ * @multiFd: the array of saveFds
+ * @nconn: number of multifd channels
+ * @vm: the virDomainObj, to release lock
+ *
+ * If multiFd is NULL, the function will return success.
+ * Returns -1 on error, 0 on success.
+ */
+int qemuSaveImageCloseMultiFd(virQEMUSaveFd *multiFd, int nconn, virDomainObj *vm)
+{
+ int idx;
+
+ if (!multiFd)
+ return 0;
+
+ for (idx = 0; idx < nconn; idx++) {
+ if (virQEMUSaveFdClose(&multiFd[idx], vm) < 0) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * qemuSaveImageCreateMultiFd: allocate and initialize all multifd virQEMUSaveFds.
+ *
+ * @driver: qemu driver data
+ * @vm: the virDomainObj
+ * @cmd: the existing multifd helper command, to pass each fd as argument.
+ * @path: pathname of the main file.
+ * @oflags: the open flags desired, to be passed to virQEMUSaveFdInit.
+ * @cfg: the driver config
+ * @nconn: number of channel files to create or open, depending on oflags.
+ *
+ * Returns the new array of virQEMUSaveFds, or NULL on error.
+ */
+virQEMUSaveFd *
+qemuSaveImageCreateMultiFd(virQEMUDriver *driver, virDomainObj *vm,
+ virCommand *cmd, const char *path,
+ int oflags, virQEMUDriverConfig *cfg,
+ int nconn)
+{
+ virQEMUSaveFd *multiFd = g_new0(virQEMUSaveFd, nconn);
+ int idx;
+
+ for (idx = 0; idx < nconn; idx++) {
+ virQEMUSaveFd *m = &multiFd[idx];
+ if (virQEMUSaveFdInit(m, path, idx + 1, oflags, cfg, true) < 0 ||
+ qemuSecuritySetImageFDLabel(driver->securityManager, vm->def, m->fd)
< 0) {
+
+ virQEMUSaveFdFini(m, vm, -1);
+ goto error;
+ }
+ virCommandAddArgFormat(cmd, "%d", m->fd);
+ virCommandPassFD(cmd, m->fd, 0);
+ }
+ return multiFd;
+
+ error:
+ qemuSaveImageFreeMultiFd(multiFd, vm, nconn, -1);
+ return NULL;
+}
+
/* 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
@@ -536,7 +639,7 @@ qemuSaveImageCreate(virQEMUDriver *driver,
oflags |= O_DIRECT;
}
- if (virQEMUSaveFdInit(&saveFd, path, oflags, cfg) < 0)
+ if (virQEMUSaveFdInit(&saveFd, path, 0, oflags, cfg, false) < 0)
goto cleanup;
if (qemuSecuritySetImageFDLabel(driver->securityManager, vm->def, saveFd.fd)
< 0)
goto cleanup;
diff --git a/src/qemu/qemu_saveimage.h b/src/qemu/qemu_saveimage.h
index e5a51955da..e85e5690b2 100644
--- a/src/qemu/qemu_saveimage.h
+++ b/src/qemu/qemu_saveimage.h
@@ -64,14 +64,25 @@ struct _virQEMUSaveFd {
#define QEMU_SAVEFD_INVALID (virQEMUSaveFd) { .path = NULL, .fd = -1, .need_unlink =
false, .wrapper = NULL }
-int virQEMUSaveFdInit(virQEMUSaveFd *saveFd, const char *base,
- int oflags, virQEMUDriverConfig *cfg)
- ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(4);
+int virQEMUSaveFdInit(virQEMUSaveFd *saveFd, const char *base, int idx,
+ int oflags, virQEMUDriverConfig *cfg, bool parallel)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(5);
int virQEMUSaveFdClose(virQEMUSaveFd *saveFd, virDomainObj *vm);
int virQEMUSaveFdFini(virQEMUSaveFd *saveFd, virDomainObj *vm, int ret);
+virQEMUSaveFd *
+qemuSaveImageCreateMultiFd(virQEMUDriver *driver, virDomainObj *vm,
+ virCommand *cmd, const char *path,
+ int oflags, virQEMUDriverConfig *cfg,
+ int nconn)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
ATTRIBUTE_NONNULL(6);
+
+int qemuSaveImageCloseMultiFd(virQEMUSaveFd *multiFd, int nconn, virDomainObj *vm);
+
+int qemuSaveImageFreeMultiFd(virQEMUSaveFd *multiFd, virDomainObj *vm, int nconn, int
ret);
+
virDomainDef *
qemuSaveImageUpdateDef(virQEMUDriver *driver,
virDomainDef *def,
--
2.35.3