diff options
author | Ming Lei <ming.lei@redhat.com> | 2019-04-28 03:39:32 -0400 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2019-06-20 15:21:33 -0400 |
commit | 3dccdf53c2f38399b11085ded4447ce1467f006c (patch) | |
tree | d5415d9704bd5dc2151e36363e5b6cfa0a1dd087 /drivers/scsi | |
parent | 92524fa12312d1f082a473e14c590c48b4ef3fe5 (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.c | 15 |
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 | |||
48 | static struct kmem_cache *scsi_sdb_cache; | 50 | static struct kmem_cache *scsi_sdb_cache; |
49 | static struct kmem_cache *scsi_sense_cache; | 51 | static struct kmem_cache *scsi_sense_cache; |
50 | static struct kmem_cache *scsi_sense_isadma_cache; | 52 | static struct kmem_cache *scsi_sense_isadma_cache; |
@@ -547,7 +549,8 @@ static void scsi_uninit_cmd(struct scsi_cmnd *cmd) | |||
547 | static void scsi_mq_free_sgtables(struct scsi_cmnd *cmd) | 549 | static 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. */ |
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) |
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) + |