Skip to content

Commit 3dccdf5

Browse files
Ming Leimartinkpetersen
authored andcommitted
scsi: core: avoid preallocating big SGL for data
scsi_mq_setup_tags() preallocates a big buffer for the IO SGL. The size is based on scsi_mq_sgl_size() which is determined based on shost->sg_tablesize and SG_CHUNK_SIZE. Modern DMA engines are often capable of dealing with very big segments so the resulting scsi_mq_sgl_size() is often too big. SG_CHUNK_SIZE results in a static 4KB SGL allocation per command. If an HBA has lots of deep queues, preallocation for the sg list can consume substantial amounts of memory. For lpfc, nr_hw_queues can be 70 and each queue's depth 3781. This means the resulting preallocation for the data SGL is 70*3781*2K = 517MB. Switch to runtime allocation for SGL for lists longer than 2 entries. This is the approach used by NVMe PCI so it should be reasonable for SCSI as well. Runtime SGL allocation has always been the case for the legacy I/O path so this is nothing new. [mkp: attempted to clarify commit desc] Cc: Christoph Hellwig <[email protected]> Cc: Bart Van Assche <[email protected]> Cc: Ewan D. Milne <[email protected]> Cc: Hannes Reinecke <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Ming Lei <[email protected]> Reviewed-by: Bart Van Assche <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 92524fa commit 3dccdf5

File tree

1 file changed

+9
-6
lines changed

1 file changed

+9
-6
lines changed

drivers/scsi/scsi_lib.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
*/
4646
#define SCSI_INLINE_PROT_SG_CNT 1
4747

48+
#define SCSI_INLINE_SG_CNT 2
49+
4850
static struct kmem_cache *scsi_sdb_cache;
4951
static struct kmem_cache *scsi_sense_cache;
5052
static struct kmem_cache *scsi_sense_isadma_cache;
@@ -547,7 +549,8 @@ static void scsi_uninit_cmd(struct scsi_cmnd *cmd)
547549
static void scsi_mq_free_sgtables(struct scsi_cmnd *cmd)
548550
{
549551
if (cmd->sdb.table.nents)
550-
sg_free_table_chained(&cmd->sdb.table, SG_CHUNK_SIZE);
552+
sg_free_table_chained(&cmd->sdb.table,
553+
SCSI_INLINE_SG_CNT);
551554
if (scsi_prot_sg_count(cmd))
552555
sg_free_table_chained(&cmd->prot_sdb->table,
553556
SCSI_INLINE_PROT_SG_CNT);
@@ -984,7 +987,7 @@ static blk_status_t scsi_init_sgtable(struct request *req,
984987
*/
985988
if (unlikely(sg_alloc_table_chained(&sdb->table,
986989
blk_rq_nr_phys_segments(req), sdb->table.sgl,
987-
SG_CHUNK_SIZE)))
990+
SCSI_INLINE_SG_CNT)))
988991
return BLK_STS_RESOURCE;
989992

990993
/*
@@ -1550,9 +1553,9 @@ static int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
15501553
}
15511554

15521555
/* Size in bytes of the sg-list stored in the scsi-mq command-private data. */
1553-
static unsigned int scsi_mq_sgl_size(struct Scsi_Host *shost)
1556+
static unsigned int scsi_mq_inline_sgl_size(struct Scsi_Host *shost)
15541557
{
1555-
return min_t(unsigned int, shost->sg_tablesize, SG_CHUNK_SIZE) *
1558+
return min_t(unsigned int, shost->sg_tablesize, SCSI_INLINE_SG_CNT) *
15561559
sizeof(struct scatterlist);
15571560
}
15581561

@@ -1734,7 +1737,7 @@ static int scsi_mq_init_request(struct blk_mq_tag_set *set, struct request *rq,
17341737
if (scsi_host_get_prot(shost)) {
17351738
sg = (void *)cmd + sizeof(struct scsi_cmnd) +
17361739
shost->hostt->cmd_size;
1737-
cmd->prot_sdb = (void *)sg + scsi_mq_sgl_size(shost);
1740+
cmd->prot_sdb = (void *)sg + scsi_mq_inline_sgl_size(shost);
17381741
}
17391742

17401743
return 0;
@@ -1828,7 +1831,7 @@ int scsi_mq_setup_tags(struct Scsi_Host *shost)
18281831
{
18291832
unsigned int cmd_size, sgl_size;
18301833

1831-
sgl_size = scsi_mq_sgl_size(shost);
1834+
sgl_size = scsi_mq_inline_sgl_size(shost);
18321835
cmd_size = sizeof(struct scsi_cmnd) + shost->hostt->cmd_size + sgl_size;
18331836
if (scsi_host_get_prot(shost))
18341837
cmd_size += sizeof(struct scsi_data_buffer) +

0 commit comments

Comments
 (0)