Skip to content

Commit 0c958ec

Browse files
abattersbyJames Bottomley
authored andcommitted
scsi: fix memory leak with scsi-mq
Fix a memory leak with scsi-mq triggered by commands with large data transfer length. __sg_alloc_table() sets both table->nents and table->orig_nents to the same value. When the scatterlist is DMA-mapped, table->nents is overwritten with the (possibly smaller) size of the DMA-mapped scatterlist, while table->orig_nents retains the original size of the allocated scatterlist. scsi_free_sgtable() should therefore check orig_nents instead of nents, and all code that initializes sdb->table without calling __sg_alloc_table() should set both nents and orig_nents. Fixes: d285203 ("scsi: add support for a blk-mq based I/O path.") Cc: <stable@vger.kernel.org> # 3.17+ Signed-off-by: Tony Battersby <tonyb@cybernetics.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Ewan D. Milne <emilne@redhat.com> Signed-off-by: James Bottomley <JBottomley@Odin.com>
1 parent 3f1c058 commit 0c958ec

File tree

2 files changed

+4
-4
lines changed

2 files changed

+4
-4
lines changed

drivers/scsi/scsi_error.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -944,7 +944,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
944944
scmd->sdb.length);
945945
scmd->sdb.table.sgl = &ses->sense_sgl;
946946
scmd->sc_data_direction = DMA_FROM_DEVICE;
947-
scmd->sdb.table.nents = 1;
947+
scmd->sdb.table.nents = scmd->sdb.table.orig_nents = 1;
948948
scmd->cmnd[0] = REQUEST_SENSE;
949949
scmd->cmnd[4] = scmd->sdb.length;
950950
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);

drivers/scsi/scsi_lib.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,7 @@ static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask)
583583

584584
static void scsi_free_sgtable(struct scsi_data_buffer *sdb, bool mq)
585585
{
586-
if (mq && sdb->table.nents <= SCSI_MAX_SG_SEGMENTS)
586+
if (mq && sdb->table.orig_nents <= SCSI_MAX_SG_SEGMENTS)
587587
return;
588588
__sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free);
589589
}
@@ -597,8 +597,8 @@ static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents, bool mq)
597597

598598
if (mq) {
599599
if (nents <= SCSI_MAX_SG_SEGMENTS) {
600-
sdb->table.nents = nents;
601-
sg_init_table(sdb->table.sgl, sdb->table.nents);
600+
sdb->table.nents = sdb->table.orig_nents = nents;
601+
sg_init_table(sdb->table.sgl, nents);
602602
return 0;
603603
}
604604
first_chunk = sdb->table.sgl;

0 commit comments

Comments
 (0)