Thread (11 messages) 11 messages, 5 authors, 2024-01-24

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);
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help