qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v4 0/3] vhost: check if vhost has capacity for hotplugged memory
@ 2015-10-06  8:37 Igor Mammedov
  2015-10-06  8:37 ` [Qemu-devel] [PATCH v4 1/3] vhost: add vhost_has_free_slot() interface Igor Mammedov
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Igor Mammedov @ 2015-10-06  8:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: marcel, mst

v3->v4:
  * rescan all vhost backends when checking for limit (Michael S. Tsirkin)
  * check that used slots are less than limit of new backend (Michael S. Tsirkin)
v2->v3:
  * add refcounting of limit by # vhost devices,
    and make vhost_has_free_slot() return true if no vhost devices
    are present at current moment
  * move limit initialization to vhost_dev_init()
  * fail vhost backend intialization if memslots number is more than its supported limit

v1->v2:
  * replace probbing with checking for
    /sys/module/vhost/parameters/max_mem_regions and
    if it's missing has non wrong value return
    hardcoded legacy limit (64 slots).

it's defensive patchset which helps to avoid QEMU crashing
at memory hotplug time by checking that vhost has free capacity
for an additional memory slot.

Igor Mammedov (3):
  vhost: add vhost_has_free_slot() interface
  pc-dimm: add vhost slots limit check before commiting to hotplug
  vhost: fail backend intialization if memslots number is more than its
    supported limit

 hw/mem/pc-dimm.c                  |  7 +++++++
 hw/virtio/vhost-backend.c         | 19 +++++++++++++++++++
 hw/virtio/vhost-user.c            |  6 ++++++
 hw/virtio/vhost.c                 | 27 +++++++++++++++++++++++++++
 include/hw/virtio/vhost-backend.h |  2 ++
 include/hw/virtio/vhost.h         |  2 ++
 stubs/Makefile.objs               |  1 +
 stubs/vhost.c                     |  6 ++++++
 8 files changed, 70 insertions(+)
 create mode 100644 stubs/vhost.c

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Qemu-devel] [PATCH v4 1/3] vhost: add vhost_has_free_slot() interface
  2015-10-06  8:37 [Qemu-devel] [PATCH v4 0/3] vhost: check if vhost has capacity for hotplugged memory Igor Mammedov
@ 2015-10-06  8:37 ` Igor Mammedov
  2015-10-06  8:37 ` [Qemu-devel] [PATCH v4 2/3] pc-dimm: add vhost slots limit check before commiting to hotplug Igor Mammedov
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Igor Mammedov @ 2015-10-06  8:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: marcel, mst

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>
---
v4:
  * rescan all vhost backends when checking for limit (Michael S. Tsirkin)
v3:
  * add refcountin of limit by # vhost devices,
    and make vhost_has_free_slot() return true if no vhost devices
    are present at current moment
  * move limit initialization to vhost_dev_init()
v2:
  * replace probbing with checking for
    /sys/module/vhost/parameters/max_mem_regions and
    if it's missing has non wrong value return
    hardcoded legacy limit (64 slots).

fixup1
---
 hw/virtio/vhost-backend.c         | 19 +++++++++++++++++++
 hw/virtio/vhost-user.c            |  6 ++++++
 hw/virtio/vhost.c                 | 21 +++++++++++++++++++++
 include/hw/virtio/vhost-backend.h |  2 ++
 include/hw/virtio/vhost.h         |  2 ++
 stubs/Makefile.objs               |  1 +
 stubs/vhost.c                     |  6 ++++++
 7 files changed, 57 insertions(+)
 create mode 100644 stubs/vhost.c

diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c
index 72d1392..910d8e0 100644
--- a/hw/virtio/vhost-backend.c
+++ b/hw/virtio/vhost-backend.c
@@ -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)
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index b11c0d2..9585637 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -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,
 };
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index c0ed5b2..a3b4f9e 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -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.
diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h
index 3a0f6e2..7d4a8ad 100644
--- a/include/hw/virtio/vhost-backend.h
+++ b/include/hw/virtio/vhost-backend.h
@@ -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;
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index c3758f3..080831e 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -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
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 85e4e81..ce6ce11 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -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
diff --git a/stubs/vhost.c b/stubs/vhost.c
new file mode 100644
index 0000000..d346b85
--- /dev/null
+++ b/stubs/vhost.c
@@ -0,0 +1,6 @@
+#include "hw/virtio/vhost.h"
+
+bool vhost_has_free_slot(void)
+{
+    return true;
+}
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [Qemu-devel] [PATCH v4 2/3] pc-dimm: add vhost slots limit check before commiting to hotplug
  2015-10-06  8:37 [Qemu-devel] [PATCH v4 0/3] vhost: check if vhost has capacity for hotplugged memory Igor Mammedov
  2015-10-06  8:37 ` [Qemu-devel] [PATCH v4 1/3] vhost: add vhost_has_free_slot() interface Igor Mammedov
@ 2015-10-06  8:37 ` Igor Mammedov
  2015-10-06  8:37 ` [Qemu-devel] [PATCH v4 3/3] vhost: fail backend intialization if memslots number is more than its supported limit Igor Mammedov
  2015-10-13 10:44 ` [Qemu-devel] [PATCH v4 0/3] vhost: check if vhost has capacity for hotplugged memory Igor Mammedov
  3 siblings, 0 replies; 5+ messages in thread
From: Igor Mammedov @ 2015-10-06  8:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: marcel, mst

it allows safely cancel memory hotplug if vhost backend
doesn't support necessary amount of memory slots and prevents
QEMU crashing in vhost due to hitting vhost limit on amount
of supported memory ranges.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 hw/mem/pc-dimm.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
index 6cc6ac3..dbf1b3a 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/pc-dimm.c
@@ -25,6 +25,7 @@
 #include "sysemu/numa.h"
 #include "sysemu/kvm.h"
 #include "trace.h"
+#include "hw/virtio/vhost.h"
 
 typedef struct pc_dimms_capacity {
      uint64_t size;
@@ -96,6 +97,12 @@ void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
         goto out;
     }
 
+    if (!vhost_has_free_slot()) {
+        error_setg(&local_err, "a used vhost backend has no free"
+                               " memory slots left");
+        goto out;
+    }
+
     memory_region_add_subregion(&hpms->mr, addr - hpms->base, mr);
     vmstate_register_ram(mr, dev);
     numa_set_mem_node_id(addr, memory_region_size(mr), dimm->node);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [Qemu-devel] [PATCH v4 3/3] vhost: fail backend intialization if memslots number is more than its supported limit
  2015-10-06  8:37 [Qemu-devel] [PATCH v4 0/3] vhost: check if vhost has capacity for hotplugged memory Igor Mammedov
  2015-10-06  8:37 ` [Qemu-devel] [PATCH v4 1/3] vhost: add vhost_has_free_slot() interface Igor Mammedov
  2015-10-06  8:37 ` [Qemu-devel] [PATCH v4 2/3] pc-dimm: add vhost slots limit check before commiting to hotplug Igor Mammedov
@ 2015-10-06  8:37 ` Igor Mammedov
  2015-10-13 10:44 ` [Qemu-devel] [PATCH v4 0/3] vhost: check if vhost has capacity for hotplugged memory Igor Mammedov
  3 siblings, 0 replies; 5+ messages in thread
From: Igor Mammedov @ 2015-10-06  8:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: marcel, mst

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
v4:
  * check that used slots are less than limit of new backend
    (Michael S. Tsirkin)
---
 hw/virtio/vhost.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index a3b4f9e..f14a5c5 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -933,6 +933,12 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
         return -errno;
     }
 
+    if (used_memslots > hdev->vhost_ops->vhost_backend_memslots_limit(hdev)) {
+        fprintf(stderr, "vhost backend memory slots limit is less"
+                " than current number of present memory slots\n");
+        close((uintptr_t)opaque);
+        return -1;
+    }
     QLIST_INSERT_HEAD(&vhost_devices, hdev, entry);
 
     r = hdev->vhost_ops->vhost_call(hdev, VHOST_SET_OWNER, NULL);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH v4 0/3] vhost: check if vhost has capacity for hotplugged memory
  2015-10-06  8:37 [Qemu-devel] [PATCH v4 0/3] vhost: check if vhost has capacity for hotplugged memory Igor Mammedov
                   ` (2 preceding siblings ...)
  2015-10-06  8:37 ` [Qemu-devel] [PATCH v4 3/3] vhost: fail backend intialization if memslots number is more than its supported limit Igor Mammedov
@ 2015-10-13 10:44 ` Igor Mammedov
  3 siblings, 0 replies; 5+ messages in thread
From: Igor Mammedov @ 2015-10-13 10:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: marcel, mst

On Tue,  6 Oct 2015 10:37:26 +0200
Igor Mammedov <imammedo@redhat.com> wrote:

> v3->v4:
>   * rescan all vhost backends when checking for limit (Michael S. Tsirkin)
>   * check that used slots are less than limit of new backend (Michael S. Tsirkin)
ping

> v2->v3:
>   * add refcounting of limit by # vhost devices,
>     and make vhost_has_free_slot() return true if no vhost devices
>     are present at current moment
>   * move limit initialization to vhost_dev_init()
>   * fail vhost backend intialization if memslots number is more than its supported limit
> 
> v1->v2:
>   * replace probbing with checking for
>     /sys/module/vhost/parameters/max_mem_regions and
>     if it's missing has non wrong value return
>     hardcoded legacy limit (64 slots).
> 
> it's defensive patchset which helps to avoid QEMU crashing
> at memory hotplug time by checking that vhost has free capacity
> for an additional memory slot.
> 
> Igor Mammedov (3):
>   vhost: add vhost_has_free_slot() interface
>   pc-dimm: add vhost slots limit check before commiting to hotplug
>   vhost: fail backend intialization if memslots number is more than its
>     supported limit
> 
>  hw/mem/pc-dimm.c                  |  7 +++++++
>  hw/virtio/vhost-backend.c         | 19 +++++++++++++++++++
>  hw/virtio/vhost-user.c            |  6 ++++++
>  hw/virtio/vhost.c                 | 27 +++++++++++++++++++++++++++
>  include/hw/virtio/vhost-backend.h |  2 ++
>  include/hw/virtio/vhost.h         |  2 ++
>  stubs/Makefile.objs               |  1 +
>  stubs/vhost.c                     |  6 ++++++
>  8 files changed, 70 insertions(+)
>  create mode 100644 stubs/vhost.c
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-10-13 10:44 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-10-06  8:37 [Qemu-devel] [PATCH v4 0/3] vhost: check if vhost has capacity for hotplugged memory Igor Mammedov
2015-10-06  8:37 ` [Qemu-devel] [PATCH v4 1/3] vhost: add vhost_has_free_slot() interface Igor Mammedov
2015-10-06  8:37 ` [Qemu-devel] [PATCH v4 2/3] pc-dimm: add vhost slots limit check before commiting to hotplug Igor Mammedov
2015-10-06  8:37 ` [Qemu-devel] [PATCH v4 3/3] vhost: fail backend intialization if memslots number is more than its supported limit Igor Mammedov
2015-10-13 10:44 ` [Qemu-devel] [PATCH v4 0/3] vhost: check if vhost has capacity for hotplugged memory Igor Mammedov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).