diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 1f73709d7f761d94e39791ae0330babf7a7789c2..f0ce78bf57ed33578e2c9d0c54046377776a80fb 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -73,6 +73,7 @@ VIR_ENUM_IMPL(qemuDomainAsyncJob, QEMU_ASYNC_JOB_LAST, "save", "dump", "snapshot", + "start", ); @@ -88,6 +89,7 @@ qemuDomainAsyncJobPhaseToString(qemuDomainAsyncJob job, case QEMU_ASYNC_JOB_SAVE: case QEMU_ASYNC_JOB_DUMP: case QEMU_ASYNC_JOB_SNAPSHOT: + case QEMU_ASYNC_JOB_START: case QEMU_ASYNC_JOB_NONE: case QEMU_ASYNC_JOB_LAST: ; /* fall through */ @@ -111,6 +113,7 @@ qemuDomainAsyncJobPhaseFromString(qemuDomainAsyncJob job, case QEMU_ASYNC_JOB_SAVE: case QEMU_ASYNC_JOB_DUMP: case QEMU_ASYNC_JOB_SNAPSHOT: + case QEMU_ASYNC_JOB_START: case QEMU_ASYNC_JOB_NONE: case QEMU_ASYNC_JOB_LAST: ; /* fall through */ diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 90b482d424c3b42970f0c16189837ef6fe4022f0..8b6b1a3e37d598a53ffeb98cb328cd1fcb7800a2 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -90,6 +90,7 @@ typedef enum { QEMU_ASYNC_JOB_SAVE, QEMU_ASYNC_JOB_DUMP, QEMU_ASYNC_JOB_SNAPSHOT, + QEMU_ASYNC_JOB_START, QEMU_ASYNC_JOB_LAST } qemuDomainAsyncJob; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 42f76fa9ea6d6c62e2ce9fb931f62f4863773908..65ccf99986af07aba906f41a988daef40aec4953 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -155,7 +155,8 @@ static int qemuStateCleanup(void); static int qemuDomainObjStart(virConnectPtr conn, virQEMUDriverPtr driver, virDomainObjPtr vm, - unsigned int flags); + unsigned int flags, + qemuDomainAsyncJob asyncJob); static int qemuDomainGetMaxVcpus(virDomainPtr dom); @@ -287,8 +288,7 @@ qemuAutostartDomain(virDomainObjPtr vm, virResetLastError(); if (vm->autostart && !virDomainObjIsActive(vm)) { - if (qemuDomainObjBeginJob(data->driver, vm, - QEMU_JOB_MODIFY) < 0) { + if (qemuProcessBeginJob(data->driver, vm) < 0) { err = virGetLastError(); VIR_ERROR(_("Failed to start job on VM '%s': %s"), vm->def->name, @@ -296,14 +296,15 @@ qemuAutostartDomain(virDomainObjPtr vm, goto cleanup; } - if (qemuDomainObjStart(data->conn, data->driver, vm, flags) < 0) { + if (qemuDomainObjStart(data->conn, data->driver, vm, flags, + QEMU_ASYNC_JOB_START) < 0) { err = virGetLastError(); VIR_ERROR(_("Failed to autostart VM '%s': %s"), vm->def->name, err ? err->message : _("unknown error")); } - qemuDomainObjEndJob(data->driver, vm); + qemuProcessEndJob(data->driver, vm); } ret = 0; @@ -1754,17 +1755,17 @@ static virDomainPtr qemuDomainCreateXML(virConnectPtr conn, virObjectRef(vm); def = NULL; - if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) { + if (qemuProcessBeginJob(driver, vm) < 0) { qemuDomainRemoveInactive(driver, vm); goto cleanup; } - if (qemuProcessStart(conn, driver, vm, QEMU_ASYNC_JOB_NONE, + if (qemuProcessStart(conn, driver, vm, QEMU_ASYNC_JOB_START, NULL, -1, NULL, NULL, VIR_NETDEV_VPORT_PROFILE_OP_CREATE, start_flags) < 0) { virDomainAuditStart(vm, "booted", false); - qemuDomainObjEndJob(driver, vm); + qemuProcessEndJob(driver, vm); qemuDomainRemoveInactive(driver, vm); goto cleanup; } @@ -1788,7 +1789,7 @@ static virDomainPtr qemuDomainCreateXML(virConnectPtr conn, if (dom) dom->id = vm->def->id; - qemuDomainObjEndJob(driver, vm); + qemuProcessEndJob(driver, vm); cleanup: virDomainDefFree(def); @@ -6634,7 +6635,8 @@ qemuDomainSaveImageStartVM(virConnectPtr conn, int *fd, const virQEMUSaveHeader *header, const char *path, - bool start_paused) + bool start_paused, + qemuDomainAsyncJob asyncJob) { int ret = -1; virObjectEventPtr event; @@ -6663,7 +6665,7 @@ qemuDomainSaveImageStartVM(virConnectPtr conn, } /* Set the migration source and start it up. */ - ret = qemuProcessStart(conn, driver, vm, QEMU_ASYNC_JOB_NONE, + ret = qemuProcessStart(conn, driver, vm, asyncJob, "stdio", *fd, path, NULL, VIR_NETDEV_VPORT_PROFILE_OP_RESTORE, VIR_QEMU_PROCESS_START_PAUSED); @@ -6707,7 +6709,7 @@ qemuDomainSaveImageStartVM(virConnectPtr conn, if (header->was_running && !start_paused) { if (qemuProcessStartCPUs(driver, vm, conn, VIR_DOMAIN_RUNNING_RESTORED, - QEMU_ASYNC_JOB_NONE) < 0) { + asyncJob) < 0) { if (virGetLastError() == NULL) virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to resume domain")); @@ -6819,15 +6821,15 @@ qemuDomainRestoreFlags(virConnectPtr conn, priv->hookRun = true; } - if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) + if (qemuProcessBeginJob(driver, vm) < 0) goto cleanup; ret = qemuDomainSaveImageStartVM(conn, driver, vm, &fd, &header, path, - false); + false, QEMU_ASYNC_JOB_START); if (virFileWrapperFdClose(wrapperFd) < 0) VIR_WARN("Failed to close %s", path); - qemuDomainObjEndJob(driver, vm); + qemuProcessEndJob(driver, vm); cleanup: virDomainDefFree(def); @@ -6970,7 +6972,8 @@ qemuDomainObjRestore(virConnectPtr conn, virDomainObjPtr vm, const char *path, bool start_paused, - bool bypass_cache) + bool bypass_cache, + qemuDomainAsyncJob asyncJob) { virDomainDefPtr def = NULL; qemuDomainObjPrivatePtr priv = vm->privateData; @@ -7030,7 +7033,7 @@ qemuDomainObjRestore(virConnectPtr conn, def = NULL; ret = qemuDomainSaveImageStartVM(conn, driver, vm, &fd, &header, path, - start_paused); + start_paused, asyncJob); if (virFileWrapperFdClose(wrapperFd) < 0) VIR_WARN("Failed to close %s", path); @@ -7325,7 +7328,8 @@ static int qemuDomainObjStart(virConnectPtr conn, virQEMUDriverPtr driver, virDomainObjPtr vm, - unsigned int flags) + unsigned int flags, + qemuDomainAsyncJob asyncJob) { int ret = -1; char *managed_save; @@ -7358,7 +7362,7 @@ qemuDomainObjStart(virConnectPtr conn, vm->hasManagedSave = false; } else { ret = qemuDomainObjRestore(conn, driver, vm, managed_save, - start_paused, bypass_cache); + start_paused, bypass_cache, asyncJob); if (ret == 0) { if (unlink(managed_save) < 0) @@ -7377,7 +7381,7 @@ qemuDomainObjStart(virConnectPtr conn, } } - ret = qemuProcessStart(conn, driver, vm, QEMU_ASYNC_JOB_NONE, + ret = qemuProcessStart(conn, driver, vm, asyncJob, NULL, -1, NULL, NULL, VIR_NETDEV_VPORT_PROFILE_OP_CREATE, start_flags); virDomainAuditStart(vm, "booted", ret >= 0); @@ -7422,7 +7426,7 @@ qemuDomainCreateWithFlags(virDomainPtr dom, unsigned int flags) if (virDomainCreateWithFlagsEnsureACL(dom->conn, vm->def) < 0) goto cleanup; - if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) + if (qemuProcessBeginJob(driver, vm) < 0) goto cleanup; if (virDomainObjIsActive(vm)) { @@ -7431,13 +7435,14 @@ qemuDomainCreateWithFlags(virDomainPtr dom, unsigned int flags) goto endjob; } - if (qemuDomainObjStart(dom->conn, driver, vm, flags) < 0) + if (qemuDomainObjStart(dom->conn, driver, vm, flags, + QEMU_ASYNC_JOB_START) < 0) goto endjob; ret = 0; endjob: - qemuDomainObjEndJob(driver, vm); + qemuProcessEndJob(driver, vm); cleanup: virDomainObjEndAPI(&vm); @@ -15334,7 +15339,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, goto cleanup; } - if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) + if (qemuProcessBeginJob(driver, vm) < 0) goto cleanup; if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot))) @@ -15439,7 +15444,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, was_running = true; if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_FROM_SNAPSHOT, - QEMU_ASYNC_JOB_NONE) < 0) + QEMU_ASYNC_JOB_START) < 0) goto endjob; /* Create an event now in case the restore fails, so * that user will be alerted that they are now paused. @@ -15454,7 +15459,10 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, goto endjob; } } - qemuDomainObjEnterMonitor(driver, vm); + + if (qemuDomainObjEnterMonitorAsync(driver, vm, + QEMU_ASYNC_JOB_START) < 0) + goto endjob; rc = qemuMonitorLoadSnapshot(priv->mon, snap->def->name); if (qemuDomainObjExitMonitor(driver, vm) < 0) goto endjob; @@ -15473,7 +15481,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, virDomainObjAssignDef(vm, config, false, NULL); rc = qemuProcessStart(snapshot->domain->conn, driver, vm, - QEMU_ASYNC_JOB_NONE, NULL, -1, NULL, snap, + QEMU_ASYNC_JOB_START, NULL, -1, NULL, snap, VIR_NETDEV_VPORT_PROFILE_OP_CREATE, VIR_QEMU_PROCESS_START_PAUSED); virDomainAuditStart(vm, "from-snapshot", rc >= 0); @@ -15508,7 +15516,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, } rc = qemuProcessStartCPUs(driver, vm, snapshot->domain->conn, VIR_DOMAIN_RUNNING_FROM_SNAPSHOT, - QEMU_ASYNC_JOB_NONE); + QEMU_ASYNC_JOB_START); if (rc < 0) goto endjob; virObjectUnref(event); @@ -15549,7 +15557,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, } if (qemuDomainSnapshotRevertInactive(driver, vm, snap) < 0) { - qemuDomainObjEndJob(driver, vm); + qemuProcessEndJob(driver, vm); qemuDomainRemoveInactive(driver, vm); goto cleanup; } @@ -15566,12 +15574,12 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, qemuDomainEventQueue(driver, event); rc = qemuProcessStart(snapshot->domain->conn, driver, vm, - QEMU_ASYNC_JOB_NONE, NULL, -1, NULL, NULL, + QEMU_ASYNC_JOB_START, NULL, -1, NULL, NULL, VIR_NETDEV_VPORT_PROFILE_OP_CREATE, start_flags); virDomainAuditStart(vm, "from-snapshot", rc >= 0); if (rc < 0) { - qemuDomainObjEndJob(driver, vm); + qemuProcessEndJob(driver, vm); qemuDomainRemoveInactive(driver, vm); goto cleanup; } @@ -15607,7 +15615,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, ret = 0; endjob: - qemuDomainObjEndJob(driver, vm); + qemuProcessEndJob(driver, vm); cleanup: if (ret == 0) { diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 9de7f66ac8c76fbadffad0a7017aa8c44f4ea201..1b20f412f58d7360ffbb89169c4a0f84608c3901 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3412,6 +3412,10 @@ qemuProcessRecoverJob(virQEMUDriverPtr driver, } break; + case QEMU_ASYNC_JOB_START: + /* Already handled in VIR_DOMAIN_PAUSED_STARTING_UP check. */ + break; + case QEMU_ASYNC_JOB_NONE: case QEMU_ASYNC_JOB_LAST: break; @@ -4202,10 +4206,40 @@ qemuProcessIncomingDefNew(virQEMUCapsPtr qemuCaps, } +/* + * This function starts a new QEMU_ASYNC_JOB_START async job. The user is + * responsible for calling qemuProcessEndJob to stop this job and for passing + * QEMU_ASYNC_JOB_START as @asyncJob argument to any function requiring this + * parameter between qemuProcessBeginJob and qemuProcessEndJob. + */ +int +qemuProcessBeginJob(virQEMUDriverPtr driver, + virDomainObjPtr vm) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + + if (qemuDomainObjBeginAsyncJob(driver, vm, QEMU_ASYNC_JOB_START) < 0) + return -1; + + qemuDomainObjSetAsyncJobMask(vm, QEMU_JOB_NONE); + priv->job.current->type = VIR_DOMAIN_JOB_UNBOUNDED; + + return 0; +} + + +void +qemuProcessEndJob(virQEMUDriverPtr driver, + virDomainObjPtr vm) +{ + qemuDomainObjEndAsyncJob(driver, vm); +} + + int qemuProcessStart(virConnectPtr conn, virQEMUDriverPtr driver, virDomainObjPtr vm, - int asyncJob, + qemuDomainAsyncJob asyncJob, const char *migrateFrom, int stdin_fd, const char *stdin_path, diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h index 7eee2b2c79793ff8f24dd20d72de872f5ff3c07a..dcba72816210f6c64a0d89717a1970c905c30ea4 100644 --- a/src/qemu/qemu_process.h +++ b/src/qemu/qemu_process.h @@ -58,6 +58,11 @@ qemuProcessIncomingDefPtr qemuProcessIncomingDefNew(virQEMUCapsPtr qemuCaps, const char *path); void qemuProcessIncomingDefFree(qemuProcessIncomingDefPtr inc); +int qemuProcessBeginJob(virQEMUDriverPtr driver, + virDomainObjPtr vm); +void qemuProcessEndJob(virQEMUDriverPtr driver, + virDomainObjPtr vm); + typedef enum { VIR_QEMU_PROCESS_START_COLD = 1 << 0, VIR_QEMU_PROCESS_START_PAUSED = 1 << 1, @@ -67,7 +72,7 @@ typedef enum { int qemuProcessStart(virConnectPtr conn, virQEMUDriverPtr driver, virDomainObjPtr vm, - int asyncJob, + qemuDomainAsyncJob asyncJob, const char *migrateFrom, int stdin_fd, const char *stdin_path,