Signed-off-by: Jim Fehlig <jfehlig@xxxxxxxx> --- src/qemu/qemu_driver.c | 22 +++++++++++++--------- src/qemu/qemu_migration.c | 2 +- src/qemu/qemu_process.c | 20 ++++++++++++++++---- src/qemu/qemu_process.h | 3 +++ src/qemu/qemu_saveimage.c | 29 +++++++++++++++++++++++++---- src/qemu/qemu_saveimage.h | 4 +++- src/qemu/qemu_snapshot.c | 8 ++++---- 7 files changed, 65 insertions(+), 23 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 34f37210d9..53674458bf 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1624,7 +1624,7 @@ static virDomainPtr qemuDomainCreateXML(virConnectPtr conn, } if (qemuProcessStart(conn, driver, vm, NULL, VIR_ASYNC_JOB_START, - NULL, -1, NULL, NULL, + NULL, -1, -1, NULL, NULL, VIR_NETDEV_VPORT_PROFILE_OP_CREATE, start_flags) < 0) { virDomainAuditStart(vm, "booted", false); @@ -5742,6 +5742,7 @@ qemuDomainRestoreInternal(virConnectPtr conn, g_autofree char *xmlout = NULL; const char *newxml = dxml; int fd = -1; + int nondirectFd = -1; int ret = -1; virQEMUSaveData *data = NULL; virFileWrapperFd *wrapperFd = NULL; @@ -5758,7 +5759,7 @@ qemuDomainRestoreInternal(virConnectPtr conn, fd = qemuSaveImageOpen(driver, NULL, path, &def, &data, (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0, - &wrapperFd, false, false); + &wrapperFd, &nondirectFd, false, false); if (fd < 0) goto cleanup; @@ -5812,13 +5813,14 @@ qemuDomainRestoreInternal(virConnectPtr conn, if (qemuProcessBeginJob(vm, VIR_DOMAIN_JOB_OPERATION_RESTORE, flags) < 0) goto cleanup; - ret = qemuSaveImageStartVM(conn, driver, vm, &fd, data, path, + ret = qemuSaveImageStartVM(conn, driver, vm, &fd, nondirectFd, data, path, false, reset_nvram, VIR_ASYNC_JOB_START); qemuProcessEndJob(vm); cleanup: VIR_FORCE_CLOSE(fd); + VIR_FORCE_CLOSE(nondirectFd); if (virFileWrapperFdClose(wrapperFd) < 0) ret = -1; virFileWrapperFdFree(wrapperFd); @@ -5893,7 +5895,7 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path, virCheckFlags(VIR_DOMAIN_SAVE_IMAGE_XML_SECURE, NULL); fd = qemuSaveImageOpen(driver, NULL, path, &def, &data, - false, NULL, false, false); + false, NULL, NULL, false, false); if (fd < 0) goto cleanup; @@ -5930,7 +5932,7 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path, state = 0; fd = qemuSaveImageOpen(driver, NULL, path, &def, &data, - false, NULL, true, false); + false, NULL, NULL, true, false); if (fd < 0) goto cleanup; @@ -6011,7 +6013,7 @@ qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom, unsigned int flags) } if ((fd = qemuSaveImageOpen(driver, priv->qemuCaps, path, &def, &data, - false, NULL, false, false)) < 0) + false, NULL, NULL, false, false)) < 0) goto cleanup; ret = qemuDomainDefFormatXML(driver, priv->qemuCaps, def, flags); @@ -6069,13 +6071,14 @@ qemuDomainObjRestore(virConnectPtr conn, g_autoptr(virDomainDef) def = NULL; qemuDomainObjPrivate *priv = vm->privateData; int fd = -1; + int nondirectFd = -1; int ret = -1; g_autofree char *xmlout = NULL; virQEMUSaveData *data = NULL; virFileWrapperFd *wrapperFd = NULL; fd = qemuSaveImageOpen(driver, NULL, path, &def, &data, - bypass_cache, &wrapperFd, false, true); + bypass_cache, &wrapperFd, &nondirectFd, false, true); if (fd < 0) { if (fd == -3) ret = 1; @@ -6120,12 +6123,13 @@ qemuDomainObjRestore(virConnectPtr conn, virDomainObjAssignDef(vm, &def, true, NULL); - ret = qemuSaveImageStartVM(conn, driver, vm, &fd, data, path, + ret = qemuSaveImageStartVM(conn, driver, vm, &fd, nondirectFd, data, path, start_paused, reset_nvram, asyncJob); cleanup: virQEMUSaveDataFree(data); VIR_FORCE_CLOSE(fd); + VIR_FORCE_CLOSE(nondirectFd); if (virFileWrapperFdClose(wrapperFd) < 0) ret = -1; virFileWrapperFdFree(wrapperFd); @@ -6321,7 +6325,7 @@ qemuDomainObjStart(virConnectPtr conn, } ret = qemuProcessStart(conn, driver, vm, NULL, asyncJob, - NULL, -1, NULL, NULL, + NULL, -1, -1, NULL, NULL, VIR_NETDEV_VPORT_PROFILE_OP_CREATE, start_flags); virDomainAuditStart(vm, "booted", ret >= 0); if (ret >= 0) { diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index a0435a0572..0b1e03394e 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -3009,7 +3009,7 @@ qemuMigrationDstPrepare(virDomainObj *vm, } return qemuProcessIncomingDefNew(vm, listenAddress, - migrateFrom, fd, NULL, 0); + migrateFrom, fd, -1, NULL, 0); } diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index f700390a8c..f5b2f9ea2b 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4688,6 +4688,7 @@ qemuProcessIncomingDefNew(virDomainObj *vm, const char *listenAddress, const char *migrateFrom, int fd, + int nondirectFd, const char *path, unsigned int flags) { @@ -4707,11 +4708,18 @@ qemuProcessIncomingDefNew(virDomainObj *vm, unsigned int fdsetId; off_t offset; - if ((offset = lseek(fd, 0, SEEK_CUR)) == -1) - offset = 0; + if (nondirectFd == -1) + offset = lseek(fd, 0, SEEK_CUR); + else + offset = lseek(nondirectFd, 0, SEEK_CUR); + + if (offset < 0) + goto error; inc->fdPassMigrate = qemuFDPassNew("migrate", priv); qemuFDPassAddFD(inc->fdPassMigrate, &fd, "-fd"); + if (nondirectFd != -1) + qemuFDPassAddFD(inc->fdPassMigrate, &nondirectFd, "-nondirect-fd"); qemuFDPassGetId(inc->fdPassMigrate, &fdsetId); inc->uri = g_strdup_printf("file:/dev/fdset/%u,offset=%#lx", fdsetId, offset); } else { @@ -8148,6 +8156,7 @@ qemuProcessStart(virConnectPtr conn, virDomainAsyncJob asyncJob, const char *migrateFrom, int migrateFd, + int migrateNondirectFd, const char *migratePath, virDomainMomentObj *snapshot, virNetDevVPortProfileOp vmop, @@ -8185,7 +8194,8 @@ qemuProcessStart(virConnectPtr conn, if (migrateFrom) { incoming = qemuProcessIncomingDefNew(vm, NULL, migrateFrom, - migrateFd, migratePath, flags); + migrateFd, migrateNondirectFd, + migratePath, flags); if (!incoming) goto stop; } @@ -8264,6 +8274,7 @@ qemuProcessStart(virConnectPtr conn, * @driver: qemu driver object * @vm: domain object * @fd: FD pointer of memory state file + * @nondirectFd: FD for memory state file, opened without O_DIRECT * @path: path to memory state file * @snapshot: internal snapshot to load when starting QEMU process or NULL * @data: data from memory state file or NULL @@ -8290,6 +8301,7 @@ qemuProcessStartWithMemoryState(virConnectPtr conn, virQEMUDriver *driver, virDomainObj *vm, int *fd, + int nondirectFd, const char *path, virDomainMomentObj *snapshot, virQEMUSaveData *data, @@ -8329,7 +8341,7 @@ qemuProcessStartWithMemoryState(virConnectPtr conn, priv->disableSlirp = true; if (qemuProcessStart(conn, driver, vm, cookie ? cookie->cpu : NULL, - asyncJob, migrateFrom, *fd, path, snapshot, + asyncJob, migrateFrom, *fd, nondirectFd, path, snapshot, VIR_NETDEV_VPORT_PROFILE_OP_RESTORE, start_flags) == 0) *started = true; diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h index a5212ee56e..6e37dac2ca 100644 --- a/src/qemu/qemu_process.h +++ b/src/qemu/qemu_process.h @@ -62,6 +62,7 @@ qemuProcessIncomingDef *qemuProcessIncomingDefNew(virDomainObj *vm, const char *listenAddress, const char *migrateFrom, int fd, + int nondirectFd, const char *path, unsigned int flags); void qemuProcessIncomingDefFree(qemuProcessIncomingDef *inc); @@ -89,6 +90,7 @@ int qemuProcessStart(virConnectPtr conn, virDomainAsyncJob asyncJob, const char *migrateFrom, int stdin_fd, + int nondirectFd, const char *stdin_path, virDomainMomentObj *snapshot, virNetDevVPortProfileOp vmop, @@ -98,6 +100,7 @@ int qemuProcessStartWithMemoryState(virConnectPtr conn, virQEMUDriver *driver, virDomainObj *vm, int *fd, + int nondirectFd, const char *path, virDomainMomentObj *snapshot, virQEMUSaveData *data, diff --git a/src/qemu/qemu_saveimage.c b/src/qemu/qemu_saveimage.c index 2b0281895a..8e634862a6 100644 --- a/src/qemu/qemu_saveimage.c +++ b/src/qemu/qemu_saveimage.c @@ -610,6 +610,7 @@ qemuSaveImageGetCompressionProgram(const char *imageFormat, * @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 + * @nondirectFd: returns file descriptor without O_DIRECT set * @open_write: open the file for writing (for updates) * @unlink_corrupt: remove the image file if it is corrupted * @@ -625,11 +626,14 @@ qemuSaveImageOpen(virQEMUDriver *driver, virQEMUSaveData **ret_data, bool bypass_cache, virFileWrapperFd **wrapperFd, + int *nondirectFd, bool open_write, bool unlink_corrupt) { g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); VIR_AUTOCLOSE fd = -1; + VIR_AUTOCLOSE nondirect_fd = -1; + int read_fd; int ret = -1; g_autoptr(virQEMUSaveData) data = NULL; virQEMUSaveHeader *header; @@ -646,6 +650,13 @@ qemuSaveImageOpen(virQEMUDriver *driver, _("bypass cache unsupported by this system")); return -1; } + + /* Also open the file without O_DIRECT for reading header and for + * qemu to use when reading unaligned state + */ + if ((nondirect_fd = qemuDomainOpenFile(cfg, NULL, path, oflags, NULL)) < 0) + return -1; + oflags |= directFlag; } @@ -655,7 +666,12 @@ qemuSaveImageOpen(virQEMUDriver *driver, data = g_new0(virQEMUSaveData, 1); header = &data->header; - if (saferead(fd, header, sizeof(*header)) != sizeof(*header)) { + if (nondirect_fd != -1) + read_fd = nondirect_fd; + else + read_fd = fd; + + if (saferead(read_fd, header, sizeof(*header)) != sizeof(*header)) { if (unlink_corrupt) { if (unlink(path) < 0) { virReportSystemError(errno, @@ -732,7 +748,7 @@ qemuSaveImageOpen(virQEMUDriver *driver, data->xml = g_new0(char, xml_len); - if (saferead(fd, data->xml, xml_len) != xml_len) { + if (saferead(read_fd, data->xml, xml_len) != xml_len) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to read domain XML")); return -1; @@ -741,7 +757,7 @@ qemuSaveImageOpen(virQEMUDriver *driver, if (cookie_len > 0) { data->cookie = g_new0(char, cookie_len); - if (saferead(fd, data->cookie, cookie_len) != cookie_len) { + if (saferead(read_fd, data->cookie, cookie_len) != cookie_len) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to read cookie")); return -1; @@ -761,6 +777,10 @@ qemuSaveImageOpen(virQEMUDriver *driver, *ret_def = g_steal_pointer(&def); *ret_data = g_steal_pointer(&data); + if (nondirectFd) { + *nondirectFd = nondirect_fd; + nondirect_fd = -1; + } ret = fd; fd = -1; @@ -774,6 +794,7 @@ qemuSaveImageStartVM(virConnectPtr conn, virQEMUDriver *driver, virDomainObj *vm, int *fd, + int nondirectFd, virQEMUSaveData *data, const char *path, bool start_paused, @@ -794,7 +815,7 @@ qemuSaveImageStartVM(virConnectPtr conn, if (header->features & QEMU_SAVE_FEATURE_MAPPED_RAM) start_flags |= VIR_QEMU_PROCESS_START_MAPPED_RAM; - if (qemuProcessStartWithMemoryState(conn, driver, vm, fd, path, NULL, data, + if (qemuProcessStartWithMemoryState(conn, driver, vm, fd, nondirectFd, path, NULL, data, asyncJob, start_flags, "restored", &started) < 0) { goto cleanup; diff --git a/src/qemu/qemu_saveimage.h b/src/qemu/qemu_saveimage.h index 81d93bf33c..0a8b35158a 100644 --- a/src/qemu/qemu_saveimage.h +++ b/src/qemu/qemu_saveimage.h @@ -67,12 +67,13 @@ qemuSaveImageStartVM(virConnectPtr conn, virQEMUDriver *driver, virDomainObj *vm, int *fd, + int nondirectFd, virQEMUSaveData *data, const char *path, bool start_paused, bool reset_nvram, virDomainAsyncJob asyncJob) - ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5) ATTRIBUTE_NONNULL(6); + ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(6) ATTRIBUTE_NONNULL(7); int qemuSaveImageOpen(virQEMUDriver *driver, @@ -82,6 +83,7 @@ qemuSaveImageOpen(virQEMUDriver *driver, virQEMUSaveData **ret_data, bool bypass_cache, virFileWrapperFd **wrapperFd, + int *nondirectFd, bool open_write, bool unlink_corrupt) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index 1e9e0e31d7..f137a79a8d 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -2115,7 +2115,7 @@ qemuSnapshotRevertExternalPrepare(virDomainObj *vm, memdata->path = snapdef->memorysnapshotfile; memdata->fd = qemuSaveImageOpen(driver, NULL, memdata->path, &savedef, &memdata->data, - false, NULL, + false, NULL, NULL, false, false); if (memdata->fd < 0) @@ -2359,7 +2359,7 @@ qemuSnapshotRevertActive(virDomainObj *vm, virDomainObjAssignDef(vm, config, true, NULL); if (qemuProcessStartWithMemoryState(snapshot->domain->conn, driver, vm, - &memdata.fd, memdata.path, loadSnap, + &memdata.fd, -1, memdata.path, loadSnap, memdata.data, VIR_ASYNC_JOB_SNAPSHOT, start_flags, "from-snapshot", &started) < 0) { @@ -2513,7 +2513,7 @@ qemuSnapshotRevertInactive(virDomainObj *vm, start_flags |= paused ? VIR_QEMU_PROCESS_START_PAUSED : 0; rc = qemuProcessStart(snapshot->domain->conn, driver, vm, NULL, - VIR_ASYNC_JOB_SNAPSHOT, NULL, -1, NULL, NULL, + VIR_ASYNC_JOB_SNAPSHOT, NULL, -1, -1, NULL, NULL, VIR_NETDEV_VPORT_PROFILE_OP_CREATE, start_flags); virDomainAuditStart(vm, "from-snapshot", rc >= 0); @@ -2991,7 +2991,7 @@ qemuSnapshotDeleteExternalPrepare(virDomainObj *vm, if (!virDomainObjIsActive(vm)) { if (qemuProcessStart(NULL, driver, vm, NULL, VIR_ASYNC_JOB_SNAPSHOT, - NULL, -1, NULL, NULL, + NULL, -1, -1, NULL, NULL, VIR_NETDEV_VPORT_PROFILE_OP_CREATE, VIR_QEMU_PROCESS_START_PAUSED) < 0) { return -1; -- 2.44.0