vhost: add vhost_has_free_slot() interface
it will allow for other parts of QEMU check if it's safe to map memory region during hotplug/runtime. That way hotplug path will have a chance to cancel hotplug operation instead of crashing in vhost_commit(). Signed-off-by: Igor Mammedov <imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
		
							parent
							
								
									052bd52fa9
								
							
						
					
					
						commit
						2ce68e4cf5
					
				| 
						 | 
				
			
			@ -11,6 +11,7 @@
 | 
			
		|||
#include "hw/virtio/vhost.h"
 | 
			
		||||
#include "hw/virtio/vhost-backend.h"
 | 
			
		||||
#include "qemu/error-report.h"
 | 
			
		||||
#include "linux/vhost.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -49,12 +50,30 @@ static int vhost_kernel_get_vq_index(struct vhost_dev *dev, int idx)
 | 
			
		|||
    return idx - dev->vq_index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int vhost_kernel_memslots_limit(struct vhost_dev *dev)
 | 
			
		||||
{
 | 
			
		||||
    int limit = 64;
 | 
			
		||||
    char *s;
 | 
			
		||||
 | 
			
		||||
    if (g_file_get_contents("/sys/module/vhost/parameters/max_mem_regions",
 | 
			
		||||
                            &s, NULL, NULL)) {
 | 
			
		||||
        uint64_t val = g_ascii_strtoull(s, NULL, 10);
 | 
			
		||||
        if (!((val == G_MAXUINT64 || !val) && errno)) {
 | 
			
		||||
            return val;
 | 
			
		||||
        }
 | 
			
		||||
        error_report("ignoring invalid max_mem_regions value in vhost module:"
 | 
			
		||||
                     " %s", s);
 | 
			
		||||
    }
 | 
			
		||||
    return limit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const VhostOps kernel_ops = {
 | 
			
		||||
        .backend_type = VHOST_BACKEND_TYPE_KERNEL,
 | 
			
		||||
        .vhost_call = vhost_kernel_call,
 | 
			
		||||
        .vhost_backend_init = vhost_kernel_init,
 | 
			
		||||
        .vhost_backend_cleanup = vhost_kernel_cleanup,
 | 
			
		||||
        .vhost_backend_get_vq_index = vhost_kernel_get_vq_index,
 | 
			
		||||
        .vhost_backend_memslots_limit = vhost_kernel_memslots_limit,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType backend_type)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -440,6 +440,11 @@ static int vhost_user_get_vq_index(struct vhost_dev *dev, int idx)
 | 
			
		|||
    return idx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int vhost_user_memslots_limit(struct vhost_dev *dev)
 | 
			
		||||
{
 | 
			
		||||
    return VHOST_MEMORY_MAX_NREGIONS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const VhostOps user_ops = {
 | 
			
		||||
        .backend_type = VHOST_BACKEND_TYPE_USER,
 | 
			
		||||
        .vhost_call = vhost_user_call,
 | 
			
		||||
| 
						 | 
				
			
			@ -447,4 +452,5 @@ const VhostOps user_ops = {
 | 
			
		|||
        .vhost_backend_cleanup = vhost_user_cleanup,
 | 
			
		||||
        .vhost_backend_get_vq_index = vhost_user_get_vq_index,
 | 
			
		||||
        .vhost_backend_set_vring_enable = vhost_user_set_vring_enable,
 | 
			
		||||
        .vhost_backend_memslots_limit = vhost_user_memslots_limit,
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,6 +26,22 @@
 | 
			
		|||
 | 
			
		||||
static struct vhost_log *vhost_log;
 | 
			
		||||
 | 
			
		||||
static unsigned int used_memslots;
 | 
			
		||||
static QLIST_HEAD(, vhost_dev) vhost_devices =
 | 
			
		||||
    QLIST_HEAD_INITIALIZER(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);
 | 
			
		||||
    }
 | 
			
		||||
    return slots_limit > used_memslots;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void vhost_dev_sync_region(struct vhost_dev *dev,
 | 
			
		||||
                                  MemoryRegionSection *section,
 | 
			
		||||
                                  uint64_t mfirst, uint64_t mlast,
 | 
			
		||||
| 
						 | 
				
			
			@ -457,6 +473,7 @@ static void vhost_set_memory(MemoryListener *listener,
 | 
			
		|||
    dev->mem_changed_start_addr = MIN(dev->mem_changed_start_addr, start_addr);
 | 
			
		||||
    dev->mem_changed_end_addr = MAX(dev->mem_changed_end_addr, start_addr + size - 1);
 | 
			
		||||
    dev->memory_changed = true;
 | 
			
		||||
    used_memslots = dev->mem->nregions;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool vhost_section(MemoryRegionSection *section)
 | 
			
		||||
| 
						 | 
				
			
			@ -916,6 +933,8 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
 | 
			
		|||
        return -errno;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QLIST_INSERT_HEAD(&vhost_devices, hdev, entry);
 | 
			
		||||
 | 
			
		||||
    r = hdev->vhost_ops->vhost_call(hdev, VHOST_SET_OWNER, NULL);
 | 
			
		||||
    if (r < 0) {
 | 
			
		||||
        goto fail;
 | 
			
		||||
| 
						 | 
				
			
			@ -972,6 +991,7 @@ fail_vq:
 | 
			
		|||
fail:
 | 
			
		||||
    r = -errno;
 | 
			
		||||
    hdev->vhost_ops->vhost_backend_cleanup(hdev);
 | 
			
		||||
    QLIST_REMOVE(hdev, entry);
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -989,6 +1009,7 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
 | 
			
		|||
    g_free(hdev->mem);
 | 
			
		||||
    g_free(hdev->mem_sections);
 | 
			
		||||
    hdev->vhost_ops->vhost_backend_cleanup(hdev);
 | 
			
		||||
    QLIST_REMOVE(hdev, entry);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Stop processing guest IO notifications in qemu.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,6 +26,7 @@ typedef int (*vhost_backend_init)(struct vhost_dev *dev, void *opaque);
 | 
			
		|||
typedef int (*vhost_backend_cleanup)(struct vhost_dev *dev);
 | 
			
		||||
typedef int (*vhost_backend_get_vq_index)(struct vhost_dev *dev, int idx);
 | 
			
		||||
typedef int (*vhost_backend_set_vring_enable)(struct vhost_dev *dev, int enable);
 | 
			
		||||
typedef int (*vhost_backend_memslots_limit)(struct vhost_dev *dev);
 | 
			
		||||
 | 
			
		||||
typedef struct VhostOps {
 | 
			
		||||
    VhostBackendType backend_type;
 | 
			
		||||
| 
						 | 
				
			
			@ -34,6 +35,7 @@ typedef struct VhostOps {
 | 
			
		|||
    vhost_backend_cleanup vhost_backend_cleanup;
 | 
			
		||||
    vhost_backend_get_vq_index vhost_backend_get_vq_index;
 | 
			
		||||
    vhost_backend_set_vring_enable vhost_backend_set_vring_enable;
 | 
			
		||||
    vhost_backend_memslots_limit vhost_backend_memslots_limit;
 | 
			
		||||
} VhostOps;
 | 
			
		||||
 | 
			
		||||
extern const VhostOps user_ops;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -59,6 +59,7 @@ struct vhost_dev {
 | 
			
		|||
    const VhostOps *vhost_ops;
 | 
			
		||||
    void *opaque;
 | 
			
		||||
    struct vhost_log *log;
 | 
			
		||||
    QLIST_ENTRY(vhost_dev) entry;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
 | 
			
		||||
| 
						 | 
				
			
			@ -83,4 +84,5 @@ uint64_t vhost_get_features(struct vhost_dev *hdev, const int *feature_bits,
 | 
			
		|||
                            uint64_t features);
 | 
			
		||||
void vhost_ack_features(struct vhost_dev *hdev, const int *feature_bits,
 | 
			
		||||
                        uint64_t features);
 | 
			
		||||
bool vhost_has_free_slot(void);
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,3 +39,4 @@ stub-obj-y += cpus.o
 | 
			
		|||
stub-obj-y += kvm.o
 | 
			
		||||
stub-obj-y += qmp_pc_dimm_device_list.o
 | 
			
		||||
stub-obj-y += target-monitor-defs.o
 | 
			
		||||
stub-obj-y += vhost.o
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
#include "hw/virtio/vhost.h"
 | 
			
		||||
 | 
			
		||||
bool vhost_has_free_slot(void)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue