mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-02 07:04:24 +00:00
iommufd: Add iopt_area_alloc()
[ Upstream commit361d744ddd
] 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:
parent
fca21e139d
commit
1baf6c5f7c
2 changed files with 17 additions and 3 deletions
|
@ -221,6 +221,18 @@ static int iopt_insert_area(struct io_pagetable *iopt, struct iopt_area *area,
|
||||||
return 0;
|
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,
|
static int iopt_alloc_area_pages(struct io_pagetable *iopt,
|
||||||
struct list_head *pages_list,
|
struct list_head *pages_list,
|
||||||
unsigned long length, unsigned long *dst_iova,
|
unsigned long length, unsigned long *dst_iova,
|
||||||
|
@ -231,7 +243,7 @@ static int iopt_alloc_area_pages(struct io_pagetable *iopt,
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
list_for_each_entry(elm, pages_list, next) {
|
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)
|
if (!elm->area)
|
||||||
return -ENOMEM;
|
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))
|
iopt_area_start_byte(area, new_start) & (alignment - 1))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
lhs = kzalloc(sizeof(*area), GFP_KERNEL_ACCOUNT);
|
lhs = iopt_area_alloc();
|
||||||
if (!lhs)
|
if (!lhs)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
rhs = kzalloc(sizeof(*area), GFP_KERNEL_ACCOUNT);
|
rhs = iopt_area_alloc();
|
||||||
if (!rhs) {
|
if (!rhs) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto err_free_lhs;
|
goto err_free_lhs;
|
||||||
|
|
|
@ -1507,6 +1507,8 @@ void iopt_area_unfill_domains(struct iopt_area *area, struct iopt_pages *pages)
|
||||||
area, domain, iopt_area_index(area),
|
area, domain, iopt_area_index(area),
|
||||||
iopt_area_last_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);
|
interval_tree_remove(&area->pages_node, &pages->domains_itree);
|
||||||
iopt_area_unfill_domain(area, pages, area->storage_domain);
|
iopt_area_unfill_domain(area, pages, area->storage_domain);
|
||||||
area->storage_domain = NULL;
|
area->storage_domain = NULL;
|
||||||
|
|
Loading…
Reference in a new issue