[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 41/56] Refactor out libvhost-user fault generation logic
From: |
Michael S. Tsirkin |
Subject: |
[PULL 41/56] Refactor out libvhost-user fault generation logic |
Date: |
Wed, 10 Jun 2020 00:28:04 -0400 |
From: Raphael Norwitz <raphael.norwitz@nutanix.com>
In libvhost-user, the incoming postcopy migration path for setting the
backend's memory tables has become convolued. In particular, moving the
logic which starts generating faults, having received the final ACK from
qemu can be moved to a separate function. This simplifies the code
substantially.
This logic will also be needed by the postcopy path once the
VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS feature is supported.
Signed-off-by: Raphael Norwitz <raphael.norwitz@nutanix.com>
Message-Id: <1588533678-23450-7-git-send-email-raphael.norwitz@nutanix.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
contrib/libvhost-user/libvhost-user.c | 147 ++++++++++++++------------
1 file changed, 79 insertions(+), 68 deletions(-)
diff --git a/contrib/libvhost-user/libvhost-user.c
b/contrib/libvhost-user/libvhost-user.c
index 3bca996c62..cccfa22209 100644
--- a/contrib/libvhost-user/libvhost-user.c
+++ b/contrib/libvhost-user/libvhost-user.c
@@ -583,6 +583,84 @@ map_ring(VuDev *dev, VuVirtq *vq)
return !(vq->vring.desc && vq->vring.used && vq->vring.avail);
}
+static bool
+generate_faults(VuDev *dev) {
+ int i;
+ for (i = 0; i < dev->nregions; i++) {
+ VuDevRegion *dev_region = &dev->regions[i];
+ int ret;
+#ifdef UFFDIO_REGISTER
+ /*
+ * We should already have an open ufd. Mark each memory
+ * range as ufd.
+ * Discard any mapping we have here; note I can't use MADV_REMOVE
+ * or fallocate to make the hole since I don't want to lose
+ * data that's already arrived in the shared process.
+ * TODO: How to do hugepage
+ */
+ ret = madvise((void *)(uintptr_t)dev_region->mmap_addr,
+ dev_region->size + dev_region->mmap_offset,
+ MADV_DONTNEED);
+ if (ret) {
+ fprintf(stderr,
+ "%s: Failed to madvise(DONTNEED) region %d: %s\n",
+ __func__, i, strerror(errno));
+ }
+ /*
+ * Turn off transparent hugepages so we dont get lose wakeups
+ * in neighbouring pages.
+ * TODO: Turn this backon later.
+ */
+ ret = madvise((void *)(uintptr_t)dev_region->mmap_addr,
+ dev_region->size + dev_region->mmap_offset,
+ MADV_NOHUGEPAGE);
+ if (ret) {
+ /*
+ * Note: This can happen legally on kernels that are configured
+ * without madvise'able hugepages
+ */
+ fprintf(stderr,
+ "%s: Failed to madvise(NOHUGEPAGE) region %d: %s\n",
+ __func__, i, strerror(errno));
+ }
+ struct uffdio_register reg_struct;
+ reg_struct.range.start = (uintptr_t)dev_region->mmap_addr;
+ reg_struct.range.len = dev_region->size + dev_region->mmap_offset;
+ reg_struct.mode = UFFDIO_REGISTER_MODE_MISSING;
+
+ if (ioctl(dev->postcopy_ufd, UFFDIO_REGISTER, ®_struct)) {
+ vu_panic(dev, "%s: Failed to userfault region %d "
+ "@%p + size:%zx offset: %zx: (ufd=%d)%s\n",
+ __func__, i,
+ dev_region->mmap_addr,
+ dev_region->size, dev_region->mmap_offset,
+ dev->postcopy_ufd, strerror(errno));
+ return false;
+ }
+ if (!(reg_struct.ioctls & ((__u64)1 << _UFFDIO_COPY))) {
+ vu_panic(dev, "%s Region (%d) doesn't support COPY",
+ __func__, i);
+ return false;
+ }
+ DPRINT("%s: region %d: Registered userfault for %"
+ PRIx64 " + %" PRIx64 "\n", __func__, i,
+ (uint64_t)reg_struct.range.start,
+ (uint64_t)reg_struct.range.len);
+ /* Now it's registered we can let the client at it */
+ if (mprotect((void *)(uintptr_t)dev_region->mmap_addr,
+ dev_region->size + dev_region->mmap_offset,
+ PROT_READ | PROT_WRITE)) {
+ vu_panic(dev, "failed to mprotect region %d for postcopy (%s)",
+ i, strerror(errno));
+ return false;
+ }
+ /* TODO: Stash 'zero' support flags somewhere */
+#endif
+ }
+
+ return true;
+}
+
static bool
vu_set_mem_table_exec_postcopy(VuDev *dev, VhostUserMsg *vmsg)
{
@@ -655,74 +733,7 @@ vu_set_mem_table_exec_postcopy(VuDev *dev, VhostUserMsg
*vmsg)
}
/* OK, now we can go and register the memory and generate faults */
- for (i = 0; i < dev->nregions; i++) {
- VuDevRegion *dev_region = &dev->regions[i];
- int ret;
-#ifdef UFFDIO_REGISTER
- /* We should already have an open ufd. Mark each memory
- * range as ufd.
- * Discard any mapping we have here; note I can't use MADV_REMOVE
- * or fallocate to make the hole since I don't want to lose
- * data that's already arrived in the shared process.
- * TODO: How to do hugepage
- */
- ret = madvise((void *)(uintptr_t)dev_region->mmap_addr,
- dev_region->size + dev_region->mmap_offset,
- MADV_DONTNEED);
- if (ret) {
- fprintf(stderr,
- "%s: Failed to madvise(DONTNEED) region %d: %s\n",
- __func__, i, strerror(errno));
- }
- /* Turn off transparent hugepages so we dont get lose wakeups
- * in neighbouring pages.
- * TODO: Turn this backon later.
- */
- ret = madvise((void *)(uintptr_t)dev_region->mmap_addr,
- dev_region->size + dev_region->mmap_offset,
- MADV_NOHUGEPAGE);
- if (ret) {
- /* Note: This can happen legally on kernels that are configured
- * without madvise'able hugepages
- */
- fprintf(stderr,
- "%s: Failed to madvise(NOHUGEPAGE) region %d: %s\n",
- __func__, i, strerror(errno));
- }
- struct uffdio_register reg_struct;
- reg_struct.range.start = (uintptr_t)dev_region->mmap_addr;
- reg_struct.range.len = dev_region->size + dev_region->mmap_offset;
- reg_struct.mode = UFFDIO_REGISTER_MODE_MISSING;
-
- if (ioctl(dev->postcopy_ufd, UFFDIO_REGISTER, ®_struct)) {
- vu_panic(dev, "%s: Failed to userfault region %d "
- "@%p + size:%zx offset: %zx: (ufd=%d)%s\n",
- __func__, i,
- dev_region->mmap_addr,
- dev_region->size, dev_region->mmap_offset,
- dev->postcopy_ufd, strerror(errno));
- return false;
- }
- if (!(reg_struct.ioctls & ((__u64)1 << _UFFDIO_COPY))) {
- vu_panic(dev, "%s Region (%d) doesn't support COPY",
- __func__, i);
- return false;
- }
- DPRINT("%s: region %d: Registered userfault for %"
- PRIx64 " + %" PRIx64 "\n", __func__, i,
- (uint64_t)reg_struct.range.start,
- (uint64_t)reg_struct.range.len);
- /* Now it's registered we can let the client at it */
- if (mprotect((void *)(uintptr_t)dev_region->mmap_addr,
- dev_region->size + dev_region->mmap_offset,
- PROT_READ | PROT_WRITE)) {
- vu_panic(dev, "failed to mprotect region %d for postcopy (%s)",
- i, strerror(errno));
- return false;
- }
- /* TODO: Stash 'zero' support flags somewhere */
-#endif
- }
+ (void)generate_faults(dev);
return false;
}
--
MST
- [PULL 29/56] pci: assert configuration access is within bounds, (continued)
- [PULL 29/56] pci: assert configuration access is within bounds, Michael S. Tsirkin, 2020/06/10
- [PULL 31/56] hw/pci/pci_bridge: Correct pci_bridge_io memory region size, Michael S. Tsirkin, 2020/06/10
- [PULL 32/56] hw/pci/pci_bridge: Use the IEC binary prefix definitions, Michael S. Tsirkin, 2020/06/10
- [PULL 33/56] hw/pci-host: Use the IEC binary prefix definitions, Michael S. Tsirkin, 2020/06/10
- [PULL 35/56] vhost-user-blk: delay vhost_user_blk_disconnect, Michael S. Tsirkin, 2020/06/10
- [PULL 34/56] char-socket: return -1 in case of disconnect during tcp_chr_write, Michael S. Tsirkin, 2020/06/10
- [PULL 36/56] Add helper to populate vhost-user message regions, Michael S. Tsirkin, 2020/06/10
- [PULL 38/56] Add VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS, Michael S. Tsirkin, 2020/06/10
- [PULL 39/56] Transmit vhost-user memory regions individually, Michael S. Tsirkin, 2020/06/10
- [PULL 40/56] Lift max memory slots limit imposed by vhost-user, Michael S. Tsirkin, 2020/06/10
- [PULL 41/56] Refactor out libvhost-user fault generation logic,
Michael S. Tsirkin <=
- [PULL 42/56] Support ram slot configuration in libvhost-user, Michael S. Tsirkin, 2020/06/10
- [PULL 44/56] Support individual region unmap in libvhost-user, Michael S. Tsirkin, 2020/06/10
- [PULL 45/56] Lift max ram slots limit in libvhost-user, Michael S. Tsirkin, 2020/06/10
- [PULL 46/56] libvhost-user: advertise vring features, Michael S. Tsirkin, 2020/06/10
- [PULL 47/56] hw/pci: Fix crash when running QEMU with "-nic model=rocker", Michael S. Tsirkin, 2020/06/10
- [PULL 48/56] vhost-vsock: add vhost-vsock-common abstraction, Michael S. Tsirkin, 2020/06/10
- [PULL 50/56] virtio: add vhost-user-vsock-pci device, Michael S. Tsirkin, 2020/06/10
- [PULL 55/56] acpi: ged: rename event memory region, Michael S. Tsirkin, 2020/06/10
- [PULL 56/56] Fix parameter type in vhost migration log path, Michael S. Tsirkin, 2020/06/10
- [PULL 03/56] hw/acpi/nvdimm: add a helper to augment SRAT generation, Michael S. Tsirkin, 2020/06/10