Skip to content

Commit

Permalink
nvme-fc: avoid calling _nvme_fc_abort_outstanding_ios from interrupt …
Browse files Browse the repository at this point in the history
…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 <[email protected]>
Reported-by: Daniel Wagner <[email protected]>
Tested-by: Daniel Wagner <[email protected]>
Signed-off-by: Christoph Hellwig <[email protected]>
  • Loading branch information
James Smart authored and Christoph Hellwig committed Jan 6, 2021
1 parent aebf5db commit 19fce04
Showing 1 changed file with 14 additions and 1 deletion.
15 changes: 14 additions & 1 deletion drivers/nvme/host/fc.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ struct nvme_fc_ctrl {
struct blk_mq_tag_set admin_tag_set;
struct blk_mq_tag_set tag_set;

struct work_struct ioerr_work;
struct delayed_work connect_work;

struct kref ref;
Expand Down Expand Up @@ -1888,6 +1889,15 @@ __nvme_fc_fcpop_chk_teardowns(struct nvme_fc_ctrl *ctrl,
}
}

static void
nvme_fc_ctrl_ioerr_work(struct work_struct *work)
{
struct nvme_fc_ctrl *ctrl =
container_of(work, struct nvme_fc_ctrl, ioerr_work);

nvme_fc_error_recovery(ctrl, "transport detected io error");
}

static void
nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
{
Expand Down Expand Up @@ -2046,7 +2056,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)

check_error:
if (terminate_assoc)
nvme_fc_error_recovery(ctrl, "transport detected io error");
queue_work(nvme_reset_wq, &ctrl->ioerr_work);
}

static int
Expand Down Expand Up @@ -3233,6 +3243,7 @@ nvme_fc_delete_ctrl(struct nvme_ctrl *nctrl)
{
struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl);

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

INIT_WORK(&ctrl->ctrl.reset_work, nvme_fc_reset_ctrl_work);
INIT_DELAYED_WORK(&ctrl->connect_work, nvme_fc_connect_ctrl_work);
INIT_WORK(&ctrl->ioerr_work, nvme_fc_ctrl_ioerr_work);
spin_lock_init(&ctrl->lock);

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

fail_ctrl:
nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING);
cancel_work_sync(&ctrl->ioerr_work);
cancel_work_sync(&ctrl->ctrl.reset_work);
cancel_delayed_work_sync(&ctrl->connect_work);

Expand Down

0 comments on commit 19fce04

Please sign in to comment.