Skip to content

Commit 19fce04

Browse files
James SmartChristoph Hellwig
authored andcommitted
nvme-fc: avoid calling _nvme_fc_abort_outstanding_ios from interrupt context
Recent patches changed calling sequences. nvme_fc_abort_outstanding_ios used to be called from a timeout or work context. Now it is being called in an io completion context, which can be an interrupt handler. Unfortunately, the abort outstanding ios routine attempts to stop nvme queues and nested routines that may try to sleep, which is in conflict with the interrupt handler. Correct replacing the direct call with a work element scheduling, and the abort outstanding ios routine will be called in the work element. Fixes: 95ced8a ("nvme-fc: eliminate terminate_io use by nvme_fc_error_recovery") Signed-off-by: James Smart <james.smart@broadcom.com> Reported-by: Daniel Wagner <dwagner@suse.de> Tested-by: Daniel Wagner <dwagner@suse.de> Signed-off-by: Christoph Hellwig <hch@lst.de>
1 parent aebf5db commit 19fce04

File tree

1 file changed

+14
-1
lines changed
  • drivers/nvme/host

1 file changed

+14
-1
lines changed

drivers/nvme/host/fc.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ struct nvme_fc_ctrl {
166166
struct blk_mq_tag_set admin_tag_set;
167167
struct blk_mq_tag_set tag_set;
168168

169+
struct work_struct ioerr_work;
169170
struct delayed_work connect_work;
170171

171172
struct kref ref;
@@ -1888,6 +1889,15 @@ __nvme_fc_fcpop_chk_teardowns(struct nvme_fc_ctrl *ctrl,
18881889
}
18891890
}
18901891

1892+
static void
1893+
nvme_fc_ctrl_ioerr_work(struct work_struct *work)
1894+
{
1895+
struct nvme_fc_ctrl *ctrl =
1896+
container_of(work, struct nvme_fc_ctrl, ioerr_work);
1897+
1898+
nvme_fc_error_recovery(ctrl, "transport detected io error");
1899+
}
1900+
18911901
static void
18921902
nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
18931903
{
@@ -2046,7 +2056,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
20462056

20472057
check_error:
20482058
if (terminate_assoc)
2049-
nvme_fc_error_recovery(ctrl, "transport detected io error");
2059+
queue_work(nvme_reset_wq, &ctrl->ioerr_work);
20502060
}
20512061

20522062
static int
@@ -3233,6 +3243,7 @@ nvme_fc_delete_ctrl(struct nvme_ctrl *nctrl)
32333243
{
32343244
struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl);
32353245

3246+
cancel_work_sync(&ctrl->ioerr_work);
32363247
cancel_delayed_work_sync(&ctrl->connect_work);
32373248
/*
32383249
* kill the association on the link side. this will block
@@ -3449,6 +3460,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
34493460

34503461
INIT_WORK(&ctrl->ctrl.reset_work, nvme_fc_reset_ctrl_work);
34513462
INIT_DELAYED_WORK(&ctrl->connect_work, nvme_fc_connect_ctrl_work);
3463+
INIT_WORK(&ctrl->ioerr_work, nvme_fc_ctrl_ioerr_work);
34523464
spin_lock_init(&ctrl->lock);
34533465

34543466
/* io queue count */
@@ -3540,6 +3552,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
35403552

35413553
fail_ctrl:
35423554
nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING);
3555+
cancel_work_sync(&ctrl->ioerr_work);
35433556
cancel_work_sync(&ctrl->ctrl.reset_work);
35443557
cancel_delayed_work_sync(&ctrl->connect_work);
35453558

0 commit comments

Comments
 (0)