]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Wire up MEMORY_DEVICE_SIZE_CHANGE event
authorMichal Privoznik <mprivozn@redhat.com>
Thu, 21 Jan 2021 13:16:44 +0000 (14:16 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Fri, 1 Oct 2021 09:04:47 +0000 (11:04 +0200)
As advertised in previous commit, this event is delivered to us
when virtio-mem module changes the allocation inside the guest.
It comes with one attribute - size - which holds the new size of
the virtio-mem (well, allocated size), in bytes.
Mind you, this is not necessarily the same number as 'requested
size'. It almost certainly will be when sizing the memory up, but
it might not be when sizing the memory down - the guest kernel
might be unable to free some blocks.

This current size is reported in the domain XML as an output
element only.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
17 files changed:
examples/c/misc/event-test.c
include/libvirt/libvirt-domain.h
src/conf/domain_event.c
src/conf/domain_event.h
src/libvirt_private.syms
src/qemu/qemu_domain.c
src/qemu/qemu_domain.h
src/qemu/qemu_driver.c
src/qemu/qemu_monitor.c
src/qemu/qemu_monitor.h
src/qemu/qemu_monitor_json.c
src/qemu/qemu_process.c
src/remote/remote_daemon_dispatch.c
src/remote/remote_driver.c
src/remote/remote_protocol.x
src/remote_protocol-structs
tools/virsh-domain.c

index 10c707e66b5b571957ff93e5e885ee55ffac9797..1eec76c79d8eb8bde6d5d6a300b888ab533c1f7f 100644 (file)
@@ -982,6 +982,22 @@ myDomainEventMemoryFailureCallback(virConnectPtr conn G_GNUC_UNUSED,
 }
 
 
+static int
+myDomainEventMemoryDeviceSizeChangeCallback(virConnectPtr conn G_GNUC_UNUSED,
+                                            virDomainPtr dom,
+                                            const char *alias,
+                                            unsigned long long size,
+                                            void *opaque G_GNUC_UNUSED)
+{
+    /* Casts to uint64_t to work around mingw not knowing %lld */
+    printf("%s EVENT: Domain %s(%d) memory device size change: "
+           "alias: '%s' new size %" PRIu64 "'\n",
+           __func__, virDomainGetName(dom), virDomainGetID(dom),
+           alias, (uint64_t)size);
+    return 0;
+}
+
+
 static int
 myDomainEventMigrationIterationCallback(virConnectPtr conn G_GNUC_UNUSED,
                                         virDomainPtr dom,
@@ -1113,6 +1129,7 @@ struct domainEventData domainEvents[] = {
     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),
+    DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_MEMORY_DEVICE_SIZE_CHANGE, myDomainEventMemoryDeviceSizeChangeCallback),
 };
 
 struct storagePoolEventData {
index 7ef8ac51e5643a0cf07a5b2ceecb388d029ebd49..eaafcc6b29fe763ea6b8fcda57b8d2980debeac9 100644 (file)
@@ -4655,6 +4655,29 @@ typedef void (*virConnectDomainEventMemoryFailureCallback)(virConnectPtr conn,
                                                            void *opaque);
 
 
+/**
+ * virConnectDomainEventMemoryDeviceSizeChangeCallback:
+ * @conn: connection object
+ * @dom: domain on which the event occurred
+ * @alias: memory device alias
+ * @size: new current size of memory device (in KiB)
+ * @opaque: application specified data
+ *
+ * The callback occurs when the guest acknowledges request to change size of
+ * memory device (so far only virtio-mem model supports this). The @size then
+ * reflects the new amount of guest visible memory (in kibibytes).
+ *
+ * The callback signature to use when registering for an event of type
+ * VIR_DOMAIN_EVENT_ID_MEMORY_DEVICE_SIZE_CHANGE with
+ * virConnectDomainEventRegisterAny().
+ */
+typedef void (*virConnectDomainEventMemoryDeviceSizeChangeCallback)(virConnectPtr conn,
+                                                                    virDomainPtr dom,
+                                                                    const char *alias,
+                                                                    unsigned long long size,
+                                                                    void *opaque);
+
+
 /**
  * VIR_DOMAIN_EVENT_CALLBACK:
  *
@@ -4698,6 +4721,7 @@ typedef enum {
     VIR_DOMAIN_EVENT_ID_METADATA_CHANGE = 23, /* virConnectDomainEventMetadataChangeCallback */
     VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD = 24, /* virConnectDomainEventBlockThresholdCallback */
     VIR_DOMAIN_EVENT_ID_MEMORY_FAILURE = 25,  /* virConnectDomainEventMemoryFailureCallback */
+    VIR_DOMAIN_EVENT_ID_MEMORY_DEVICE_SIZE_CHANGE = 26, /* virConnectDomainEventMemoryDeviceSizeChangeCallback */
 
 # ifdef VIR_ENUM_SENTINELS
     VIR_DOMAIN_EVENT_ID_LAST
index 15a3baedf7ef59e81e74f159eaee32cd1aef8be0..18539e348bcc232ff07279be8c209c93e5b57d50 100644 (file)
@@ -58,6 +58,7 @@ static virClass *virDomainEventDeviceRemovalFailedClass;
 static virClass *virDomainEventMetadataChangeClass;
 static virClass *virDomainEventBlockThresholdClass;
 static virClass *virDomainEventMemoryFailureClass;
+static virClass *virDomainEventMemoryDeviceSizeChangeClass;
 
 static void virDomainEventDispose(void *obj);
 static void virDomainEventLifecycleDispose(void *obj);
@@ -81,6 +82,7 @@ static void virDomainEventDeviceRemovalFailedDispose(void *obj);
 static void virDomainEventMetadataChangeDispose(void *obj);
 static void virDomainEventBlockThresholdDispose(void *obj);
 static void virDomainEventMemoryFailureDispose(void *obj);
+static void virDomainEventMemoryDeviceSizeChangeDispose(void *obj);
 
 static void
 virDomainEventDispatchDefaultFunc(virConnectPtr conn,
@@ -277,6 +279,15 @@ struct _virDomainEventMemoryFailure {
 };
 typedef struct _virDomainEventMemoryFailure virDomainEventMemoryFailure;
 
+struct _virDomainEventMemoryDeviceSizeChange {
+    virDomainEvent parent;
+
+    char *alias;
+    unsigned long long size;
+};
+typedef struct _virDomainEventMemoryDeviceSizeChange virDomainEventMemoryDeviceSizeChange;
+typedef virDomainEventMemoryDeviceSizeChange *virDomainEventMemoryDeviceSizeChangePtr;
+
 static int
 virDomainEventsOnceInit(void)
 {
@@ -324,6 +335,8 @@ virDomainEventsOnceInit(void)
         return -1;
     if (!VIR_CLASS_NEW(virDomainEventMemoryFailure, virDomainEventClass))
         return -1;
+    if (!VIR_CLASS_NEW(virDomainEventMemoryDeviceSizeChange, virDomainEventClass))
+        return -1;
     return 0;
 }
 
@@ -540,6 +553,14 @@ virDomainEventMemoryFailureDispose(void *obj)
     VIR_DEBUG("obj=%p", event);
 }
 
+static void
+virDomainEventMemoryDeviceSizeChangeDispose(void *obj)
+{
+    virDomainEventMemoryDeviceSizeChangePtr event = obj;
+    VIR_DEBUG("obj=%p", event);
+
+    g_free(event->alias);
+}
 
 static void *
 virDomainEventNew(virClass *klass,
@@ -1664,6 +1685,57 @@ virDomainEventMemoryFailureNewFromDom(virDomainPtr dom,
                                           recipient, action, flags);
 }
 
+
+static virObjectEvent *
+virDomainEventMemoryDeviceSizeChangeNew(int id,
+                                        const char *name,
+                                        unsigned char *uuid,
+                                        const char *alias,
+                                        unsigned long long size)
+{
+    virDomainEventMemoryDeviceSizeChangePtr ev;
+
+    if (virDomainEventsInitialize() < 0)
+        return NULL;
+
+    if (!(ev = virDomainEventNew(virDomainEventMemoryDeviceSizeChangeClass,
+                                 VIR_DOMAIN_EVENT_ID_MEMORY_DEVICE_SIZE_CHANGE,
+                                 id, name, uuid)))
+        return NULL;
+
+    ev->alias = g_strdup(alias);
+    ev->size = size;
+
+    return (virObjectEvent *)ev;
+}
+
+
+virObjectEvent *
+virDomainEventMemoryDeviceSizeChangeNewFromObj(virDomainObj *obj,
+                                               const char *alias,
+                                               unsigned long long size)
+{
+    return virDomainEventMemoryDeviceSizeChangeNew(obj->def->id,
+                                                   obj->def->name,
+                                                   obj->def->uuid,
+                                                   alias,
+                                                   size);
+}
+
+
+virObjectEvent *
+virDomainEventMemoryDeviceSizeChangeNewFromDom(virDomainPtr dom,
+                                               const char *alias,
+                                               unsigned long long size)
+{
+    return virDomainEventMemoryDeviceSizeChangeNew(dom->id,
+                                                   dom->name,
+                                                   dom->uuid,
+                                                   alias,
+                                                   size);
+}
+
+
 static void
 virDomainEventDispatchDefaultFunc(virConnectPtr conn,
                                   virObjectEvent *event,
@@ -1960,6 +2032,18 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn,
             goto cleanup;
         }
 
+    case VIR_DOMAIN_EVENT_ID_MEMORY_DEVICE_SIZE_CHANGE:
+        {
+            virDomainEventMemoryDeviceSizeChangePtr memoryDeviceSizeChangeEvent;
+
+            memoryDeviceSizeChangeEvent = (virDomainEventMemoryDeviceSizeChangePtr)event;
+            ((virConnectDomainEventMemoryDeviceSizeChangeCallback)cb)(conn, dom,
+                                                                      memoryDeviceSizeChangeEvent->alias,
+                                                                      memoryDeviceSizeChangeEvent->size,
+                                                                      cbopaque);
+            goto cleanup;
+        }
+
     case VIR_DOMAIN_EVENT_ID_LAST:
         break;
     }
index 2a59e613cdb1e6185ab86e3ba86da66a6a32ff84..4a9f6b988b5c94f45ab98530e12c4ab6d8cb8fc8 100644 (file)
@@ -267,6 +267,16 @@ virDomainEventMemoryFailureNewFromDom(virDomainPtr dom,
                                       int action,
                                       unsigned int flags);
 
+virObjectEvent *
+virDomainEventMemoryDeviceSizeChangeNewFromObj(virDomainObj *obj,
+                                               const char *alias,
+                                               unsigned long long size);
+
+virObjectEvent *
+virDomainEventMemoryDeviceSizeChangeNewFromDom(virDomainPtr dom,
+                                               const char *alias,
+                                               unsigned long long size);
+
 int
 virDomainEventStateRegister(virConnectPtr conn,
                             virObjectEventState *state,
index bf00f1942ec0e27469fbbe26291edc0dcf6f79e5..fd0eea0777e2e324423394b14956fc9f1f6c28b0 100644 (file)
@@ -726,6 +726,8 @@ virDomainEventLifecycleNew;
 virDomainEventLifecycleNewFromDef;
 virDomainEventLifecycleNewFromDom;
 virDomainEventLifecycleNewFromObj;
+virDomainEventMemoryDeviceSizeChangeNewFromDom;
+virDomainEventMemoryDeviceSizeChangeNewFromObj;
 virDomainEventMemoryFailureNewFromDom;
 virDomainEventMemoryFailureNewFromObj;
 virDomainEventMetadataChangeNewFromDom;
index 9197090639da596ebe9321d8ec290a4e50777def..031ca4e00dddee942cc03d0f7debe9f6d9f0788b 100644 (file)
@@ -10861,6 +10861,9 @@ qemuProcessEventFree(struct qemuProcessEvent *event)
     case QEMU_PROCESS_EVENT_JOB_STATUS_CHANGE:
         virObjectUnref(event->data);
         break;
+    case QEMU_PROCESS_EVENT_MEMORY_DEVICE_SIZE_CHANGE:
+        qemuMonitorMemoryDeviceSizeChangeFree(event->data);
+        break;
     case QEMU_PROCESS_EVENT_PR_DISCONNECT:
     case QEMU_PROCESS_EVENT_LAST:
         break;
index f8004efbb16c1f0cd9509f4d0022fdfe59097560..64f92988b76be807bb364792f7004a02f67a1a9e 100644 (file)
@@ -415,6 +415,7 @@ typedef enum {
     QEMU_PROCESS_EVENT_PR_DISCONNECT,
     QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED,
     QEMU_PROCESS_EVENT_GUEST_CRASHLOADED,
+    QEMU_PROCESS_EVENT_MEMORY_DEVICE_SIZE_CHANGE,
 
     QEMU_PROCESS_EVENT_LAST
 } qemuProcessEventType;
index 15c74cf773a5a9deb17129dc26431282ca2eb3a4..cd11b41905e4fece8634c4e0c35ce3c28fff04a3 100644 (file)
@@ -4246,6 +4246,40 @@ processGuestCrashloadedEvent(virQEMUDriver *driver,
 }
 
 
+static void
+processMemoryDeviceSizeChange(virQEMUDriver *driver,
+                              virDomainObj *vm,
+                              qemuMonitorMemoryDeviceSizeChange *info)
+{
+    virDomainMemoryDef *mem = NULL;
+    virObjectEvent *event = NULL;
+
+    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
+        return;
+
+    if (!virDomainObjIsActive(vm)) {
+        VIR_DEBUG("Domain is not running");
+        goto endjob;
+    }
+
+    mem = virDomainMemoryFindByDeviceAlias(vm->def, info->devAlias);
+    if (!mem) {
+        VIR_DEBUG("Memory device '%s' not found", info->devAlias);
+        goto endjob;
+    }
+
+    mem->currentsize = VIR_DIV_UP(info->size, 1024);
+
+    event = virDomainEventMemoryDeviceSizeChangeNewFromObj(vm,
+                                                           info->devAlias,
+                                                           mem->currentsize);
+
+ endjob:
+    qemuDomainObjEndJob(driver, vm);
+    virObjectEventStateQueue(driver->domainEventState, event);
+}
+
+
 static void qemuProcessEventHandler(void *data, void *opaque)
 {
     struct qemuProcessEvent *processEvent = data;
@@ -4295,6 +4329,9 @@ static void qemuProcessEventHandler(void *data, void *opaque)
     case QEMU_PROCESS_EVENT_GUEST_CRASHLOADED:
         processGuestCrashloadedEvent(driver, vm);
         break;
+    case QEMU_PROCESS_EVENT_MEMORY_DEVICE_SIZE_CHANGE:
+        processMemoryDeviceSizeChange(driver, vm, processEvent->data);
+        break;
     case QEMU_PROCESS_EVENT_LAST:
         break;
     }
index 24119ef66e332c3507d242bea82a340219108c6b..5fc23f13d3bf530446565ee32222d85ba6b18d98 100644 (file)
@@ -1382,6 +1382,17 @@ qemuMonitorEmitSpiceMigrated(qemuMonitor *mon)
 }
 
 
+void
+qemuMonitorEmitMemoryDeviceSizeChange(qemuMonitor *mon,
+                                      const char *devAlias,
+                                      unsigned long long size)
+{
+    VIR_DEBUG("mon=%p, devAlias='%s', size=%llu", mon, devAlias, size);
+
+    QEMU_MONITOR_CALLBACK(mon, domainMemoryDeviceSizeChange, mon->vm, devAlias, size);
+}
+
+
 void
 qemuMonitorEmitMemoryFailure(qemuMonitor *mon,
                              qemuMonitorEventMemoryFailure *mfp)
@@ -4266,6 +4277,16 @@ qemuMonitorEventRdmaGidStatusFree(qemuMonitorRdmaGidStatus *info)
 }
 
 
+void
+qemuMonitorMemoryDeviceSizeChangeFree(qemuMonitorMemoryDeviceSizeChangePtr info)
+{
+    if (!info)
+        return;
+
+    g_free(info->devAlias);
+}
+
+
 int
 qemuMonitorSetWatchdogAction(qemuMonitor *mon,
                              const char *action)
index 0ebe73ac0445e940f6c5a9d8a81234fd2223f2d8..962b5165422ebee5fc9a2b035cb2ec021dd768dd 100644 (file)
@@ -101,6 +101,14 @@ struct _qemuMonitorRdmaGidStatus {
 };
 
 
+typedef struct _qemuMonitorMemoryDeviceSizeChange qemuMonitorMemoryDeviceSizeChange;
+typedef qemuMonitorMemoryDeviceSizeChange *qemuMonitorMemoryDeviceSizeChangePtr;
+struct _qemuMonitorMemoryDeviceSizeChange {
+    char *devAlias;
+    unsigned long long size;
+};
+
+
 typedef enum {
     QEMU_MONITOR_ACTION_SHUTDOWN_KEEP, /* do not change the current setting */
     QEMU_MONITOR_ACTION_SHUTDOWN_POWEROFF,
@@ -187,6 +195,7 @@ struct _qemuMonitorJobInfo {
 char *qemuMonitorGuestPanicEventInfoFormatMsg(qemuMonitorEventPanicInfo *info);
 void qemuMonitorEventPanicInfoFree(qemuMonitorEventPanicInfo *info);
 void qemuMonitorEventRdmaGidStatusFree(qemuMonitorRdmaGidStatus *info);
+void qemuMonitorMemoryDeviceSizeChangeFree(qemuMonitorMemoryDeviceSizeChange *info);
 
 typedef void (*qemuMonitorDestroyCallback)(qemuMonitor *mon,
                                            virDomainObj *vm,
@@ -403,6 +412,12 @@ typedef void (*qemuMonitorDomainMemoryFailureCallback)(qemuMonitor *mon,
                                                        qemuMonitorEventMemoryFailure *mfp,
                                                        void *opaque);
 
+typedef int (*qemuMonitorDomainMemoryDeviceSizeChange)(qemuMonitor *mon,
+                                                       virDomainObj *vm,
+                                                       const char *alias,
+                                                       unsigned long long size,
+                                                       void *opaque);
+
 typedef struct _qemuMonitorCallbacks qemuMonitorCallbacks;
 struct _qemuMonitorCallbacks {
     qemuMonitorEofNotifyCallback eofNotify;
@@ -437,6 +452,7 @@ struct _qemuMonitorCallbacks {
     qemuMonitorDomainRdmaGidStatusChangedCallback domainRdmaGidStatusChanged;
     qemuMonitorDomainGuestCrashloadedCallback domainGuestCrashloaded;
     qemuMonitorDomainMemoryFailureCallback domainMemoryFailure;
+    qemuMonitorDomainMemoryDeviceSizeChange domainMemoryDeviceSizeChange;
 };
 
 qemuMonitor *qemuMonitorOpen(virDomainObj *vm,
@@ -532,6 +548,10 @@ void qemuMonitorEmitSerialChange(qemuMonitor *mon,
                                  bool connected);
 void qemuMonitorEmitSpiceMigrated(qemuMonitor *mon);
 
+void qemuMonitorEmitMemoryDeviceSizeChange(qemuMonitor *mon,
+                                           const char *devAlias,
+                                           unsigned long long size);
+
 void qemuMonitorEmitMemoryFailure(qemuMonitor *mon,
                                   qemuMonitorEventMemoryFailure *mfp);
 
index 4ef8abb5376f6d5518d80711cf38be1411c640fe..fc3bb388be31fff265f7b55c5d4fd47c6fc8bfe1 100644 (file)
@@ -112,6 +112,7 @@ static void qemuMonitorJSONHandleDumpCompleted(qemuMonitor *mon, virJSONValue *d
 static void qemuMonitorJSONHandlePRManagerStatusChanged(qemuMonitor *mon, virJSONValue *data);
 static void qemuMonitorJSONHandleRdmaGidStatusChanged(qemuMonitor *mon, virJSONValue *data);
 static void qemuMonitorJSONHandleMemoryFailure(qemuMonitor *mon, virJSONValue *data);
+static void qemuMonitorJSONHandleMemoryDeviceSizeChange(qemuMonitor *mon, virJSONValue *data);
 
 typedef struct {
     const char *type;
@@ -132,6 +133,7 @@ static qemuEventHandler eventHandlers[] = {
     { "GUEST_CRASHLOADED", qemuMonitorJSONHandleGuestCrashloaded, },
     { "GUEST_PANICKED", qemuMonitorJSONHandleGuestPanic, },
     { "JOB_STATUS_CHANGE", qemuMonitorJSONHandleJobStatusChange, },
+    { "MEMORY_DEVICE_SIZE_CHANGE", qemuMonitorJSONHandleMemoryDeviceSizeChange, },
     { "MEMORY_FAILURE", qemuMonitorJSONHandleMemoryFailure, },
     { "MIGRATION", qemuMonitorJSONHandleMigrationStatus, },
     { "MIGRATION_PASS", qemuMonitorJSONHandleMigrationPass, },
@@ -1313,6 +1315,28 @@ qemuMonitorJSONHandleSpiceMigrated(qemuMonitor *mon,
 }
 
 
+static void
+qemuMonitorJSONHandleMemoryDeviceSizeChange(qemuMonitor *mon,
+                                            virJSONValue *data)
+{
+    const char *name;
+    unsigned long long size;
+
+    if (!(name = virJSONValueObjectGetString(data, "id"))) {
+        VIR_WARN("missing device alias in MEMORY_DEVICE_SIZE_CHANGE event");
+        return;
+    }
+
+    if (virJSONValueObjectGetNumberUlong(data, "size", &size) < 0) {
+        VIR_WARN("missing new size for '%s' in MEMORY_DEVICE_SIZE_CHANGE event", name);
+        return;
+    }
+
+
+    qemuMonitorEmitMemoryDeviceSizeChange(mon, name, size);
+}
+
+
 static void
 qemuMonitorJSONHandleMemoryFailure(qemuMonitor *mon,
                                    virJSONValue *data)
index ca53335d5de46e3e04938fa76d8910f2fa035fc9..b2c708ff71b74ffa7529ad5e293c9253ddaec5e5 100644 (file)
@@ -1833,6 +1833,47 @@ qemuProcessHandleMemoryFailure(qemuMonitor *mon G_GNUC_UNUSED,
 }
 
 
+static int
+qemuProcessHandleMemoryDeviceSizeChange(qemuMonitor *mon G_GNUC_UNUSED,
+                                        virDomainObj *vm,
+                                        const char *devAlias,
+                                        unsigned long long size,
+                                        void *opaque)
+{
+    virQEMUDriver *driver = opaque;
+    struct qemuProcessEvent *processEvent = NULL;
+    qemuMonitorMemoryDeviceSizeChange *info = NULL;
+    int ret = -1;
+
+    virObjectLock(vm);
+
+    VIR_DEBUG("Memory device '%s' changed size to '%llu' in domain '%s'",
+              devAlias, size, vm->def->name);
+
+    info = g_new0(qemuMonitorMemoryDeviceSizeChange, 1);
+    info->devAlias = g_strdup(devAlias);
+    info->size = size;
+
+    processEvent = g_new0(struct qemuProcessEvent, 1);
+    processEvent->eventType = QEMU_PROCESS_EVENT_MEMORY_DEVICE_SIZE_CHANGE;
+    processEvent->vm = virObjectRef(vm);
+    processEvent->data = g_steal_pointer(&info);
+
+    if (virThreadPoolSendJob(driver->workerPool, 0, processEvent) < 0) {
+        qemuProcessEventFree(processEvent);
+        virObjectUnref(vm);
+        goto cleanup;
+    }
+
+    processEvent = NULL;
+    ret = 0;
+ cleanup:
+    qemuProcessEventFree(processEvent);
+    virObjectUnlock(vm);
+    return ret;
+}
+
+
 static qemuMonitorCallbacks monitorCallbacks = {
     .eofNotify = qemuProcessHandleMonitorEOF,
     .errorNotify = qemuProcessHandleMonitorError,
@@ -1866,6 +1907,7 @@ static qemuMonitorCallbacks monitorCallbacks = {
     .domainRdmaGidStatusChanged = qemuProcessHandleRdmaGidStatusChanged,
     .domainGuestCrashloaded = qemuProcessHandleGuestCrashloaded,
     .domainMemoryFailure = qemuProcessHandleMemoryFailure,
+    .domainMemoryDeviceSizeChange = qemuProcessHandleMemoryDeviceSizeChange,
 };
 
 static void
index 0bac7d4f51d1ecd0ed7f5648ecd58b306826fa9a..bcfeadc2ae5b12e3138a59ab525122b1344cc411 100644 (file)
@@ -1334,6 +1334,35 @@ remoteRelayDomainEventMemoryFailure(virConnectPtr conn,
 }
 
 
+static int
+remoteRelayDomainEventMemoryDeviceSizeChange(virConnectPtr conn,
+                                             virDomainPtr dom,
+                                             const char *alias,
+                                             unsigned long long size,
+                                             void *opaque)
+{
+    daemonClientEventCallback *callback = opaque;
+    remote_domain_event_memory_device_size_change_msg data;
+
+    if (callback->callbackID < 0 ||
+        !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
+        return -1;
+
+    /* build return data */
+    memset(&data, 0, sizeof(data));
+    data.callbackID = callback->callbackID;
+    data.alias = g_strdup(alias);
+    data.size = size;
+    make_nonnull_domain(&data.dom, dom);
+
+    remoteDispatchObjectEventSend(callback->client, remoteProgram,
+                                  REMOTE_PROC_DOMAIN_EVENT_MEMORY_DEVICE_SIZE_CHANGE,
+                                  (xdrproc_t)xdr_remote_domain_event_memory_device_size_change_msg,
+                                  &data);
+    return 0;
+}
+
+
 static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot),
@@ -1361,6 +1390,7 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMetadataChange),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockThreshold),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMemoryFailure),
+    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMemoryDeviceSizeChange),
 };
 
 G_STATIC_ASSERT(G_N_ELEMENTS(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
index 83ea33e91b887e56d487afb8731e2470e37eb3b5..719fcf4297824e3a15412c8becca1a30ee98da63 100644 (file)
@@ -410,6 +410,10 @@ remoteDomainBuildEventMemoryFailure(virNetClientProgram *prog,
                                     void *evdata, void *opaque);
 
 static void
+remoteDomainBuildEventMemoryDeviceSizeChange(virNetClientProgram *prog,
+                                             virNetClient *client,
+                                             void *evdata, void *opaque);
+static void
 remoteConnectNotifyEventConnectionClosed(virNetClientProgram *prog G_GNUC_UNUSED,
                                          virNetClient *client G_GNUC_UNUSED,
                                          void *evdata, void *opaque);
@@ -624,6 +628,10 @@ static virNetClientProgramEvent remoteEvents[] = {
       remoteDomainBuildEventMemoryFailure,
       sizeof(remote_domain_event_memory_failure_msg),
       (xdrproc_t)xdr_remote_domain_event_memory_failure_msg },
+    { REMOTE_PROC_DOMAIN_EVENT_MEMORY_DEVICE_SIZE_CHANGE,
+      remoteDomainBuildEventMemoryDeviceSizeChange,
+      sizeof(remote_domain_event_memory_device_size_change_msg),
+      (xdrproc_t)xdr_remote_domain_event_memory_device_size_change_msg },
 };
 
 static void
@@ -5436,6 +5444,30 @@ remoteDomainBuildEventMemoryFailure(virNetClientProgram *prog G_GNUC_UNUSED,
 }
 
 
+static void
+remoteDomainBuildEventMemoryDeviceSizeChange(virNetClientProgram *prog G_GNUC_UNUSED,
+                                             virNetClient *client G_GNUC_UNUSED,
+                                             void *evdata, void *opaque)
+{
+    virConnectPtr conn = opaque;
+    remote_domain_event_memory_device_size_change_msg *msg = evdata;
+    struct private_data *priv = conn->privateData;
+    virDomainPtr dom;
+    virObjectEvent *event = NULL;
+
+    if (!(dom = get_nonnull_domain(conn, msg->dom)))
+        return;
+
+    event = virDomainEventMemoryDeviceSizeChangeNewFromDom(dom,
+                                                           msg->alias,
+                                                           msg->size);
+
+    virObjectUnref(dom);
+
+    virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID);
+}
+
+
 static int
 remoteStreamSend(virStreamPtr st,
                  const char *data,
index 296610a94da454d5872844be92794c52863e9fe3..60010778caadc96b60e90a054a5cffb15bd4dc38 100644 (file)
@@ -3893,6 +3893,13 @@ struct remote_domain_start_dirty_rate_calc_args {
 };
 
 
+struct remote_domain_event_memory_device_size_change_msg {
+    int callbackID;
+    remote_nonnull_domain dom;
+    remote_nonnull_string alias;
+    unsigned hyper size;
+};
+
 /*----- Protocol. -----*/
 
 /* Define the program number, protocol version and procedure numbers here. */
@@ -6892,5 +6899,11 @@ enum remote_procedure {
      * @acl: network:write
      * @acl: network:start
      */
-    REMOTE_PROC_NETWORK_CREATE_XML_FLAGS = 437
+    REMOTE_PROC_NETWORK_CREATE_XML_FLAGS = 437,
+
+    /**
+     * @generate: both
+     * @acl: none
+     */
+    REMOTE_PROC_DOMAIN_EVENT_MEMORY_DEVICE_SIZE_CHANGE = 438
 };
index de06895d537c5e33c3bd642178f6eb49f73a496f..dbef4ace79e2ac2173f44d5ca12023c1b5686d09 100644 (file)
@@ -3235,6 +3235,12 @@ struct remote_domain_start_dirty_rate_calc_args {
         int                        seconds;
         u_int                      flags;
 };
+struct remote_domain_event_memory_device_size_change_msg {
+        int                        callbackID;
+        remote_nonnull_domain      dom;
+        remote_nonnull_string      alias;
+        uint64_t                   size;
+};
 enum remote_procedure {
         REMOTE_PROC_CONNECT_OPEN = 1,
         REMOTE_PROC_CONNECT_CLOSE = 2,
@@ -3673,4 +3679,5 @@ enum remote_procedure {
         REMOTE_PROC_NODE_DEVICE_IS_PERSISTENT = 435,
         REMOTE_PROC_NODE_DEVICE_IS_ACTIVE = 436,
         REMOTE_PROC_NETWORK_CREATE_XML_FLAGS = 437,
+        REMOTE_PROC_DOMAIN_EVENT_MEMORY_DEVICE_SIZE_CHANGE = 438,
 };
index 0b78fbf7280ff5fb73f7675744e13dc9b52ff5cd..5c13bb4ae7dc813a63b6e03684d7902d1e4feca5 100644 (file)
@@ -13154,6 +13154,24 @@ virshEventMemoryFailurePrint(virConnectPtr conn G_GNUC_UNUSED,
 }
 
 
+static void
+virshEventMemoryDeviceSizeChangePrint(virConnectPtr conn G_GNUC_UNUSED,
+                                      virDomainPtr dom,
+                                      const char *alias,
+                                      unsigned long long size,
+                                      void *opaque)
+{
+    g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
+
+    virBufferAsprintf(&buf,
+                      _("event 'memory-device-size-change' for domain '%s':\n"
+                        "alias: %s\nsize: %llu\n"),
+                      virDomainGetName(dom), alias, size);
+
+    virshEventPrint(opaque, &buf);
+}
+
+
 virshDomainEventCallback virshDomainEventCallbacks[] = {
     { "lifecycle",
       VIR_DOMAIN_EVENT_CALLBACK(virshEventLifecyclePrint), },
@@ -13205,6 +13223,8 @@ virshDomainEventCallback virshDomainEventCallbacks[] = {
       VIR_DOMAIN_EVENT_CALLBACK(virshEventBlockThresholdPrint), },
     { "memory-failure",
       VIR_DOMAIN_EVENT_CALLBACK(virshEventMemoryFailurePrint), },
+    { "memory-device-size-change",
+      VIR_DOMAIN_EVENT_CALLBACK(virshEventMemoryDeviceSizeChangePrint), },
 };
 G_STATIC_ASSERT(VIR_DOMAIN_EVENT_ID_LAST == G_N_ELEMENTS(virshDomainEventCallbacks));