iommufd: Add iopt_area_alloc()

[ Upstream commit 361d744ddd ]

We never initialize the two interval tree nodes, and zero fill is not the
same as RB_CLEAR_NODE. This can hide issues where we missed adding the
area to the trees. Factor out the allocation and clear the two nodes.

Fixes: 51fe6141f0 ("iommufd: Data structure to provide IOVA to PFN mapping")
Link: https://lore.kernel.org/r/20231030145035.GG691768@ziepe.ca
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Jason Gunthorpe 2023-10-30 11:26:33 -03:00 committed by Greg Kroah-Hartman
parent fca21e139d
commit 1baf6c5f7c
2 changed files with 17 additions and 3 deletions

View File

@ -221,6 +221,18 @@ static int iopt_insert_area(struct io_pagetable *iopt, struct iopt_area *area,
return 0;
}
static struct iopt_area *iopt_area_alloc(void)
{
struct iopt_area *area;
area = kzalloc(sizeof(*area), GFP_KERNEL_ACCOUNT);
if (!area)
return NULL;
RB_CLEAR_NODE(&area->node.rb);
RB_CLEAR_NODE(&area->pages_node.rb);
return area;
}
static int iopt_alloc_area_pages(struct io_pagetable *iopt,
struct list_head *pages_list,
unsigned long length, unsigned long *dst_iova,
@ -231,7 +243,7 @@ static int iopt_alloc_area_pages(struct io_pagetable *iopt,
int rc = 0;
list_for_each_entry(elm, pages_list, next) {
elm->area = kzalloc(sizeof(*elm->area), GFP_KERNEL_ACCOUNT);
elm->area = iopt_area_alloc();
if (!elm->area)
return -ENOMEM;
}
@ -1005,11 +1017,11 @@ static int iopt_area_split(struct iopt_area *area, unsigned long iova)
iopt_area_start_byte(area, new_start) & (alignment - 1))
return -EINVAL;
lhs = kzalloc(sizeof(*area), GFP_KERNEL_ACCOUNT);
lhs = iopt_area_alloc();
if (!lhs)
return -ENOMEM;
rhs = kzalloc(sizeof(*area), GFP_KERNEL_ACCOUNT);
rhs = iopt_area_alloc();
if (!rhs) {
rc = -ENOMEM;
goto err_free_lhs;

View File

@ -1507,6 +1507,8 @@ void iopt_area_unfill_domains(struct iopt_area *area, struct iopt_pages *pages)
area, domain, iopt_area_index(area),
iopt_area_last_index(area));
if (IS_ENABLED(CONFIG_IOMMUFD_TEST))
WARN_ON(RB_EMPTY_NODE(&area->pages_node.rb));
interval_tree_remove(&area->pages_node, &pages->domains_itree);
iopt_area_unfill_domain(area, pages, area->storage_domain);
area->storage_domain = NULL;