fnic: Cleanup the I/O pending with fw and has timed out and is used to issue LUN reset
In case of LUN reset, the device reset command is issued with one of the I/Os that has timed out on that LUN. The change is to also return this I/O with error status set to DID_RESET. In case when the reset is issued using the sg_reset tool (from sg3_utils) it is a new command and new_sc is set to 1. Fnic driver version changed from 1.6.0.19 to 1.6.0.20 [mkp: Fixed checkpatch warning] Signed-off-by: Satish Kharat <satishkh@cisco.com> Signed-off-by: Sesidhar Baddela <sebaddel@cisco.com> Reviewed-by: Ewan Milne <emilne@redhat.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Родитель
691a837c20
Коммит
a36f5dd07d
|
@ -39,7 +39,7 @@
|
||||||
|
|
||||||
#define DRV_NAME "fnic"
|
#define DRV_NAME "fnic"
|
||||||
#define DRV_DESCRIPTION "Cisco FCoE HBA Driver"
|
#define DRV_DESCRIPTION "Cisco FCoE HBA Driver"
|
||||||
#define DRV_VERSION "1.6.0.19"
|
#define DRV_VERSION "1.6.0.20"
|
||||||
#define PFX DRV_NAME ": "
|
#define PFX DRV_NAME ": "
|
||||||
#define DFX DRV_NAME "%d: "
|
#define DFX DRV_NAME "%d: "
|
||||||
|
|
||||||
|
|
|
@ -2039,7 +2039,9 @@ lr_io_req_end:
|
||||||
* successfully aborted, 1 otherwise
|
* successfully aborted, 1 otherwise
|
||||||
*/
|
*/
|
||||||
static int fnic_clean_pending_aborts(struct fnic *fnic,
|
static int fnic_clean_pending_aborts(struct fnic *fnic,
|
||||||
struct scsi_cmnd *lr_sc)
|
struct scsi_cmnd *lr_sc,
|
||||||
|
bool new_sc)
|
||||||
|
|
||||||
{
|
{
|
||||||
int tag, abt_tag;
|
int tag, abt_tag;
|
||||||
struct fnic_io_req *io_req;
|
struct fnic_io_req *io_req;
|
||||||
|
@ -2057,10 +2059,10 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
|
||||||
spin_lock_irqsave(io_lock, flags);
|
spin_lock_irqsave(io_lock, flags);
|
||||||
sc = scsi_host_find_tag(fnic->lport->host, tag);
|
sc = scsi_host_find_tag(fnic->lport->host, tag);
|
||||||
/*
|
/*
|
||||||
* ignore this lun reset cmd or cmds that do not belong to
|
* ignore this lun reset cmd if issued using new SC
|
||||||
* this lun
|
* or cmds that do not belong to this lun
|
||||||
*/
|
*/
|
||||||
if (!sc || sc == lr_sc || sc->device != lun_dev) {
|
if (!sc || ((sc == lr_sc) && new_sc) || sc->device != lun_dev) {
|
||||||
spin_unlock_irqrestore(io_lock, flags);
|
spin_unlock_irqrestore(io_lock, flags);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2166,13 +2168,29 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
|
||||||
goto clean_pending_aborts_end;
|
goto clean_pending_aborts_end;
|
||||||
}
|
}
|
||||||
CMD_STATE(sc) = FNIC_IOREQ_ABTS_COMPLETE;
|
CMD_STATE(sc) = FNIC_IOREQ_ABTS_COMPLETE;
|
||||||
|
|
||||||
|
/* original sc used for lr is handled by dev reset code */
|
||||||
|
if (sc != lr_sc)
|
||||||
CMD_SP(sc) = NULL;
|
CMD_SP(sc) = NULL;
|
||||||
spin_unlock_irqrestore(io_lock, flags);
|
spin_unlock_irqrestore(io_lock, flags);
|
||||||
|
|
||||||
|
/* original sc used for lr is handled by dev reset code */
|
||||||
|
if (sc != lr_sc) {
|
||||||
fnic_release_ioreq_buf(fnic, io_req, sc);
|
fnic_release_ioreq_buf(fnic, io_req, sc);
|
||||||
mempool_free(io_req, fnic->io_req_pool);
|
mempool_free(io_req, fnic->io_req_pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Any IO is returned during reset, it needs to call scsi_done
|
||||||
|
* to return the scsi_cmnd to upper layer.
|
||||||
|
*/
|
||||||
|
if (sc->scsi_done) {
|
||||||
|
/* Set result to let upper SCSI layer retry */
|
||||||
|
sc->result = DID_RESET << 16;
|
||||||
|
sc->scsi_done(sc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
schedule_timeout(msecs_to_jiffies(2 * fnic->config.ed_tov));
|
schedule_timeout(msecs_to_jiffies(2 * fnic->config.ed_tov));
|
||||||
|
|
||||||
/* walk again to check, if IOs are still pending in fw */
|
/* walk again to check, if IOs are still pending in fw */
|
||||||
|
@ -2264,6 +2282,7 @@ int fnic_device_reset(struct scsi_cmnd *sc)
|
||||||
int tag = 0;
|
int tag = 0;
|
||||||
DECLARE_COMPLETION_ONSTACK(tm_done);
|
DECLARE_COMPLETION_ONSTACK(tm_done);
|
||||||
int tag_gen_flag = 0; /*to track tags allocated by fnic driver*/
|
int tag_gen_flag = 0; /*to track tags allocated by fnic driver*/
|
||||||
|
bool new_sc = 0;
|
||||||
|
|
||||||
/* Wait for rport to unblock */
|
/* Wait for rport to unblock */
|
||||||
fc_block_scsi_eh(sc);
|
fc_block_scsi_eh(sc);
|
||||||
|
@ -2309,13 +2328,12 @@ int fnic_device_reset(struct scsi_cmnd *sc)
|
||||||
* fix the way the EH ioctls work for real, but until
|
* fix the way the EH ioctls work for real, but until
|
||||||
* that happens we fail these explicit requests here.
|
* that happens we fail these explicit requests here.
|
||||||
*/
|
*/
|
||||||
if (shost_use_blk_mq(sc->device->host))
|
|
||||||
goto fnic_device_reset_end;
|
|
||||||
|
|
||||||
tag = fnic_scsi_host_start_tag(fnic, sc);
|
tag = fnic_scsi_host_start_tag(fnic, sc);
|
||||||
if (unlikely(tag == SCSI_NO_TAG))
|
if (unlikely(tag == SCSI_NO_TAG))
|
||||||
goto fnic_device_reset_end;
|
goto fnic_device_reset_end;
|
||||||
tag_gen_flag = 1;
|
tag_gen_flag = 1;
|
||||||
|
new_sc = 1;
|
||||||
}
|
}
|
||||||
io_lock = fnic_io_lock_hash(fnic, sc);
|
io_lock = fnic_io_lock_hash(fnic, sc);
|
||||||
spin_lock_irqsave(io_lock, flags);
|
spin_lock_irqsave(io_lock, flags);
|
||||||
|
@ -2450,7 +2468,7 @@ int fnic_device_reset(struct scsi_cmnd *sc)
|
||||||
* the lun reset cmd. If all cmds get cleaned, the lun reset
|
* the lun reset cmd. If all cmds get cleaned, the lun reset
|
||||||
* succeeds
|
* succeeds
|
||||||
*/
|
*/
|
||||||
if (fnic_clean_pending_aborts(fnic, sc)) {
|
if (fnic_clean_pending_aborts(fnic, sc, new_sc)) {
|
||||||
spin_lock_irqsave(io_lock, flags);
|
spin_lock_irqsave(io_lock, flags);
|
||||||
io_req = (struct fnic_io_req *)CMD_SP(sc);
|
io_req = (struct fnic_io_req *)CMD_SP(sc);
|
||||||
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
|
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче