Do not requeue requests if REQ_FAILFAST is set Any requests with the REQ_FAILFAST flag set should not be requeued to the requeust queue, but rather terminated directly. Otherwise the multipath failover will stall until the command timeout triggers. Signed-off-by: Hannes Reinecke diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 277f1b6..a12d2f1 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1200,6 +1200,11 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) */ if (!(req->cmd_flags & REQ_PREEMPT)) ret = BLKPREP_DEFER; + /* + * Return failfast requests immediately + */ + if (req->cmd_flags & REQ_FAILFAST) + ret = BLKPREP_KILL; break; default: /* @@ -1327,6 +1332,17 @@ static inline int scsi_host_queue_ready(struct request_queue *q, return 1; } +static void __scsi_kill_request(struct request *req) +{ + struct scsi_cmnd *cmd = req->special; + struct scsi_device *sdev = cmd->device; + + cmd->result = DID_NO_CONNECT << 16; + atomic_inc(&cmd->device->iorequest_cnt); + sdev->device_busy--; + __scsi_done(cmd); +} + /* * Kill a request for a dead device */ @@ -1440,8 +1456,16 @@ static void scsi_request_fn(struct request_queue *q) * accept it. */ req = elv_next_request(q); - if (!req || !scsi_dev_queue_ready(q, sdev)) + if (!req) + break; + + if (!scsi_dev_queue_ready(q, sdev)) { + if (req->cmd_flags & REQ_FAILFAST) { + scsi_kill_request(req, q); + continue; + } break; + } if (unlikely(!scsi_device_online(sdev))) { sdev_printk(KERN_ERR, sdev, @@ -1522,8 +1546,12 @@ static void scsi_request_fn(struct request_queue *q) * later time. */ spin_lock_irq(q->queue_lock); - blk_requeue_request(q, req); - sdev->device_busy--; + if (unlikely(req->cmd_flags & REQ_FAILFAST)) + __scsi_kill_request(req); + else { + blk_requeue_request(q, req); + sdev->device_busy--; + } if(sdev->device_busy == 0) blk_plug_device(q); out: