Messages in this thread | | | From | Logan Gunthorpe <> | Date | Fri, 25 Oct 2019 15:55:21 -0600 | Subject | Re: [RFC PATCH 3/3] nvme: Introduce nvme_execute_passthru_rq_nowait() |
| |
On 2019-10-25 3:40 p.m., Sagi Grimberg wrote: >> Hmm, that's going to be a bit tricky. Seeing the work_struct belongs >> potentially to a number of different requests, we can't just flush the >> individual work items. I think we'd have to create a work-queue per ctrl >> and flush that. Any objections to that? > > I'd object to that overhead... > > How about marking the request if the workqueue path is taken and > in nvme_stop_ctrl you add a blk_mq_tagset_busy_iter and cancel > it in the callback?
Oh, cool. That looks great, I'll do that. Thanks!
Logan
> Something like: > -- > diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c > index fa7ba09dca77..13dbbec5497d 100644 > --- a/drivers/nvme/host/core.c > +++ b/drivers/nvme/host/core.c > @@ -3955,12 +3955,33 @@ void nvme_complete_async_event(struct nvme_ctrl > *ctrl, __le16 status, > } > EXPORT_SYMBOL_GPL(nvme_complete_async_event); > > +static bool nvme_flush_async_passthru_request(struct request *rq, > + void *data, bool reserved) > +{ > + if (!(nvme_req(rq)->flags & NVME_REQ_ASYNC_PASSTHRU)) > + return true; > + > + dev_dbg_ratelimited(((struct nvme_ctrl *) data)->device, > + "Cancelling passthru I/O %d", req->tag); > + flush_work(&nvme_req(rq)->work); > + return true; > +} > + > +static void nvme_flush_async_passthru_requests(struct nvme_ctrl *ctrl) > +{ > + blk_mq_tagset_busy_iter(ctrl->tagset, > + nvme_flush_async_passthru_request, ctrl); > + blk_mq_tagset_busy_iter(ctrl->admin_tagset, > + nvme_flush_async_passthru_request, ctrl); > +} > + > void nvme_stop_ctrl(struct nvme_ctrl *ctrl) > { > nvme_mpath_stop(ctrl); > nvme_stop_keep_alive(ctrl); > flush_work(&ctrl->async_event_work); > cancel_work_sync(&ctrl->fw_act_work); > + nvme_flush_async_passthru_requests(ctrl); > } > EXPORT_SYMBOL_GPL(nvme_stop_ctrl); > --
| |