From d37bad5cb5da2804d51cd6c45903f538d9ec85c5 Mon Sep 17 00:00:00 2001 Message-Id: From: Jiri Denemark Date: Tue, 6 Jun 2017 22:29:24 +0200 Subject: [PATCH] qemu: Introduce virQEMUSaveData{New,Free} This is a preparation for creating a new virQEMUSaveData structure which will encapsulate all save image header data. Signed-off-by: Jiri Denemark Reviewed-by: Pavel Hrdina (cherry picked from commit a2d2aae148980f00dd83093d61b1aa06c54fbe96) https://bugzilla.redhat.com/show_bug.cgi?id=1441662 Signed-off-by: Jiri Denemark --- src/qemu/qemu_driver.c | 128 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 83 insertions(+), 45 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5db92b04a1..4a05793339 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -2826,6 +2826,36 @@ bswap_header(virQEMUSaveHeaderPtr hdr) } +static void +virQEMUSaveDataFree(virQEMUSaveHeaderPtr header) +{ + if (!header) + return; + + VIR_FREE(header); +} + + +static virQEMUSaveHeaderPtr +virQEMUSaveDataNew(char *domXML, + bool running, + int compressed) +{ + virQEMUSaveHeaderPtr header = NULL; + + if (VIR_ALLOC(header) < 0) + return NULL; + + memcpy(header->magic, QEMU_SAVE_PARTIAL, sizeof(header->magic)); + header->version = QEMU_SAVE_VERSION; + header->was_running = running ? 1 : 0; + header->compressed = compressed; + header->data_len = strlen(domXML) + 1; + + return header; +} + + /* return -errno on failure, or 0 on success */ static int qemuDomainSaveHeader(int fd, const char *path, const char *xml, @@ -3048,13 +3078,11 @@ qemuDomainSaveMemory(virQEMUDriverPtr driver, virDomainObjPtr vm, const char *path, const char *domXML, - int compressed, + virQEMUSaveHeaderPtr header, const char *compressedpath, - bool was_running, unsigned int flags, qemuDomainAsyncJob asyncJob) { - virQEMUSaveHeader header; bool bypassSecurityDriver = false; bool needUnlink = false; int ret = -1; @@ -3063,13 +3091,6 @@ qemuDomainSaveMemory(virQEMUDriverPtr driver, virFileWrapperFdPtr wrapperFd = NULL; unsigned int wrapperFlags = VIR_FILE_WRAPPER_NON_BLOCKING; - memset(&header, 0, sizeof(header)); - memcpy(header.magic, QEMU_SAVE_PARTIAL, sizeof(header.magic)); - header.version = QEMU_SAVE_VERSION; - header.was_running = was_running ? 1 : 0; - header.compressed = compressed; - header.data_len = strlen(domXML) + 1; - /* Obtain the file handle. */ if ((flags & VIR_DOMAIN_SAVE_BYPASS_CACHE)) { wrapperFlags |= VIR_FILE_WRAPPER_BYPASS_CACHE; @@ -3093,7 +3114,7 @@ qemuDomainSaveMemory(virQEMUDriverPtr driver, goto cleanup; /* Write header to file, followed by XML */ - if (qemuDomainSaveHeader(fd, path, domXML, &header) < 0) + if (qemuDomainSaveHeader(fd, path, domXML, header) < 0) goto cleanup; /* Perform the migration */ @@ -3117,7 +3138,7 @@ qemuDomainSaveMemory(virQEMUDriverPtr driver, if ((fd = qemuOpenFile(driver, vm, path, O_WRONLY, NULL, NULL)) < 0) goto cleanup; - memcpy(header.magic, QEMU_SAVE_MAGIC, sizeof(header.magic)); + memcpy(header->magic, QEMU_SAVE_MAGIC, sizeof(header->magic)); if (safewrite(fd, &header, sizeof(header)) != sizeof(header)) { virReportSystemError(errno, _("unable to write %s"), path); @@ -3158,6 +3179,7 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom, virObjectEventPtr event = NULL; qemuDomainObjPrivatePtr priv = vm->privateData; virCapsPtr caps; + virQEMUSaveHeaderPtr header = NULL; if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -3223,9 +3245,11 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom, goto endjob; } - ret = qemuDomainSaveMemory(driver, vm, path, xml, compressed, - compressedpath, was_running, flags, - QEMU_ASYNC_JOB_SAVE); + if (!(header = virQEMUSaveDataNew(xml, was_running, compressed))) + goto endjob; + + ret = qemuDomainSaveMemory(driver, vm, path, xml, header, compressedpath, + flags, QEMU_ASYNC_JOB_SAVE); if (ret < 0) goto endjob; @@ -3258,6 +3282,7 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom, cleanup: VIR_FREE(xml); + virQEMUSaveDataFree(header); qemuDomainEventQueue(driver, event); virObjectUnref(caps); return ret; @@ -6189,7 +6214,7 @@ static int ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4) qemuDomainSaveImageOpen(virQEMUDriverPtr driver, const char *path, virDomainDefPtr *ret_def, - virQEMUSaveHeaderPtr ret_header, + virQEMUSaveHeaderPtr *ret_header, char **xmlout, bool bypass_cache, virFileWrapperFdPtr *wrapperFd, @@ -6197,8 +6222,8 @@ qemuDomainSaveImageOpen(virQEMUDriverPtr driver, bool unlink_corrupt) { int fd = -1; - virQEMUSaveHeader header; char *xml = NULL; + virQEMUSaveHeaderPtr header = NULL; virDomainDefPtr def = NULL; int oflags = open_write ? O_RDWR : O_RDONLY; virCapsPtr caps = NULL; @@ -6223,7 +6248,10 @@ qemuDomainSaveImageOpen(virQEMUDriverPtr driver, VIR_FILE_WRAPPER_BYPASS_CACHE))) goto error; - if (saferead(fd, &header, sizeof(header)) != sizeof(header)) { + if (VIR_ALLOC(header) < 0) + goto error; + + if (saferead(fd, header, sizeof(*header)) != sizeof(*header)) { if (unlink_corrupt) { if (VIR_CLOSE(fd) < 0 || unlink(path) < 0) { virReportSystemError(errno, @@ -6239,11 +6267,11 @@ qemuDomainSaveImageOpen(virQEMUDriverPtr driver, goto error; } - if (memcmp(header.magic, QEMU_SAVE_MAGIC, sizeof(header.magic)) != 0) { + if (memcmp(header->magic, QEMU_SAVE_MAGIC, sizeof(header->magic)) != 0) { const char *msg = _("image magic is incorrect"); - if (memcmp(header.magic, QEMU_SAVE_PARTIAL, - sizeof(header.magic)) == 0) { + if (memcmp(header->magic, QEMU_SAVE_PARTIAL, + sizeof(header->magic)) == 0) { msg = _("save image is incomplete"); if (unlink_corrupt) { if (VIR_CLOSE(fd) < 0 || unlink(path) < 0) { @@ -6260,28 +6288,28 @@ qemuDomainSaveImageOpen(virQEMUDriverPtr driver, goto error; } - if (header.version > QEMU_SAVE_VERSION) { + if (header->version > QEMU_SAVE_VERSION) { /* convert endianess and try again */ - bswap_header(&header); + bswap_header(header); } - if (header.version > QEMU_SAVE_VERSION) { + if (header->version > QEMU_SAVE_VERSION) { virReportError(VIR_ERR_OPERATION_FAILED, _("image version is not supported (%d > %d)"), - header.version, QEMU_SAVE_VERSION); + header->version, QEMU_SAVE_VERSION); goto error; } - if (header.data_len <= 0) { + if (header->data_len <= 0) { virReportError(VIR_ERR_OPERATION_FAILED, - _("invalid XML length: %d"), header.data_len); + _("invalid XML length: %d"), header->data_len); goto error; } - if (VIR_ALLOC_N(xml, header.data_len) < 0) + if (VIR_ALLOC_N(xml, header->data_len) < 0) goto error; - if (saferead(fd, xml, header.data_len) != header.data_len) { + if (saferead(fd, xml, header->data_len) != header->data_len) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to read XML")); goto error; @@ -6308,6 +6336,7 @@ qemuDomainSaveImageOpen(virQEMUDriverPtr driver, error: virDomainDefFree(def); VIR_FREE(xml); + virQEMUSaveDataFree(header); VIR_FORCE_CLOSE(fd); virObjectUnref(caps); @@ -6319,7 +6348,7 @@ qemuDomainSaveImageStartVM(virConnectPtr conn, virQEMUDriverPtr driver, virDomainObjPtr vm, int *fd, - const virQEMUSaveHeader *header, + virQEMUSaveHeaderPtr header, const char *path, bool start_paused, qemuDomainAsyncJob asyncJob) @@ -6445,7 +6474,7 @@ qemuDomainRestoreFlags(virConnectPtr conn, const char *newxml = dxml; int fd = -1; int ret = -1; - virQEMUSaveHeader header; + virQEMUSaveHeaderPtr header = NULL; virFileWrapperFdPtr wrapperFd = NULL; bool hook_taint = false; @@ -6502,9 +6531,9 @@ qemuDomainRestoreFlags(virConnectPtr conn, def = NULL; if (flags & VIR_DOMAIN_SAVE_RUNNING) - header.was_running = 1; + header->was_running = 1; else if (flags & VIR_DOMAIN_SAVE_PAUSED) - header.was_running = 0; + header->was_running = 0; if (hook_taint) { priv = vm->privateData; @@ -6514,7 +6543,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, header, path, false, QEMU_ASYNC_JOB_START); if (virFileWrapperFdClose(wrapperFd) < 0) VIR_WARN("Failed to close %s", path); @@ -6525,6 +6554,7 @@ qemuDomainRestoreFlags(virConnectPtr conn, virDomainDefFree(def); VIR_FORCE_CLOSE(fd); VIR_FREE(xml); + virQEMUSaveDataFree(header); VIR_FREE(xmlout); virFileWrapperFdFree(wrapperFd); if (vm && ret < 0) @@ -6549,7 +6579,7 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path, char *ret = NULL; virDomainDefPtr def = NULL; int fd = -1; - virQEMUSaveHeader header; + virQEMUSaveHeaderPtr header = NULL; /* We only take subset of virDomainDefFormat flags. */ virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL); @@ -6566,6 +6596,7 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path, ret = qemuDomainDefFormatXML(driver, def, flags); cleanup: + virQEMUSaveDataFree(header); virDomainDefFree(def); VIR_FORCE_CLOSE(fd); return ret; @@ -6580,9 +6611,9 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path, virDomainDefPtr def = NULL; virDomainDefPtr newdef = NULL; int fd = -1; - virQEMUSaveHeader header; char *xml = NULL; size_t len; + virQEMUSaveHeaderPtr header = NULL; int state = -1; virCheckFlags(VIR_DOMAIN_SAVE_RUNNING | @@ -6603,14 +6634,14 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path, goto cleanup; if (STREQ(xml, dxml) && - (state < 0 || state == header.was_running)) { + (state < 0 || state == header->was_running)) { /* no change to the XML */ ret = 0; goto cleanup; } if (state >= 0) - header.was_running = state; + header->was_running = state; if (!(newdef = qemuDomainSaveImageUpdateDef(driver, def, dxml))) goto cleanup; @@ -6625,12 +6656,12 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path, goto cleanup; len = strlen(xml) + 1; - if (len > header.data_len) { + if (len > header->data_len) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("new xml too large to fit in file")); goto cleanup; } - if (VIR_EXPAND_N(xml, len, header.data_len - len) < 0) + if (VIR_EXPAND_N(xml, len, header->data_len - len) < 0) goto cleanup; if (lseek(fd, 0, SEEK_SET) != 0) { @@ -6651,6 +6682,7 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path, virDomainDefFree(newdef); VIR_FORCE_CLOSE(fd); VIR_FREE(xml); + virQEMUSaveDataFree(header); return ret; } @@ -6671,7 +6703,7 @@ qemuDomainObjRestore(virConnectPtr conn, int ret = -1; char *xml = NULL; char *xmlout = NULL; - virQEMUSaveHeader header; + virQEMUSaveHeaderPtr header = NULL; virFileWrapperFdPtr wrapperFd = NULL; fd = qemuDomainSaveImageOpen(driver, path, &def, &header, &xml, @@ -6722,13 +6754,14 @@ qemuDomainObjRestore(virConnectPtr conn, virDomainObjAssignDef(vm, def, true, NULL); def = NULL; - ret = qemuDomainSaveImageStartVM(conn, driver, vm, &fd, &header, path, + ret = qemuDomainSaveImageStartVM(conn, driver, vm, &fd, header, path, start_paused, asyncJob); if (virFileWrapperFdClose(wrapperFd) < 0) VIR_WARN("Failed to close %s", path); cleanup: VIR_FREE(xml); + virQEMUSaveDataFree(header); VIR_FREE(xmlout); virDomainDefFree(def); VIR_FORCE_CLOSE(fd); @@ -14301,6 +14334,7 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn, virQEMUDriverConfigPtr cfg = NULL; int compressed; char *compressedpath = NULL; + virQEMUSaveHeaderPtr header = NULL; /* If quiesce was requested, then issue a freeze command, and a * counterpart thaw command when it is actually sent to agent. @@ -14372,9 +14406,12 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn, if (!(xml = qemuDomainDefFormatLive(driver, vm->def, true, true))) goto cleanup; - if ((ret = qemuDomainSaveMemory(driver, vm, snap->def->file, xml, - compressed, compressedpath, resume, - 0, QEMU_ASYNC_JOB_SNAPSHOT)) < 0) + if (!(header = virQEMUSaveDataNew(xml, resume, compressed))) + goto cleanup; + + if ((ret = qemuDomainSaveMemory(driver, vm, snap->def->file, xml, header, + compressedpath, 0, + QEMU_ASYNC_JOB_SNAPSHOT)) < 0) goto cleanup; /* the memory image was created, remove it on errors */ @@ -14442,6 +14479,7 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn, ret = -1; } + virQEMUSaveDataFree(header); VIR_FREE(xml); VIR_FREE(compressedpath); virObjectUnref(cfg); -- 2.13.1