On Tue, Jul 28, 2020 at 06:10:42PM +0800, Ming Lei wrote: > + struct blk_mq_hw_ctx *hctx = (void *)srcu - > + sizeof(struct blk_mq_hw_ctx); I think this should use container_of. > +{ > + struct blk_mq_hw_ctx *hctx; > + unsigned int i; > + > + blk_mq_quiesce_queue_nowait(q); > + > + queue_for_each_hw_ctx(q, hctx, i) { > + WARN_ON_ONCE(!(hctx->flags & BLK_MQ_F_BLOCKING)); > + init_rcu_head(&hctx->srcu->head); We only need to initialize the rcu head once when we allocate the hctx. > + mutex_lock(&set->tag_list_lock); > + if (set->flags & BLK_MQ_F_BLOCKING) { > + int count = 0; > + > + list_for_each_entry(q, &set->tag_list, tag_set_list) > + count++; > + > + atomic_set(&set->quiesce_count, count); > + init_completion(&set->quiesce_completion); > + > + list_for_each_entry(q, &set->tag_list, tag_set_list) > + blk_mq_quiesce_blocking_queue_async(q); > + wait_for_completion(&set->quiesce_completion); > + } else { > + list_for_each_entry(q, &set->tag_list, tag_set_list) > + blk_mq_quiesce_queue_nowait(q); > + synchronize_rcu(); > + } > + mutex_unlock(&set->tag_list_lock); It would be great to do the wait_for_completion and synchronize_rcu outside the lock. Also I think the blocking case probably wants to be split into a separate little helper.