aboutsummaryrefslogtreecommitdiff
path: root/lib/dma.c
diff options
context:
space:
mode:
authorJohn Levon <john.levon@nutanix.com>2021-05-10 12:59:01 +0100
committerGitHub <noreply@github.com>2021-05-10 12:59:01 +0100
commitb95c886ed23b4cc4c539030bf383b55aae8859a3 (patch)
treed032be6eff881d8ff69ea94a29b459546876d97a /lib/dma.c
parent12ee57e1101e7059361d41011211bc4e8aef20fc (diff)
downloadlibvfio-user-b95c886ed23b4cc4c539030bf383b55aae8859a3.zip
libvfio-user-b95c886ed23b4cc4c539030bf383b55aae8859a3.tar.gz
libvfio-user-b95c886ed23b4cc4c539030bf383b55aae8859a3.tar.bz2
fix dma unregister callback during region removal (#464)
There are two issues with the unregister callback: - we were requiring the callback to be set when removing a region, but it's only required if a consumer wants to map regions - when we removed all regions (for example, on a reset), we weren't triggering the callback Signed-off-by: John Levon <john.levon@nutanix.com> swapnil code review add assert Reviewed-by: Swapnil Ingle <swapnil.ingle@nutanix.com>
Diffstat (limited to 'lib/dma.c')
-rw-r--r--lib/dma.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/lib/dma.c b/lib/dma.c
index 2aad1a8..9b29cc9 100644
--- a/lib/dma.c
+++ b/lib/dma.c
@@ -154,7 +154,7 @@ MOCK_DEFINE(dma_controller_remove_region)(dma_controller_t *dma,
continue;
}
- err = dma_unregister(data, &region->info);
+ err = dma_unregister == NULL ? 0 : dma_unregister(data, &region->info);
if (err != 0) {
err = errno;
vfu_log(dma->vfu_ctx, LOG_ERR,
@@ -178,7 +178,9 @@ MOCK_DEFINE(dma_controller_remove_region)(dma_controller_t *dma,
}
void
-dma_controller_remove_regions(dma_controller_t *dma)
+dma_controller_remove_all_regions(dma_controller_t *dma,
+ vfu_dma_unregister_cb_t *dma_unregister,
+ void *data)
{
int i;
@@ -186,6 +188,7 @@ dma_controller_remove_regions(dma_controller_t *dma)
for (i = 0; i < dma->nregions; i++) {
dma_memory_region_t *region = &dma->regions[i];
+ int err;
vfu_log(dma->vfu_ctx, LOG_DEBUG, "removing DMA region "
"iova=[%p, %p) vaddr=%p mapping=[%p, %p)",
@@ -193,6 +196,14 @@ dma_controller_remove_regions(dma_controller_t *dma)
region->info.vaddr,
region->info.mapping.iov_base, iov_end(&region->info.mapping));
+ err = dma_unregister == NULL ? 0 : 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): %m",
+ region->info.iova.iov_base, iov_end(&region->info.iova));
+ }
+
if (region->info.vaddr != NULL) {
dma_controller_unmap_region(dma, region);
} else {
@@ -207,11 +218,7 @@ dma_controller_remove_regions(dma_controller_t *dma)
void
dma_controller_destroy(dma_controller_t *dma)
{
- if (dma == NULL) {
- return;
- }
-
- dma_controller_remove_regions(dma);
+ assert(dma->nregions == 0);
free(dma);
}