IB/srp: Fail I/O requests if the transport is offline
If an SRP target is no longer reachable and srp_reset_host() fails to reconnect then ib_srp will invoke scsi_remove_host(). That function will invoke __scsi_remove_device() for each LUN. And that last function will change the device state from SDEV_TRANSPORT_OFFLINE into SDEV_CANCEL. Certain user space software, e.g. older versions of multipathd, continue queueing I/O to SCSI devices that are in the SDEV_CANCEL state. If these I/O requests are submitted as SG_IO that means that the REQ_PREEMPT flag will be set and hence that these requests will be passed to srp_queuecommand(). These requests will time out. If new requests are queued fast enough from user space these active requests will prevent __scsi_remove_device() to finish. Avoid this by failing I/O requests in the SDEV_CANCEL state if the transport is offline. Introduce a new variable to keep track of the transport state instead of failing requests if (!target->connected || target->qp_in_error), so that the SCSI error handler has a chance to retry commands after a transport layer failure occurred. Signed-off-by: Bart Van Assche <bvanassche@acm.org> Cc: <stable@vger.kernel.org> # 3.8 Signed-off-by: Roland Dreier <roland@purestorage.com>
This commit is contained in:
parent
c7c4e7ff80
commit
2ce19e72f4
2 changed files with 8 additions and 0 deletions
|
@ -734,6 +734,7 @@ static int srp_reconnect_target(struct srp_target_port *target)
|
|||
|
||||
scsi_target_unblock(&shost->shost_gendev, ret == 0 ? SDEV_RUNNING :
|
||||
SDEV_TRANSPORT_OFFLINE);
|
||||
target->transport_offline = !!ret;
|
||||
|
||||
if (ret)
|
||||
goto err;
|
||||
|
@ -1353,6 +1354,12 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
|
|||
unsigned long flags;
|
||||
int len;
|
||||
|
||||
if (unlikely(target->transport_offline)) {
|
||||
scmnd->result = DID_NO_CONNECT << 16;
|
||||
scmnd->scsi_done(scmnd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&target->lock, flags);
|
||||
iu = __srp_get_tx_iu(target, SRP_IU_CMD);
|
||||
if (!iu)
|
||||
|
|
|
@ -140,6 +140,7 @@ struct srp_target_port {
|
|||
unsigned int cmd_sg_cnt;
|
||||
unsigned int indirect_size;
|
||||
bool allow_ext_sg;
|
||||
bool transport_offline;
|
||||
|
||||
/* Everything above this point is used in the hot path of
|
||||
* command processing. Try to keep them packed into cachelines.
|
||||
|
|
Loading…
Reference in a new issue