[PATCH v2 4/4] virsh: implement memory failure event

zhenwei pi pizhenwei at bytedance.com
Mon Oct 12 12:31:59 UTC 2020


Implement memory failure event for virsh command and test.

Notice:
The full patch set includes 4 patches:
virsh: implement memory failure event         (current patch)
qemu: monitor: handle memory failure event
qemu: process: implement domainMemoryFailure
API: introduce memory failure

To avoid build/test errors, the 4 patches should be merged/removed
together. Test all the patches with a little complex environment
(nested KVM):
1, install newly built libvirt in L1, and start a L2 vm. run command
in L1:
 ~# virsh event l2 --event memory-failure

2, run command in L0 to inject MCE to L1:
 ~# virsh qemu-monitor-command l1 --hmp mce 0 9 0xbd000000000000c0 0xd 0x62000000 0x8c

Test result in l1(recipient hypervisor case):
event 'memory-failure' for domain l2:
recipient: hypervisor
action: ignore
flags:
	action required: 0
	recursive: 0

Test result in l1(recipient guest case):
event 'memory-failure' for domain l2:
recipient: guest
action: inject
flags:
	action required: 0
	recursive: 0

Signed-off-by: zhenwei pi <pizhenwei at bytedance.com>
---
 examples/c/misc/event-test.c | 16 ++++++++++++++++
 tools/virsh-domain.c         | 40 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/examples/c/misc/event-test.c b/examples/c/misc/event-test.c
index 52caa8ffa8..1651efe019 100644
--- a/examples/c/misc/event-test.c
+++ b/examples/c/misc/event-test.c
@@ -964,6 +964,21 @@ myDomainEventBlockThresholdCallback(virConnectPtr conn G_GNUC_UNUSED,
 
 
 static int
+myDomainEventMemoryFailureCallback(virConnectPtr conn G_GNUC_UNUSED,
+                                   virDomainPtr dom,
+                                   virDomainMemoryFailureRecipientType recipient,
+                                   virDomainMemoryFailureActionType action,
+                                   unsigned int flags,
+                                   void *opaque G_GNUC_UNUSED)
+{
+    printf("%s EVENT: Domain %s(%d) memory failure: recipient '%d', "
+           "aciont '%d', flags '%d'", __func__, virDomainGetName(dom),
+           virDomainGetID(dom), recipient, action, flags);
+    return 0;
+}
+
+
+static int
 myDomainEventMigrationIterationCallback(virConnectPtr conn G_GNUC_UNUSED,
                                         virDomainPtr dom,
                                         int iteration,
@@ -1093,6 +1108,7 @@ struct domainEventData domainEvents[] = {
     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED, myDomainEventDeviceRemovalFailedCallback),
     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_METADATA_CHANGE, myDomainEventMetadataChangeCallback),
     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD, myDomainEventBlockThresholdCallback),
+    DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_MEMORY_FAILURE, myDomainEventMemoryFailureCallback),
 };
 
 struct storagePoolEventData {
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 8f11393197..2bfb33e528 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -13590,6 +13590,44 @@ virshEventBlockThresholdPrint(virConnectPtr conn G_GNUC_UNUSED,
 }
 
 
+VIR_ENUM_DECL(virshEventMemoryFailureRecipientType);
+VIR_ENUM_IMPL(virshEventMemoryFailureRecipientType,
+              VIR_DOMAIN_EVENT_MEMORY_FAILURE_RECIPIENT_LAST,
+              N_("hypervisor"),
+              N_("guest"));
+
+VIR_ENUM_DECL(virshEventMemoryFailureActionType);
+VIR_ENUM_IMPL(virshEventMemoryFailureActionType,
+              VIR_DOMAIN_EVENT_MEMORY_FAILURE_ACTION_LAST,
+              N_("ignore"),
+              N_("inject"),
+              N_("fatal"),
+              N_("reset"));
+
+static void
+virshEventMemoryFailurePrint(virConnectPtr conn G_GNUC_UNUSED,
+                             virDomainPtr dom,
+                             virDomainMemoryFailureRecipientType recipient,
+                             virDomainMemoryFailureActionType action,
+                             unsigned int flags,
+                             void *opaque)
+{
+    g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
+
+    virBufferAsprintf(&buf, _("event 'memory-failure' for domain %s:\n"
+                              "recipient: %s\naction: %s\n"),
+                      virDomainGetName(dom),
+                      UNKNOWNSTR(virshEventMemoryFailureRecipientTypeTypeToString(recipient)),
+                      UNKNOWNSTR(virshEventMemoryFailureActionTypeTypeToString(action)));
+    virBufferAsprintf(&buf, _("flags:\n"
+                              "\taction required: %d\n\trecursive: %d\n"),
+                      !!(flags & VIR_DOMAIN_MEMORY_FAILURE_ACTION_REQUIRED),
+                      !!(flags & VIR_DOMAIN_MEMORY_FAILURE_RECURSIVE));
+
+    virshEventPrint(opaque, &buf);
+}
+
+
 virshDomainEventCallback virshDomainEventCallbacks[] = {
     { "lifecycle",
       VIR_DOMAIN_EVENT_CALLBACK(virshEventLifecyclePrint), },
@@ -13639,6 +13677,8 @@ virshDomainEventCallback virshDomainEventCallbacks[] = {
       VIR_DOMAIN_EVENT_CALLBACK(virshEventMetadataChangePrint), },
     { "block-threshold",
       VIR_DOMAIN_EVENT_CALLBACK(virshEventBlockThresholdPrint), },
+    { "memory-failure",
+      VIR_DOMAIN_EVENT_CALLBACK(virshEventMemoryFailurePrint), },
 };
 G_STATIC_ASSERT(VIR_DOMAIN_EVENT_ID_LAST == G_N_ELEMENTS(virshDomainEventCallbacks));
 
-- 
2.11.0




More information about the libvir-list mailing list