util: add iova_tree_find_iova

This function does the reverse operation of iova_tree_find: To look for
a mapping that match a translated address so we can do the reverse.

This have linear complexity instead of logarithmic, but it supports
overlapping HVA. Future developments could reduce it.

Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
This commit is contained in:
Eugenio Pérez 2022-03-14 18:34:49 +01:00 committed by Jason Wang
parent 9376bde894
commit 193d17be0b
2 changed files with 53 additions and 1 deletions

View File

@ -83,7 +83,7 @@ int iova_tree_remove(IOVATree *tree, const DMAMap *map);
* @tree: the iova tree to search from
* @map: the mapping to search
*
* Search for a mapping in the iova tree that overlaps with the
* Search for a mapping in the iova tree that iova overlaps with the
* mapping range specified. Only the first found mapping will be
* returned.
*
@ -95,6 +95,24 @@ int iova_tree_remove(IOVATree *tree, const DMAMap *map);
*/
const DMAMap *iova_tree_find(const IOVATree *tree, const DMAMap *map);
/**
* iova_tree_find_iova:
*
* @tree: the iova tree to search from
* @map: the mapping to search
*
* Search for a mapping in the iova tree that translated_addr overlaps with the
* mapping range specified. Only the first found mapping will be
* returned.
*
* Return: DMAMap pointer if found, or NULL if not found. Note that
* the returned DMAMap pointer is maintained internally. User should
* only read the content but never modify or free the content. Also,
* user is responsible to make sure the pointer is valid (say, no
* concurrent deletion in progress).
*/
const DMAMap *iova_tree_find_iova(const IOVATree *tree, const DMAMap *map);
/**
* iova_tree_find_address:
*

View File

@ -37,6 +37,11 @@ struct IOVATreeAllocArgs {
bool iova_found;
};
typedef struct IOVATreeFindIOVAArgs {
const DMAMap *needle;
const DMAMap *result;
} IOVATreeFindIOVAArgs;
/**
* Iterate args to the next hole
*
@ -81,6 +86,35 @@ const DMAMap *iova_tree_find(const IOVATree *tree, const DMAMap *map)
return g_tree_lookup(tree->tree, map);
}
static gboolean iova_tree_find_address_iterator(gpointer key, gpointer value,
gpointer data)
{
const DMAMap *map = key;
IOVATreeFindIOVAArgs *args = data;
const DMAMap *needle;
g_assert(key == value);
needle = args->needle;
if (map->translated_addr + map->size < needle->translated_addr ||
needle->translated_addr + needle->size < map->translated_addr) {
return false;
}
args->result = map;
return true;
}
const DMAMap *iova_tree_find_iova(const IOVATree *tree, const DMAMap *map)
{
IOVATreeFindIOVAArgs args = {
.needle = map,
};
g_tree_foreach(tree->tree, iova_tree_find_address_iterator, &args);
return args.result;
}
const DMAMap *iova_tree_find_address(const IOVATree *tree, hwaddr iova)
{
const DMAMap map = { .iova = iova, .size = 0 };