In my case, I want all hw queues owned by this device to be clean. Because in the virtio device, each hw queue corresponds to a virtqueue, and all virtqueues will be deleted when vdev suspends. The blk_mq_tagset_wait_request_completed() function can ensure that the device has processed all in_flight requests , and these requests have become the complete state. I don’t understand the blk_mq_freeze_queue() function very well. Can the function ensure that all requests have become complete status? How should I use the function to achieve the same effect? ps: requests become in_flight status in virtio_queue_rq() and become complete status in virtblk_done(). Yi On Wed, Jan 24, 2024 at 3:14 AM Keith Busch <kbusch@xxxxxxxxxx> wrote: > > On Mon, Jan 22, 2024 at 07:07:21PM +0800, Yi Sun wrote: > > In some cases, it is necessary to wait for all requests to become complete > > status before performing other operations. Otherwise, these requests will never > > be processed successfully. > > > > For example, when the virtio device is in hibernation, the virtqueues > > will be deleted. It must be ensured that virtqueue is not in use before being deleted. > > Otherwise the requests in the virtqueue will be lost. This function can ensure > > that all requests have been taken out of the virtqueues. > > > > Prepare for fixing this kind of issue by introducing > > blk_mq_tagset_wait_request_completed(). > > Does blk_mq_freeze_queue() not work for your use case? I think that > should work unless you have some driver specific requests entered that > don't ever get released. > > > +static bool blk_mq_tagset_count_inflight_rqs(struct request *rq, void *data) > > +{ > > + unsigned int *count = data; > > + > > + if (blk_mq_request_started(rq) && !blk_mq_request_completed(rq)) > > + (*count)++; > > + return true; > > +} > > + > > +/** > > + * blk_mq_tagset_wait_request_completed - Wait for all inflight requests > > + * to become completed. > > + * > > + * Note: This function has to be run after all IO queues are shutdown. > > + */ > > +void blk_mq_tagset_wait_request_completed(struct blk_mq_tag_set *tagset) > > +{ > > + while (true) { > > + unsigned int count = 0; > > + > > + blk_mq_tagset_busy_iter(tagset, > > + blk_mq_tagset_count_inflight_rqs, &count); > > If the tagset is shared, then one active user can prevent this from ever > completing. It sounds like your use case cares about just one specific > request_queue, not all of them. > > > + if (!count) > > + break; > > + msleep(20); > > + } > > +} > > +EXPORT_SYMBOL(blk_mq_tagset_wait_request_completed);