From: Himanshu Madhani <himanshu.madhani@xxxxxxxxxx> Add check for multipath reqeust when scsi_complete is called. For error handling case, call scsi_mpath_failover_req() to complete the multipath IO. Signed-off-by: Himanshu Madhani <himanshu.madhani@xxxxxxxxxx> --- drivers/scsi/scsi_lib.c | 25 +++++++++++++++++++++++++ include/scsi/scsi.h | 1 + 2 files changed, 26 insertions(+) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 0561b318dade..1c8113abc154 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -33,6 +33,7 @@ #include <scsi/scsi_eh.h> #include <scsi/scsi_host.h> #include <scsi/scsi_transport.h> /* scsi_init_limits() */ +#include <scsi/scsi_multipath.h> #include <scsi/scsi_dh.h> #include <trace/events/scsi.h> @@ -620,6 +621,14 @@ static void scsi_run_queue_async(struct scsi_device *sdev) } } +static inline void __scsi_mpath_end_request(struct request *req, + blk_status_t status) +{ + if (req->cmd_flags & REQ_SCSI_MPATH) + scsi_mpath_end_request(req); + blk_mq_end_request(req, status); +} + /* Returns false when no more bytes to process, true if there are more */ static bool scsi_end_request(struct request *req, blk_status_t error, unsigned int bytes) @@ -661,6 +670,9 @@ static bool scsi_end_request(struct request *req, blk_status_t error, */ percpu_ref_get(&q->q_usage_counter); + if (req->cmd_flags & REQ_SCSI_MPATH) + scsi_mpath_end_request(req); + __blk_mq_end_request(req, error); scsi_run_queue_async(sdev); @@ -1528,6 +1540,9 @@ static void scsi_complete(struct request *rq) case ADD_TO_MLQUEUE: scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); break; + case FAILOVER: + scsi_mpath_failover_req(rq); + break; default: scsi_eh_scmd_add(cmd); break; @@ -1840,6 +1855,9 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx, memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); cmd->submitter = SUBMITTED_BY_BLOCK_LAYER; + if (req->cmd_flags & REQ_SCSI_MPATH) + scsi_mpath_start_request(req); + blk_mq_start_request(req); reason = scsi_dispatch_cmd(cmd); if (reason) { @@ -2811,6 +2829,9 @@ EXPORT_SYMBOL(scsi_target_resume); static int __scsi_internal_device_block_nowait(struct scsi_device *sdev) { + if (scsi_mpath_enabled(sdev)) + scsi_mpath_clear_current_path(sdev); + if (scsi_device_set_state(sdev, SDEV_BLOCK)) return scsi_device_set_state(sdev, SDEV_CREATED_BLOCK); @@ -2927,6 +2948,10 @@ int scsi_internal_device_unblock_nowait(struct scsi_device *sdev, return -EINVAL; } + /* For multipath device set the path live */ + if (scsi_mpath_enabled(sdev)) + scsi_mpath_set_live(sdev); + /* * Try to transition the scsi device to SDEV_RUNNING or one of the * offlined states and goose the device queue if successful. diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 96b350366670..544153a01b3f 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -103,6 +103,7 @@ enum scsi_disposition { TIMEOUT_ERROR = 0x2007, SCSI_RETURN_NOT_HANDLED = 0x2008, FAST_IO_FAIL = 0x2009, + FAILOVER = 0x2010, }; /* -- 2.41.0.rc2