@@ -122,6 +122,8 @@ static VhostUserMsg m __attribute__ ((unused));
/* The version of the protocol we support */
#define VHOST_USER_VERSION (0x1)
+static unsigned int vhost_user_used_memslots;
+
struct vhost_user {
CharBackend *chr;
int slave_fd;
@@ -922,6 +924,33 @@ static void vhost_user_set_iotlb_callback(struct vhost_dev *dev, int enabled)
/* No-op as the receive channel is not dedicated to IOTLB messages. */
}
+static void vhost_user_set_used_memslots(struct vhost_dev *dev)
+{
+ int counter = 0;
+ int i;
+
+ for (i = 0; i < dev->mem->nregions; ++i) {
+ struct vhost_memory_region *reg = dev->mem->regions + i;
+ ram_addr_t offset;
+ MemoryRegion *mr;
+ int fd;
+
+ assert((uintptr_t)reg->userspace_addr == reg->userspace_addr);
+ mr = memory_region_from_host((void *)(uintptr_t)reg->userspace_addr,
+ &offset);
+ fd = memory_region_get_fd(mr);
+ if (fd > 0) {
+ counter++;
+ }
+ }
+ vhost_user_used_memslots = counter;
+}
+
+static unsigned int vhost_user_get_used_memslots(void)
+{
+ return vhost_user_used_memslots;
+}
+
const VhostOps user_ops = {
.backend_type = VHOST_BACKEND_TYPE_USER,
.vhost_backend_init = vhost_user_init,
@@ -948,4 +977,6 @@ const VhostOps user_ops = {
.vhost_net_set_mtu = vhost_user_net_set_mtu,
.vhost_set_iotlb_callback = vhost_user_set_iotlb_callback,
.vhost_send_device_iotlb_msg = vhost_user_send_device_iotlb_msg,
+ .vhost_set_used_memslots = vhost_user_set_used_memslots,
+ .vhost_get_used_memslots = vhost_user_get_used_memslots,
};
@@ -49,14 +49,21 @@ static QLIST_HEAD(, vhost_dev) vhost_devices =
bool vhost_has_free_slot(void)
{
- unsigned int slots_limit = ~0U;
struct vhost_dev *hdev;
QLIST_FOREACH(hdev, &vhost_devices, entry) {
unsigned int r = hdev->vhost_ops->vhost_backend_memslots_limit(hdev);
- slots_limit = MIN(slots_limit, r);
+
+ if (hdev->vhost_ops->vhost_get_used_memslots) {
+ if (hdev->vhost_ops->vhost_get_used_memslots() >= r) {
+ return false;
+ }
+ } else if (used_memslots >= r) {
+ return false;
+ }
}
- return slots_limit > used_memslots;
+
+ return true;
}
static void vhost_dev_sync_region(struct vhost_dev *dev,
@@ -607,6 +614,9 @@ static void vhost_set_memory(MemoryListener *listener,
dev->mem_changed_end_addr = MAX(dev->mem_changed_end_addr, start_addr + size - 1);
dev->memory_changed = true;
used_memslots = dev->mem->nregions;
+ if (dev->vhost_ops->vhost_set_used_memslots) {
+ dev->vhost_ops->vhost_set_used_memslots(dev);
+ }
}
static bool vhost_section(MemoryRegionSection *section)
@@ -1239,6 +1249,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
uint64_t features;
int i, r, n_initialized_vqs = 0;
Error *local_err = NULL;
+ unsigned int n_memslots = 0;
hdev->vdev = NULL;
hdev->migration_blocker = NULL;
@@ -1251,7 +1262,13 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
goto fail;
}
- if (used_memslots > hdev->vhost_ops->vhost_backend_memslots_limit(hdev)) {
+ if (hdev->vhost_ops->vhost_get_used_memslots) {
+ n_memslots = hdev->vhost_ops->vhost_get_used_memslots();
+ } else {
+ n_memslots = used_memslots;
+ }
+
+ if (n_memslots > hdev->vhost_ops->vhost_backend_memslots_limit(hdev)) {
error_report("vhost backend memory slots limit is less"
" than current number of present memory slots");
r = -1;
@@ -84,6 +84,8 @@ typedef void (*vhost_set_iotlb_callback_op)(struct vhost_dev *dev,
int enabled);
typedef int (*vhost_send_device_iotlb_msg_op)(struct vhost_dev *dev,
struct vhost_iotlb_msg *imsg);
+typedef void (*vhost_set_used_memslots_op)(struct vhost_dev *dev);
+typedef unsigned int (*vhost_get_used_memslots_op)(void);
typedef struct VhostOps {
VhostBackendType backend_type;
@@ -118,6 +120,8 @@ typedef struct VhostOps {
vhost_vsock_set_running_op vhost_vsock_set_running;
vhost_set_iotlb_callback_op vhost_set_iotlb_callback;
vhost_send_device_iotlb_msg_op vhost_send_device_iotlb_msg;
+ vhost_set_used_memslots_op vhost_set_used_memslots;
+ vhost_get_used_memslots_op vhost_get_used_memslots;
} VhostOps;
extern const VhostOps user_ops;