aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/irq.c8
-rw-r--r--lib/libvfio-user.c30
-rw-r--r--lib/private.h4
-rw-r--r--test/unit-tests.c6
4 files changed, 33 insertions, 15 deletions
diff --git a/lib/irq.c b/lib/irq.c
index e5c0b6d..9a4beff 100644
--- a/lib/irq.c
+++ b/lib/irq.c
@@ -171,9 +171,13 @@ irqs_set_data_eventfd(vfu_ctx_t *vfu_ctx, struct vfio_irq_set *irq_set,
vfu_ctx->irqs->efds[i] = -1;
}
- if (data[j] >= 0) {
+ if (data[j] >= 0) { /* TODO IIUC this will always be >= 0? */
vfu_ctx->irqs->efds[i] = data[j];
- consume_fd(data, j);
+ /*
+ * We've already checked in handle_device_set_irqs that
+ * nr_fds == irq_set->count.
+ */
+ consume_fd(data, irq_set->count, j);
}
vfu_log(vfu_ctx, VFU_DBG, "event fd[%d]=%d", i, vfu_ctx->irqs->efds[i]);
}
diff --git a/lib/libvfio-user.c b/lib/libvfio-user.c
index a930258..e0b8465 100644
--- a/lib/libvfio-user.c
+++ b/lib/libvfio-user.c
@@ -500,10 +500,24 @@ handle_device_get_info(vfu_ctx_t *vfu_ctx, uint32_t size,
return 0;
}
+int
+consume_fd(int *fds, size_t nr_fds, size_t index)
+{
+ int fd;
+
+ if (index >= nr_fds) {
+ return -EINVAL;
+ }
+
+ fd = fds[index];
+ fds[index] = -1;
+ return fd;
+}
+
void
-consume_fd(int *fds, size_t index)
+restore_fd(int *fds, size_t index, int fd)
{
- fds[index] = -1;
+ fds[index] = fd;
}
/*
@@ -549,11 +563,11 @@ handle_dma_map_or_unmap(vfu_ctx_t *vfu_ctx, uint32_t size, bool map,
if (map) {
int fd = -1;
if (dma_regions[i].flags == VFIO_USER_F_DMA_REGION_MAPPABLE) {
- if (fdi == nr_fds) {
- ret = -EINVAL;
+ fd = consume_fd(fds, nr_fds, fdi++);
+ if (fd < 0) {
+ ret = fd;
break;
}
- fd = fds[fdi];
}
ret = dma_controller_add_region(vfu_ctx->dma,
@@ -562,6 +576,9 @@ handle_dma_map_or_unmap(vfu_ctx_t *vfu_ctx, uint32_t size, bool map,
fd,
dma_regions[i].offset);
if (ret < 0) {
+ if (fd != -1) {
+ restore_fd(fds, fdi - 1, fd);
+ }
vfu_log(vfu_ctx, VFU_INF,
"failed to add DMA region %#lx-%#lx offset=%#lx fd=%d: %s",
dma_regions[i].addr,
@@ -570,9 +587,6 @@ handle_dma_map_or_unmap(vfu_ctx_t *vfu_ctx, uint32_t size, bool map,
strerror(-ret));
break;
}
- if (dma_regions[i].flags == VFIO_USER_F_DMA_REGION_MAPPABLE) {
- consume_fd(fds, fdi++);
- }
vfu_log(vfu_ctx, VFU_DBG,
"added DMA region %#lx-%#lx offset=%#lx fd=%d",
dma_regions[i].addr,
diff --git a/lib/private.h b/lib/private.h
index 2753a20..a2fb3a7 100644
--- a/lib/private.h
+++ b/lib/private.h
@@ -163,8 +163,8 @@ exec_command(vfu_ctx_t *vfu_ctx, struct vfio_user_header *hdr, size_t size,
int
process_request(vfu_ctx_t *vfu_ctx);
-void
-consume_fd(int *fds, size_t index);
+int
+consume_fd(int *fds, size_t nr_fds, size_t index);
#endif /* LIB_VFIO_USER_PRIVATE_H */
diff --git a/test/unit-tests.c b/test/unit-tests.c
index 17f1dad..306f70a 100644
--- a/test/unit-tests.c
+++ b/test/unit-tests.c
@@ -98,7 +98,7 @@ test_dma_map_without_fd(void **state __attribute__((unused)))
}
/*
- * Tests that adding multiple DMA regions where not all of them are mappable
+ * Tests that adding multiple DMA regions that not all of them are mappable
* results in only the mappable one being memory mapped.
*/
static void
@@ -120,7 +120,7 @@ test_dma_add_regions_mixed(void **state __attribute__((unused)))
.flags = VFIO_USER_F_DMA_REGION_MAPPABLE
}
};
- int fd = 0x8badf00d;
+ int fd = 0x0badf00d;
patch(dma_controller_add_region);
will_return(__wrap_dma_controller_add_region, 0);
@@ -168,7 +168,7 @@ test_dma_add_regions_mixed_partial_failure(void **state __attribute__((unused)))
.flags = VFIO_USER_F_DMA_REGION_MAPPABLE
}
};
- int fds[] = {0x8badf00d, 0xbad8f00d};
+ int fds[] = {0xa, 0xb};
patch(dma_controller_add_region);