nvme-fc: address target disconnect race conditions in fcp io submit
authorJames Smart <jsmart2021@gmail.com>
Tue, 18 Jul 2017 21:29:34 +0000 (14:29 -0700)
committerChristoph Hellwig <hch@lst.de>
Tue, 25 Jul 2017 15:58:47 +0000 (17:58 +0200)
There are cases where threads are in the process of submitting new
io when the LLDD calls in to remove the remote port. In some cases,
the next io actually goes to the LLDD, who knows the remoteport isn't
present and rejects it. To properly recovery/restart these i/o's we
don't want to hard fail them, we want to treat them as temporary
resource errors in which a delayed retry will work.

Add a couple more checks on remoteport connectivity and commonize the
busy response handling when it's seen.

Signed-off-by: James Smart <james.smart@broadcom.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
drivers/nvme/host/fc.c

index d666ada..5630ca4 100644 (file)
@@ -1888,7 +1888,7 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,
         * the target device is present
         */
        if (ctrl->rport->remoteport.port_state != FC_OBJSTATE_ONLINE)
-               return BLK_STS_IOERR;
+               goto busy;
 
        if (!nvme_fc_ctrl_get(ctrl))
                return BLK_STS_IOERR;
@@ -1958,22 +1958,25 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,
                                        queue->lldd_handle, &op->fcp_req);
 
        if (ret) {
-               if (op->rq)                     /* normal request */
+               if (!(op->flags & FCOP_FLAGS_AEN))
                        nvme_fc_unmap_data(ctrl, op->rq, op);
-               /* else - aen. no cleanup needed */
 
                nvme_fc_ctrl_put(ctrl);
 
-               if (ret != -EBUSY)
+               if (ctrl->rport->remoteport.port_state == FC_OBJSTATE_ONLINE &&
+                               ret != -EBUSY)
                        return BLK_STS_IOERR;
 
-               if (op->rq)
-                       blk_mq_delay_run_hw_queue(queue->hctx, NVMEFC_QUEUE_DELAY);
-
-               return BLK_STS_RESOURCE;
+               goto busy;
        }
 
        return BLK_STS_OK;
+
+busy:
+       if (!(op->flags & FCOP_FLAGS_AEN) && queue->hctx)
+               blk_mq_delay_run_hw_queue(queue->hctx, NVMEFC_QUEUE_DELAY);
+
+       return BLK_STS_RESOURCE;
 }
 
 static blk_status_t