use this data type to encapsulate the pathname,
file descriptor, wrapper, and need to unlink.
This will make management of the resources associated
with an FD used for QEMU save/restore much easier,
reducing the amount of explicit cleanup required.
Signed-off-by: Claudio Fontana <cfontana(a)suse.de>
---
src/qemu/qemu_saveimage.c | 112 ++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_saveimage.h | 18 ++++++
2 files changed, 130 insertions(+)
diff --git a/src/qemu/qemu_saveimage.c b/src/qemu/qemu_saveimage.c
index 5cc4ede6f5..1ec178eae0 100644
--- a/src/qemu/qemu_saveimage.c
+++ b/src/qemu/qemu_saveimage.c
@@ -396,6 +396,118 @@ qemuSaveImageGetCompressionCommand(virQEMUSaveFormat compression)
return ret;
}
+/*
+ * virQEMUSaveFdInit: initialize a virQEMUSaveFd
+ *
+ * @saveFd: the structure to initialize
+ * @base: the file name
+ * @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 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;
+
+ 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;
+ /*
+ * For O_CREAT, we always add the wrapper,
+ * and for !O_CREAT, we only add the wrapper if using O_DIRECT.
+ */
+ if (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
diff --git a/src/qemu/qemu_saveimage.h b/src/qemu/qemu_saveimage.h
index f12374b3d7..d2798aeff6 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 oflags, virQEMUDriverConfig *cfg)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(4);
+
+int virQEMUSaveFdClose(virQEMUSaveFd *saveFd, virDomainObj *vm);
+
+int virQEMUSaveFdFini(virQEMUSaveFd *saveFd, virDomainObj *vm, int ret);
+
virDomainDef *
qemuSaveImageUpdateDef(virQEMUDriver *driver,
virDomainDef *def,
--
2.35.3