iommufd: Add iopt_area_alloc()
authorJason Gunthorpe <jgg@nvidia.com>
Mon, 30 Oct 2023 14:26:33 +0000 (11:26 -0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Nov 2023 10:59:17 +0000 (11:59 +0100)
[ Upstream commit 361d744ddd61de065fbeb042aaed590d32dd92ec ]

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: 51fe6141f0f6 ("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>
drivers/iommu/iommufd/io_pagetable.c
drivers/iommu/iommufd/pages.c

index 3a59818..a4da181 100644 (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;
index 8d9aa29..528f356 100644 (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;