diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 40c1d785c5..2b4a66434f 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -2811,6 +2811,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) { @@ -2822,31 +2830,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; } @@ -2860,17 +2876,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) { @@ -2893,7 +2909,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'"), @@ -2910,10 +2926,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) || @@ -3142,8 +3160,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) @@ -3178,7 +3195,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 */ @@ -3200,7 +3217,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; @@ -3232,7 +3249,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; @@ -3298,10 +3315,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; @@ -3335,7 +3353,7 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom, cleanup: VIR_FREE(xml); - virQEMUSaveDataFree(header); + virQEMUSaveDataFree(data); qemuDomainEventQueue(driver, event); virObjectUnref(caps); return ret; @@ -6244,8 +6262,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) @@ -6259,16 +6276,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; @@ -6293,9 +6309,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) { @@ -6347,32 +6364,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); @@ -6380,8 +6392,7 @@ qemuDomainSaveImageOpen(virQEMUDriverPtr driver, error: virDomainDefFree(def); - VIR_FREE(xml); - virQEMUSaveDataFree(header); + virQEMUSaveDataFree(data); VIR_FORCE_CLOSE(fd); virObjectUnref(caps); @@ -6393,7 +6404,7 @@ qemuDomainSaveImageStartVM(virConnectPtr conn, virQEMUDriverPtr driver, virDomainObjPtr vm, int *fd, - virQEMUSaveHeaderPtr header, + virQEMUSaveDataPtr data, const char *path, bool start_paused, qemuDomainAsyncJob asyncJob) @@ -6405,6 +6416,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)) { @@ -6514,12 +6526,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; @@ -6530,7 +6541,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) @@ -6546,7 +6557,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; @@ -6576,9 +6587,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; @@ -6588,7 +6599,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); @@ -6598,8 +6609,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) @@ -6624,12 +6634,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) @@ -6641,7 +6651,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; @@ -6656,8 +6666,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 | @@ -6668,7 +6677,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) @@ -6677,25 +6686,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) { @@ -6703,7 +6712,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) { @@ -6717,8 +6726,7 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path, virDomainDefFree(def); virDomainDefFree(newdef); VIR_FORCE_CLOSE(fd); - VIR_FREE(xml); - virQEMUSaveDataFree(header); + virQEMUSaveDataFree(data); return ret; } @@ -6737,12 +6745,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) @@ -6756,7 +6763,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)) { @@ -6790,14 +6797,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); @@ -14363,7 +14369,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. @@ -14435,10 +14441,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; @@ -14508,7 +14515,7 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn, ret = -1; } - virQEMUSaveDataFree(header); + virQEMUSaveDataFree(data); VIR_FREE(xml); VIR_FREE(compressedpath); virObjectUnref(cfg);