} else {
vmem->size -= size;
}
+ notifier_list_notify(&vmem->size_change_notifiers, &vmem->size);
return VIRTIO_MEM_RESP_ACK;
}
return -EBUSY;
}
bitmap_clear(vmem->bitmap, 0, vmem->bitmap_size);
- vmem->size = 0;
+ if (vmem->size) {
+ vmem->size = 0;
+ notifier_list_notify(&vmem->size_change_notifiers, &vmem->size);
+ }
virtio_mem_resize_usable_region(vmem, vmem->requested_size, true);
return 0;
return &vmem->memdev->mr;
}
+static void virtio_mem_add_size_change_notifier(VirtIOMEM *vmem,
+ Notifier *notifier)
+{
+ notifier_list_add(&vmem->size_change_notifiers, notifier);
+}
+
+static void virtio_mem_remove_size_change_notifier(VirtIOMEM *vmem,
+ Notifier *notifier)
+{
+ notifier_remove(notifier);
+}
+
static void virtio_mem_get_size(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
VirtIOMEM *vmem = VIRTIO_MEM(obj);
vmem->block_size = VIRTIO_MEM_MIN_BLOCK_SIZE;
+ notifier_list_init(&vmem->size_change_notifiers);
object_property_add(obj, VIRTIO_MEM_SIZE_PROP, "size", virtio_mem_get_size,
NULL, NULL, NULL);
vmc->fill_device_info = virtio_mem_fill_device_info;
vmc->get_memory_region = virtio_mem_get_memory_region;
+ vmc->add_size_change_notifier = virtio_mem_add_size_change_notifier;
+ vmc->remove_size_change_notifier = virtio_mem_remove_size_change_notifier;
}
static const TypeInfo virtio_mem_info = {
/* block size and alignment */
uint64_t block_size;
+
+ /* notifiers to notify when "size" changes */
+ NotifierList size_change_notifiers;
} VirtIOMEM;
typedef struct VirtIOMEMClass {
/* public */
void (*fill_device_info)(const VirtIOMEM *vmen, VirtioMEMDeviceInfo *vi);
MemoryRegion *(*get_memory_region)(VirtIOMEM *vmem, Error **errp);
+ void (*add_size_change_notifier)(VirtIOMEM *vmem, Notifier *notifier);
+ void (*remove_size_change_notifier)(VirtIOMEM *vmem, Notifier *notifier);
} VirtIOMEMClass;
#endif