summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMing Lei <ming.lei@redhat.com>2019-04-28 03:39:32 -0400
committerMartin K. Petersen <martin.petersen@oracle.com>2019-06-20 15:21:33 -0400
commit3dccdf53c2f38399b11085ded4447ce1467f006c (patch)
treed5415d9704bd5dc2151e36363e5b6cfa0a1dd087 /drivers/scsi
parent92524fa12312d1f082a473e14c590c48b4ef3fe5 (diff)
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 <hch@lst.de> Cc: Bart Van Assche <bvanassche@acm.org> Cc: Ewan D. Milne <emilne@redhat.com> Cc: Hannes Reinecke <hare@suse.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Ming Lei <ming.lei@redhat.com> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/scsi_lib.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index c115458c835e..45b43e97505c 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -45,6 +45,8 @@
45 */ 45 */
46#define SCSI_INLINE_PROT_SG_CNT 1 46#define SCSI_INLINE_PROT_SG_CNT 1
47 47
48#define SCSI_INLINE_SG_CNT 2
49
48static struct kmem_cache *scsi_sdb_cache; 50static struct kmem_cache *scsi_sdb_cache;
49static struct kmem_cache *scsi_sense_cache; 51static struct kmem_cache *scsi_sense_cache;
50static struct kmem_cache *scsi_sense_isadma_cache; 52static struct kmem_cache *scsi_sense_isadma_cache;
@@ -547,7 +549,8 @@ static void scsi_uninit_cmd(struct scsi_cmnd *cmd)
547static void scsi_mq_free_sgtables(struct scsi_cmnd *cmd) 549static void scsi_mq_free_sgtables(struct scsi_cmnd *cmd)
548{ 550{
549 if (cmd->sdb.table.nents) 551 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);
551 if (scsi_prot_sg_count(cmd)) 554 if (scsi_prot_sg_count(cmd))
552 sg_free_table_chained(&cmd->prot_sdb->table, 555 sg_free_table_chained(&cmd->prot_sdb->table,
553 SCSI_INLINE_PROT_SG_CNT); 556 SCSI_INLINE_PROT_SG_CNT);
@@ -984,7 +987,7 @@ static blk_status_t scsi_init_sgtable(struct request *req,
984 */ 987 */
985 if (unlikely(sg_alloc_table_chained(&sdb->table, 988 if (unlikely(sg_alloc_table_chained(&sdb->table,
986 blk_rq_nr_phys_segments(req), sdb->table.sgl, 989 blk_rq_nr_phys_segments(req), sdb->table.sgl,
987 SG_CHUNK_SIZE))) 990 SCSI_INLINE_SG_CNT)))
988 return BLK_STS_RESOURCE; 991 return BLK_STS_RESOURCE;
989 992
990 /* 993 /*
@@ -1550,9 +1553,9 @@ static int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
1550} 1553}
1551 1554
1552/* Size in bytes of the sg-list stored in the scsi-mq command-private data. */ 1555/* Size in bytes of the sg-list stored in the scsi-mq command-private data. */
1553static unsigned int scsi_mq_sgl_size(struct Scsi_Host *shost) 1556static unsigned int scsi_mq_inline_sgl_size(struct Scsi_Host *shost)
1554{ 1557{
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) *
1556 sizeof(struct scatterlist); 1559 sizeof(struct scatterlist);
1557} 1560}
1558 1561
@@ -1734,7 +1737,7 @@ static int scsi_mq_init_request(struct blk_mq_tag_set *set, struct request *rq,
1734 if (scsi_host_get_prot(shost)) { 1737 if (scsi_host_get_prot(shost)) {
1735 sg = (void *)cmd + sizeof(struct scsi_cmnd) + 1738 sg = (void *)cmd + sizeof(struct scsi_cmnd) +
1736 shost->hostt->cmd_size; 1739 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);
1738 } 1741 }
1739 1742
1740 return 0; 1743 return 0;
@@ -1828,7 +1831,7 @@ int scsi_mq_setup_tags(struct Scsi_Host *shost)
1828{ 1831{
1829 unsigned int cmd_size, sgl_size; 1832 unsigned int cmd_size, sgl_size;
1830 1833
1831 sgl_size = scsi_mq_sgl_size(shost); 1834 sgl_size = scsi_mq_inline_sgl_size(shost);
1832 cmd_size = sizeof(struct scsi_cmnd) + shost->hostt->cmd_size + sgl_size; 1835 cmd_size = sizeof(struct scsi_cmnd) + shost->hostt->cmd_size + sgl_size;
1833 if (scsi_host_get_prot(shost)) 1836 if (scsi_host_get_prot(shost))
1834 cmd_size += sizeof(struct scsi_data_buffer) + 1837 cmd_size += sizeof(struct scsi_data_buffer) +