On Wed, Mar 20, 2019 at 07:04:09PM -0700, Sagi Grimberg wrote: > > > > Hi Bart, > > > > > > If I understand the race correctly, its not between the requests > > > completion and the queue pairs removal nor the timeout handler > > > necessarily, but rather it is between the async requests completion and > > > the tagset deallocation. > > > > > > Think of surprise removal (or disconnect) during I/O, drivers > > > usually stop/quiesce/freeze the queues, terminate/abort inflight > > > I/Os and then teardown the hw queues and the tagset. > > > > > > IIRC, the same race holds for srp if this happens during I/O: > > > 1. srp_rport_delete() -> srp_remove_target() -> srp_stop_rport_timers() -> > > > __rport_fail_io_fast() > > > > > > 2. complete all I/Os (async remotely via smp) > > > > > > Then continue.. > > > > > > 3. scsi_host_put() -> scsi_host_dev_release() -> scsi_mq_destroy_tags() > > > > > > What is preventing (3) from happening before (2) if its async? I would > > > think that scsi drivers need the exact same thing... > > > > blk_cleanup_queue() will do that, but it can't be used in device recovery > > obviously. > > But in device recovery we never free the tagset... I might be missing > the race here then... For example, nvme_rdma_complete_rq ->nvme_rdma_unmap_data ->ib_mr_pool_put But the ib queue pair may has been destroyed by nvme_rdma_destroy_io_queues() before request's remote completion. nvme_rdma_teardown_io_queues: nvme_stop_queues(&ctrl->ctrl); nvme_rdma_stop_io_queues(ctrl); blk_mq_tagset_busy_iter(&ctrl->tag_set, nvme_cancel_request, &ctrl->ctrl); if (remove) nvme_start_queues(&ctrl->ctrl); nvme_rdma_destroy_io_queues(ctrl, remove); > > > BTW, blk_mq_complete_request_sync() is a bit misleading, maybe > > blk_mq_complete_request_locally() is better. > > Not really... Naming is always the hard part... Thanks, Ming