Skip to content

Commit a971574

Browse files
Tao ChiuChristoph Hellwig
authored andcommitted
nvme: move the fabrics queue ready check routines to core
queue_rq() in pci only checks if the dispatched queue (nvmeq) is ready, e.g. not being suspended. Since nvme_alloc_admin_tags() in reset flow restarts the admin queue, users are able to submit admin commands to a controller before reset_work() completes. Commands submitted under this condition may interfere with commands that performs identify, IO queue setup in reset_work(), and may result in a hang described in the following patch. As seen in the fabrics, user commands are prevented from being executed under inproper controller states. We may reuse this logic to maintain a clear admin queue during reset_work(). Signed-off-by: Tao Chiu <[email protected]> Signed-off-by: Cody Wong <[email protected]> Reviewed-by: Leon Chien <[email protected]> Reviewed-by: Keith Busch <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]>
1 parent 51ad06c commit a971574

File tree

8 files changed

+83
-78
lines changed

8 files changed

+83
-78
lines changed

drivers/nvme/host/core.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,66 @@ static struct request *nvme_alloc_request_qid(struct request_queue *q,
639639
return req;
640640
}
641641

642+
/*
643+
* For something we're not in a state to send to the device the default action
644+
* is to busy it and retry it after the controller state is recovered. However,
645+
* if the controller is deleting or if anything is marked for failfast or
646+
* nvme multipath it is immediately failed.
647+
*
648+
* Note: commands used to initialize the controller will be marked for failfast.
649+
* Note: nvme cli/ioctl commands are marked for failfast.
650+
*/
651+
blk_status_t nvme_fail_nonready_command(struct nvme_ctrl *ctrl,
652+
struct request *rq)
653+
{
654+
if (ctrl->state != NVME_CTRL_DELETING_NOIO &&
655+
ctrl->state != NVME_CTRL_DEAD &&
656+
!test_bit(NVME_CTRL_FAILFAST_EXPIRED, &ctrl->flags) &&
657+
!blk_noretry_request(rq) && !(rq->cmd_flags & REQ_NVME_MPATH))
658+
return BLK_STS_RESOURCE;
659+
return nvme_host_path_error(rq);
660+
}
661+
EXPORT_SYMBOL_GPL(nvme_fail_nonready_command);
662+
663+
bool __nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq,
664+
bool queue_live)
665+
{
666+
struct nvme_request *req = nvme_req(rq);
667+
668+
/*
669+
* currently we have a problem sending passthru commands
670+
* on the admin_q if the controller is not LIVE because we can't
671+
* make sure that they are going out after the admin connect,
672+
* controller enable and/or other commands in the initialization
673+
* sequence. until the controller will be LIVE, fail with
674+
* BLK_STS_RESOURCE so that they will be rescheduled.
675+
*/
676+
if (rq->q == ctrl->admin_q && (req->flags & NVME_REQ_USERCMD))
677+
return false;
678+
679+
if (ctrl->ops->flags & NVME_F_FABRICS) {
680+
/*
681+
* Only allow commands on a live queue, except for the connect
682+
* command, which is require to set the queue live in the
683+
* appropinquate states.
684+
*/
685+
switch (ctrl->state) {
686+
case NVME_CTRL_CONNECTING:
687+
if (blk_rq_is_passthrough(rq) && nvme_is_fabrics(req->cmd) &&
688+
req->cmd->fabrics.fctype == nvme_fabrics_type_connect)
689+
return true;
690+
break;
691+
default:
692+
break;
693+
case NVME_CTRL_DEAD:
694+
return false;
695+
}
696+
}
697+
698+
return queue_live;
699+
}
700+
EXPORT_SYMBOL_GPL(__nvme_check_ready);
701+
642702
static int nvme_toggle_streams(struct nvme_ctrl *ctrl, bool enable)
643703
{
644704
struct nvme_command c;

drivers/nvme/host/fabrics.c

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -533,63 +533,6 @@ static struct nvmf_transport_ops *nvmf_lookup_transport(
533533
return NULL;
534534
}
535535

536-
/*
537-
* For something we're not in a state to send to the device the default action
538-
* is to busy it and retry it after the controller state is recovered. However,
539-
* if the controller is deleting or if anything is marked for failfast or
540-
* nvme multipath it is immediately failed.
541-
*
542-
* Note: commands used to initialize the controller will be marked for failfast.
543-
* Note: nvme cli/ioctl commands are marked for failfast.
544-
*/
545-
blk_status_t nvmf_fail_nonready_command(struct nvme_ctrl *ctrl,
546-
struct request *rq)
547-
{
548-
if (ctrl->state != NVME_CTRL_DELETING_NOIO &&
549-
ctrl->state != NVME_CTRL_DEAD &&
550-
!test_bit(NVME_CTRL_FAILFAST_EXPIRED, &ctrl->flags) &&
551-
!blk_noretry_request(rq) && !(rq->cmd_flags & REQ_NVME_MPATH))
552-
return BLK_STS_RESOURCE;
553-
return nvme_host_path_error(rq);
554-
}
555-
EXPORT_SYMBOL_GPL(nvmf_fail_nonready_command);
556-
557-
bool __nvmf_check_ready(struct nvme_ctrl *ctrl, struct request *rq,
558-
bool queue_live)
559-
{
560-
struct nvme_request *req = nvme_req(rq);
561-
562-
/*
563-
* currently we have a problem sending passthru commands
564-
* on the admin_q if the controller is not LIVE because we can't
565-
* make sure that they are going out after the admin connect,
566-
* controller enable and/or other commands in the initialization
567-
* sequence. until the controller will be LIVE, fail with
568-
* BLK_STS_RESOURCE so that they will be rescheduled.
569-
*/
570-
if (rq->q == ctrl->admin_q && (req->flags & NVME_REQ_USERCMD))
571-
return false;
572-
573-
/*
574-
* Only allow commands on a live queue, except for the connect command,
575-
* which is require to set the queue live in the appropinquate states.
576-
*/
577-
switch (ctrl->state) {
578-
case NVME_CTRL_CONNECTING:
579-
if (blk_rq_is_passthrough(rq) && nvme_is_fabrics(req->cmd) &&
580-
req->cmd->fabrics.fctype == nvme_fabrics_type_connect)
581-
return true;
582-
break;
583-
default:
584-
break;
585-
case NVME_CTRL_DEAD:
586-
return false;
587-
}
588-
589-
return queue_live;
590-
}
591-
EXPORT_SYMBOL_GPL(__nvmf_check_ready);
592-
593536
static const match_table_t opt_tokens = {
594537
{ NVMF_OPT_TRANSPORT, "transport=%s" },
595538
{ NVMF_OPT_TRADDR, "traddr=%s" },

drivers/nvme/host/fabrics.h

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -184,20 +184,7 @@ void nvmf_unregister_transport(struct nvmf_transport_ops *ops);
184184
void nvmf_free_options(struct nvmf_ctrl_options *opts);
185185
int nvmf_get_address(struct nvme_ctrl *ctrl, char *buf, int size);
186186
bool nvmf_should_reconnect(struct nvme_ctrl *ctrl);
187-
blk_status_t nvmf_fail_nonready_command(struct nvme_ctrl *ctrl,
188-
struct request *rq);
189-
bool __nvmf_check_ready(struct nvme_ctrl *ctrl, struct request *rq,
190-
bool queue_live);
191187
bool nvmf_ip_options_match(struct nvme_ctrl *ctrl,
192188
struct nvmf_ctrl_options *opts);
193189

194-
static inline bool nvmf_check_ready(struct nvme_ctrl *ctrl, struct request *rq,
195-
bool queue_live)
196-
{
197-
if (likely(ctrl->state == NVME_CTRL_LIVE ||
198-
ctrl->state == NVME_CTRL_DELETING))
199-
return true;
200-
return __nvmf_check_ready(ctrl, rq, queue_live);
201-
}
202-
203190
#endif /* _NVME_FABRICS_H */

drivers/nvme/host/fc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2766,8 +2766,8 @@ nvme_fc_queue_rq(struct blk_mq_hw_ctx *hctx,
27662766
blk_status_t ret;
27672767

27682768
if (ctrl->rport->remoteport.port_state != FC_OBJSTATE_ONLINE ||
2769-
!nvmf_check_ready(&queue->ctrl->ctrl, rq, queue_ready))
2770-
return nvmf_fail_nonready_command(&queue->ctrl->ctrl, rq);
2769+
!nvme_check_ready(&queue->ctrl->ctrl, rq, queue_ready))
2770+
return nvme_fail_nonready_command(&queue->ctrl->ctrl, rq);
27712771

27722772
ret = nvme_setup_cmd(ns, rq);
27732773
if (ret)

drivers/nvme/host/nvme.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,21 @@ struct request *nvme_alloc_request(struct request_queue *q,
638638
struct nvme_command *cmd, blk_mq_req_flags_t flags);
639639
void nvme_cleanup_cmd(struct request *req);
640640
blk_status_t nvme_setup_cmd(struct nvme_ns *ns, struct request *req);
641+
blk_status_t nvme_fail_nonready_command(struct nvme_ctrl *ctrl,
642+
struct request *req);
643+
bool __nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq,
644+
bool queue_live);
645+
646+
static inline bool nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq,
647+
bool queue_live)
648+
{
649+
if (likely(ctrl->state == NVME_CTRL_LIVE))
650+
return true;
651+
if (ctrl->ops->flags & NVME_F_FABRICS &&
652+
ctrl->state == NVME_CTRL_DELETING)
653+
return true;
654+
return __nvme_check_ready(ctrl, rq, queue_live);
655+
}
641656
int nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
642657
void *buf, unsigned bufflen);
643658
int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,

drivers/nvme/host/rdma.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2050,8 +2050,8 @@ static blk_status_t nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
20502050

20512051
WARN_ON_ONCE(rq->tag < 0);
20522052

2053-
if (!nvmf_check_ready(&queue->ctrl->ctrl, rq, queue_ready))
2054-
return nvmf_fail_nonready_command(&queue->ctrl->ctrl, rq);
2053+
if (!nvme_check_ready(&queue->ctrl->ctrl, rq, queue_ready))
2054+
return nvme_fail_nonready_command(&queue->ctrl->ctrl, rq);
20552055

20562056
dev = queue->device->dev;
20572057

drivers/nvme/host/tcp.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2338,8 +2338,8 @@ static blk_status_t nvme_tcp_queue_rq(struct blk_mq_hw_ctx *hctx,
23382338
bool queue_ready = test_bit(NVME_TCP_Q_LIVE, &queue->flags);
23392339
blk_status_t ret;
23402340

2341-
if (!nvmf_check_ready(&queue->ctrl->ctrl, rq, queue_ready))
2342-
return nvmf_fail_nonready_command(&queue->ctrl->ctrl, rq);
2341+
if (!nvme_check_ready(&queue->ctrl->ctrl, rq, queue_ready))
2342+
return nvme_fail_nonready_command(&queue->ctrl->ctrl, rq);
23432343

23442344
ret = nvme_tcp_setup_cmd_pdu(ns, rq);
23452345
if (unlikely(ret))

drivers/nvme/target/loop.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,8 @@ static blk_status_t nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx,
138138
bool queue_ready = test_bit(NVME_LOOP_Q_LIVE, &queue->flags);
139139
blk_status_t ret;
140140

141-
if (!nvmf_check_ready(&queue->ctrl->ctrl, req, queue_ready))
142-
return nvmf_fail_nonready_command(&queue->ctrl->ctrl, req);
141+
if (!nvme_check_ready(&queue->ctrl->ctrl, req, queue_ready))
142+
return nvme_fail_nonready_command(&queue->ctrl->ctrl, req);
143143

144144
ret = nvme_setup_cmd(ns, req);
145145
if (ret)

0 commit comments

Comments
 (0)