[PATCH v1 1/2] dma: return 0 from dma_opt_mapping_size() when no real hint exists

Ionut Nechita (Wind River) ionut.nechita at windriver.com
Mon Mar 16 13:39:55 PDT 2026


From: Ionut Nechita <ionut.nechita at windriver.com>

dma_opt_mapping_size() currently initializes its local size to SIZE_MAX
and, when neither an IOMMU nor a DMA ops opt_mapping_size callback is
present, returns min(dma_max_mapping_size(dev), SIZE_MAX).  That value
is a large but finite number that has nothing to do with an optimal
transfer size — it is simply the maximum the DMA layer can map.

Callers such as scsi_transport_sas treat the return value as a genuine
optimization hint and propagate it into Scsi_Host.opt_sectors, which in
turn becomes the block device's optimal_io_size.  On SAS controllers
like mpt3sas running with IOMMU in passthrough mode the bogus value
(max_sectors << 9 = 16776704, rounded to 16773120) reaches mkfs.xfs,
which computes swidth=4095 and sunit=2.  Because 4095 is not a multiple
of 2, XFS rejects the geometry with "SB stripe unit sanity check
failed", making it impossible to create filesystems during system
bootstrap.

Fix this by returning 0 when no backend provides an optimal mapping size
hint.  A return value of 0 unambiguously means "no preference" and lets
callers that use min() or min_not_zero() do the right thing without
special-casing.

The only other in-tree caller (nvme-pci) is adjusted in the next patch.

Fixes: a229cc14f339 ("dma-mapping: add dma_opt_mapping_size()")
Cc: stable at vger.kernel.org
Signed-off-by: Ionut Nechita <ionut.nechita at windriver.com>
---
 kernel/dma/mapping.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
index 78d8b4039c3e6..fffa6a3f191a3 100644
--- a/kernel/dma/mapping.c
+++ b/kernel/dma/mapping.c
@@ -984,14 +984,17 @@ EXPORT_SYMBOL_GPL(dma_max_mapping_size);
 size_t dma_opt_mapping_size(struct device *dev)
 {
 	const struct dma_map_ops *ops = get_dma_ops(dev);
-	size_t size = SIZE_MAX;
 
 	if (use_dma_iommu(dev))
-		size = iommu_dma_opt_mapping_size();
-	else if (ops && ops->opt_mapping_size)
-		size = ops->opt_mapping_size();
+		return iommu_dma_opt_mapping_size();
+	if (ops && ops->opt_mapping_size)
+		return ops->opt_mapping_size();
 
-	return min(dma_max_mapping_size(dev), size);
+	/*
+	 * No backend provided an optimal size hint. Return 0 so that
+	 * callers can distinguish "no hint" from a real value.
+	 */
+	return 0;
 }
 EXPORT_SYMBOL_GPL(dma_opt_mapping_size);
 
-- 
2.53.0




More information about the Linux-nvme mailing list