[PATCH 0/2] qemu: refresh state after reset

This series implements domain state refreshing after reset from libvirt API and reboot from the guest OS. Kristina Hanicova (2): qemu: refresh state after reset qemu: refresh state after reboot initiated from the guest src/qemu/qemu_domain.c | 1 + src/qemu/qemu_domain.h | 1 + src/qemu/qemu_driver.c | 22 +++++++++++++++++++++- src/qemu/qemu_process.c | 2 ++ 4 files changed, 25 insertions(+), 1 deletion(-) -- 2.38.1

Domain state may change during the reset and qemu does not always send events about it. In case it happens, the state would be inconsistent with the internal state of qemu which could cause additional problems. The solution is to refresh state after a successful reset to query qemu about the current domain state. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1824722 Signed-off-by: Kristina Hanicova <khanicov@redhat.com> --- src/qemu/qemu_driver.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ff5a743716..b2060ee843 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -2000,6 +2000,7 @@ qemuDomainReset(virDomainPtr dom, unsigned int flags) int ret = -1; qemuDomainObjPrivate *priv; virDomainState state; + virQEMUDriver *driver = dom->conn->privateData; virCheckFlags(0, -1); @@ -2023,8 +2024,11 @@ qemuDomainReset(virDomainPtr dom, unsigned int flags) priv->fakeReboot = false; state = virDomainObjGetState(vm, NULL); - if (state == VIR_DOMAIN_CRASHED) + if (state == VIR_DOMAIN_CRASHED) { virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_CRASHED); + } else if (qemuProcessRefreshState(driver, vm, VIR_ASYNC_JOB_NONE) < 0) { + goto cleanup; + } endjob: virDomainObjEndJob(vm); -- 2.38.1

On Wed, Nov 23, 2022 at 02:31:16PM +0100, Kristina Hanicova wrote:
Domain state may change during the reset and qemu does not always send events about it. In case it happens, the state would be inconsistent with the internal state of qemu which could cause additional problems. The solution is to refresh state after a successful reset to query qemu about the current domain state.
I had to look in the BZ and RefreshState to figure out you did not actually mean the state (paused, running, crashed) but rather the internal state of the domain.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1824722
Signed-off-by: Kristina Hanicova <khanicov@redhat.com> --- src/qemu/qemu_driver.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ff5a743716..b2060ee843 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -2000,6 +2000,7 @@ qemuDomainReset(virDomainPtr dom, unsigned int flags) int ret = -1; qemuDomainObjPrivate *priv; virDomainState state; + virQEMUDriver *driver = dom->conn->privateData;
virCheckFlags(0, -1);
@@ -2023,8 +2024,11 @@ qemuDomainReset(virDomainPtr dom, unsigned int flags) priv->fakeReboot = false;
state = virDomainObjGetState(vm, NULL); - if (state == VIR_DOMAIN_CRASHED) + if (state == VIR_DOMAIN_CRASHED) { virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_CRASHED); + } else if (qemuProcessRefreshState(driver, vm, VIR_ASYNC_JOB_NONE) < 0) { + goto cleanup;
You need to goto endjob here, otherwise the job will not end. Could we not call this unconditionally, even for the crashed domain? Especially when we do not refresh the state when resuming the domain afterwards?
+ }
endjob: virDomainObjEndJob(vm); -- 2.38.1

Domain state needs to be refreshed after reset from the guest side because it may be inconsistent with the internal qemu state. Signed-off-by: Kristina Hanicova <khanicov@redhat.com> --- src/qemu/qemu_domain.c | 1 + src/qemu/qemu_domain.h | 1 + src/qemu/qemu_driver.c | 16 ++++++++++++++++ src/qemu/qemu_process.c | 2 ++ 4 files changed, 20 insertions(+) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 8ae458ae45..02d759876a 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -11159,6 +11159,7 @@ qemuProcessEventFree(struct qemuProcessEvent *event) break; case QEMU_PROCESS_EVENT_PR_DISCONNECT: case QEMU_PROCESS_EVENT_UNATTENDED_MIGRATION: + case QEMU_PROCESS_EVENT_RESET: case QEMU_PROCESS_EVENT_LAST: break; } diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index a9af8502d2..2f027fad87 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -448,6 +448,7 @@ typedef enum { QEMU_PROCESS_EVENT_GUEST_CRASHLOADED, QEMU_PROCESS_EVENT_MEMORY_DEVICE_SIZE_CHANGE, QEMU_PROCESS_EVENT_UNATTENDED_MIGRATION, + QEMU_PROCESS_EVENT_RESET, QEMU_PROCESS_EVENT_LAST } qemuProcessEventType; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index b2060ee843..070a623c43 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3923,6 +3923,19 @@ processMemoryDeviceSizeChange(virQEMUDriver *driver, } +static void +processResetEvent(virQEMUDriver *driver, + virDomainObj *vm) +{ + if (virDomainObjBeginJob(vm, VIR_JOB_MODIFY) < 0) + return; + + qemuProcessRefreshState(driver, vm, VIR_ASYNC_JOB_NONE); + + virDomainObjEndJob(vm); +} + + static void qemuProcessEventHandler(void *data, void *opaque) { struct qemuProcessEvent *processEvent = data; @@ -3974,6 +3987,9 @@ static void qemuProcessEventHandler(void *data, void *opaque) processEvent->action, processEvent->status); break; + case QEMU_PROCESS_EVENT_RESET: + processResetEvent(driver, vm); + break; case QEMU_PROCESS_EVENT_LAST: break; } diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index e1c18dde90..2ce6dc79ba 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -432,6 +432,8 @@ qemuProcessHandleReset(qemuMonitor *mon G_GNUC_UNUSED, qemuDomainSetFakeReboot(vm, false); qemuDomainSaveStatus(vm); + qemuProcessEventSubmit(vm, QEMU_PROCESS_EVENT_RESET, 0, 0, NULL); + unlock: virObjectUnlock(vm); virObjectEventStateQueue(driver->domainEventState, event); -- 2.38.1
participants (2)
-
Kristina Hanicova
-
Martin Kletzander