mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
qemu: support Panic Crashloaded event handling
Pvpanic device supports bit 1 as crashloaded event, it means that guest actually panicked and run kexec to handle error by guest side. Handle crashloaded as a lifecyle event in libvirt. Test case: Guest side: before testing, we need make sure kdump is enabled, 1, build new pvpanic driver (with commit from upstream e0b9a42735f2672ca2764cfbea6e55a81098d5ba 191941692a3d1b6a9614502b279be062926b70f5) 2, insmod new kmod 3, enable crash_kexec_post_notifiers, # echo 1 > /sys/module/kernel/parameters/crash_kexec_post_notifiers 4, trigger kernel panic # echo 1 > /proc/sys/kernel/sysrq # echo c > /proc/sysrq-trigger Host side: 1, build new qemu with pvpanic patches (with commit from upstream 600d7b47e8f5085919fd1d1157f25950ea8dbc11 7dc58deea79a343ac3adc5cadb97215086054c86) 2, build libvirt with this patch 3, handle lifecycle event and trigger guest side panic # virsh event stretch --event lifecycle event 'lifecycle' for domain stretch: Crashed Crashloaded events received: 1 Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
This commit is contained in:
parent
039787c71a
commit
26badd13e8
@ -273,6 +273,9 @@ eventDetailToString(int event,
|
|||||||
case VIR_DOMAIN_EVENT_CRASHED_PANICKED:
|
case VIR_DOMAIN_EVENT_CRASHED_PANICKED:
|
||||||
return "Panicked";
|
return "Panicked";
|
||||||
|
|
||||||
|
case VIR_DOMAIN_EVENT_CRASHED_CRASHLOADED:
|
||||||
|
return "Crashloaded";
|
||||||
|
|
||||||
case VIR_DOMAIN_EVENT_CRASHED_LAST:
|
case VIR_DOMAIN_EVENT_CRASHED_LAST:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3175,6 +3175,7 @@ typedef enum {
|
|||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
VIR_DOMAIN_EVENT_CRASHED_PANICKED = 0, /* Guest was panicked */
|
VIR_DOMAIN_EVENT_CRASHED_PANICKED = 0, /* Guest was panicked */
|
||||||
|
VIR_DOMAIN_EVENT_CRASHED_CRASHLOADED = 1, /* Guest was crashloaded */
|
||||||
|
|
||||||
# ifdef VIR_ENUM_SENTINELS
|
# ifdef VIR_ENUM_SENTINELS
|
||||||
VIR_DOMAIN_EVENT_CRASHED_LAST
|
VIR_DOMAIN_EVENT_CRASHED_LAST
|
||||||
|
@ -16375,6 +16375,7 @@ qemuProcessEventFree(struct qemuProcessEvent *event)
|
|||||||
case QEMU_PROCESS_EVENT_SERIAL_CHANGED:
|
case QEMU_PROCESS_EVENT_SERIAL_CHANGED:
|
||||||
case QEMU_PROCESS_EVENT_BLOCK_JOB:
|
case QEMU_PROCESS_EVENT_BLOCK_JOB:
|
||||||
case QEMU_PROCESS_EVENT_MONITOR_EOF:
|
case QEMU_PROCESS_EVENT_MONITOR_EOF:
|
||||||
|
case QEMU_PROCESS_EVENT_GUEST_CRASHLOADED:
|
||||||
VIR_FREE(event->data);
|
VIR_FREE(event->data);
|
||||||
break;
|
break;
|
||||||
case QEMU_PROCESS_EVENT_JOB_STATUS_CHANGE:
|
case QEMU_PROCESS_EVENT_JOB_STATUS_CHANGE:
|
||||||
|
@ -583,6 +583,7 @@ typedef enum {
|
|||||||
QEMU_PROCESS_EVENT_MONITOR_EOF,
|
QEMU_PROCESS_EVENT_MONITOR_EOF,
|
||||||
QEMU_PROCESS_EVENT_PR_DISCONNECT,
|
QEMU_PROCESS_EVENT_PR_DISCONNECT,
|
||||||
QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED,
|
QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED,
|
||||||
|
QEMU_PROCESS_EVENT_GUEST_CRASHLOADED,
|
||||||
|
|
||||||
QEMU_PROCESS_EVENT_LAST
|
QEMU_PROCESS_EVENT_LAST
|
||||||
} qemuProcessEventType;
|
} qemuProcessEventType;
|
||||||
|
@ -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)
|
static void qemuProcessEventHandler(void *data, void *opaque)
|
||||||
{
|
{
|
||||||
struct qemuProcessEvent *processEvent = data;
|
struct qemuProcessEvent *processEvent = data;
|
||||||
@ -4922,6 +4936,9 @@ static void qemuProcessEventHandler(void *data, void *opaque)
|
|||||||
case QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED:
|
case QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED:
|
||||||
processRdmaGidStatusChangedEvent(vm, processEvent->data);
|
processRdmaGidStatusChangedEvent(vm, processEvent->data);
|
||||||
break;
|
break;
|
||||||
|
case QEMU_PROCESS_EVENT_GUEST_CRASHLOADED:
|
||||||
|
processGuestCrashloadedEvent(driver, vm);
|
||||||
|
break;
|
||||||
case QEMU_PROCESS_EVENT_LAST:
|
case QEMU_PROCESS_EVENT_LAST:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -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
|
int
|
||||||
qemuMonitorSetCapabilities(qemuMonitorPtr mon)
|
qemuMonitorSetCapabilities(qemuMonitorPtr mon)
|
||||||
{
|
{
|
||||||
|
@ -345,6 +345,10 @@ typedef int (*qemuMonitorDomainRdmaGidStatusChangedCallback)(qemuMonitorPtr mon,
|
|||||||
unsigned long long interface_id,
|
unsigned long long interface_id,
|
||||||
void *opaque);
|
void *opaque);
|
||||||
|
|
||||||
|
typedef int (*qemuMonitorDomainGuestCrashloadedCallback)(qemuMonitorPtr mon,
|
||||||
|
virDomainObjPtr vm,
|
||||||
|
void *opaque);
|
||||||
|
|
||||||
typedef struct _qemuMonitorCallbacks qemuMonitorCallbacks;
|
typedef struct _qemuMonitorCallbacks qemuMonitorCallbacks;
|
||||||
typedef qemuMonitorCallbacks *qemuMonitorCallbacksPtr;
|
typedef qemuMonitorCallbacks *qemuMonitorCallbacksPtr;
|
||||||
struct _qemuMonitorCallbacks {
|
struct _qemuMonitorCallbacks {
|
||||||
@ -380,6 +384,7 @@ struct _qemuMonitorCallbacks {
|
|||||||
qemuMonitorDomainDumpCompletedCallback domainDumpCompleted;
|
qemuMonitorDomainDumpCompletedCallback domainDumpCompleted;
|
||||||
qemuMonitorDomainPRManagerStatusChangedCallback domainPRManagerStatusChanged;
|
qemuMonitorDomainPRManagerStatusChangedCallback domainPRManagerStatusChanged;
|
||||||
qemuMonitorDomainRdmaGidStatusChangedCallback domainRdmaGidStatusChanged;
|
qemuMonitorDomainRdmaGidStatusChangedCallback domainRdmaGidStatusChanged;
|
||||||
|
qemuMonitorDomainGuestCrashloadedCallback domainGuestCrashloaded;
|
||||||
};
|
};
|
||||||
|
|
||||||
qemuMonitorPtr qemuMonitorOpen(virDomainObjPtr vm,
|
qemuMonitorPtr qemuMonitorOpen(virDomainObjPtr vm,
|
||||||
@ -512,6 +517,8 @@ int qemuMonitorEmitRdmaGidStatusChanged(qemuMonitorPtr mon,
|
|||||||
unsigned long long subnet_prefix,
|
unsigned long long subnet_prefix,
|
||||||
unsigned long long interface_id);
|
unsigned long long interface_id);
|
||||||
|
|
||||||
|
int qemuMonitorEmitGuestCrashloaded(qemuMonitorPtr mon);
|
||||||
|
|
||||||
int qemuMonitorStartCPUs(qemuMonitorPtr mon);
|
int qemuMonitorStartCPUs(qemuMonitorPtr mon);
|
||||||
int qemuMonitorStopCPUs(qemuMonitorPtr mon);
|
int qemuMonitorStopCPUs(qemuMonitorPtr mon);
|
||||||
|
|
||||||
|
@ -99,6 +99,7 @@ static void qemuMonitorJSONHandleBlockJobReady(qemuMonitorPtr mon, virJSONValueP
|
|||||||
static void qemuMonitorJSONHandleJobStatusChange(qemuMonitorPtr mon, virJSONValuePtr data);
|
static void qemuMonitorJSONHandleJobStatusChange(qemuMonitorPtr mon, virJSONValuePtr data);
|
||||||
static void qemuMonitorJSONHandleBalloonChange(qemuMonitorPtr mon, virJSONValuePtr data);
|
static void qemuMonitorJSONHandleBalloonChange(qemuMonitorPtr mon, virJSONValuePtr data);
|
||||||
static void qemuMonitorJSONHandlePMSuspendDisk(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 qemuMonitorJSONHandleGuestPanic(qemuMonitorPtr mon, virJSONValuePtr data);
|
||||||
static void qemuMonitorJSONHandleDeviceDeleted(qemuMonitorPtr mon, virJSONValuePtr data);
|
static void qemuMonitorJSONHandleDeviceDeleted(qemuMonitorPtr mon, virJSONValuePtr data);
|
||||||
static void qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitorPtr mon, virJSONValuePtr data);
|
static void qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitorPtr mon, virJSONValuePtr data);
|
||||||
@ -128,6 +129,7 @@ static qemuEventHandler eventHandlers[] = {
|
|||||||
{ "DEVICE_DELETED", qemuMonitorJSONHandleDeviceDeleted, },
|
{ "DEVICE_DELETED", qemuMonitorJSONHandleDeviceDeleted, },
|
||||||
{ "DEVICE_TRAY_MOVED", qemuMonitorJSONHandleTrayChange, },
|
{ "DEVICE_TRAY_MOVED", qemuMonitorJSONHandleTrayChange, },
|
||||||
{ "DUMP_COMPLETED", qemuMonitorJSONHandleDumpCompleted, },
|
{ "DUMP_COMPLETED", qemuMonitorJSONHandleDumpCompleted, },
|
||||||
|
{ "GUEST_CRASHLOADED", qemuMonitorJSONHandleGuestCrashloaded, },
|
||||||
{ "GUEST_PANICKED", qemuMonitorJSONHandleGuestPanic, },
|
{ "GUEST_PANICKED", qemuMonitorJSONHandleGuestPanic, },
|
||||||
{ "JOB_STATUS_CHANGE", qemuMonitorJSONHandleJobStatusChange, },
|
{ "JOB_STATUS_CHANGE", qemuMonitorJSONHandleJobStatusChange, },
|
||||||
{ "MIGRATION", qemuMonitorJSONHandleMigrationStatus, },
|
{ "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
|
int
|
||||||
qemuMonitorJSONHumanCommand(qemuMonitorPtr mon,
|
qemuMonitorJSONHumanCommand(qemuMonitorPtr mon,
|
||||||
const char *cmd_str,
|
const char *cmd_str,
|
||||||
|
@ -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 = {
|
static qemuMonitorCallbacks monitorCallbacks = {
|
||||||
.eofNotify = qemuProcessHandleMonitorEOF,
|
.eofNotify = qemuProcessHandleMonitorEOF,
|
||||||
.errorNotify = qemuProcessHandleMonitorError,
|
.errorNotify = qemuProcessHandleMonitorError,
|
||||||
@ -1879,6 +1908,7 @@ static qemuMonitorCallbacks monitorCallbacks = {
|
|||||||
.domainDumpCompleted = qemuProcessHandleDumpCompleted,
|
.domainDumpCompleted = qemuProcessHandleDumpCompleted,
|
||||||
.domainPRManagerStatusChanged = qemuProcessHandlePRManagerStatusChanged,
|
.domainPRManagerStatusChanged = qemuProcessHandlePRManagerStatusChanged,
|
||||||
.domainRdmaGidStatusChanged = qemuProcessHandleRdmaGidStatusChanged,
|
.domainRdmaGidStatusChanged = qemuProcessHandleRdmaGidStatusChanged,
|
||||||
|
.domainGuestCrashloaded = qemuProcessHandleGuestCrashloaded,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -12910,7 +12910,8 @@ VIR_ENUM_IMPL(virshDomainEventPMSuspended,
|
|||||||
VIR_ENUM_DECL(virshDomainEventCrashed);
|
VIR_ENUM_DECL(virshDomainEventCrashed);
|
||||||
VIR_ENUM_IMPL(virshDomainEventCrashed,
|
VIR_ENUM_IMPL(virshDomainEventCrashed,
|
||||||
VIR_DOMAIN_EVENT_CRASHED_LAST,
|
VIR_DOMAIN_EVENT_CRASHED_LAST,
|
||||||
N_("Panicked"));
|
N_("Panicked"),
|
||||||
|
N_("Crashloaded"));
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
virshDomainEventDetailToString(int event, int detail)
|
virshDomainEventDetailToString(int event, int detail)
|
||||||
|
Loading…
Reference in New Issue
Block a user