lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAEHaoC3t8nFhR4MAYV1AaR5mjN4ndkkWrKUyBY_smbtpDykAEA@mail.gmail.com>
Date: Sun, 3 Aug 2025 14:13:37 +0300
From: Constantine Gavrilov <cgavrilov@...inidat.com>
To: linux-kernel@...r.kernel.org, Marek Szyprowski <m.szyprowski@...sung.com>, 
	Robin Murphy <robin.murphy@....com>, iommu@...ts.linux.dev
Subject: [PATCH 5/8] Large DMA alloc/remove max32_alloc_size field

This is the sixth patch from the set of patches that enable large IOMMU
DMA registrations. Entire work is available at the master branch of the
master branch of git@...hub.com:cgavrilov/linux.git repo.

This patch removes max32_alloc_size field from the iova_domain structure.
This field was introduced to optimize the path of allocation failure (return
failed allocation without checking for available regions), but was not
implemented correctly, resulting in failed allocations when the space maybe
available.

commit cfdad4eb84e8c5dc7aa3f868575007de2e1fc1e4
Author: Constantine Gavrilov <cgavrilov@...inidat.com>
Date:   Tue Jul 1 10:05:11 2025 +0300

    Removed max32_alloc_size field from the iova_domain structure.

    This field exists for the purpose of optimizing a path of failed
    allocations in 32-bit DMA space, when the 32-bit range is depleted.
    There are a number of issues:

    1. max32_alloc_size is updated in __alloc_and_insert_iova_range()
       without checking the size after allocation of the range fails. This
       will cause a wrong failed small allocation after a "big" allocation
       fails.
    2. max32_alloc_size is updated in __cached_rbnode_delete_update()
       without checking the top bound of the released range and the size
       of the released range. This defeats the purpose of the intended
       "optimization".
    3. Alignment constraints and DMA  address limits are not taken into account
       when updating this field after the allocation fails. This results in
       future allocation failures that can succeed if looking for available
       ranges is not skipped.

    Rather than fixing this "optimization", remove it altogether. We shall
    not optimize for failed allocation path that is rare, and the optimizing
    affect of this feature is questionable.

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index aba58630be12..0c436dd35404 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -52,7 +52,6 @@ init_iova_domain(struct iova_domain *iovad, unsigned
long granule,
     iovad->granule = granule;
     iovad->start_pfn = start_pfn;
     iovad->dma_32bit_pfn = 1UL << (32 - iova_shift(iovad));
-    iovad->max32_alloc_size = iovad->dma_32bit_pfn;
     iovad->anchor.pfn_lo = iovad->anchor.pfn_hi = IOVA_ANCHOR;
     rb_link_node(&iovad->anchor.node, NULL, &iovad->rbroot.rb_node);
     rb_insert_color(&iovad->anchor.node, &iovad->rbroot);
@@ -88,9 +87,6 @@ __cached_rbnode_delete_update(struct iova_domain
*iovad, struct iova *free)
          free->pfn_lo >= cached_iova->pfn_lo))
         iovad->cached32_node = rb_next(&free->node);

-    if (free->pfn_lo < iovad->dma_32bit_pfn)
-        iovad->max32_alloc_size = iovad->dma_32bit_pfn;
-
     cached_iova = to_iova(iovad->cached_node);
     if (free->pfn_lo >= cached_iova->pfn_lo)
         iovad->cached_node = rb_next(&free->node);
@@ -182,9 +178,6 @@ static int __alloc_and_insert_iova_range(struct
iova_domain *iovad,

     /* Walk the tree backwards */
     spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
-    if (limit_pfn <= iovad->dma_32bit_pfn &&
-            size >= iovad->max32_alloc_size)
-        goto iova32_full;

     curr = __get_cached_rbnode(iovad, limit_pfn);
     curr_iova = to_iova(curr);
@@ -207,7 +200,6 @@ static int __alloc_and_insert_iova_range(struct
iova_domain *iovad,
             curr_iova = to_iova(curr);
             goto retry;
         }
-        iovad->max32_alloc_size = size;
         goto iova32_full;
     }

diff --git a/include/linux/iova.h b/include/linux/iova.h
index 30ce5ad499d2..2800bdc203b1 100644
--- a/include/linux/iova.h
+++ b/include/linux/iova.h
@@ -33,7 +33,6 @@ struct iova_domain {
     unsigned long    granule;    /* pfn granularity for this domain */
     unsigned long    start_pfn;    /* Lower limit for this domain */
     unsigned long    dma_32bit_pfn;
-    unsigned long    max32_alloc_size; /* Size of last failed allocation */
     struct iova    anchor;        /* rbtree lookup anchor */

     struct iova_rcache    *rcaches;


-- 
----------------------------------------
Constantine Gavrilov
System Architect and Platform Engineer
Infinidat
----------------------------------------

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ