Skip to content

Commit

Permalink
nvmet-fc: avoid deadlock on delete association path
Browse files Browse the repository at this point in the history
When deleting an association the shutdown path is deadlocking because we
try to flush the nvmet_wq nested. Avoid this by deadlock by deferring
the put work into its own work item.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Daniel Wagner <dwagner@suse.de>
Signed-off-by: Keith Busch <kbusch@kernel.org>
  • Loading branch information
Daniel Wagner authored and Keith Busch committed Feb 1, 2024
1 parent 3146345 commit 710c69d
Showing 1 changed file with 13 additions and 3 deletions.
16 changes: 13 additions & 3 deletions drivers/nvme/target/fc.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ struct nvmet_fc_tgtport {
struct nvmet_fc_port_entry *pe;
struct kref ref;
u32 max_sg_cnt;

struct work_struct put_work;
};

struct nvmet_fc_port_entry {
Expand Down Expand Up @@ -247,6 +249,13 @@ static int nvmet_fc_tgt_a_get(struct nvmet_fc_tgt_assoc *assoc);
static void nvmet_fc_tgt_q_put(struct nvmet_fc_tgt_queue *queue);
static int nvmet_fc_tgt_q_get(struct nvmet_fc_tgt_queue *queue);
static void nvmet_fc_tgtport_put(struct nvmet_fc_tgtport *tgtport);
static void nvmet_fc_put_tgtport_work(struct work_struct *work)
{
struct nvmet_fc_tgtport *tgtport =
container_of(work, struct nvmet_fc_tgtport, put_work);

nvmet_fc_tgtport_put(tgtport);
}
static int nvmet_fc_tgtport_get(struct nvmet_fc_tgtport *tgtport);
static void nvmet_fc_handle_fcp_rqst(struct nvmet_fc_tgtport *tgtport,
struct nvmet_fc_fcp_iod *fod);
Expand Down Expand Up @@ -358,7 +367,7 @@ __nvmet_fc_finish_ls_req(struct nvmet_fc_ls_req_op *lsop)

if (!lsop->req_queued) {
spin_unlock_irqrestore(&tgtport->lock, flags);
goto out_puttgtport;
goto out_putwork;
}

list_del(&lsop->lsreq_list);
Expand All @@ -371,8 +380,8 @@ __nvmet_fc_finish_ls_req(struct nvmet_fc_ls_req_op *lsop)
(lsreq->rqstlen + lsreq->rsplen),
DMA_BIDIRECTIONAL);

out_puttgtport:
nvmet_fc_tgtport_put(tgtport);
out_putwork:
queue_work(nvmet_wq, &tgtport->put_work);
}

static int
Expand Down Expand Up @@ -1396,6 +1405,7 @@ nvmet_fc_register_targetport(struct nvmet_fc_port_info *pinfo,
kref_init(&newrec->ref);
ida_init(&newrec->assoc_cnt);
newrec->max_sg_cnt = template->max_sgl_segments;
INIT_WORK(&newrec->put_work, nvmet_fc_put_tgtport_work);

ret = nvmet_fc_alloc_ls_iodlist(newrec);
if (ret) {
Expand Down

0 comments on commit 710c69d

Please sign in to comment.