qemu: Wire up MEMORY_DEVICE_SIZE_CHANGE event

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>
This commit is contained in:
Michal Privoznik 2021-01-21 14:16:44 +01:00
parent dcd9f8e2c5
commit 9985f62b51
17 changed files with 388 additions and 1 deletions

View 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 static int
myDomainEventMigrationIterationCallback(virConnectPtr conn G_GNUC_UNUSED, myDomainEventMigrationIterationCallback(virConnectPtr conn G_GNUC_UNUSED,
virDomainPtr dom, virDomainPtr dom,
@ -1113,6 +1129,7 @@ struct domainEventData domainEvents[] = {
DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_METADATA_CHANGE, myDomainEventMetadataChangeCallback), DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_METADATA_CHANGE, myDomainEventMetadataChangeCallback),
DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD, myDomainEventBlockThresholdCallback), 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_FAILURE, myDomainEventMemoryFailureCallback),
DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_MEMORY_DEVICE_SIZE_CHANGE, myDomainEventMemoryDeviceSizeChangeCallback),
}; };
struct storagePoolEventData { struct storagePoolEventData {

View File

@ -4655,6 +4655,29 @@ typedef void (*virConnectDomainEventMemoryFailureCallback)(virConnectPtr conn,
void *opaque); 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: * VIR_DOMAIN_EVENT_CALLBACK:
* *
@ -4698,6 +4721,7 @@ typedef enum {
VIR_DOMAIN_EVENT_ID_METADATA_CHANGE = 23, /* virConnectDomainEventMetadataChangeCallback */ VIR_DOMAIN_EVENT_ID_METADATA_CHANGE = 23, /* virConnectDomainEventMetadataChangeCallback */
VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD = 24, /* virConnectDomainEventBlockThresholdCallback */ VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD = 24, /* virConnectDomainEventBlockThresholdCallback */
VIR_DOMAIN_EVENT_ID_MEMORY_FAILURE = 25, /* virConnectDomainEventMemoryFailureCallback */ VIR_DOMAIN_EVENT_ID_MEMORY_FAILURE = 25, /* virConnectDomainEventMemoryFailureCallback */
VIR_DOMAIN_EVENT_ID_MEMORY_DEVICE_SIZE_CHANGE = 26, /* virConnectDomainEventMemoryDeviceSizeChangeCallback */
# ifdef VIR_ENUM_SENTINELS # ifdef VIR_ENUM_SENTINELS
VIR_DOMAIN_EVENT_ID_LAST VIR_DOMAIN_EVENT_ID_LAST

View File

@ -58,6 +58,7 @@ static virClass *virDomainEventDeviceRemovalFailedClass;
static virClass *virDomainEventMetadataChangeClass; static virClass *virDomainEventMetadataChangeClass;
static virClass *virDomainEventBlockThresholdClass; static virClass *virDomainEventBlockThresholdClass;
static virClass *virDomainEventMemoryFailureClass; static virClass *virDomainEventMemoryFailureClass;
static virClass *virDomainEventMemoryDeviceSizeChangeClass;
static void virDomainEventDispose(void *obj); static void virDomainEventDispose(void *obj);
static void virDomainEventLifecycleDispose(void *obj); static void virDomainEventLifecycleDispose(void *obj);
@ -81,6 +82,7 @@ static void virDomainEventDeviceRemovalFailedDispose(void *obj);
static void virDomainEventMetadataChangeDispose(void *obj); static void virDomainEventMetadataChangeDispose(void *obj);
static void virDomainEventBlockThresholdDispose(void *obj); static void virDomainEventBlockThresholdDispose(void *obj);
static void virDomainEventMemoryFailureDispose(void *obj); static void virDomainEventMemoryFailureDispose(void *obj);
static void virDomainEventMemoryDeviceSizeChangeDispose(void *obj);
static void static void
virDomainEventDispatchDefaultFunc(virConnectPtr conn, virDomainEventDispatchDefaultFunc(virConnectPtr conn,
@ -277,6 +279,15 @@ struct _virDomainEventMemoryFailure {
}; };
typedef struct _virDomainEventMemoryFailure virDomainEventMemoryFailure; typedef struct _virDomainEventMemoryFailure virDomainEventMemoryFailure;
struct _virDomainEventMemoryDeviceSizeChange {
virDomainEvent parent;
char *alias;
unsigned long long size;
};
typedef struct _virDomainEventMemoryDeviceSizeChange virDomainEventMemoryDeviceSizeChange;
typedef virDomainEventMemoryDeviceSizeChange *virDomainEventMemoryDeviceSizeChangePtr;
static int static int
virDomainEventsOnceInit(void) virDomainEventsOnceInit(void)
{ {
@ -324,6 +335,8 @@ virDomainEventsOnceInit(void)
return -1; return -1;
if (!VIR_CLASS_NEW(virDomainEventMemoryFailure, virDomainEventClass)) if (!VIR_CLASS_NEW(virDomainEventMemoryFailure, virDomainEventClass))
return -1; return -1;
if (!VIR_CLASS_NEW(virDomainEventMemoryDeviceSizeChange, virDomainEventClass))
return -1;
return 0; return 0;
} }
@ -540,6 +553,14 @@ virDomainEventMemoryFailureDispose(void *obj)
VIR_DEBUG("obj=%p", event); VIR_DEBUG("obj=%p", event);
} }
static void
virDomainEventMemoryDeviceSizeChangeDispose(void *obj)
{
virDomainEventMemoryDeviceSizeChangePtr event = obj;
VIR_DEBUG("obj=%p", event);
g_free(event->alias);
}
static void * static void *
virDomainEventNew(virClass *klass, virDomainEventNew(virClass *klass,
@ -1664,6 +1685,57 @@ virDomainEventMemoryFailureNewFromDom(virDomainPtr dom,
recipient, action, flags); 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 static void
virDomainEventDispatchDefaultFunc(virConnectPtr conn, virDomainEventDispatchDefaultFunc(virConnectPtr conn,
virObjectEvent *event, virObjectEvent *event,
@ -1960,6 +2032,18 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn,
goto cleanup; 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: case VIR_DOMAIN_EVENT_ID_LAST:
break; break;
} }

View File

@ -267,6 +267,16 @@ virDomainEventMemoryFailureNewFromDom(virDomainPtr dom,
int action, int action,
unsigned int flags); 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 int
virDomainEventStateRegister(virConnectPtr conn, virDomainEventStateRegister(virConnectPtr conn,
virObjectEventState *state, virObjectEventState *state,

View File

@ -726,6 +726,8 @@ virDomainEventLifecycleNew;
virDomainEventLifecycleNewFromDef; virDomainEventLifecycleNewFromDef;
virDomainEventLifecycleNewFromDom; virDomainEventLifecycleNewFromDom;
virDomainEventLifecycleNewFromObj; virDomainEventLifecycleNewFromObj;
virDomainEventMemoryDeviceSizeChangeNewFromDom;
virDomainEventMemoryDeviceSizeChangeNewFromObj;
virDomainEventMemoryFailureNewFromDom; virDomainEventMemoryFailureNewFromDom;
virDomainEventMemoryFailureNewFromObj; virDomainEventMemoryFailureNewFromObj;
virDomainEventMetadataChangeNewFromDom; virDomainEventMetadataChangeNewFromDom;

View File

@ -10861,6 +10861,9 @@ qemuProcessEventFree(struct qemuProcessEvent *event)
case QEMU_PROCESS_EVENT_JOB_STATUS_CHANGE: case QEMU_PROCESS_EVENT_JOB_STATUS_CHANGE:
virObjectUnref(event->data); virObjectUnref(event->data);
break; break;
case QEMU_PROCESS_EVENT_MEMORY_DEVICE_SIZE_CHANGE:
qemuMonitorMemoryDeviceSizeChangeFree(event->data);
break;
case QEMU_PROCESS_EVENT_PR_DISCONNECT: case QEMU_PROCESS_EVENT_PR_DISCONNECT:
case QEMU_PROCESS_EVENT_LAST: case QEMU_PROCESS_EVENT_LAST:
break; break;

View File

@ -415,6 +415,7 @@ typedef enum {
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_GUEST_CRASHLOADED,
QEMU_PROCESS_EVENT_MEMORY_DEVICE_SIZE_CHANGE,
QEMU_PROCESS_EVENT_LAST QEMU_PROCESS_EVENT_LAST
} qemuProcessEventType; } qemuProcessEventType;

View 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) static void qemuProcessEventHandler(void *data, void *opaque)
{ {
struct qemuProcessEvent *processEvent = data; struct qemuProcessEvent *processEvent = data;
@ -4295,6 +4329,9 @@ static void qemuProcessEventHandler(void *data, void *opaque)
case QEMU_PROCESS_EVENT_GUEST_CRASHLOADED: case QEMU_PROCESS_EVENT_GUEST_CRASHLOADED:
processGuestCrashloadedEvent(driver, vm); processGuestCrashloadedEvent(driver, vm);
break; break;
case QEMU_PROCESS_EVENT_MEMORY_DEVICE_SIZE_CHANGE:
processMemoryDeviceSizeChange(driver, vm, processEvent->data);
break;
case QEMU_PROCESS_EVENT_LAST: case QEMU_PROCESS_EVENT_LAST:
break; break;
} }

View 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 void
qemuMonitorEmitMemoryFailure(qemuMonitor *mon, qemuMonitorEmitMemoryFailure(qemuMonitor *mon,
qemuMonitorEventMemoryFailure *mfp) qemuMonitorEventMemoryFailure *mfp)
@ -4266,6 +4277,16 @@ qemuMonitorEventRdmaGidStatusFree(qemuMonitorRdmaGidStatus *info)
} }
void
qemuMonitorMemoryDeviceSizeChangeFree(qemuMonitorMemoryDeviceSizeChangePtr info)
{
if (!info)
return;
g_free(info->devAlias);
}
int int
qemuMonitorSetWatchdogAction(qemuMonitor *mon, qemuMonitorSetWatchdogAction(qemuMonitor *mon,
const char *action) const char *action)

View File

@ -101,6 +101,14 @@ struct _qemuMonitorRdmaGidStatus {
}; };
typedef struct _qemuMonitorMemoryDeviceSizeChange qemuMonitorMemoryDeviceSizeChange;
typedef qemuMonitorMemoryDeviceSizeChange *qemuMonitorMemoryDeviceSizeChangePtr;
struct _qemuMonitorMemoryDeviceSizeChange {
char *devAlias;
unsigned long long size;
};
typedef enum { typedef enum {
QEMU_MONITOR_ACTION_SHUTDOWN_KEEP, /* do not change the current setting */ QEMU_MONITOR_ACTION_SHUTDOWN_KEEP, /* do not change the current setting */
QEMU_MONITOR_ACTION_SHUTDOWN_POWEROFF, QEMU_MONITOR_ACTION_SHUTDOWN_POWEROFF,
@ -187,6 +195,7 @@ struct _qemuMonitorJobInfo {
char *qemuMonitorGuestPanicEventInfoFormatMsg(qemuMonitorEventPanicInfo *info); char *qemuMonitorGuestPanicEventInfoFormatMsg(qemuMonitorEventPanicInfo *info);
void qemuMonitorEventPanicInfoFree(qemuMonitorEventPanicInfo *info); void qemuMonitorEventPanicInfoFree(qemuMonitorEventPanicInfo *info);
void qemuMonitorEventRdmaGidStatusFree(qemuMonitorRdmaGidStatus *info); void qemuMonitorEventRdmaGidStatusFree(qemuMonitorRdmaGidStatus *info);
void qemuMonitorMemoryDeviceSizeChangeFree(qemuMonitorMemoryDeviceSizeChange *info);
typedef void (*qemuMonitorDestroyCallback)(qemuMonitor *mon, typedef void (*qemuMonitorDestroyCallback)(qemuMonitor *mon,
virDomainObj *vm, virDomainObj *vm,
@ -403,6 +412,12 @@ typedef void (*qemuMonitorDomainMemoryFailureCallback)(qemuMonitor *mon,
qemuMonitorEventMemoryFailure *mfp, qemuMonitorEventMemoryFailure *mfp,
void *opaque); void *opaque);
typedef int (*qemuMonitorDomainMemoryDeviceSizeChange)(qemuMonitor *mon,
virDomainObj *vm,
const char *alias,
unsigned long long size,
void *opaque);
typedef struct _qemuMonitorCallbacks qemuMonitorCallbacks; typedef struct _qemuMonitorCallbacks qemuMonitorCallbacks;
struct _qemuMonitorCallbacks { struct _qemuMonitorCallbacks {
qemuMonitorEofNotifyCallback eofNotify; qemuMonitorEofNotifyCallback eofNotify;
@ -437,6 +452,7 @@ struct _qemuMonitorCallbacks {
qemuMonitorDomainRdmaGidStatusChangedCallback domainRdmaGidStatusChanged; qemuMonitorDomainRdmaGidStatusChangedCallback domainRdmaGidStatusChanged;
qemuMonitorDomainGuestCrashloadedCallback domainGuestCrashloaded; qemuMonitorDomainGuestCrashloadedCallback domainGuestCrashloaded;
qemuMonitorDomainMemoryFailureCallback domainMemoryFailure; qemuMonitorDomainMemoryFailureCallback domainMemoryFailure;
qemuMonitorDomainMemoryDeviceSizeChange domainMemoryDeviceSizeChange;
}; };
qemuMonitor *qemuMonitorOpen(virDomainObj *vm, qemuMonitor *qemuMonitorOpen(virDomainObj *vm,
@ -532,6 +548,10 @@ void qemuMonitorEmitSerialChange(qemuMonitor *mon,
bool connected); bool connected);
void qemuMonitorEmitSpiceMigrated(qemuMonitor *mon); void qemuMonitorEmitSpiceMigrated(qemuMonitor *mon);
void qemuMonitorEmitMemoryDeviceSizeChange(qemuMonitor *mon,
const char *devAlias,
unsigned long long size);
void qemuMonitorEmitMemoryFailure(qemuMonitor *mon, void qemuMonitorEmitMemoryFailure(qemuMonitor *mon,
qemuMonitorEventMemoryFailure *mfp); qemuMonitorEventMemoryFailure *mfp);

View File

@ -112,6 +112,7 @@ static void qemuMonitorJSONHandleDumpCompleted(qemuMonitor *mon, virJSONValue *d
static void qemuMonitorJSONHandlePRManagerStatusChanged(qemuMonitor *mon, virJSONValue *data); static void qemuMonitorJSONHandlePRManagerStatusChanged(qemuMonitor *mon, virJSONValue *data);
static void qemuMonitorJSONHandleRdmaGidStatusChanged(qemuMonitor *mon, virJSONValue *data); static void qemuMonitorJSONHandleRdmaGidStatusChanged(qemuMonitor *mon, virJSONValue *data);
static void qemuMonitorJSONHandleMemoryFailure(qemuMonitor *mon, virJSONValue *data); static void qemuMonitorJSONHandleMemoryFailure(qemuMonitor *mon, virJSONValue *data);
static void qemuMonitorJSONHandleMemoryDeviceSizeChange(qemuMonitor *mon, virJSONValue *data);
typedef struct { typedef struct {
const char *type; const char *type;
@ -132,6 +133,7 @@ static qemuEventHandler eventHandlers[] = {
{ "GUEST_CRASHLOADED", qemuMonitorJSONHandleGuestCrashloaded, }, { "GUEST_CRASHLOADED", qemuMonitorJSONHandleGuestCrashloaded, },
{ "GUEST_PANICKED", qemuMonitorJSONHandleGuestPanic, }, { "GUEST_PANICKED", qemuMonitorJSONHandleGuestPanic, },
{ "JOB_STATUS_CHANGE", qemuMonitorJSONHandleJobStatusChange, }, { "JOB_STATUS_CHANGE", qemuMonitorJSONHandleJobStatusChange, },
{ "MEMORY_DEVICE_SIZE_CHANGE", qemuMonitorJSONHandleMemoryDeviceSizeChange, },
{ "MEMORY_FAILURE", qemuMonitorJSONHandleMemoryFailure, }, { "MEMORY_FAILURE", qemuMonitorJSONHandleMemoryFailure, },
{ "MIGRATION", qemuMonitorJSONHandleMigrationStatus, }, { "MIGRATION", qemuMonitorJSONHandleMigrationStatus, },
{ "MIGRATION_PASS", qemuMonitorJSONHandleMigrationPass, }, { "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 static void
qemuMonitorJSONHandleMemoryFailure(qemuMonitor *mon, qemuMonitorJSONHandleMemoryFailure(qemuMonitor *mon,
virJSONValue *data) virJSONValue *data)

View 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 = { static qemuMonitorCallbacks monitorCallbacks = {
.eofNotify = qemuProcessHandleMonitorEOF, .eofNotify = qemuProcessHandleMonitorEOF,
.errorNotify = qemuProcessHandleMonitorError, .errorNotify = qemuProcessHandleMonitorError,
@ -1866,6 +1907,7 @@ static qemuMonitorCallbacks monitorCallbacks = {
.domainRdmaGidStatusChanged = qemuProcessHandleRdmaGidStatusChanged, .domainRdmaGidStatusChanged = qemuProcessHandleRdmaGidStatusChanged,
.domainGuestCrashloaded = qemuProcessHandleGuestCrashloaded, .domainGuestCrashloaded = qemuProcessHandleGuestCrashloaded,
.domainMemoryFailure = qemuProcessHandleMemoryFailure, .domainMemoryFailure = qemuProcessHandleMemoryFailure,
.domainMemoryDeviceSizeChange = qemuProcessHandleMemoryDeviceSizeChange,
}; };
static void static void

View 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[] = { static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot),
@ -1361,6 +1390,7 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMetadataChange), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMetadataChange),
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockThreshold), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockThreshold),
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMemoryFailure), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMemoryFailure),
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMemoryDeviceSizeChange),
}; };
G_STATIC_ASSERT(G_N_ELEMENTS(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST); G_STATIC_ASSERT(G_N_ELEMENTS(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);

View File

@ -410,6 +410,10 @@ remoteDomainBuildEventMemoryFailure(virNetClientProgram *prog,
void *evdata, void *opaque); void *evdata, void *opaque);
static void static void
remoteDomainBuildEventMemoryDeviceSizeChange(virNetClientProgram *prog,
virNetClient *client,
void *evdata, void *opaque);
static void
remoteConnectNotifyEventConnectionClosed(virNetClientProgram *prog G_GNUC_UNUSED, remoteConnectNotifyEventConnectionClosed(virNetClientProgram *prog G_GNUC_UNUSED,
virNetClient *client G_GNUC_UNUSED, virNetClient *client G_GNUC_UNUSED,
void *evdata, void *opaque); void *evdata, void *opaque);
@ -624,6 +628,10 @@ static virNetClientProgramEvent remoteEvents[] = {
remoteDomainBuildEventMemoryFailure, remoteDomainBuildEventMemoryFailure,
sizeof(remote_domain_event_memory_failure_msg), sizeof(remote_domain_event_memory_failure_msg),
(xdrproc_t)xdr_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 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 static int
remoteStreamSend(virStreamPtr st, remoteStreamSend(virStreamPtr st,
const char *data, const char *data,

View 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. -----*/ /*----- Protocol. -----*/
/* Define the program number, protocol version and procedure numbers here. */ /* Define the program number, protocol version and procedure numbers here. */
@ -6892,5 +6899,11 @@ enum remote_procedure {
* @acl: network:write * @acl: network:write
* @acl: network:start * @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
}; };

View File

@ -3235,6 +3235,12 @@ struct remote_domain_start_dirty_rate_calc_args {
int seconds; int seconds;
u_int flags; 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 { enum remote_procedure {
REMOTE_PROC_CONNECT_OPEN = 1, REMOTE_PROC_CONNECT_OPEN = 1,
REMOTE_PROC_CONNECT_CLOSE = 2, REMOTE_PROC_CONNECT_CLOSE = 2,
@ -3673,4 +3679,5 @@ enum remote_procedure {
REMOTE_PROC_NODE_DEVICE_IS_PERSISTENT = 435, REMOTE_PROC_NODE_DEVICE_IS_PERSISTENT = 435,
REMOTE_PROC_NODE_DEVICE_IS_ACTIVE = 436, REMOTE_PROC_NODE_DEVICE_IS_ACTIVE = 436,
REMOTE_PROC_NETWORK_CREATE_XML_FLAGS = 437, REMOTE_PROC_NETWORK_CREATE_XML_FLAGS = 437,
REMOTE_PROC_DOMAIN_EVENT_MEMORY_DEVICE_SIZE_CHANGE = 438,
}; };

View 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[] = { virshDomainEventCallback virshDomainEventCallbacks[] = {
{ "lifecycle", { "lifecycle",
VIR_DOMAIN_EVENT_CALLBACK(virshEventLifecyclePrint), }, VIR_DOMAIN_EVENT_CALLBACK(virshEventLifecyclePrint), },
@ -13205,6 +13223,8 @@ virshDomainEventCallback virshDomainEventCallbacks[] = {
VIR_DOMAIN_EVENT_CALLBACK(virshEventBlockThresholdPrint), }, VIR_DOMAIN_EVENT_CALLBACK(virshEventBlockThresholdPrint), },
{ "memory-failure", { "memory-failure",
VIR_DOMAIN_EVENT_CALLBACK(virshEventMemoryFailurePrint), }, 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)); G_STATIC_ASSERT(VIR_DOMAIN_EVENT_ID_LAST == G_N_ELEMENTS(virshDomainEventCallbacks));