@@ -450,10 +450,40 @@ static int virtio_mem_set_block_state(VirtIOMEM *vmem, uint64_t start_gpa,
return -EBUSY;
}
virtio_mem_notify_unplug(vmem, offset, size);
- } else if (virtio_mem_notify_plug(vmem, offset, size)) {
- /* Could be a mapping attempt resulted in memory getting populated. */
- ram_block_discard_range(vmem->memdev->mr.ram_block, offset, size);
- return -EBUSY;
+ } else {
+ int ret = 0;
+
+ if (vmem->prealloc) {
+ void *area = memory_region_get_ram_ptr(&vmem->memdev->mr) + offset;
+ int fd = memory_region_get_fd(&vmem->memdev->mr);
+ Error *local_err = NULL;
+
+ os_mem_prealloc(fd, area, size, 1, &local_err);
+ if (local_err) {
+ static bool warned;
+
+ /*
+ * Warn only once, we don't want to fill the log with these
+ * warnings.
+ */
+ if (!warned) {
+ warn_report_err(local_err);
+ warned = true;
+ } else {
+ error_free(local_err);
+ }
+ ret = -EBUSY;
+ }
+ }
+ if (!ret) {
+ ret = virtio_mem_notify_plug(vmem, offset, size);
+ }
+
+ if (ret) {
+ /* Could be preallocation or a notifier populated memory. */
+ ram_block_discard_range(vmem->memdev->mr.ram_block, offset, size);
+ return -EBUSY;
+ }
}
virtio_mem_set_bitmap(vmem, start_gpa, size, plug);
return 0;
@@ -1165,6 +1195,7 @@ static void virtio_mem_instance_init(Object *obj)
static Property virtio_mem_properties[] = {
DEFINE_PROP_UINT64(VIRTIO_MEM_ADDR_PROP, VirtIOMEM, addr, 0),
DEFINE_PROP_UINT32(VIRTIO_MEM_NODE_PROP, VirtIOMEM, node, 0),
+ DEFINE_PROP_BOOL(VIRTIO_MEM_PREALLOC_PROP, VirtIOMEM, prealloc, false),
DEFINE_PROP_LINK(VIRTIO_MEM_MEMDEV_PROP, VirtIOMEM, memdev,
TYPE_MEMORY_BACKEND, HostMemoryBackend *),
#if defined(VIRTIO_MEM_HAS_LEGACY_GUESTS)
@@ -31,6 +31,7 @@ OBJECT_DECLARE_TYPE(VirtIOMEM, VirtIOMEMClass,
#define VIRTIO_MEM_BLOCK_SIZE_PROP "block-size"
#define VIRTIO_MEM_ADDR_PROP "memaddr"
#define VIRTIO_MEM_UNPLUGGED_INACCESSIBLE_PROP "unplugged-inaccessible"
+#define VIRTIO_MEM_PREALLOC_PROP "prealloc"
struct VirtIOMEM {
VirtIODevice parent_obj;
@@ -70,6 +71,9 @@ struct VirtIOMEM {
*/
OnOffAuto unplugged_inaccessible;
+ /* whether to prealloc memory when plugging new blocks */
+ bool prealloc;
+
/* notifiers to notify when "size" changes */
NotifierList size_change_notifiers;