Re: [PATCH 1/2] blk-mq: introduce blk_mq_tagset_wait_request_completed()
From: yi sun <hidden>
Date: 2024-01-24 11:23:00
Also in:
lkml, virtualization
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 [off-list ref] wrote:
On Mon, Jan 22, 2024 at 07:07:21PM +0800, Yi Sun wrote:quoted
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.quoted
+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.quoted
+ if (!count) + break; + msleep(20); + } +} +EXPORT_SYMBOL(blk_mq_tagset_wait_request_completed);