scsi: sd_zbc: block: Respect bio vector limits for REPORT ZONES buffer
authorSteve Siwinski <ssiwinski@atto.com>
Thu, 8 May 2025 20:01:22 +0000 (16:01 -0400)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 13 May 2025 02:35:48 +0000 (22:35 -0400)
The REPORT ZONES buffer size is currently limited by the HBA's maximum
segment count to ensure the buffer can be mapped. However, the block
layer further limits the number of iovec entries to 1024 when allocating
a bio.

To avoid allocation of buffers too large to be mapped, further restrict
the maximum buffer size to BIO_MAX_INLINE_VECS.

Replace the UIO_MAXIOV symbolic name with the more contextually
appropriate BIO_MAX_INLINE_VECS.

Fixes: b091ac616846 ("sd_zbc: Fix report zones buffer allocation")
Cc: stable@vger.kernel.org
Signed-off-by: Steve Siwinski <ssiwinski@atto.com>
Link: https://lore.kernel.org/r/20250508200122.243129-1-ssiwinski@atto.com
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
block/bio.c
drivers/scsi/sd_zbc.c
include/linux/bio.h

index 4e6c85a33d74dbc1f025c5dbc1965ad8f40aa4c1..4be592d37fb66642dc5eef759a058c68000cc27d 100644 (file)
@@ -611,7 +611,7 @@ struct bio *bio_kmalloc(unsigned short nr_vecs, gfp_t gfp_mask)
 {
        struct bio *bio;
 
-       if (nr_vecs > UIO_MAXIOV)
+       if (nr_vecs > BIO_MAX_INLINE_VECS)
                return NULL;
        return kmalloc(struct_size(bio, bi_inline_vecs, nr_vecs), gfp_mask);
 }
index 7a447ff600d276a3e7c8e602f24b4d7682baef1f..a8db66428f80d456330c828ebb1fdda1e674eb4a 100644 (file)
@@ -169,6 +169,7 @@ static void *sd_zbc_alloc_report_buffer(struct scsi_disk *sdkp,
                                        unsigned int nr_zones, size_t *buflen)
 {
        struct request_queue *q = sdkp->disk->queue;
+       unsigned int max_segments;
        size_t bufsize;
        void *buf;
 
@@ -180,12 +181,15 @@ static void *sd_zbc_alloc_report_buffer(struct scsi_disk *sdkp,
         * Furthermore, since the report zone command cannot be split, make
         * sure that the allocated buffer can always be mapped by limiting the
         * number of pages allocated to the HBA max segments limit.
+        * Since max segments can be larger than the max inline bio vectors,
+        * further limit the allocated buffer to BIO_MAX_INLINE_VECS.
         */
        nr_zones = min(nr_zones, sdkp->zone_info.nr_zones);
        bufsize = roundup((nr_zones + 1) * 64, SECTOR_SIZE);
        bufsize = min_t(size_t, bufsize,
                        queue_max_hw_sectors(q) << SECTOR_SHIFT);
-       bufsize = min_t(size_t, bufsize, queue_max_segments(q) << PAGE_SHIFT);
+       max_segments = min(BIO_MAX_INLINE_VECS, queue_max_segments(q));
+       bufsize = min_t(size_t, bufsize, max_segments << PAGE_SHIFT);
 
        while (bufsize >= SECTOR_SIZE) {
                buf = kvzalloc(bufsize, GFP_KERNEL | __GFP_NORETRY);
index cafc7c215de8bece6c2cb4532ba7c2c9ec85e0cc..b786ec5bcc81d0c909b4e0ccbd186ae342bd5d84 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/uio.h>
 
 #define BIO_MAX_VECS           256U
+#define BIO_MAX_INLINE_VECS    UIO_MAXIOV
 
 struct queue_limits;