aboutsummaryrefslogtreecommitdiff
path: root/samples/client.c
diff options
context:
space:
mode:
authorThanos Makatos <thanos.makatos@nutanix.com>2020-12-15 14:56:32 +0000
committerGitHub <noreply@github.com>2020-12-15 14:56:32 +0000
commit8694149b351e3e125aa8f1740f8d5925e7ec112c (patch)
tree55fae56b5280eddd8c5c23d8c846fe36425e7ba2 /samples/client.c
parent3148a598f4ac0711d2f46ef9186e51a4779f1bf1 (diff)
downloadlibvfio-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.c55
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));
}