diff options
| author | Hollin <hollinisme@gmail.com> | 2026-04-17 04:36:41 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-04-16 21:36:41 +0100 |
| commit | 4d9f663450fa80ff375612dbbafe073700e3d3d8 (patch) | |
| tree | 9b83eeaecae8a43c03628713c3c8d0d97b852f5e /lib | |
| parent | 2311cde4a933dc62ee65b4fe8f408e37bf2bb390 (diff) | |
| download | libvfio-user-master.tar.gz libvfio-user-master.tar.bz2 libvfio-user-master.zip | |
The dirty bitmap was allocated when dirty tracking is enabled for a DMA
region, but was not released during region teardown.
This could lead to memory leaks over time with repeated DMA map/unmap
operations while dirty page logging is active.
Signed-off-by: liuhaolin <hollinisme@gmail.com>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/dma.c | 50 |
1 files changed, 30 insertions, 20 deletions
@@ -66,6 +66,32 @@ fd_get_blocksize(int fd) return st.st_blksize; } +static int +dirty_page_logging_start_on_region(dma_memory_region_t *region, size_t pgsize) +{ + assert(region->fd != -1); + + ssize_t size = get_bitmap_size(region->info.iova.iov_len, pgsize); + if (size < 0) { + return size; + } + + region->dirty_bitmap = calloc(size, 1); + if (region->dirty_bitmap == NULL) { + return ERROR_INT(errno); + } + return 0; +} + +static void +dirty_page_logging_stop_on_region(dma_memory_region_t *region) +{ + if (region->dirty_bitmap != NULL) { + free(region->dirty_bitmap); + region->dirty_bitmap = NULL; + } +} + dma_controller_t * dma_controller_create(vfu_ctx_t *vfu_ctx, size_t max_regions, size_t max_size) { @@ -135,6 +161,8 @@ MOCK_DEFINE(dma_controller_unmap_region)(dma_controller_t *dma, assert(region->fd != -1); + dirty_page_logging_stop_on_region(region); + err = fd_cache_put(®ion->fd); assert(err == 0); } @@ -258,23 +286,6 @@ dma_map_region(dma_controller_t *dma, dma_memory_region_t *region) return 0; } -static int -dirty_page_logging_start_on_region(dma_memory_region_t *region, size_t pgsize) -{ - assert(region->fd != -1); - - ssize_t size = get_bitmap_size(region->info.iova.iov_len, pgsize); - if (size < 0) { - return size; - } - - region->dirty_bitmap = calloc(size, 1); - if (region->dirty_bitmap == NULL) { - return ERROR_INT(errno); - } - return 0; -} - dma_memory_region_t * MOCK_DEFINE(dma_controller_add_region)(dma_controller_t *dma, vfu_dma_addr_t dma_addr, uint64_t size, @@ -413,7 +424,7 @@ rollback: if (region->info.vaddr != NULL) { dma_controller_unmap_region(dma, region); } - free(region->dirty_bitmap); + dirty_page_logging_stop_on_region(region); free(region); } err = fd_cache_put(&fd); @@ -475,8 +486,7 @@ dma_controller_dirty_page_logging_reset(dma_controller_t *dma) for (btree_iter_init(&dma->regions, 0, &iter); (region = btree_iter_get(&iter, NULL)) != NULL; btree_iter_next(&iter)) { - free(region->dirty_bitmap); - region->dirty_bitmap = NULL; + dirty_page_logging_stop_on_region(region); } dma->dirty_pgsize = 0; } |
