Skip to content

Commit 41df7b0

Browse files
Hiral ShahChristoph Hellwig
authored andcommitted
Fnic: Fnic Driver crashed with NULL pointer reference
When issuing I/O request, if the I/O completes before returning from fnic_queuecommand(), we may be referencing scsi_cmnd structure that may be freed by interrupt handler. Acquring IO lock would synchronize fnic_queuecommand and interrupt handler. - Increment fnic version from 1.6.0.15 to 1.6.0.16 Signed-off-by: Hiral Shah <[email protected]> Signed-off-by: Sesidhar Baddela <[email protected]> Signed-off-by: Anil Chintalapati <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]>
1 parent 0ee7b87 commit 41df7b0

File tree

2 files changed

+19
-4
lines changed

2 files changed

+19
-4
lines changed

drivers/scsi/fnic/fnic.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939

4040
#define DRV_NAME "fnic"
4141
#define DRV_DESCRIPTION "Cisco FCoE HBA Driver"
42-
#define DRV_VERSION "1.6.0.15"
42+
#define DRV_VERSION "1.6.0.16"
4343
#define PFX DRV_NAME ": "
4444
#define DFX DRV_NAME "%d: "
4545

drivers/scsi/fnic/fnic_scsi.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -421,9 +421,10 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
421421
int ret;
422422
u64 cmd_trace;
423423
int sg_count = 0;
424-
unsigned long flags;
424+
unsigned long flags = 0;
425425
unsigned long ptr;
426426
struct fc_rport_priv *rdata;
427+
spinlock_t *io_lock = NULL;
427428

428429
if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_IO_BLOCKED)))
429430
return SCSI_MLQUEUE_HOST_BUSY;
@@ -509,6 +510,13 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
509510
}
510511
}
511512

513+
/*
514+
* Will acquire lock defore setting to IO initialized.
515+
*/
516+
517+
io_lock = fnic_io_lock_hash(fnic, sc);
518+
spin_lock_irqsave(io_lock, flags);
519+
512520
/* initialize rest of io_req */
513521
io_req->port_id = rport->port_id;
514522
io_req->start_time = jiffies;
@@ -525,11 +533,9 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
525533
* In case another thread cancelled the request,
526534
* refetch the pointer under the lock.
527535
*/
528-
spinlock_t *io_lock = fnic_io_lock_hash(fnic, sc);
529536
FNIC_TRACE(fnic_queuecommand, sc->device->host->host_no,
530537
sc->request->tag, sc, 0, 0, 0,
531538
(((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
532-
spin_lock_irqsave(io_lock, flags);
533539
io_req = (struct fnic_io_req *)CMD_SP(sc);
534540
CMD_SP(sc) = NULL;
535541
CMD_STATE(sc) = FNIC_IOREQ_CMD_COMPLETE;
@@ -538,6 +544,10 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
538544
fnic_release_ioreq_buf(fnic, io_req, sc);
539545
mempool_free(io_req, fnic->io_req_pool);
540546
}
547+
atomic_dec(&fnic->in_flight);
548+
/* acquire host lock before returning to SCSI */
549+
spin_lock(lp->host->host_lock);
550+
return ret;
541551
} else {
542552
atomic64_inc(&fnic_stats->io_stats.active_ios);
543553
atomic64_inc(&fnic_stats->io_stats.num_ios);
@@ -559,6 +569,11 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
559569
sc->request->tag, sc, io_req,
560570
sg_count, cmd_trace,
561571
(((u64)CMD_FLAGS(sc) >> 32) | CMD_STATE(sc)));
572+
573+
/* if only we issued IO, will we have the io lock */
574+
if (CMD_FLAGS(sc) & FNIC_IO_INITIALIZED)
575+
spin_unlock_irqrestore(io_lock, flags);
576+
562577
atomic_dec(&fnic->in_flight);
563578
/* acquire host lock before returning to SCSI */
564579
spin_lock(lp->host->host_lock);

0 commit comments

Comments
 (0)