On Wed, Dec 15, 2021 at 09:24:18AM -0700, Jens Axboe wrote: > + /* > + * Peek first request and see if we have a ->queue_rqs() hook. > + * If we do, we can dispatch the whole plug list in one go. We > + * already know at this point that all requests belong to the > + * same queue, caller must ensure that's the case. > + * > + * Since we pass off the full list to the driver at this point, > + * we do not increment the active request count for the queue. > + * Bypass shared tags for now because of that. > + */ > + if (q->mq_ops->queue_rqs && > + !(rq->mq_hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)) { > + blk_mq_run_dispatch_ops(q, > + q->mq_ops->queue_rqs(&plug->mq_list)); I think we still need to verify the queue isn't quiesced within blk_mq_run_dispatch_ops()'s rcu protected area, prior to calling .queue_rqs(). Something like below. Or is this supposed to be the low-level drivers responsibility now? --- +void __blk_mq_flush_plug_list(struct request_queue *q, struct blk_plug *plug) +{ + if (blk_queue_quiesced(q)) + return; + q->mq_ops->queue_rqs(&plug->mq_list); +} + void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule) { struct blk_mq_hw_ctx *this_hctx; @@ -2580,7 +2587,7 @@ void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule) if (q->mq_ops->queue_rqs && !(rq->mq_hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)) { blk_mq_run_dispatch_ops(q, - q->mq_ops->queue_rqs(&plug->mq_list)); + __blk_mq_flush_plug_list(q, plug)); if (rq_list_empty(plug->mq_list)) return; } --