Skip to content

Commit 733ab7e

Browse files
David Jefferymartinkpetersen
authored andcommitted
scsi: fnic: Finish scsi_cmnd before dropping the spinlock
When aborting a SCSI command through fnic, there is a race with the fnic interrupt handler which can result in the SCSI command and its request being completed twice. If the interrupt handler claims the command by setting CMD_SP to NULL first, the abort handler assumes the interrupt handler has completed the command and returns SUCCESS, causing the request for the scsi_cmnd to be re-queued. But the interrupt handler may not have finished the command yet. After it drops the spinlock protecting CMD_SP, it does memory cleanup before finally calling scsi_done() to complete the scsi_cmnd. If the call to scsi_done occurs after the abort handler finishes and re-queues the request, the completion of the scsi_cmnd will advance and try to double complete a request already queued for retry. This patch fixes the issue by moving scsi_done() and any other use of scsi_cmnd to before the spinlock is released by the interrupt handler. Link: https://lore.kernel.org/r/20220311184359.2345319-1-djeffery@redhat.com Reviewed-by: Laurence Oberman <loberman@redhat.com> Reviewed-by: Ming Lei <ming.lei@redhat.com> Signed-off-by: David Jeffery <djeffery@redhat.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 69ad4ef commit 733ab7e

1 file changed

Lines changed: 6 additions & 7 deletions

File tree

drivers/scsi/fnic/fnic_scsi.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -986,8 +986,6 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
986986
CMD_SP(sc) = NULL;
987987
CMD_FLAGS(sc) |= FNIC_IO_DONE;
988988

989-
spin_unlock_irqrestore(io_lock, flags);
990-
991989
if (hdr_status != FCPIO_SUCCESS) {
992990
atomic64_inc(&fnic_stats->io_stats.io_failures);
993991
shost_printk(KERN_ERR, fnic->lport->host, "hdr status = %s\n",
@@ -996,8 +994,6 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
996994

997995
fnic_release_ioreq_buf(fnic, io_req, sc);
998996

999-
mempool_free(io_req, fnic->io_req_pool);
1000-
1001997
cmd_trace = ((u64)hdr_status << 56) |
1002998
(u64)icmnd_cmpl->scsi_status << 48 |
1003999
(u64)icmnd_cmpl->flags << 40 | (u64)sc->cmnd[0] << 32 |
@@ -1021,6 +1017,12 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
10211017
} else
10221018
fnic->lport->host_stats.fcp_control_requests++;
10231019

1020+
/* Call SCSI completion function to complete the IO */
1021+
scsi_done(sc);
1022+
spin_unlock_irqrestore(io_lock, flags);
1023+
1024+
mempool_free(io_req, fnic->io_req_pool);
1025+
10241026
atomic64_dec(&fnic_stats->io_stats.active_ios);
10251027
if (atomic64_read(&fnic->io_cmpl_skip))
10261028
atomic64_dec(&fnic->io_cmpl_skip);
@@ -1049,9 +1051,6 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
10491051
if(io_duration_time > atomic64_read(&fnic_stats->io_stats.current_max_io_time))
10501052
atomic64_set(&fnic_stats->io_stats.current_max_io_time, io_duration_time);
10511053
}
1052-
1053-
/* Call SCSI completion function to complete the IO */
1054-
scsi_done(sc);
10551054
}
10561055

10571056
/* fnic_fcpio_itmf_cmpl_handler

0 commit comments

Comments
 (0)