diff --git a/examples/c/misc/event-test.c b/examples/c/misc/event-test.c index 7e48cecc92..52caa8ffa8 100644 --- a/examples/c/misc/event-test.c +++ b/examples/c/misc/event-test.c @@ -273,6 +273,9 @@ eventDetailToString(int event, case VIR_DOMAIN_EVENT_CRASHED_PANICKED: return "Panicked"; + case VIR_DOMAIN_EVENT_CRASHED_CRASHLOADED: + return "Crashloaded"; + case VIR_DOMAIN_EVENT_CRASHED_LAST: break; } diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 5846e93d98..b440818ec2 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -3175,6 +3175,7 @@ typedef enum { */ typedef enum { VIR_DOMAIN_EVENT_CRASHED_PANICKED = 0, /* Guest was panicked */ + VIR_DOMAIN_EVENT_CRASHED_CRASHLOADED = 1, /* Guest was crashloaded */ # ifdef VIR_ENUM_SENTINELS VIR_DOMAIN_EVENT_CRASHED_LAST diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 1b4825a539..6fc0bd4e68 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -16375,6 +16375,7 @@ qemuProcessEventFree(struct qemuProcessEvent *event) case QEMU_PROCESS_EVENT_SERIAL_CHANGED: case QEMU_PROCESS_EVENT_BLOCK_JOB: case QEMU_PROCESS_EVENT_MONITOR_EOF: + case QEMU_PROCESS_EVENT_GUEST_CRASHLOADED: VIR_FREE(event->data); break; case QEMU_PROCESS_EVENT_JOB_STATUS_CHANGE: diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index c581b3a162..f8fb48f2ff 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -583,6 +583,7 @@ typedef enum { QEMU_PROCESS_EVENT_MONITOR_EOF, QEMU_PROCESS_EVENT_PR_DISCONNECT, QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED, + QEMU_PROCESS_EVENT_GUEST_CRASHLOADED, QEMU_PROCESS_EVENT_LAST } qemuProcessEventType; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 502f4ce342..e69d083836 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4876,6 +4876,20 @@ processRdmaGidStatusChangedEvent(virDomainObjPtr vm, } +static void +processGuestCrashloadedEvent(virQEMUDriverPtr driver, + virDomainObjPtr vm) +{ + virObjectEventPtr event = NULL; + + event = virDomainEventLifecycleNewFromObj(vm, + VIR_DOMAIN_EVENT_CRASHED, + VIR_DOMAIN_EVENT_CRASHED_CRASHLOADED); + + virObjectEventStateQueue(driver->domainEventState, event); +} + + static void qemuProcessEventHandler(void *data, void *opaque) { struct qemuProcessEvent *processEvent = data; @@ -4922,6 +4936,9 @@ static void qemuProcessEventHandler(void *data, void *opaque) case QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED: processRdmaGidStatusChangedEvent(vm, processEvent->data); break; + case QEMU_PROCESS_EVENT_GUEST_CRASHLOADED: + processGuestCrashloadedEvent(driver, vm); + break; case QEMU_PROCESS_EVENT_LAST: break; } diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index ceedcd527a..ba70d01d47 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -1590,6 +1590,16 @@ qemuMonitorEmitRdmaGidStatusChanged(qemuMonitorPtr mon, } +int +qemuMonitorEmitGuestCrashloaded(qemuMonitorPtr mon) +{ + int ret = -1; + VIR_DEBUG("mon=%p", mon); + QEMU_MONITOR_CALLBACK(mon, ret, domainGuestCrashloaded, mon->vm); + return ret; +} + + int qemuMonitorSetCapabilities(qemuMonitorPtr mon) { diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index cca2cdcb27..89197cfe0d 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -345,6 +345,10 @@ typedef int (*qemuMonitorDomainRdmaGidStatusChangedCallback)(qemuMonitorPtr mon, unsigned long long interface_id, void *opaque); +typedef int (*qemuMonitorDomainGuestCrashloadedCallback)(qemuMonitorPtr mon, + virDomainObjPtr vm, + void *opaque); + typedef struct _qemuMonitorCallbacks qemuMonitorCallbacks; typedef qemuMonitorCallbacks *qemuMonitorCallbacksPtr; struct _qemuMonitorCallbacks { @@ -380,6 +384,7 @@ struct _qemuMonitorCallbacks { qemuMonitorDomainDumpCompletedCallback domainDumpCompleted; qemuMonitorDomainPRManagerStatusChangedCallback domainPRManagerStatusChanged; qemuMonitorDomainRdmaGidStatusChangedCallback domainRdmaGidStatusChanged; + qemuMonitorDomainGuestCrashloadedCallback domainGuestCrashloaded; }; qemuMonitorPtr qemuMonitorOpen(virDomainObjPtr vm, @@ -512,6 +517,8 @@ int qemuMonitorEmitRdmaGidStatusChanged(qemuMonitorPtr mon, unsigned long long subnet_prefix, unsigned long long interface_id); +int qemuMonitorEmitGuestCrashloaded(qemuMonitorPtr mon); + int qemuMonitorStartCPUs(qemuMonitorPtr mon); int qemuMonitorStopCPUs(qemuMonitorPtr mon); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index dc1fc310ca..5defd29f3b 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -99,6 +99,7 @@ static void qemuMonitorJSONHandleBlockJobReady(qemuMonitorPtr mon, virJSONValueP static void qemuMonitorJSONHandleJobStatusChange(qemuMonitorPtr mon, virJSONValuePtr data); static void qemuMonitorJSONHandleBalloonChange(qemuMonitorPtr mon, virJSONValuePtr data); static void qemuMonitorJSONHandlePMSuspendDisk(qemuMonitorPtr mon, virJSONValuePtr data); +static void qemuMonitorJSONHandleGuestCrashloaded(qemuMonitorPtr mon, virJSONValuePtr data); static void qemuMonitorJSONHandleGuestPanic(qemuMonitorPtr mon, virJSONValuePtr data); static void qemuMonitorJSONHandleDeviceDeleted(qemuMonitorPtr mon, virJSONValuePtr data); static void qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitorPtr mon, virJSONValuePtr data); @@ -128,6 +129,7 @@ static qemuEventHandler eventHandlers[] = { { "DEVICE_DELETED", qemuMonitorJSONHandleDeviceDeleted, }, { "DEVICE_TRAY_MOVED", qemuMonitorJSONHandleTrayChange, }, { "DUMP_COMPLETED", qemuMonitorJSONHandleDumpCompleted, }, + { "GUEST_CRASHLOADED", qemuMonitorJSONHandleGuestCrashloaded, }, { "GUEST_PANICKED", qemuMonitorJSONHandleGuestPanic, }, { "JOB_STATUS_CHANGE", qemuMonitorJSONHandleJobStatusChange, }, { "MIGRATION", qemuMonitorJSONHandleMigrationStatus, }, @@ -1543,6 +1545,16 @@ static void qemuMonitorJSONHandleRdmaGidStatusChanged(qemuMonitorPtr mon, } +static void +qemuMonitorJSONHandleGuestCrashloaded(qemuMonitorPtr mon, + virJSONValuePtr data) +{ + VIR_DEBUG("qemuMonitorJSONHandleGuestCrashloaded event, mon %p, data %p", mon, data); + + qemuMonitorEmitGuestCrashloaded(mon); +} + + int qemuMonitorJSONHumanCommand(qemuMonitorPtr mon, const char *cmd_str, diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index e3df75d281..bf987a3bc3 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -1848,6 +1848,35 @@ qemuProcessHandleRdmaGidStatusChanged(qemuMonitorPtr mon G_GNUC_UNUSED, } +static int +qemuProcessHandleGuestCrashloaded(qemuMonitorPtr mon G_GNUC_UNUSED, + virDomainObjPtr vm, + void *opaque) +{ + virQEMUDriverPtr driver = opaque; + struct qemuProcessEvent *processEvent; + + virObjectLock(vm); + if (VIR_ALLOC(processEvent) < 0) + goto cleanup; + + processEvent->eventType = QEMU_PROCESS_EVENT_GUEST_CRASHLOADED; + processEvent->vm = virObjectRef(vm); + + if (virThreadPoolSendJob(driver->workerPool, 0, processEvent) < 0) { + if (!virObjectUnref(vm)) + vm = NULL; + qemuProcessEventFree(processEvent); + } + + cleanup: + if (vm) + virObjectUnlock(vm); + + return 0; +} + + static qemuMonitorCallbacks monitorCallbacks = { .eofNotify = qemuProcessHandleMonitorEOF, .errorNotify = qemuProcessHandleMonitorError, @@ -1879,6 +1908,7 @@ static qemuMonitorCallbacks monitorCallbacks = { .domainDumpCompleted = qemuProcessHandleDumpCompleted, .domainPRManagerStatusChanged = qemuProcessHandlePRManagerStatusChanged, .domainRdmaGidStatusChanged = qemuProcessHandleRdmaGidStatusChanged, + .domainGuestCrashloaded = qemuProcessHandleGuestCrashloaded, }; static void diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 781463f0e2..91bf280f8e 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -12910,7 +12910,8 @@ VIR_ENUM_IMPL(virshDomainEventPMSuspended, VIR_ENUM_DECL(virshDomainEventCrashed); VIR_ENUM_IMPL(virshDomainEventCrashed, VIR_DOMAIN_EVENT_CRASHED_LAST, - N_("Panicked")); + N_("Panicked"), + N_("Crashloaded")); static const char * virshDomainEventDetailToString(int event, int detail)