Skip to content

Commit

Permalink
vfio/type1: massage unmap iteration
Browse files Browse the repository at this point in the history
Modify the iteration in vfio_dma_do_unmap so it does not depend on deletion
of each dma entry.  Add a variant of vfio_find_dma that returns the entry
with the lowest iova in the search range to initialize the iteration.  No
externally visible change, but this behavior is needed in the subsequent
update-vaddr patch.

Signed-off-by: Steve Sistare <steven.sistare@oracle.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
  • Loading branch information
Steve Sistare authored and Alex Williamson committed Feb 1, 2021
1 parent 441e810 commit 40ae9b8
Showing 1 changed file with 34 additions and 1 deletion.
35 changes: 34 additions & 1 deletion drivers/vfio/vfio_iommu_type1.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,31 @@ static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu,
return NULL;
}

static struct rb_node *vfio_find_dma_first_node(struct vfio_iommu *iommu,
dma_addr_t start, size_t size)
{
struct rb_node *res = NULL;
struct rb_node *node = iommu->dma_list.rb_node;
struct vfio_dma *dma_res = NULL;

while (node) {
struct vfio_dma *dma = rb_entry(node, struct vfio_dma, node);

if (start < dma->iova + dma->size) {
res = node;
dma_res = dma;
if (start >= dma->iova)
break;
node = node->rb_left;
} else {
node = node->rb_right;
}
}
if (res && size && dma_res->iova >= start + size)
res = NULL;
return res;
}

static void vfio_link_dma(struct vfio_iommu *iommu, struct vfio_dma *new)
{
struct rb_node **link = &iommu->dma_list.rb_node, *parent = NULL;
Expand Down Expand Up @@ -1079,6 +1104,7 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
dma_addr_t iova = unmap->iova;
unsigned long size = unmap->size;
bool unmap_all = unmap->flags & VFIO_DMA_UNMAP_FLAG_ALL;
struct rb_node *n;

mutex_lock(&iommu->lock);

Expand Down Expand Up @@ -1149,7 +1175,13 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
}

ret = 0;
while ((dma = vfio_find_dma(iommu, iova, size))) {
n = vfio_find_dma_first_node(iommu, iova, size);

while (n) {
dma = rb_entry(n, struct vfio_dma, node);
if (dma->iova >= iova + size)
break;

if (!iommu->v2 && iova > dma->iova)
break;
/*
Expand Down Expand Up @@ -1194,6 +1226,7 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
}

unmapped += dma->size;
n = rb_next(n);
vfio_remove_dma(iommu, dma);
}

Expand Down

0 comments on commit 40ae9b8

Please sign in to comment.