From 56a60bd1b230c86195778e4fda2f44052faae10c Mon Sep 17 00:00:00 2001 Message-Id: <56a60bd1b230c86195778e4fda2f44052faae10c@dist-git> From: Jiri Denemark Date: Wed, 7 Jun 2017 00:08:25 +0200 Subject: [PATCH] qemu: Introduce virQEMUSaveData structure The new structure encapsulates save image header and associated data (domain XML). Signed-off-by: Jiri Denemark Reviewed-by: Pavel Hrdina (cherry picked from commit 47e60ac306273559b8c14527ea15a92c6ac6dd91) https://bugzilla.redhat.com/show_bug.cgi?id=1441662 Signed-off-by: Jiri Denemark --- src/qemu/qemu_driver.c | 165 ++++++++++++++++++++++++++----------------------- 1 file changed, 86 insertions(+), 79 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 1629f27470..7ce0f01f70 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -2816,6 +2816,14 @@ struct _virQEMUSaveHeader { uint32_t unused[15]; }; +typedef struct _virQEMUSaveData virQEMUSaveData; +typedef virQEMUSaveData *virQEMUSaveDataPtr; +struct _virQEMUSaveData { + virQEMUSaveHeader header; + char *xml; +}; + + static inline void bswap_header(virQEMUSaveHeaderPtr hdr) { @@ -2827,31 +2835,39 @@ bswap_header(virQEMUSaveHeaderPtr hdr) static void -virQEMUSaveDataFree(virQEMUSaveHeaderPtr header) +virQEMUSaveDataFree(virQEMUSaveDataPtr data) { - if (!header) + if (!data) return; - VIR_FREE(header); + VIR_FREE(data->xml); + VIR_FREE(data); } -static virQEMUSaveHeaderPtr -virQEMUSaveDataNew(char *domXML ATTRIBUTE_UNUSED, +/** + * This function steals @domXML on success. + */ +static virQEMUSaveDataPtr +virQEMUSaveDataNew(char *domXML, bool running, int compressed) { - virQEMUSaveHeaderPtr header = NULL; + virQEMUSaveDataPtr data = NULL; + virQEMUSaveHeaderPtr header; - if (VIR_ALLOC(header) < 0) + if (VIR_ALLOC(data) < 0) return NULL; + VIR_STEAL_PTR(data->xml, domXML); + + header = &data->header; memcpy(header->magic, QEMU_SAVE_PARTIAL, sizeof(header->magic)); header->version = QEMU_SAVE_VERSION; header->was_running = running ? 1 : 0; header->compressed = compressed; - return header; + return data; } @@ -2865,17 +2881,17 @@ virQEMUSaveDataNew(char *domXML ATTRIBUTE_UNUSED, * Returns -1 on failure, or 0 on success. */ static int -virQEMUSaveDataWrite(virQEMUSaveHeaderPtr header, - const char *xml, +virQEMUSaveDataWrite(virQEMUSaveDataPtr data, int fd, const char *path) { + virQEMUSaveHeaderPtr header = &data->header; size_t len; int ret = -1; size_t zerosLen = 0; char *zeros = NULL; - len = strlen(xml) + 1; + len = strlen(data->xml) + 1; if (header->data_len > 0) { if (len > header->data_len) { @@ -2898,7 +2914,7 @@ virQEMUSaveDataWrite(virQEMUSaveHeaderPtr header, goto cleanup; } - if (safewrite(fd, xml, header->data_len) != header->data_len || + if (safewrite(fd, data->xml, header->data_len) != header->data_len || safewrite(fd, zeros, zerosLen) != zerosLen) { virReportSystemError(errno, _("failed to write domain xml to '%s'"), @@ -2915,10 +2931,12 @@ virQEMUSaveDataWrite(virQEMUSaveHeaderPtr header, static int -virQEMUSaveDataFinish(virQEMUSaveHeaderPtr header, +virQEMUSaveDataFinish(virQEMUSaveDataPtr data, int *fd, const char *path) { + virQEMUSaveHeaderPtr header = &data->header; + memcpy(header->magic, QEMU_SAVE_MAGIC, sizeof(header->magic)); if (safewrite(*fd, header, sizeof(*header)) != sizeof(*header) || @@ -3128,8 +3146,7 @@ static int qemuDomainSaveMemory(virQEMUDriverPtr driver, virDomainObjPtr vm, const char *path, - const char *domXML, - virQEMUSaveHeaderPtr header, + virQEMUSaveDataPtr data, const char *compressedpath, unsigned int flags, qemuDomainAsyncJob asyncJob) @@ -3164,7 +3181,7 @@ qemuDomainSaveMemory(virQEMUDriverPtr driver, if (!(wrapperFd = virFileWrapperFdNew(&fd, path, wrapperFlags))) goto cleanup; - if (virQEMUSaveDataWrite(header, domXML, fd, path) < 0) + if (virQEMUSaveDataWrite(data, fd, path) < 0) goto cleanup; /* Perform the migration */ @@ -3186,7 +3203,7 @@ qemuDomainSaveMemory(virQEMUDriverPtr driver, goto cleanup; if ((fd = qemuOpenFile(driver, vm, path, O_WRONLY, NULL, NULL)) < 0 || - virQEMUSaveDataFinish(header, &fd, path) < 0) + virQEMUSaveDataFinish(data, &fd, path) < 0) goto cleanup; ret = 0; @@ -3218,7 +3235,7 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom, virObjectEventPtr event = NULL; qemuDomainObjPrivatePtr priv = vm->privateData; virCapsPtr caps; - virQEMUSaveHeaderPtr header = NULL; + virQEMUSaveDataPtr data = NULL; if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -3284,10 +3301,11 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom, goto endjob; } - if (!(header = virQEMUSaveDataNew(xml, was_running, compressed))) + if (!(data = virQEMUSaveDataNew(xml, was_running, compressed))) goto endjob; + xml = NULL; - ret = qemuDomainSaveMemory(driver, vm, path, xml, header, compressedpath, + ret = qemuDomainSaveMemory(driver, vm, path, data, compressedpath, flags, QEMU_ASYNC_JOB_SAVE); if (ret < 0) goto endjob; @@ -3321,7 +3339,7 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom, cleanup: VIR_FREE(xml); - virQEMUSaveDataFree(header); + virQEMUSaveDataFree(data); qemuDomainEventQueue(driver, event); virObjectUnref(caps); return ret; @@ -6238,8 +6256,7 @@ qemuDomainSaveImageUpdateDef(virQEMUDriverPtr driver, * @driver: qemu driver data * @path: path of the save image * @ret_def: returns domain definition created from the XML stored in the image - * @ret_header: returns structure filled with data from the image header - * @xmlout: returns the XML from the image file (may be NULL) + * @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) @@ -6253,16 +6270,15 @@ static int ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4) qemuDomainSaveImageOpen(virQEMUDriverPtr driver, const char *path, virDomainDefPtr *ret_def, - virQEMUSaveHeaderPtr *ret_header, - char **xmlout, + virQEMUSaveDataPtr *ret_data, bool bypass_cache, virFileWrapperFdPtr *wrapperFd, bool open_write, bool unlink_corrupt) { int fd = -1; - char *xml = NULL; - virQEMUSaveHeaderPtr header = NULL; + virQEMUSaveDataPtr data = NULL; + virQEMUSaveHeaderPtr header; virDomainDefPtr def = NULL; int oflags = open_write ? O_RDWR : O_RDONLY; virCapsPtr caps = NULL; @@ -6287,9 +6303,10 @@ qemuDomainSaveImageOpen(virQEMUDriverPtr driver, VIR_FILE_WRAPPER_BYPASS_CACHE))) goto error; - if (VIR_ALLOC(header) < 0) + if (VIR_ALLOC(data) < 0) goto error; + header = &data->header; if (saferead(fd, header, sizeof(*header)) != sizeof(*header)) { if (unlink_corrupt) { if (VIR_CLOSE(fd) < 0 || unlink(path) < 0) { @@ -6341,32 +6358,27 @@ qemuDomainSaveImageOpen(virQEMUDriverPtr driver, if (header->data_len <= 0) { virReportError(VIR_ERR_OPERATION_FAILED, - _("invalid XML length: %d"), header->data_len); + _("invalid header data length: %d"), header->data_len); goto error; } - if (VIR_ALLOC_N(xml, header->data_len) < 0) + if (VIR_ALLOC_N(data->xml, header->data_len) < 0) goto error; - if (saferead(fd, xml, header->data_len) != header->data_len) { + if (saferead(fd, data->xml, header->data_len) != header->data_len) { virReportError(VIR_ERR_OPERATION_FAILED, - "%s", _("failed to read XML")); + "%s", _("failed to read domain XML")); goto error; } /* Create a domain from this XML */ - if (!(def = virDomainDefParseString(xml, caps, driver->xmlopt, NULL, + if (!(def = virDomainDefParseString(data->xml, caps, driver->xmlopt, NULL, VIR_DOMAIN_DEF_PARSE_INACTIVE | VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE))) goto error; - if (xmlout) - *xmlout = xml; - else - VIR_FREE(xml); - *ret_def = def; - *ret_header = header; + *ret_data = data; virObjectUnref(caps); @@ -6374,8 +6386,7 @@ qemuDomainSaveImageOpen(virQEMUDriverPtr driver, error: virDomainDefFree(def); - VIR_FREE(xml); - virQEMUSaveDataFree(header); + virQEMUSaveDataFree(data); VIR_FORCE_CLOSE(fd); virObjectUnref(caps); @@ -6387,7 +6398,7 @@ qemuDomainSaveImageStartVM(virConnectPtr conn, virQEMUDriverPtr driver, virDomainObjPtr vm, int *fd, - virQEMUSaveHeaderPtr header, + virQEMUSaveDataPtr data, const char *path, bool start_paused, qemuDomainAsyncJob asyncJob) @@ -6399,6 +6410,7 @@ qemuDomainSaveImageStartVM(virConnectPtr conn, virCommandPtr cmd = NULL; char *errbuf = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + virQEMUSaveHeaderPtr header = &data->header; if ((header->version == 2) && (header->compressed != QEMU_SAVE_FORMAT_RAW)) { @@ -6508,12 +6520,11 @@ qemuDomainRestoreFlags(virConnectPtr conn, qemuDomainObjPrivatePtr priv = NULL; virDomainDefPtr def = NULL; virDomainObjPtr vm = NULL; - char *xml = NULL; char *xmlout = NULL; const char *newxml = dxml; int fd = -1; int ret = -1; - virQEMUSaveHeaderPtr header = NULL; + virQEMUSaveDataPtr data = NULL; virFileWrapperFdPtr wrapperFd = NULL; bool hook_taint = false; @@ -6524,7 +6535,7 @@ qemuDomainRestoreFlags(virConnectPtr conn, virNWFilterReadLockFilterUpdates(); - fd = qemuDomainSaveImageOpen(driver, path, &def, &header, &xml, + fd = qemuDomainSaveImageOpen(driver, path, &def, &data, (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0, &wrapperFd, false, false); if (fd < 0) @@ -6540,7 +6551,7 @@ qemuDomainRestoreFlags(virConnectPtr conn, VIR_HOOK_QEMU_OP_RESTORE, VIR_HOOK_SUBOP_BEGIN, NULL, - dxml ? dxml : xml, + dxml ? dxml : data->xml, &xmlout)) < 0) goto cleanup; @@ -6570,9 +6581,9 @@ qemuDomainRestoreFlags(virConnectPtr conn, def = NULL; if (flags & VIR_DOMAIN_SAVE_RUNNING) - header->was_running = 1; + data->header.was_running = 1; else if (flags & VIR_DOMAIN_SAVE_PAUSED) - header->was_running = 0; + data->header.was_running = 0; if (hook_taint) { priv = vm->privateData; @@ -6582,7 +6593,7 @@ qemuDomainRestoreFlags(virConnectPtr conn, if (qemuProcessBeginJob(driver, vm, VIR_DOMAIN_JOB_OPERATION_RESTORE) < 0) goto cleanup; - ret = qemuDomainSaveImageStartVM(conn, driver, vm, &fd, header, path, + ret = qemuDomainSaveImageStartVM(conn, driver, vm, &fd, data, path, false, QEMU_ASYNC_JOB_START); if (virFileWrapperFdClose(wrapperFd) < 0) VIR_WARN("Failed to close %s", path); @@ -6592,8 +6603,7 @@ qemuDomainRestoreFlags(virConnectPtr conn, cleanup: virDomainDefFree(def); VIR_FORCE_CLOSE(fd); - VIR_FREE(xml); - virQEMUSaveDataFree(header); + virQEMUSaveDataFree(data); VIR_FREE(xmlout); virFileWrapperFdFree(wrapperFd); if (vm && ret < 0) @@ -6618,12 +6628,12 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path, char *ret = NULL; virDomainDefPtr def = NULL; int fd = -1; - virQEMUSaveHeaderPtr header = NULL; + virQEMUSaveDataPtr data = NULL; /* We only take subset of virDomainDefFormat flags. */ virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL); - fd = qemuDomainSaveImageOpen(driver, path, &def, &header, NULL, + fd = qemuDomainSaveImageOpen(driver, path, &def, &data, false, NULL, false, false); if (fd < 0) @@ -6635,7 +6645,7 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path, ret = qemuDomainDefFormatXML(driver, def, flags); cleanup: - virQEMUSaveDataFree(header); + virQEMUSaveDataFree(data); virDomainDefFree(def); VIR_FORCE_CLOSE(fd); return ret; @@ -6650,8 +6660,7 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path, virDomainDefPtr def = NULL; virDomainDefPtr newdef = NULL; int fd = -1; - char *xml = NULL; - virQEMUSaveHeaderPtr header = NULL; + virQEMUSaveDataPtr data = NULL; int state = -1; virCheckFlags(VIR_DOMAIN_SAVE_RUNNING | @@ -6662,7 +6671,7 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path, else if (flags & VIR_DOMAIN_SAVE_PAUSED) state = 0; - fd = qemuDomainSaveImageOpen(driver, path, &def, &header, &xml, + fd = qemuDomainSaveImageOpen(driver, path, &def, &data, false, NULL, true, false); if (fd < 0) @@ -6671,25 +6680,25 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path, if (virDomainSaveImageDefineXMLEnsureACL(conn, def) < 0) goto cleanup; - if (STREQ(xml, dxml) && - (state < 0 || state == header->was_running)) { + if (STREQ(data->xml, dxml) && + (state < 0 || state == data->header.was_running)) { /* no change to the XML */ ret = 0; goto cleanup; } if (state >= 0) - header->was_running = state; + data->header.was_running = state; if (!(newdef = qemuDomainSaveImageUpdateDef(driver, def, dxml))) goto cleanup; - VIR_FREE(xml); + VIR_FREE(data->xml); - if (!(xml = qemuDomainDefFormatXML(driver, newdef, - VIR_DOMAIN_XML_INACTIVE | - VIR_DOMAIN_XML_SECURE | - VIR_DOMAIN_XML_MIGRATABLE))) + if (!(data->xml = qemuDomainDefFormatXML(driver, newdef, + VIR_DOMAIN_XML_INACTIVE | + VIR_DOMAIN_XML_SECURE | + VIR_DOMAIN_XML_MIGRATABLE))) goto cleanup; if (lseek(fd, 0, SEEK_SET) != 0) { @@ -6697,7 +6706,7 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path, goto cleanup; } - if (virQEMUSaveDataWrite(header, xml, fd, path) < 0) + if (virQEMUSaveDataWrite(data, fd, path) < 0) goto cleanup; if (VIR_CLOSE(fd) < 0) { @@ -6711,8 +6720,7 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path, virDomainDefFree(def); virDomainDefFree(newdef); VIR_FORCE_CLOSE(fd); - VIR_FREE(xml); - virQEMUSaveDataFree(header); + virQEMUSaveDataFree(data); return ret; } @@ -6731,12 +6739,11 @@ qemuDomainObjRestore(virConnectPtr conn, qemuDomainObjPrivatePtr priv = vm->privateData; int fd = -1; int ret = -1; - char *xml = NULL; char *xmlout = NULL; - virQEMUSaveHeaderPtr header = NULL; + virQEMUSaveDataPtr data = NULL; virFileWrapperFdPtr wrapperFd = NULL; - fd = qemuDomainSaveImageOpen(driver, path, &def, &header, &xml, + fd = qemuDomainSaveImageOpen(driver, path, &def, &data, bypass_cache, &wrapperFd, false, true); if (fd < 0) { if (fd == -3) @@ -6750,7 +6757,7 @@ qemuDomainObjRestore(virConnectPtr conn, if ((hookret = virHookCall(VIR_HOOK_DRIVER_QEMU, def->name, VIR_HOOK_QEMU_OP_RESTORE, VIR_HOOK_SUBOP_BEGIN, - NULL, xml, &xmlout)) < 0) + NULL, data->xml, &xmlout)) < 0) goto cleanup; if (hookret == 0 && !virStringIsEmpty(xmlout)) { @@ -6784,14 +6791,13 @@ qemuDomainObjRestore(virConnectPtr conn, virDomainObjAssignDef(vm, def, true, NULL); def = NULL; - ret = qemuDomainSaveImageStartVM(conn, driver, vm, &fd, header, path, + ret = qemuDomainSaveImageStartVM(conn, driver, vm, &fd, data, path, start_paused, asyncJob); if (virFileWrapperFdClose(wrapperFd) < 0) VIR_WARN("Failed to close %s", path); cleanup: - VIR_FREE(xml); - virQEMUSaveDataFree(header); + virQEMUSaveDataFree(data); VIR_FREE(xmlout); virDomainDefFree(def); VIR_FORCE_CLOSE(fd); @@ -14364,7 +14370,7 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn, virQEMUDriverConfigPtr cfg = NULL; int compressed; char *compressedpath = NULL; - virQEMUSaveHeaderPtr header = NULL; + virQEMUSaveDataPtr data = NULL; /* If quiesce was requested, then issue a freeze command, and a * counterpart thaw command when it is actually sent to agent. @@ -14436,10 +14442,11 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn, if (!(xml = qemuDomainDefFormatLive(driver, vm->def, true, true))) goto cleanup; - if (!(header = virQEMUSaveDataNew(xml, resume, compressed))) + if (!(data = virQEMUSaveDataNew(xml, resume, compressed))) goto cleanup; + xml = NULL; - if ((ret = qemuDomainSaveMemory(driver, vm, snap->def->file, xml, header, + if ((ret = qemuDomainSaveMemory(driver, vm, snap->def->file, data, compressedpath, 0, QEMU_ASYNC_JOB_SNAPSHOT)) < 0) goto cleanup; @@ -14509,7 +14516,7 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn, ret = -1; } - virQEMUSaveDataFree(header); + virQEMUSaveDataFree(data); VIR_FREE(xml); VIR_FREE(compressedpath); virObjectUnref(cfg); -- 2.13.1