diff options
author | Thanos Makatos <thanos.makatos@nutanix.com> | 2020-12-15 14:56:32 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-15 14:56:32 +0000 |
commit | 8694149b351e3e125aa8f1740f8d5925e7ec112c (patch) | |
tree | 55fae56b5280eddd8c5c23d8c846fe36425e7ba2 /samples/client.c | |
parent | 3148a598f4ac0711d2f46ef9186e51a4779f1bf1 (diff) | |
download | libvfio-user-8694149b351e3e125aa8f1740f8d5925e7ec112c.zip libvfio-user-8694149b351e3e125aa8f1740f8d5925e7ec112c.tar.gz libvfio-user-8694149b351e3e125aa8f1740f8d5925e7ec112c.tar.bz2 |
send file descriptors for sparse areas in get region info (#201)
Signed-off-by: Thanos Makatos <thanos.makatos@nutanix.com>
Diffstat (limited to 'samples/client.c')
-rw-r--r-- | samples/client.c | 55 |
1 files changed, 38 insertions, 17 deletions
diff --git a/samples/client.c b/samples/client.c index 3e3ba54..576815d 100644 --- a/samples/client.c +++ b/samples/client.c @@ -207,10 +207,10 @@ send_device_reset(int sock) /* returns whether a VFIO migration capability is found */ static bool -get_region_vfio_caps(struct vfio_info_cap_header *header) +get_region_vfio_caps(struct vfio_info_cap_header *header, + struct vfio_region_info_cap_sparse_mmap *sparse) { struct vfio_region_info_cap_type *type; - struct vfio_region_info_cap_sparse_mmap *sparse; unsigned int i; bool migr = false; @@ -247,13 +247,12 @@ get_region_vfio_caps(struct vfio_info_cap_header *header) } static void -do_get_device_region_info(int sock, struct vfio_region_info *region_info) +do_get_device_region_info(int sock, struct vfio_region_info *region_info, + int *fds, size_t *nr_fds) { - int ret = vfu_msg(sock, 0, - VFIO_USER_DEVICE_GET_REGION_INFO, - region_info, region_info->argsz, - NULL, - region_info, region_info->argsz); + int ret = vfu_msg_fds(sock, 0, VFIO_USER_DEVICE_GET_REGION_INFO, + region_info, region_info->argsz, NULL, + region_info, region_info->argsz, fds, nr_fds); if (ret < 0) { errx(EXIT_FAILURE, "failed to get device region info: %s", strerror(-ret)); @@ -266,19 +265,24 @@ get_device_region_info(int sock, uint32_t index) struct vfio_region_info *region_info; size_t cap_sz; size_t size = sizeof(struct vfio_region_info); + size_t nr_fds = CLIENT_MAX_FDS; + int fds[nr_fds]; region_info = alloca(size); region_info->argsz = size; region_info->index = index; - do_get_device_region_info(sock, region_info); + do_get_device_region_info(sock, region_info, NULL, 0); if (region_info->argsz > size) { size = region_info->size; region_info = alloca(size); region_info->argsz = size; region_info->index = index; - do_get_device_region_info(sock, region_info); + do_get_device_region_info(sock, region_info, fds, &nr_fds); assert(region_info->size == size); + assert(nr_fds == 2); + assert(fds[0] >= 0); + assert(fds[1] >= 0); } cap_sz = region_info->argsz - sizeof(struct vfio_region_info); @@ -286,7 +290,25 @@ get_device_region_info(int sock, uint32_t index) "cap_sz %lu\n", __func__, index, region_info->offset, region_info->flags, region_info->size, cap_sz); if (cap_sz) { - if (get_region_vfio_caps((struct vfio_info_cap_header*)(region_info + 1))) { + struct vfio_region_info_cap_sparse_mmap *sparse = NULL; + if (get_region_vfio_caps((struct vfio_info_cap_header*)(region_info + 1), + sparse)) { + if (sparse != NULL) { + size_t i; + assert(nr_fds == 2); + assert(sparse->nr_areas == 2); + for (i = 0; i < sparse->nr_areas; i++) { + void *addr = mmap(NULL, sparse->areas[i].size, + PROT_READ | PROT_WRITE, MAP_SHARED, + fds[i], sparse->areas[i].offset); + if (addr == MAP_FAILED) { + err(EXIT_FAILURE, + "failed to mmap sparse region %lu (%#llx-%#llx)", + i, sparse->areas[i].offset, + sparse->areas[i].offset + sparse->areas[i].size - 1); + } + } + } return true; } } @@ -386,7 +408,7 @@ configure_irqs(int sock) ret = vfu_msg_iovec(sock, msg_id, VFIO_USER_DEVICE_SET_IRQS, iovecs, ARRAY_SIZE(iovecs), &irq_fd, 1, - NULL, NULL, 0); + NULL, NULL, 0, NULL, 0); if (ret < 0) { errx(EXIT_FAILURE, "failed to send configure IRQs message: %s", @@ -435,7 +457,7 @@ access_region(int sock, int region, bool is_write, uint64_t offset, ret = vfu_msg_iovec(sock, 0, op, send_iovecs, nr_send_iovecs, NULL, 0, NULL, - &recv_data, recv_data_len); + &recv_data, recv_data_len, NULL, 0); if (ret != 0) { warnx("failed to %s region %d %#lx-%#lx: %s", is_write ? "write to" : "read from", region, offset, @@ -475,8 +497,7 @@ wait_for_irqs(int sock, int irq_fd) printf("INTx triggered!\n"); size = sizeof(vfio_user_irq_info); - ret = vfu_recv(sock, &hdr, false, &msg_id, - &vfio_user_irq_info, &size); + ret = vfu_recv(sock, &hdr, false, &msg_id, &vfio_user_irq_info, &size); if (ret < 0) { errx(EXIT_FAILURE, "failed to receive IRQ message: %s", strerror(-ret)); @@ -664,7 +685,7 @@ get_dirty_bitmaps(int sock, struct vfio_user_dma_region *dma_regions, ret = vfu_msg_iovec(sock, 0, VFIO_USER_DIRTY_PAGES, iovecs, ARRAY_SIZE(iovecs), NULL, 0, - &hdr, data, ARRAY_SIZE(data)); + &hdr, data, ARRAY_SIZE(data), NULL, 0); if (ret != 0) { errx(EXIT_FAILURE, "failed to start dirty page logging: %s", strerror(-ret)); @@ -903,7 +924,7 @@ map_dma_regions(int sock, int max_fds, struct vfio_user_dma_region *dma_regions, ret = vfu_msg_iovec(sock, i, VFIO_USER_DMA_MAP, iovecs, ARRAY_SIZE(iovecs), dma_region_fds + (i * max_fds), max_fds, - NULL, NULL, 0); + NULL, NULL, 0, NULL, 0); if (ret < 0) { errx(EXIT_FAILURE, "failed to map DMA regions: %s", strerror(-ret)); } |