Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@yandex-team.ru> --- hw/virtio/vhost.c | 71 ++++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 31 deletions(-)
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index a8f8b85012..f9163ba895 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -1553,11 +1553,49 @@ static void vhost_virtqueue_cleanup(struct vhost_virtqueue *vq) } } +static bool check_memslots(struct vhost_dev *hdev, Error **errp) +{ + unsigned int used, reserved, limit; + + limit = hdev->vhost_ops->vhost_backend_memslots_limit(hdev); + if (limit < MEMORY_DEVICES_SAFE_MAX_MEMSLOTS && + memory_devices_memslot_auto_decision_active()) { + error_setg(errp, "some memory device (like virtio-mem)" + " decided how many memory slots to use based on the overall" + " number of memory slots; this vhost backend would further" + " restricts the overall number of memory slots"); + error_append_hint(errp, "Try plugging this vhost backend before" + " plugging such memory devices.\n"); + return false; + } + + /* + * The listener we registered properly setup the number of required + * memslots in vhost_commit(). + */ + used = hdev->mem->nregions; + + /* + * We assume that all reserved memslots actually require a real memslot + * in our vhost backend. This might not be true, for example, if the + * memslot would be ROM. If ever relevant, we can optimize for that -- + * but we'll need additional information about the reservations. + */ + reserved = memory_devices_get_reserved_memslots(); + if (used + reserved > limit) { + error_setg(errp, "vhost backend memory slots limit (%d) is less" + " than current number of used (%d) and reserved (%d)" + " memory slots for memory devices.", limit, used, reserved); + return false; + } + + return true; +} + int vhost_dev_init(struct vhost_dev *hdev, void *opaque, VhostBackendType backend_type, uint32_t busyloop_timeout, Error **errp) { - unsigned int used, reserved, limit; uint64_t features; int i, r, n_initialized_vqs = 0; @@ -1584,19 +1622,6 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, goto fail; } - limit = hdev->vhost_ops->vhost_backend_memslots_limit(hdev); - if (limit < MEMORY_DEVICES_SAFE_MAX_MEMSLOTS && - memory_devices_memslot_auto_decision_active()) { - error_setg(errp, "some memory device (like virtio-mem)" - " decided how many memory slots to use based on the overall" - " number of memory slots; this vhost backend would further" - " restricts the overall number of memory slots"); - error_append_hint(errp, "Try plugging this vhost backend before" - " plugging such memory devices.\n"); - r = -EINVAL; - goto fail; - } - for (i = 0; i < hdev->nvqs; ++i, ++n_initialized_vqs) { r = vhost_virtqueue_init(hdev, hdev->vqs + i, hdev->vq_index + i, busyloop_timeout); @@ -1655,23 +1680,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, memory_listener_register(&hdev->memory_listener, &address_space_memory); QLIST_INSERT_HEAD(&vhost_devices, hdev, entry); - /* - * The listener we registered properly setup the number of required - * memslots in vhost_commit(). - */ - used = hdev->mem->nregions; - - /* - * We assume that all reserved memslots actually require a real memslot - * in our vhost backend. This might not be true, for example, if the - * memslot would be ROM. If ever relevant, we can optimize for that -- - * but we'll need additional information about the reservations. - */ - reserved = memory_devices_get_reserved_memslots(); - if (used + reserved > limit) { - error_setg(errp, "vhost backend memory slots limit (%d) is less" - " than current number of used (%d) and reserved (%d)" - " memory slots for memory devices.", limit, used, reserved); + if (!check_memslots(hdev, errp)) { r = -EINVAL; goto fail; } -- 2.48.1