aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libvfio-user.h6
-rw-r--r--lib/dma.c78
-rw-r--r--lib/dma.h13
-rw-r--r--lib/irq.c2
-rw-r--r--lib/libvfio-user.c19
-rw-r--r--lib/pci.c1
-rw-r--r--lib/private.h8
-rw-r--r--lib/tran_sock.c1
-rw-r--r--samples/server.c14
-rw-r--r--test/mocks.c1
-rw-r--r--test/unit-tests.c17
11 files changed, 88 insertions, 72 deletions
diff --git a/include/libvfio-user.h b/include/libvfio-user.h
index a43f38a..f2876a1 100644
--- a/include/libvfio-user.h
+++ b/include/libvfio-user.h
@@ -404,9 +404,9 @@ typedef void (vfu_dma_register_cb_t)(vfu_ctx_t *vfu_ctx, vfu_dma_info_t *info);
* This is required if you want to be able to access guest memory directly via
* a mapping.
*
- * The callback should return 0 on success, errno on failure (although
- * unregister should not fail: this will not stop a guest from unregistering the
- * region).
+ * The callback should return 0 on success, -1 with errno set on failure
+ * (although unregister should not fail: this will not stop a guest from
+ * unregistering the region).
*
* @vfu_ctx: the libvfio-user context
* @info: the DMA info
diff --git a/lib/dma.c b/lib/dma.c
index 82bb8c2..2aad1a8 100644
--- a/lib/dma.c
+++ b/lib/dma.c
@@ -156,11 +156,11 @@ MOCK_DEFINE(dma_controller_remove_region)(dma_controller_t *dma,
err = dma_unregister(data, &region->info);
if (err != 0) {
+ err = errno;
vfu_log(dma->vfu_ctx, LOG_ERR,
- "failed to dma_unregister() DMA region [%p, %p): %s",
- region->info.iova.iov_base, iov_end(&region->info.iova),
- strerror(err));
- return -err;
+ "failed to dma_unregister() DMA region [%p, %p): %m",
+ region->info.iova.iov_base, iov_end(&region->info.iova));
+ return ERROR_INT(err);
}
assert(region->refcnt == 0);
@@ -174,7 +174,7 @@ MOCK_DEFINE(dma_controller_remove_region)(dma_controller_t *dma,
array_remove(&dma->regions, sizeof (*region), idx, &dma->nregions);
return 0;
}
- return -ENOENT;
+ return ERROR_INT(ENOENT);
}
void
@@ -229,7 +229,7 @@ dma_map_region(dma_controller_t *dma, dma_memory_region_t *region)
region->fd, offset);
if (mmap_base == MAP_FAILED) {
- return -errno;
+ return -1;
}
// Do not dump.
@@ -258,7 +258,6 @@ MOCK_DEFINE(dma_controller_add_region)(dma_controller_t *dma,
int page_size = 0;
char rstr[1024];
int idx;
- int ret;
assert(dma != NULL);
@@ -274,8 +273,7 @@ MOCK_DEFINE(dma_controller_add_region)(dma_controller_t *dma,
if (offset != region->offset) {
vfu_log(dma->vfu_ctx, LOG_ERR, "bad offset for new DMA region "
"%s; existing=%#lx", rstr, region->offset);
- ret = -EINVAL;
- goto out;
+ return ERROR_INT(EINVAL);
}
if (!fds_are_same_file(region->fd, fd)) {
/*
@@ -286,14 +284,12 @@ MOCK_DEFINE(dma_controller_add_region)(dma_controller_t *dma,
*/
vfu_log(dma->vfu_ctx, LOG_ERR, "bad fd for new DMA region %s; "
"existing=%d", rstr, region->fd);
- ret = -EINVAL;
- goto out;
+ return ERROR_INT(EINVAL);
}
if (region->info.prot != prot) {
vfu_log(dma->vfu_ctx, LOG_ERR, "bad prot for new DMA region "
"%s; existing=%#x", rstr, region->info.prot);
- ret = -EINVAL;
- goto out;
+ return ERROR_INT(EINVAL);
}
return idx;
}
@@ -306,15 +302,13 @@ MOCK_DEFINE(dma_controller_add_region)(dma_controller_t *dma,
vfu_log(dma->vfu_ctx, LOG_INFO, "new DMA region %s overlaps with "
"DMA region [%p, %p)", rstr, region->info.iova.iov_base,
iov_end(&region->info.iova));
- ret = -EINVAL;
- goto out;
+ return ERROR_INT(EINVAL);
}
}
if (dma->nregions == dma->max_regions) {
vfu_log(dma->vfu_ctx, LOG_ERR, "hit max regions %d", dma->max_regions);
- ret = -EINVAL;
- goto out;
+ return ERROR_INT(EINVAL);
}
idx = dma->nregions;
@@ -324,8 +318,7 @@ MOCK_DEFINE(dma_controller_add_region)(dma_controller_t *dma,
page_size = fd_get_blocksize(fd);
if (page_size < 0) {
vfu_log(dma->vfu_ctx, LOG_ERR, "bad page size %d", page_size);
- ret = -EINVAL;
- goto out;
+ return ERROR_INT(EINVAL);
}
}
page_size = MAX(page_size, getpagesize());
@@ -340,26 +333,24 @@ MOCK_DEFINE(dma_controller_add_region)(dma_controller_t *dma,
region->fd = fd;
if (fd != -1) {
- ret = dma_map_region(dma, region);
+ int ret = dma_map_region(dma, region);
if (ret != 0) {
+ ret = errno;
vfu_log(dma->vfu_ctx, LOG_ERR,
- "failed to memory map DMA region %s: %s", rstr,
- strerror(-ret));
+ "failed to memory map DMA region %s: %m", rstr);
if (close(region->fd) == -1) {
vfu_log(dma->vfu_ctx, LOG_WARNING,
"failed to close fd %d: %m", region->fd);
}
- goto out;
+
+ return ERROR_INT(ret);
}
}
- ret = idx;
dma->nregions++;
-
-out:
- return ret;
+ return idx;
}
int
@@ -407,8 +398,7 @@ out:
if (!found) {
// There is still a region which was not found.
assert(len > 0);
- errno = ENOENT;
- return -1;
+ return ERROR_INT(ENOENT);
} else if (cnt > max_sg) {
cnt = -cnt - 1;
}
@@ -420,10 +410,10 @@ static ssize_t
get_bitmap_size(size_t region_size, size_t pgsize)
{
if (pgsize == 0) {
- return -EINVAL;
+ return ERROR_INT(EINVAL);
}
if (region_size < pgsize) {
- return -EINVAL;
+ return ERROR_INT(EINVAL);
}
size_t nr_pages = (region_size / pgsize) + (region_size % pgsize != 0);
return (nr_pages / CHAR_BIT) + (nr_pages % CHAR_BIT != 0);
@@ -431,22 +421,22 @@ get_bitmap_size(size_t region_size, size_t pgsize)
int dma_controller_dirty_page_logging_start(dma_controller_t *dma, size_t pgsize)
{
- int i;
+ size_t i;
assert(dma != NULL);
if (pgsize == 0) {
- return -EINVAL;
+ return ERROR_INT(EINVAL);
}
if (dma->dirty_pgsize > 0) {
if (dma->dirty_pgsize != pgsize) {
- return -EINVAL;
+ return ERROR_INT(EINVAL);
}
return 0;
}
- for (i = 0; i < dma->nregions; i++) {
+ for (i = 0; i < (size_t)dma->nregions; i++) {
dma_memory_region_t *region = &dma->regions[i];
ssize_t bitmap_size;
@@ -457,27 +447,30 @@ int dma_controller_dirty_page_logging_start(dma_controller_t *dma, size_t pgsize
}
region->dirty_bitmap = calloc(bitmap_size, sizeof(char));
if (region->dirty_bitmap == NULL) {
- int j, ret = -errno;
+ int ret = errno;
+ size_t j;
+
for (j = 0; j < i; j++) {
region = &dma->regions[j];
free(region->dirty_bitmap);
region->dirty_bitmap = NULL;
}
- return ret;
+ return ERROR_INT(ret);
}
}
dma->dirty_pgsize = pgsize;
return 0;
}
-int dma_controller_dirty_page_logging_stop(dma_controller_t *dma)
+void
+dma_controller_dirty_page_logging_stop(dma_controller_t *dma)
{
int i;
assert(dma != NULL);
if (dma->dirty_pgsize == 0) {
- return 0;
+ return;
}
for (i = 0; i < dma->nregions; i++) {
@@ -485,7 +478,6 @@ int dma_controller_dirty_page_logging_stop(dma_controller_t *dma)
dma->regions[i].dirty_bitmap = NULL;
}
dma->dirty_pgsize = 0;
- return 0;
}
int
@@ -507,11 +499,11 @@ dma_controller_dirty_page_get(dma_controller_t *dma, vfu_dma_addr_t addr,
*/
ret = dma_addr_to_sg(dma, addr, len, &sg, 1, PROT_NONE);
if (ret != 1 || sg.dma_addr != addr || sg.length != len) {
- return -ENOTSUP;
+ return ERROR_INT(ENOTSUP);
}
if (pgsize != dma->dirty_pgsize) {
- return -EINVAL;
+ return ERROR_INT(EINVAL);
}
bitmap_size = get_bitmap_size(len, pgsize);
@@ -524,7 +516,7 @@ dma_controller_dirty_page_get(dma_controller_t *dma, vfu_dma_addr_t addr,
* expects to receive.
*/
if (size != (size_t)bitmap_size) {
- return -EINVAL;
+ return ERROR_INT(EINVAL);
}
region = &dma->regions[sg.region];
diff --git a/lib/dma.h b/lib/dma.h
index 5e086a0..861b8d3 100644
--- a/lib/dma.h
+++ b/lib/dma.h
@@ -76,6 +76,7 @@
#include "libvfio-user.h"
#include "common.h"
+#include "private.h"
#define iov_end(iov) ((iov)->iov_base + (iov)->iov_len)
@@ -89,7 +90,7 @@ typedef struct {
char *dirty_bitmap; // Dirty page bitmap
} dma_memory_region_t;
-typedef struct {
+typedef struct dma_controller {
int max_regions;
int nregions;
struct vfu_ctx *vfu_ctx;
@@ -187,8 +188,7 @@ dma_init_sg(const dma_controller_t *dma, dma_sg_t *sg, vfu_dma_addr_t dma_addr,
const dma_memory_region_t *const region = &dma->regions[region_index];
if ((prot & PROT_WRITE) && !(region->info.prot & PROT_WRITE)) {
- errno = EACCES;
- return -1;
+ return ERROR_INT(EACCES);
}
sg->dma_addr = region->info.iova.iov_base;
@@ -260,12 +260,12 @@ dma_map_sg(dma_controller_t *dma, const dma_sg_t *sg, struct iovec *iov,
for (i = 0; i < cnt; i++) {
if (sg[i].region >= dma->nregions) {
- return -EINVAL;
+ return ERROR_INT(EINVAL);
}
region = &dma->regions[sg[i].region];
if (region->info.vaddr == NULL) {
- return -EFAULT;
+ return ERROR_INT(EFAULT);
}
vfu_log(dma->vfu_ctx, LOG_DEBUG, "map %p-%p",
@@ -304,13 +304,12 @@ dma_unmap_sg(dma_controller_t *dma, const dma_sg_t *sg,
sg[i].dma_addr + sg[i].offset + sg[i].length);
r->refcnt--;
}
- return;
}
int
dma_controller_dirty_page_logging_start(dma_controller_t *dma, size_t pgsize);
-int
+void
dma_controller_dirty_page_logging_stop(dma_controller_t *dma);
int
diff --git a/lib/irq.c b/lib/irq.c
index bc48d4f..1dec459 100644
--- a/lib/irq.c
+++ b/lib/irq.c
@@ -30,8 +30,10 @@
*
*/
+#include <assert.h>
#include <errno.h>
#include <limits.h>
+#include <stdlib.h>
#include <sys/eventfd.h>
#include "irq.h"
diff --git a/lib/libvfio-user.c b/lib/libvfio-user.c
index 0440351..f4aa804 100644
--- a/lib/libvfio-user.c
+++ b/lib/libvfio-user.c
@@ -532,11 +532,12 @@ handle_dma_map_or_unmap(vfu_ctx_t *vfu_ctx, uint32_t size, bool map,
region->size, fd, region->offset,
region->prot);
if (ret < 0) {
+ ret = -errno;
+ vfu_log(vfu_ctx, LOG_ERR, "failed to add DMA region %s: %m",
+ rstr);
if (fd != -1) {
close(fd);
}
- vfu_log(vfu_ctx, LOG_ERR, "failed to add DMA region %s: %s",
- rstr, strerror(-ret));
break;
}
@@ -553,8 +554,9 @@ handle_dma_map_or_unmap(vfu_ctx_t *vfu_ctx, uint32_t size, bool map,
vfu_ctx->dma_unregister,
vfu_ctx);
if (ret < 0) {
- vfu_log(vfu_ctx, LOG_ERR, "failed to remove DMA region %s: %s",
- rstr, strerror(-ret));
+ ret = -errno;
+ vfu_log(vfu_ctx, LOG_ERR, "failed to remove DMA region %s: %m",
+ rstr);
break;
}
}
@@ -603,6 +605,7 @@ handle_dirty_pages_get(vfu_ctx_t *vfu_ctx,
r->bitmap.size,
(char**)&((*iovecs)[i].iov_base));
if (ret != 0) {
+ ret = -errno;
goto out;
}
(*iovecs)[i].iov_len = r->bitmap.size;
@@ -637,8 +640,12 @@ MOCK_DEFINE(handle_dirty_pages)(vfu_ctx_t *vfu_ctx, uint32_t size,
if (dirty_bitmap->flags & VFIO_IOMMU_DIRTY_PAGES_FLAG_START) {
ret = dma_controller_dirty_page_logging_start(vfu_ctx->dma,
migration_get_pgsize(vfu_ctx->migration));
+ if (ret == -1) {
+ ret = -errno;
+ }
} else if (dirty_bitmap->flags & VFIO_IOMMU_DIRTY_PAGES_FLAG_STOP) {
- ret = dma_controller_dirty_page_logging_stop(vfu_ctx->dma);
+ dma_controller_dirty_page_logging_stop(vfu_ctx->dma);
+ ret = 0;
} else if (dirty_bitmap->flags & VFIO_IOMMU_DIRTY_PAGES_FLAG_GET_BITMAP) {
ret = handle_dirty_pages_get(vfu_ctx, iovecs, nr_iovecs,
(struct vfio_iommu_type1_dirty_bitmap_get*)(dirty_bitmap + 1),
@@ -1520,7 +1527,7 @@ vfu_map_sg(vfu_ctx_t *vfu_ctx, const dma_sg_t *sg,
ret = dma_map_sg(vfu_ctx->dma, sg, iov, cnt);
if (ret < 0) {
- return ERROR_INT(-ret);
+ return -1;
}
return 0;
diff --git a/lib/pci.c b/lib/pci.c
index 39470d9..54e90f9 100644
--- a/lib/pci.c
+++ b/lib/pci.c
@@ -33,6 +33,7 @@
#include <assert.h>
#include <errno.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
diff --git a/lib/private.h b/lib/private.h
index 49f9152..fde5e3c 100644
--- a/lib/private.h
+++ b/lib/private.h
@@ -33,8 +33,10 @@
#ifndef LIB_VFIO_USER_PRIVATE_H
#define LIB_VFIO_USER_PRIVATE_H
+#include <errno.h>
+
#include "pci_caps.h"
-#include "dma.h"
+#include "common.h"
static inline int
ERROR_INT(int err)
@@ -109,9 +111,11 @@ struct pci_dev {
size_t nr_ext_caps;
};
+struct dma_controller;
+
struct vfu_ctx {
void *pvt;
- dma_controller_t *dma;
+ struct dma_controller *dma;
vfu_reset_cb_t *reset;
int log_level;
vfu_log_fn_t *log;
diff --git a/lib/tran_sock.c b/lib/tran_sock.c
index ce3430a..a1d6a1a 100644
--- a/lib/tran_sock.c
+++ b/lib/tran_sock.c
@@ -30,6 +30,7 @@
*
*/
+#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
diff --git a/samples/server.c b/samples/server.c
index f9bde30..a449bb6 100644
--- a/samples/server.c
+++ b/samples/server.c
@@ -45,6 +45,7 @@
#include "common.h"
#include "libvfio-user.h"
+#include "private.h"
#include "tran_sock.h"
struct dma_regions {
@@ -184,7 +185,7 @@ dma_unregister(vfu_ctx_t *vfu_ctx, vfu_dma_info_t *info)
}
}
- return -EINVAL;
+ return ERROR_INT(EINVAL);
}
static void
@@ -219,10 +220,9 @@ static void do_dma_io(vfu_ctx_t *vfu_ctx, struct server_data *server_data)
(vfu_dma_addr_t)server_data->regions[0].iova.iov_base,
count, &sg, 1, PROT_WRITE);
if (ret < 0) {
- errx(EXIT_FAILURE, "failed to map %p-%p: %s",
- server_data->regions[0].iova.iov_base,
- server_data->regions[0].iova.iov_base + count -1,
- strerror(-ret));
+ err(EXIT_FAILURE, "failed to map %p-%p",
+ server_data->regions[0].iova.iov_base,
+ server_data->regions[0].iova.iov_base + count -1);
}
memset(buf, 'A', count);
@@ -231,7 +231,7 @@ static void do_dma_io(vfu_ctx_t *vfu_ctx, struct server_data *server_data)
server_data->regions[0].iova.iov_base, count);
ret = vfu_dma_write(vfu_ctx, &sg, buf);
if (ret < 0) {
- errx(EXIT_FAILURE, "vfu_dma_write failed: %s", strerror(-ret));
+ err(EXIT_FAILURE, "vfu_dma_write failed");
}
memset(buf, 0, count);
@@ -239,7 +239,7 @@ static void do_dma_io(vfu_ctx_t *vfu_ctx, struct server_data *server_data)
server_data->regions[0].iova.iov_base, count);
ret = vfu_dma_read(vfu_ctx, &sg, buf);
if (ret < 0) {
- errx(EXIT_FAILURE, "vfu_dma_read failed: %s", strerror(-ret));
+ err(EXIT_FAILURE, "vfu_dma_read failed");
}
get_md5sum(buf, count, md5sum2);
for(i = 0; i < MD5_DIGEST_LENGTH; i++) {
diff --git a/test/mocks.c b/test/mocks.c
index b01011e..7121826 100644
--- a/test/mocks.c
+++ b/test/mocks.c
@@ -125,6 +125,7 @@ dma_controller_add_region(dma_controller_t *dma, void *dma_addr,
check_expected(fd);
check_expected(offset);
check_expected(prot);
+ errno = mock();
return mock();
}
diff --git a/test/unit-tests.c b/test/unit-tests.c
index 3b1d227..1e245a5 100644
--- a/test/unit-tests.c
+++ b/test/unit-tests.c
@@ -95,6 +95,7 @@ test_dma_map_without_fd(void **state UNUSED)
patch("dma_controller_add_region");
will_return(dma_controller_add_region, 0);
+ will_return(dma_controller_add_region, 0);
expect_value(dma_controller_add_region, dma, vfu_ctx.dma);
expect_value(dma_controller_add_region, dma_addr, r.addr);
expect_value(dma_controller_add_region, size, r.size);
@@ -164,6 +165,7 @@ test_dma_add_regions_mixed(void **state UNUSED)
patch("dma_controller_add_region");
/* 1st region */
will_return(dma_controller_add_region, 0);
+ will_return(dma_controller_add_region, 0);
expect_value(dma_controller_add_region, dma, vfu_ctx.dma);
expect_value(dma_controller_add_region, dma_addr, r[0].addr);
expect_value(dma_controller_add_region, size, r[0].size);
@@ -174,6 +176,7 @@ test_dma_add_regions_mixed(void **state UNUSED)
expect_check(mock_dma_register, info, check_dma_info,
&dma->regions[0].info);
/* 2nd region */
+ will_return(dma_controller_add_region, 0);
will_return(dma_controller_add_region, 1);
expect_value(dma_controller_add_region, dma, vfu_ctx.dma);
expect_value(dma_controller_add_region, dma_addr, r[1].addr);
@@ -231,6 +234,7 @@ test_dma_add_regions_mixed_partial_failure(void **state UNUSED)
expect_value(dma_controller_add_region, offset, r[0].offset);
expect_value(dma_controller_add_region, prot, r[0].prot);
will_return(dma_controller_add_region, 0);
+ will_return(dma_controller_add_region, 0);
/* 2nd region */
expect_value(dma_controller_add_region, dma, vfu_ctx.dma);
@@ -240,6 +244,7 @@ test_dma_add_regions_mixed_partial_failure(void **state UNUSED)
expect_value(dma_controller_add_region, offset, r[1].offset);
expect_value(dma_controller_add_region, prot, r[1].prot);
will_return(dma_controller_add_region, 0);
+ will_return(dma_controller_add_region, 0);
/* 3rd region */
expect_value(dma_controller_add_region, dma, vfu_ctx.dma);
@@ -248,13 +253,14 @@ test_dma_add_regions_mixed_partial_failure(void **state UNUSED)
expect_value(dma_controller_add_region, fd, fds[1]);
expect_value(dma_controller_add_region, offset, r[2].offset);
expect_value(dma_controller_add_region, prot, r[2].prot);
- will_return(dma_controller_add_region, -0x1234);
+ will_return(dma_controller_add_region, EREMOTEIO);
+ will_return(dma_controller_add_region, -1);
patch("close");
expect_value(close, fd, 0xb);
will_return(close, 0);
- assert_int_equal(-0x1234,
+ assert_int_equal(-EREMOTEIO,
handle_dma_map_or_unmap(&vfu_ctx,
ARRAY_SIZE(r) * sizeof(struct vfio_user_dma_region),
true, fds, 2, r));
@@ -280,6 +286,7 @@ test_dma_map_return_value(void **state UNUSED)
expect_value(dma_controller_add_region, fd, -1);
expect_value(dma_controller_add_region, offset, r.offset);
expect_value(dma_controller_add_region, prot, r.prot);
+ will_return(dma_controller_add_region, 0);
will_return(dma_controller_add_region, 2);
assert_int_equal(0,
@@ -1254,11 +1261,13 @@ test_dma_map_sg(void **state UNUSED)
dma->nregions = 1;
/* bad region */
- assert_int_equal(-EINVAL, dma_map_sg(dma, &sg, &iovec, 1));
+ assert_int_equal(-1, dma_map_sg(dma, &sg, &iovec, 1));
+ assert_int_equal(EINVAL, errno);
/* w/o fd */
sg.region = 0;
- assert_int_equal(-EFAULT, dma_map_sg(dma, &sg, &iovec, 1));
+ assert_int_equal(-1, dma_map_sg(dma, &sg, &iovec, 1));
+ assert_int_equal(EFAULT, errno);
/* w/ fd */
dma->regions[0].info.vaddr = (void *)0xdead0000;