All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V4 1/4] qapi/misc: Fix missed query-iothreads items
@ 2026-02-13 17:16 Zhang Chen
  2026-02-13 17:16 ` [PATCH V4 2/4] iothread: introduce iothread_ref/unref to track attached devices Zhang Chen
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Zhang Chen @ 2026-02-13 17:16 UTC (permalink / raw)
  To: qemu-devel, Dr . David Alan Gilbert, Eric Blake,
	Markus Armbruster, Michael S . Tsirkin, Stefan Hajnoczi
  Cc: Zhang Chen, qemu-stable

The example is incomplete: it misses members @poll-max-ns, @poll-grow,
@poll-shrink, @aio-max-batch.  Messed up in commit 5fc00480ab1
(monitor: add poll-* properties into query-iothreads result) and
commit 1793ad0247c (iothread: add aio-max-batch parameter).

cc: qemu-stable@nongnu.org

Reviewed-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
---
 qapi/misc.json | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/qapi/misc.json b/qapi/misc.json
index 28c641fe2f..1f5062df2a 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -117,11 +117,19 @@
 #     <- { "return": [
 #              {
 #                 "id":"iothread0",
-#                 "thread-id":3134
+#                 "thread-id":3134,
+#                 "poll-max-ns":32768,
+#                 "poll-grow":0,
+#                 "poll-shrink":0,
+#                 "aio-max-batch":0
 #              },
 #              {
 #                 "id":"iothread1",
-#                 "thread-id":3135
+#                 "thread-id":3135,
+#                 "poll-max-ns":32768,
+#                 "poll-grow":0,
+#                 "poll-shrink":0,
+#                 "aio-max-batch":0
 #              }
 #           ]
 #        }
-- 
2.49.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH V4 2/4] iothread: introduce iothread_ref/unref to track attached devices
  2026-02-13 17:16 [PATCH V4 1/4] qapi/misc: Fix missed query-iothreads items Zhang Chen
@ 2026-02-13 17:16 ` Zhang Chen
  2026-02-18 20:53   ` Stefan Hajnoczi
  2026-02-13 17:16 ` [PATCH V4 3/4] iothread: track virtio-blk devices using IOThread reference counting Zhang Chen
  2026-02-13 17:16 ` [PATCH V4 4/4] qapi: examine IOThread attachment status via query-iothreads Zhang Chen
  2 siblings, 1 reply; 14+ messages in thread
From: Zhang Chen @ 2026-02-13 17:16 UTC (permalink / raw)
  To: qemu-devel, Dr . David Alan Gilbert, Eric Blake,
	Markus Armbruster, Michael S . Tsirkin, Stefan Hajnoczi
  Cc: Zhang Chen

Currently, IOThreads do not maintain a record of which devices are
associated with them. This makes it difficult to monitor the
workload distribution of IOThreads, especially in complex
hotplug scenarios involving multiple virtio-blk or virtio-scsi devices.

This patch introduces a reference counting and tracking mechanism
within the IOThread object:

- iothread_ref(): Increments the attachment counter and prepends the
  device's QOM path to a list. Note: The IOThread takes ownership of
  the passed 'holder' string.
- iothread_unref(): Searches for the device path using a custom
  string comparison (g_strcmp0), decrements the counter, and
  releases the associated memory upon a successful match.
- attached_cnt: Tracks the number of active device attachments.
- attached_dev: A GList storing the QOM paths of attached devices
  for runtime introspection.

This infrastructure allows management tools and QMP commands to
query the attachment status of IOThreads.

Signed-off-by: Zhang Chen <zhangckid@gmail.com>
---
 include/system/iothread.h |  4 ++++
 iothread.c                | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/include/system/iothread.h b/include/system/iothread.h
index e26d13c6c7..4a2ffdb9bd 100644
--- a/include/system/iothread.h
+++ b/include/system/iothread.h
@@ -33,6 +33,8 @@ struct IOThread {
     bool stopping;              /* has iothread_stop() been called? */
     bool running;               /* should iothread_run() continue? */
     int thread_id;
+    int attached_cnt;
+    GList *attached_dev;
 
     /* AioContext poll parameters */
     int64_t poll_max_ns;
@@ -48,6 +50,8 @@ char *iothread_get_id(IOThread *iothread);
 IOThread *iothread_by_id(const char *id);
 AioContext *iothread_get_aio_context(IOThread *iothread);
 GMainContext *iothread_get_g_main_context(IOThread *iothread);
+void iothread_ref(IOThread *iothread, const char* holder);
+void iothread_unref(IOThread *iothread, const char* holder);
 
 /*
  * Helpers used to allocate iothreads for internal use.  These
diff --git a/iothread.c b/iothread.c
index caf68e0764..b869637497 100644
--- a/iothread.c
+++ b/iothread.c
@@ -36,6 +36,41 @@
 #define IOTHREAD_POLL_MAX_NS_DEFAULT 0ULL
 #endif
 
+/*
+ * Increment iothread's reference count,
+ * and add holder device path to the list.
+ */
+void iothread_ref(IOThread *iothread, const char *holder)
+{
+    iothread->attached_cnt++;
+    iothread->attached_dev = g_list_prepend(iothread->attached_dev,
+                                           (gpointer)holder);
+}
+
+/*
+ * Decrement iothread's reference count,
+ * and delete holder device path from the list.
+ */
+void iothread_unref(IOThread *iothread, const char *holder)
+{
+    if (iothread->attached_cnt > 0) {
+        GList *link = g_list_find_custom(iothread->attached_dev,
+                                         holder, (GCompareFunc)g_strcmp0);
+
+        if (link) {
+            g_free(link->data);
+            iothread->attached_dev = g_list_delete_link(iothread->attached_dev,
+                                                        link);
+            iothread->attached_cnt--;
+        } else {
+            error_report("iohtread_unref can't find device. attached_dev=%s",
+                        holder);
+        }
+    } else {
+        error_report("iohtread_unref counter error. attached_dev=%s", holder);
+    }
+}
+
 static void *iothread_run(void *opaque)
 {
     IOThread *iothread = opaque;
-- 
2.49.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH V4 3/4] iothread: track virtio-blk devices using IOThread reference counting
  2026-02-13 17:16 [PATCH V4 1/4] qapi/misc: Fix missed query-iothreads items Zhang Chen
  2026-02-13 17:16 ` [PATCH V4 2/4] iothread: introduce iothread_ref/unref to track attached devices Zhang Chen
@ 2026-02-13 17:16 ` Zhang Chen
  2026-02-18 20:55   ` Stefan Hajnoczi
  2026-02-13 17:16 ` [PATCH V4 4/4] qapi: examine IOThread attachment status via query-iothreads Zhang Chen
  2 siblings, 1 reply; 14+ messages in thread
From: Zhang Chen @ 2026-02-13 17:16 UTC (permalink / raw)
  To: qemu-devel, Dr . David Alan Gilbert, Eric Blake,
	Markus Armbruster, Michael S . Tsirkin, Stefan Hajnoczi
  Cc: Zhang Chen

Add reference counting and device path tracking to IOThread to monitor
which devices are currently attached. This is implemented by adding
iothread_ref() and iothread_unref() calls during the virtio-blk
AioContext initialization and cleanup paths.

The IOThread now maintains:
 - attached_cnt: A counter of devices using the iothread.
 - attached_dev: A list of QOM paths for the attached devices.

This tracking is essential for management tools to understand the
relationship between IOThreads and devices, especially during hotplug
and unplug operations.

Future work will extend this ref/unref mechanism to other iothread-capable
devices (e.g. virtio-scsi).

Signed-off-by: Zhang Chen <zhangckid@gmail.com>
---
 hw/block/virtio-blk.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index ddf0e9ee53..247d6d41f3 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -1462,6 +1462,9 @@ static bool virtio_blk_vq_aio_context_init(VirtIOBlock *s, Error **errp)
             return false;
         }
     } else if (conf->iothread) {
+        char *path = object_get_canonical_path(OBJECT(s));
+
+        iothread_ref(conf->iothread, path);
         AioContext *ctx = iothread_get_aio_context(conf->iothread);
         for (unsigned i = 0; i < conf->num_queues; i++) {
             s->vq_aio_context[i] = ctx;
@@ -1491,7 +1494,12 @@ static void virtio_blk_vq_aio_context_cleanup(VirtIOBlock *s)
     }
 
     if (conf->iothread) {
+        char *path = object_get_canonical_path(OBJECT(s));
+
+        iothread_unref(conf->iothread, path);
         object_unref(OBJECT(conf->iothread));
+
+        g_free(path);
     }
 
     g_free(s->vq_aio_context);
-- 
2.49.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH V4 4/4] qapi: examine IOThread attachment status via query-iothreads
  2026-02-13 17:16 [PATCH V4 1/4] qapi/misc: Fix missed query-iothreads items Zhang Chen
  2026-02-13 17:16 ` [PATCH V4 2/4] iothread: introduce iothread_ref/unref to track attached devices Zhang Chen
  2026-02-13 17:16 ` [PATCH V4 3/4] iothread: track virtio-blk devices using IOThread reference counting Zhang Chen
@ 2026-02-13 17:16 ` Zhang Chen
  2026-02-17  7:51   ` Markus Armbruster
  2 siblings, 1 reply; 14+ messages in thread
From: Zhang Chen @ 2026-02-13 17:16 UTC (permalink / raw)
  To: qemu-devel, Dr . David Alan Gilbert, Eric Blake,
	Markus Armbruster, Michael S . Tsirkin, Stefan Hajnoczi
  Cc: Zhang Chen

Extend the 'IOThreadInfo' structure to include attachment metrics.
This allows users to monitor how many devices are associated with
a specific IOThread and identify them by their QOM paths.

New fields added to IOThreadInfo:
- @attached-cnt: An integer representing the number of devices
  currently using this IOThread's AioContext.
- @attached-dev: A string containing a delimited list ("|") of
  QOM paths for the attached devices.

These fields are also exposed via the Human Monitor Interface (HMP)
command 'info iothreads' to assist with manual debugging and
performance tuning.

Example QMP output:
{
    "id": "iothread0",
    "thread-id": 3134,
    "attached-cnt": 2,
    "attached-dev": "/machine/peripheral/blk1/virtio-backend | /machine/peripheral/blk0/virtio-backend",
    ...
}

Signed-off-by: Zhang Chen <zhangckid@gmail.com>
---
 iothread.c         | 24 ++++++++++++++++++++++++
 monitor/hmp-cmds.c |  3 +++
 qapi/misc.json     | 19 +++++++++++++++++++
 3 files changed, 46 insertions(+)

diff --git a/iothread.c b/iothread.c
index b869637497..4fceed28c5 100644
--- a/iothread.c
+++ b/iothread.c
@@ -71,6 +71,28 @@ void iothread_unref(IOThread *iothread, const char *holder)
     }
 }
 
+static char *iothread_get_attached_dev_list(IOThread *iothread)
+{
+    guint len = g_list_length(iothread->attached_dev);
+
+    if (len == 0) {
+        return g_strdup("none");
+    }
+
+    gchar **array = g_new0(gchar *, len + 1);
+    GList *l;
+    int i = 0;
+
+    for (l = iothread->attached_dev; l != NULL; l = l->next) {
+        array[i++] = l->data;
+    }
+
+    char *result = g_strjoinv(" | ", array);
+    g_free(array);
+
+    return result;
+}
+
 static void *iothread_run(void *opaque)
 {
     IOThread *iothread = opaque;
@@ -388,6 +410,8 @@ static int query_one_iothread(Object *object, void *opaque)
     info = g_new0(IOThreadInfo, 1);
     info->id = iothread_get_id(iothread);
     info->thread_id = iothread->thread_id;
+    info->attached_cnt = iothread->attached_cnt;
+    info->attached_dev = iothread_get_attached_dev_list(iothread);
     info->poll_max_ns = iothread->poll_max_ns;
     info->poll_grow = iothread->poll_grow;
     info->poll_shrink = iothread->poll_shrink;
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index bad034937a..026bed1545 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -203,6 +203,9 @@ void hmp_info_iothreads(Monitor *mon, const QDict *qdict)
         value = info->value;
         monitor_printf(mon, "%s:\n", value->id);
         monitor_printf(mon, "  thread_id=%" PRId64 "\n", value->thread_id);
+        monitor_printf(mon, "  attached-cnt=%" PRId64 "\n",
+                       value->attached_cnt);
+        monitor_printf(mon, "  attached-dev=%s\n", value->attached_dev);
         monitor_printf(mon, "  poll-max-ns=%" PRId64 "\n", value->poll_max_ns);
         monitor_printf(mon, "  poll-grow=%" PRId64 "\n", value->poll_grow);
         monitor_printf(mon, "  poll-shrink=%" PRId64 "\n", value->poll_shrink);
diff --git a/qapi/misc.json b/qapi/misc.json
index 1f5062df2a..ca53638684 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -76,6 +76,19 @@
 #
 # @thread-id: ID of the underlying host thread
 #
+# @attached-cnt: The parameter is a counter indicating how many
+#     active devices are currently associated with this iothread
+#     (e.g. virtio-blk).  In hotplug scenarios, users can
+#     pre-allocate multiple iothread objects to serve as a persistent
+#     thread pool.  When a device is hot-unplugged, the corresponding
+#     IOThread is released but remains available, allowing subsequent
+#     hot-plugged devices to attach to and reuse the existing thread.
+#     (since 11.0)
+#
+# @attached-dev: A list of QOM paths for the devices currently
+#     associated with this IOThread, delimited by " | ".
+#     Returns "none" if no devices are attached. (since 11.0)
+#
 # @poll-max-ns: maximum polling time in ns, 0 means polling is
 #     disabled (since 2.9)
 #
@@ -93,6 +106,8 @@
 { 'struct': 'IOThreadInfo',
   'data': {'id': 'str',
            'thread-id': 'int',
+           'attached-cnt': 'int',
+           'attached-dev': 'str',
            'poll-max-ns': 'int',
            'poll-grow': 'int',
            'poll-shrink': 'int',
@@ -118,6 +133,8 @@
 #              {
 #                 "id":"iothread0",
 #                 "thread-id":3134,
+#                 "attached-cnt":2,
+#                 "attached-dev":/machine/peripheral/blk1/virtio-backend | /machine/peripheral/blk0/virtio-backend,
 #                 "poll-max-ns":32768,
 #                 "poll-grow":0,
 #                 "poll-shrink":0,
@@ -126,6 +143,8 @@
 #              {
 #                 "id":"iothread1",
 #                 "thread-id":3135,
+#                 "attached-cnt":1,
+#                 "attached-dev":/machine/peripheral/blk3/virtio-backend,
 #                 "poll-max-ns":32768,
 #                 "poll-grow":0,
 #                 "poll-shrink":0,
-- 
2.49.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH V4 4/4] qapi: examine IOThread attachment status via query-iothreads
  2026-02-13 17:16 ` [PATCH V4 4/4] qapi: examine IOThread attachment status via query-iothreads Zhang Chen
@ 2026-02-17  7:51   ` Markus Armbruster
  2026-02-24  2:42     ` Zhang Chen
  0 siblings, 1 reply; 14+ messages in thread
From: Markus Armbruster @ 2026-02-17  7:51 UTC (permalink / raw)
  To: Zhang Chen
  Cc: qemu-devel, Dr . David Alan Gilbert, Eric Blake,
	Michael S . Tsirkin, Stefan Hajnoczi

Zhang Chen <zhangckid@gmail.com> writes:

> Extend the 'IOThreadInfo' structure to include attachment metrics.
> This allows users to monitor how many devices are associated with
> a specific IOThread and identify them by their QOM paths.
>
> New fields added to IOThreadInfo:
> - @attached-cnt: An integer representing the number of devices
>   currently using this IOThread's AioContext.
> - @attached-dev: A string containing a delimited list ("|") of
>   QOM paths for the attached devices.
>
> These fields are also exposed via the Human Monitor Interface (HMP)
> command 'info iothreads' to assist with manual debugging and
> performance tuning.
>
> Example QMP output:
> {
>     "id": "iothread0",
>     "thread-id": 3134,
>     "attached-cnt": 2,
>     "attached-dev": "/machine/peripheral/blk1/virtio-backend | /machine/peripheral/blk0/virtio-backend",
>     ...
> }
>
> Signed-off-by: Zhang Chen <zhangckid@gmail.com>

[...]

> diff --git a/qapi/misc.json b/qapi/misc.json
> index 1f5062df2a..ca53638684 100644
> --- a/qapi/misc.json
> +++ b/qapi/misc.json
> @@ -76,6 +76,19 @@
>  #
>  # @thread-id: ID of the underlying host thread
>  #
> +# @attached-cnt: The parameter is a counter indicating how many
> +#     active devices are currently associated with this iothread
> +#     (e.g. virtio-blk).  In hotplug scenarios, users can
> +#     pre-allocate multiple iothread objects to serve as a persistent
> +#     thread pool.  When a device is hot-unplugged, the corresponding
> +#     IOThread is released but remains available, allowing subsequent
> +#     hot-plugged devices to attach to and reuse the existing thread.
> +#     (since 11.0)
> +#
> +# @attached-dev: A list of QOM paths for the devices currently
> +#     associated with this IOThread, delimited by " | ".
> +#     Returns "none" if no devices are attached. (since 11.0)

QAPI schema design maxim: do not encode structured data as strings.
@attached-devs should be an array of QOM paths instead.

Unless I misunderstand your docs, @attached-cnt is the number of QOM
paths in @attached-dev, i.e. @attached-dev is redundant.  If this is the
case, drop it.  If it isn't, educate me :)

We generally avoid abbreviations in the QAPI schema: @attached-count,
@attached-devices.

> +#
>  # @poll-max-ns: maximum polling time in ns, 0 means polling is
>  #     disabled (since 2.9)
>  #
> @@ -93,6 +106,8 @@
>  { 'struct': 'IOThreadInfo',
>    'data': {'id': 'str',
>             'thread-id': 'int',
> +           'attached-cnt': 'int',
> +           'attached-dev': 'str',
>             'poll-max-ns': 'int',
>             'poll-grow': 'int',
>             'poll-shrink': 'int',
> @@ -118,6 +133,8 @@
>  #              {
>  #                 "id":"iothread0",
>  #                 "thread-id":3134,
> +#                 "attached-cnt":2,
> +#                 "attached-dev":/machine/peripheral/blk1/virtio-backend | /machine/peripheral/blk0/virtio-backend,

Once again, the example is syntactically incorrect (the value lacks
double quotes), and once again I recommend to create example I/O by
actually running a test.  Getting tired of this, to be frank.

>  #                 "poll-max-ns":32768,
>  #                 "poll-grow":0,
>  #                 "poll-shrink":0,
> @@ -126,6 +143,8 @@
>  #              {
>  #                 "id":"iothread1",
>  #                 "thread-id":3135,
> +#                 "attached-cnt":1,
> +#                 "attached-dev":/machine/peripheral/blk3/virtio-backend,

Likewise.

>  #                 "poll-max-ns":32768,
>  #                 "poll-grow":0,
>  #                 "poll-shrink":0,



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH V4 2/4] iothread: introduce iothread_ref/unref to track attached devices
  2026-02-13 17:16 ` [PATCH V4 2/4] iothread: introduce iothread_ref/unref to track attached devices Zhang Chen
@ 2026-02-18 20:53   ` Stefan Hajnoczi
  2026-02-25 11:38     ` Zhang Chen
  0 siblings, 1 reply; 14+ messages in thread
From: Stefan Hajnoczi @ 2026-02-18 20:53 UTC (permalink / raw)
  To: Zhang Chen
  Cc: qemu-devel, Dr . David Alan Gilbert, Eric Blake,
	Markus Armbruster, Michael S . Tsirkin

[-- Attachment #1: Type: text/plain, Size: 5803 bytes --]

On Sat, Feb 14, 2026 at 01:16:20AM +0800, Zhang Chen wrote:
> Currently, IOThreads do not maintain a record of which devices are
> associated with them. This makes it difficult to monitor the
> workload distribution of IOThreads, especially in complex
> hotplug scenarios involving multiple virtio-blk or virtio-scsi devices.
> 
> This patch introduces a reference counting and tracking mechanism
> within the IOThread object:
> 
> - iothread_ref(): Increments the attachment counter and prepends the
>   device's QOM path to a list. Note: The IOThread takes ownership of
>   the passed 'holder' string.
> - iothread_unref(): Searches for the device path using a custom
>   string comparison (g_strcmp0), decrements the counter, and
>   releases the associated memory upon a successful match.
> - attached_cnt: Tracks the number of active device attachments.
> - attached_dev: A GList storing the QOM paths of attached devices
>   for runtime introspection.
> 
> This infrastructure allows management tools and QMP commands to
> query the attachment status of IOThreads.
> 
> Signed-off-by: Zhang Chen <zhangckid@gmail.com>
> ---
>  include/system/iothread.h |  4 ++++
>  iothread.c                | 35 +++++++++++++++++++++++++++++++++++
>  2 files changed, 39 insertions(+)
> 
> diff --git a/include/system/iothread.h b/include/system/iothread.h
> index e26d13c6c7..4a2ffdb9bd 100644
> --- a/include/system/iothread.h
> +++ b/include/system/iothread.h
> @@ -33,6 +33,8 @@ struct IOThread {
>      bool stopping;              /* has iothread_stop() been called? */
>      bool running;               /* should iothread_run() continue? */
>      int thread_id;
> +    int attached_cnt;

Is this field necessary given that the user can see the list of holders?

> +    GList *attached_dev;

IOThreads are general eventloop concept in QEMU and not limited to
device emulation. Non-device code may also wish to add itself (e.g.
block/export/export.c). Please call this GList *holders.

This raises questions:
- Is it mandatory for users of the IOThread's AioContext to add
  themselves?
- How does it relate to object_ref()/object_unref()?

I would prefer to set things up as follows:

It is mandatory for users of the IOThread's AioContext to add
themselves. This is enforced by modifying iothread_get_aio_context() to
take a string argument with the name of the holder.

iothread_get_aio_context() is also extended to call
object_ref(OBJECT(iothread)). This guarantees that the IOThread and its
AioContext remain alive as long as there is a holder. (Some users
already do this themselves, so I think it makes sense to build this
behavior into the API so that all users get it automatically.)

A new iothread_put_aio_context() function is introduced to remove the
hold and object_unref(OBJECT(iothread)).

All existing callers of iothread_get_aio_context() need to be updated to
pass in their QOM object path as the name of the holder, remove their own
object_ref() call (if present), and call iothread_put_aio_context() at
the appropriate point.

>  
>      /* AioContext poll parameters */
>      int64_t poll_max_ns;
> @@ -48,6 +50,8 @@ char *iothread_get_id(IOThread *iothread);
>  IOThread *iothread_by_id(const char *id);
>  AioContext *iothread_get_aio_context(IOThread *iothread);
>  GMainContext *iothread_get_g_main_context(IOThread *iothread);
> +void iothread_ref(IOThread *iothread, const char* holder);
> +void iothread_unref(IOThread *iothread, const char* holder);
>  
>  /*
>   * Helpers used to allocate iothreads for internal use.  These
> diff --git a/iothread.c b/iothread.c
> index caf68e0764..b869637497 100644
> --- a/iothread.c
> +++ b/iothread.c
> @@ -36,6 +36,41 @@
>  #define IOTHREAD_POLL_MAX_NS_DEFAULT 0ULL
>  #endif
>  
> +/*
> + * Increment iothread's reference count,
> + * and add holder device path to the list.
> + */
> +void iothread_ref(IOThread *iothread, const char *holder)
> +{
> +    iothread->attached_cnt++;
> +    iothread->attached_dev = g_list_prepend(iothread->attached_dev,
> +                                           (gpointer)holder);

It's safer to g_strdup(holder) so the caller doesn't need to worry about
the lifetime of the argument. This is not a performance-critical code
path so the cost of the strdup is acceptable.

> +}
> +
> +/*
> + * Decrement iothread's reference count,
> + * and delete holder device path from the list.
> + */
> +void iothread_unref(IOThread *iothread, const char *holder)
> +{
> +    if (iothread->attached_cnt > 0) {
> +        GList *link = g_list_find_custom(iothread->attached_dev,
> +                                         holder, (GCompareFunc)g_strcmp0);
> +
> +        if (link) {
> +            g_free(link->data);

iothread_ref() originally took a _const_ char * so it must not free the
pointer here. The reason why the compiler didn't complain was because
iothread_ref() cast the pointer to non-const gpointer. In any case, as
mentioned above, it's probably best to use g_strdup() and avoid placing
constraints on the lifetime of the caller's string.

> +            iothread->attached_dev = g_list_delete_link(iothread->attached_dev,
> +                                                        link);
> +            iothread->attached_cnt--;
> +        } else {
> +            error_report("iohtread_unref can't find device. attached_dev=%s",

"iohtread" typo here and in the line below.

> +                        holder);
> +        }
> +    } else {
> +        error_report("iohtread_unref counter error. attached_dev=%s", holder);
> +    }
> +}
> +
>  static void *iothread_run(void *opaque)
>  {
>      IOThread *iothread = opaque;
> -- 
> 2.49.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH V4 3/4] iothread: track virtio-blk devices using IOThread reference counting
  2026-02-13 17:16 ` [PATCH V4 3/4] iothread: track virtio-blk devices using IOThread reference counting Zhang Chen
@ 2026-02-18 20:55   ` Stefan Hajnoczi
  2026-02-24  2:55     ` Zhang Chen
  0 siblings, 1 reply; 14+ messages in thread
From: Stefan Hajnoczi @ 2026-02-18 20:55 UTC (permalink / raw)
  To: Zhang Chen
  Cc: qemu-devel, Dr . David Alan Gilbert, Eric Blake,
	Markus Armbruster, Michael S . Tsirkin

[-- Attachment #1: Type: text/plain, Size: 482 bytes --]

On Sat, Feb 14, 2026 at 01:16:21AM +0800, Zhang Chen wrote:
> Future work will extend this ref/unref mechanism to other iothread-capable
> devices (e.g. virtio-scsi).

All IOThread users should be tracked so that this mechanism is used
consistently. Otherwise it will be hard to change the behavior in the
future: software that runs against multiple QEMU versions won't be able
to rely on finding certain objects in the list if not all objects are
added from the beginning.

Stefan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH V4 4/4] qapi: examine IOThread attachment status via query-iothreads
  2026-02-17  7:51   ` Markus Armbruster
@ 2026-02-24  2:42     ` Zhang Chen
  2026-02-24  8:42       ` Markus Armbruster
  0 siblings, 1 reply; 14+ messages in thread
From: Zhang Chen @ 2026-02-24  2:42 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, Dr . David Alan Gilbert, Eric Blake,
	Michael S . Tsirkin, Stefan Hajnoczi

On Tue, Feb 17, 2026 at 3:51 PM Markus Armbruster <armbru@redhat.com> wrote:
>
> Zhang Chen <zhangckid@gmail.com> writes:
>
> > Extend the 'IOThreadInfo' structure to include attachment metrics.
> > This allows users to monitor how many devices are associated with
> > a specific IOThread and identify them by their QOM paths.
> >
> > New fields added to IOThreadInfo:
> > - @attached-cnt: An integer representing the number of devices
> >   currently using this IOThread's AioContext.
> > - @attached-dev: A string containing a delimited list ("|") of
> >   QOM paths for the attached devices.
> >
> > These fields are also exposed via the Human Monitor Interface (HMP)
> > command 'info iothreads' to assist with manual debugging and
> > performance tuning.
> >
> > Example QMP output:
> > {
> >     "id": "iothread0",
> >     "thread-id": 3134,
> >     "attached-cnt": 2,
> >     "attached-dev": "/machine/peripheral/blk1/virtio-backend | /machine/peripheral/blk0/virtio-backend",
> >     ...
> > }
> >
> > Signed-off-by: Zhang Chen <zhangckid@gmail.com>
>
> [...]
>
> > diff --git a/qapi/misc.json b/qapi/misc.json
> > index 1f5062df2a..ca53638684 100644
> > --- a/qapi/misc.json
> > +++ b/qapi/misc.json
> > @@ -76,6 +76,19 @@
> >  #
> >  # @thread-id: ID of the underlying host thread
> >  #
> > +# @attached-cnt: The parameter is a counter indicating how many
> > +#     active devices are currently associated with this iothread
> > +#     (e.g. virtio-blk).  In hotplug scenarios, users can
> > +#     pre-allocate multiple iothread objects to serve as a persistent
> > +#     thread pool.  When a device is hot-unplugged, the corresponding
> > +#     IOThread is released but remains available, allowing subsequent
> > +#     hot-plugged devices to attach to and reuse the existing thread.
> > +#     (since 11.0)
> > +#
> > +# @attached-dev: A list of QOM paths for the devices currently
> > +#     associated with this IOThread, delimited by " | ".
> > +#     Returns "none" if no devices are attached. (since 11.0)
>
> QAPI schema design maxim: do not encode structured data as strings.
> @attached-devs should be an array of QOM paths instead.

OK, will fix in next version.

>
> Unless I misunderstand your docs, @attached-cnt is the number of QOM
> paths in @attached-dev, i.e. @attached-dev is redundant.  If this is the
> case, drop it.  If it isn't, educate me :)

As Stefan's comments, I try to address more specific needs:
https://mail.gnu.org/archive/html/qemu-devel/2026-02/msg01892.html


>
> We generally avoid abbreviations in the QAPI schema: @attached-count,
> @attached-devices.
>
> > +#
> >  # @poll-max-ns: maximum polling time in ns, 0 means polling is
> >  #     disabled (since 2.9)
> >  #
> > @@ -93,6 +106,8 @@
> >  { 'struct': 'IOThreadInfo',
> >    'data': {'id': 'str',
> >             'thread-id': 'int',
> > +           'attached-cnt': 'int',
> > +           'attached-dev': 'str',
> >             'poll-max-ns': 'int',
> >             'poll-grow': 'int',
> >             'poll-shrink': 'int',
> > @@ -118,6 +133,8 @@
> >  #              {
> >  #                 "id":"iothread0",
> >  #                 "thread-id":3134,
> > +#                 "attached-cnt":2,
> > +#                 "attached-dev":/machine/peripheral/blk1/virtio-backend | /machine/peripheral/blk0/virtio-backend,
>
> Once again, the example is syntactically incorrect (the value lacks
> double quotes), and once again I recommend to create example I/O by
> actually running a test.  Getting tired of this, to be frank.

Sorry for that again. Will fix in next version.
And I tested this series before send the mail like this:

(qemu) info iothreads
iothread2:
  thread_id=434428
  attached-cnt=0
  attached-dev=none
  poll-max-ns=32768
  poll-grow=0
  poll-shrink=0
  aio-max-batch=0
iothread1:
  thread_id=434427
  attached-cnt=2
  attached-dev=/machine/peripheral/blk1/virtio-backend |
/machine/peripheral/blk0/virtio-backend
  poll-max-ns=32768
  poll-grow=0
  poll-shrink=0
  aio-max-batch=0


>
> >  #                 "poll-max-ns":32768,
> >  #                 "poll-grow":0,
> >  #                 "poll-shrink":0,
> > @@ -126,6 +143,8 @@
> >  #              {
> >  #                 "id":"iothread1",
> >  #                 "thread-id":3135,
> > +#                 "attached-cnt":1,
> > +#                 "attached-dev":/machine/peripheral/blk3/virtio-backend,
>
> Likewise.

Thanks
Chen

>
> >  #                 "poll-max-ns":32768,
> >  #                 "poll-grow":0,
> >  #                 "poll-shrink":0,
>


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH V4 3/4] iothread: track virtio-blk devices using IOThread reference counting
  2026-02-18 20:55   ` Stefan Hajnoczi
@ 2026-02-24  2:55     ` Zhang Chen
  0 siblings, 0 replies; 14+ messages in thread
From: Zhang Chen @ 2026-02-24  2:55 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: qemu-devel, Dr . David Alan Gilbert, Eric Blake,
	Markus Armbruster, Michael S . Tsirkin

On Thu, Feb 19, 2026 at 4:55 AM Stefan Hajnoczi <stefanha@redhat.com> wrote:
>
> On Sat, Feb 14, 2026 at 01:16:21AM +0800, Zhang Chen wrote:
> > Future work will extend this ref/unref mechanism to other iothread-capable
> > devices (e.g. virtio-scsi).
>
> All IOThread users should be tracked so that this mechanism is used
> consistently. Otherwise it will be hard to change the behavior in the
> future: software that runs against multiple QEMU versions won't be able
> to rely on finding certain objects in the list if not all objects are
> added from the beginning.
>

Sure, this patch is a demo to confirm I do understand what you mean.
I will add the "iothread_ref/unref" to all the IOThread users in next version.

Thanks
Chen

> Stefan


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH V4 4/4] qapi: examine IOThread attachment status via query-iothreads
  2026-02-24  2:42     ` Zhang Chen
@ 2026-02-24  8:42       ` Markus Armbruster
  2026-02-25 10:29         ` Zhang Chen
  0 siblings, 1 reply; 14+ messages in thread
From: Markus Armbruster @ 2026-02-24  8:42 UTC (permalink / raw)
  To: Zhang Chen
  Cc: qemu-devel, Dr . David Alan Gilbert, Eric Blake,
	Michael S . Tsirkin, Stefan Hajnoczi

Zhang Chen <zhangckid@gmail.com> writes:

> On Tue, Feb 17, 2026 at 3:51 PM Markus Armbruster <armbru@redhat.com> wrote:
>>
>> Zhang Chen <zhangckid@gmail.com> writes:
>>
>> > Extend the 'IOThreadInfo' structure to include attachment metrics.
>> > This allows users to monitor how many devices are associated with
>> > a specific IOThread and identify them by their QOM paths.
>> >
>> > New fields added to IOThreadInfo:
>> > - @attached-cnt: An integer representing the number of devices
>> >   currently using this IOThread's AioContext.
>> > - @attached-dev: A string containing a delimited list ("|") of
>> >   QOM paths for the attached devices.
>> >
>> > These fields are also exposed via the Human Monitor Interface (HMP)
>> > command 'info iothreads' to assist with manual debugging and
>> > performance tuning.
>> >
>> > Example QMP output:
>> > {
>> >     "id": "iothread0",
>> >     "thread-id": 3134,
>> >     "attached-cnt": 2,
>> >     "attached-dev": "/machine/peripheral/blk1/virtio-backend | /machine/peripheral/blk0/virtio-backend",
>> >     ...
>> > }
>> >
>> > Signed-off-by: Zhang Chen <zhangckid@gmail.com>
>>
>> [...]
>>
>> > diff --git a/qapi/misc.json b/qapi/misc.json
>> > index 1f5062df2a..ca53638684 100644
>> > --- a/qapi/misc.json
>> > +++ b/qapi/misc.json
>> > @@ -76,6 +76,19 @@
>> >  #
>> >  # @thread-id: ID of the underlying host thread
>> >  #
>> > +# @attached-cnt: The parameter is a counter indicating how many
>> > +#     active devices are currently associated with this iothread
>> > +#     (e.g. virtio-blk).  In hotplug scenarios, users can
>> > +#     pre-allocate multiple iothread objects to serve as a persistent
>> > +#     thread pool.  When a device is hot-unplugged, the corresponding
>> > +#     IOThread is released but remains available, allowing subsequent
>> > +#     hot-plugged devices to attach to and reuse the existing thread.
>> > +#     (since 11.0)
>> > +#
>> > +# @attached-dev: A list of QOM paths for the devices currently
>> > +#     associated with this IOThread, delimited by " | ".
>> > +#     Returns "none" if no devices are attached. (since 11.0)

Does not compile:

    In file included from ../qapi/qapi-schema.json:66:
    ../qapi/misc.json:90:49: Use two spaces between sentences
    If this not the end of a sentence, please report a bug.

This error has been in master for almost three months.  Is your tree
that far behind?

>>
>> QAPI schema design maxim: do not encode structured data as strings.
>> @attached-devs should be an array of QOM paths instead.
>
> OK, will fix in next version.

Thanks!

>> Unless I misunderstand your docs, @attached-cnt is the number of QOM
>> paths in @attached-dev, i.e. @attached-dev is redundant.  If this is the
>> case, drop it.  If it isn't, educate me :)
>
> As Stefan's comments, I try to address more specific needs:
> https://mail.gnu.org/archive/html/qemu-devel/2026-02/msg01892.html

As far as I can tell, Stefan asked for the QOM paths of attached
devices.  @attached-dev provides it.  Good.  Why have @attached-cnt as
well?

>> We generally avoid abbreviations in the QAPI schema: @attached-count,
>> @attached-devices.
>>
>> > +#
>> >  # @poll-max-ns: maximum polling time in ns, 0 means polling is
>> >  #     disabled (since 2.9)
>> >  #
>> > @@ -93,6 +106,8 @@
>> >  { 'struct': 'IOThreadInfo',
>> >    'data': {'id': 'str',
>> >             'thread-id': 'int',
>> > +           'attached-cnt': 'int',
>> > +           'attached-dev': 'str',
>> >             'poll-max-ns': 'int',
>> >             'poll-grow': 'int',
>> >             'poll-shrink': 'int',
>> > @@ -118,6 +133,8 @@
>> >  #              {
>> >  #                 "id":"iothread0",
>> >  #                 "thread-id":3134,
>> > +#                 "attached-cnt":2,
>> > +#                 "attached-dev":/machine/peripheral/blk1/virtio-backend | /machine/peripheral/blk0/virtio-backend,
>>
>> Once again, the example is syntactically incorrect (the value lacks
>> double quotes), and once again I recommend to create example I/O by
>> actually running a test.  Getting tired of this, to be frank.
>
> Sorry for that again. Will fix in next version.
> And I tested this series before send the mail like this:
>
> (qemu) info iothreads
> iothread2:
>   thread_id=434428
>   attached-cnt=0
>   attached-dev=none
>   poll-max-ns=32768
>   poll-grow=0
>   poll-shrink=0
>   aio-max-batch=0
> iothread1:
>   thread_id=434427
>   attached-cnt=2
>   attached-dev=/machine/peripheral/blk1/virtio-backend |
> /machine/peripheral/blk0/virtio-backend
>   poll-max-ns=32768
>   poll-grow=0
>   poll-shrink=0
>   aio-max-batch=0

You can manually test QMP like this:

    $ qemu-system-x86_64 -S -display none -chardev socket,id=qmp,path=test-qmp,server=on,wait=off -mon mode=control,chardev=qmp -object iothread,id=iot0

In another terminal:

    $ socat "READLINE,history=$HOME/.qmp_history,prompt=QMP> " UNIX-CONNECT:test-qmp 
    {"QMP": {"version": {"qemu": {"micro": 50, "minor": 2, "major": 10}, "package": "v10.2.0-1533-g627cf8d1ed-dirty"}, "capabilities": ["oob"]}}
    QMP> {"execute": "qmp_capabilities", "arguments": {"enable": ["oob"]}}
    {"return": {}}
    QMP> {"execute": "query-iothreads"}
    {"return": [{"poll-shrink": 0, "thread-id": 2140323, "aio-max-batch": 0, "attached-dev": "none", "poll-grow": 0, "attached-cnt": 0, "poll-max-ns": 32768, "id": "iot0"}]}
    QMP> {"execute": "quit"}
    {"timestamp": {"seconds": 1771922506, "microseconds": 801687}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
    {"return": {}}


>> >  #                 "poll-max-ns":32768,
>> >  #                 "poll-grow":0,
>> >  #                 "poll-shrink":0,
>> > @@ -126,6 +143,8 @@
>> >  #              {
>> >  #                 "id":"iothread1",
>> >  #                 "thread-id":3135,
>> > +#                 "attached-cnt":1,
>> > +#                 "attached-dev":/machine/peripheral/blk3/virtio-backend,
>>
>> Likewise.
>
> Thanks
> Chen
>
>>
>> >  #                 "poll-max-ns":32768,
>> >  #                 "poll-grow":0,
>> >  #                 "poll-shrink":0,
>>



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH V4 4/4] qapi: examine IOThread attachment status via query-iothreads
  2026-02-24  8:42       ` Markus Armbruster
@ 2026-02-25 10:29         ` Zhang Chen
  2026-02-25 10:54           ` Markus Armbruster
  0 siblings, 1 reply; 14+ messages in thread
From: Zhang Chen @ 2026-02-25 10:29 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, Dr . David Alan Gilbert, Eric Blake,
	Michael S . Tsirkin, Stefan Hajnoczi

On Tue, Feb 24, 2026 at 4:42 PM Markus Armbruster <armbru@redhat.com> wrote:
>
> Zhang Chen <zhangckid@gmail.com> writes:
>
> > On Tue, Feb 17, 2026 at 3:51 PM Markus Armbruster <armbru@redhat.com> wrote:
> >>
> >> Zhang Chen <zhangckid@gmail.com> writes:
> >>
> >> > Extend the 'IOThreadInfo' structure to include attachment metrics.
> >> > This allows users to monitor how many devices are associated with
> >> > a specific IOThread and identify them by their QOM paths.
> >> >
> >> > New fields added to IOThreadInfo:
> >> > - @attached-cnt: An integer representing the number of devices
> >> >   currently using this IOThread's AioContext.
> >> > - @attached-dev: A string containing a delimited list ("|") of
> >> >   QOM paths for the attached devices.
> >> >
> >> > These fields are also exposed via the Human Monitor Interface (HMP)
> >> > command 'info iothreads' to assist with manual debugging and
> >> > performance tuning.
> >> >
> >> > Example QMP output:
> >> > {
> >> >     "id": "iothread0",
> >> >     "thread-id": 3134,
> >> >     "attached-cnt": 2,
> >> >     "attached-dev": "/machine/peripheral/blk1/virtio-backend | /machine/peripheral/blk0/virtio-backend",
> >> >     ...
> >> > }
> >> >
> >> > Signed-off-by: Zhang Chen <zhangckid@gmail.com>
> >>
> >> [...]
> >>
> >> > diff --git a/qapi/misc.json b/qapi/misc.json
> >> > index 1f5062df2a..ca53638684 100644
> >> > --- a/qapi/misc.json
> >> > +++ b/qapi/misc.json
> >> > @@ -76,6 +76,19 @@
> >> >  #
> >> >  # @thread-id: ID of the underlying host thread
> >> >  #
> >> > +# @attached-cnt: The parameter is a counter indicating how many
> >> > +#     active devices are currently associated with this iothread
> >> > +#     (e.g. virtio-blk).  In hotplug scenarios, users can
> >> > +#     pre-allocate multiple iothread objects to serve as a persistent
> >> > +#     thread pool.  When a device is hot-unplugged, the corresponding
> >> > +#     IOThread is released but remains available, allowing subsequent
> >> > +#     hot-plugged devices to attach to and reuse the existing thread.
> >> > +#     (since 11.0)
> >> > +#
> >> > +# @attached-dev: A list of QOM paths for the devices currently
> >> > +#     associated with this IOThread, delimited by " | ".
> >> > +#     Returns "none" if no devices are attached. (since 11.0)
>
> Does not compile:
>
>     In file included from ../qapi/qapi-schema.json:66:
>     ../qapi/misc.json:90:49: Use two spaces between sentences
>     If this not the end of a sentence, please report a bug.
>
> This error has been in master for almost three months.  Is your tree
> that far behind?
>

Oh, my mistake, this version has undergone some minor description
improvements after testing.
Will cleanup it for full test.

> >>
> >> QAPI schema design maxim: do not encode structured data as strings.
> >> @attached-devs should be an array of QOM paths instead.
> >
> > OK, will fix in next version.
>
> Thanks!
>
> >> Unless I misunderstand your docs, @attached-cnt is the number of QOM
> >> paths in @attached-dev, i.e. @attached-dev is redundant.  If this is the
> >> case, drop it.  If it isn't, educate me :)
> >
> > As Stefan's comments, I try to address more specific needs:
> > https://mail.gnu.org/archive/html/qemu-devel/2026-02/msg01892.html
>
> As far as I can tell, Stefan asked for the QOM paths of attached
> devices.  @attached-dev provides it.  Good.  Why have @attached-cnt as
> well?
>

Users can obtain the quantity more conveniently, avoiding the need to
count the number of @attached-dev.
If you think the @attached-cnt is redundant, I will remove it in next version.


> >> We generally avoid abbreviations in the QAPI schema: @attached-count,
> >> @attached-devices.
> >>
> >> > +#
> >> >  # @poll-max-ns: maximum polling time in ns, 0 means polling is
> >> >  #     disabled (since 2.9)
> >> >  #
> >> > @@ -93,6 +106,8 @@
> >> >  { 'struct': 'IOThreadInfo',
> >> >    'data': {'id': 'str',
> >> >             'thread-id': 'int',
> >> > +           'attached-cnt': 'int',
> >> > +           'attached-dev': 'str',
> >> >             'poll-max-ns': 'int',
> >> >             'poll-grow': 'int',
> >> >             'poll-shrink': 'int',
> >> > @@ -118,6 +133,8 @@
> >> >  #              {
> >> >  #                 "id":"iothread0",
> >> >  #                 "thread-id":3134,
> >> > +#                 "attached-cnt":2,
> >> > +#                 "attached-dev":/machine/peripheral/blk1/virtio-backend | /machine/peripheral/blk0/virtio-backend,
> >>
> >> Once again, the example is syntactically incorrect (the value lacks
> >> double quotes), and once again I recommend to create example I/O by
> >> actually running a test.  Getting tired of this, to be frank.
> >
> > Sorry for that again. Will fix in next version.
> > And I tested this series before send the mail like this:
> >
> > (qemu) info iothreads
> > iothread2:
> >   thread_id=434428
> >   attached-cnt=0
> >   attached-dev=none
> >   poll-max-ns=32768
> >   poll-grow=0
> >   poll-shrink=0
> >   aio-max-batch=0
> > iothread1:
> >   thread_id=434427
> >   attached-cnt=2
> >   attached-dev=/machine/peripheral/blk1/virtio-backend |
> > /machine/peripheral/blk0/virtio-backend
> >   poll-max-ns=32768
> >   poll-grow=0
> >   poll-shrink=0
> >   aio-max-batch=0
>
> You can manually test QMP like this:
>
>     $ qemu-system-x86_64 -S -display none -chardev socket,id=qmp,path=test-qmp,server=on,wait=off -mon mode=control,chardev=qmp -object iothread,id=iot0
>
> In another terminal:
>
>     $ socat "READLINE,history=$HOME/.qmp_history,prompt=QMP> " UNIX-CONNECT:test-qmp
>     {"QMP": {"version": {"qemu": {"micro": 50, "minor": 2, "major": 10}, "package": "v10.2.0-1533-g627cf8d1ed-dirty"}, "capabilities": ["oob"]}}
>     QMP> {"execute": "qmp_capabilities", "arguments": {"enable": ["oob"]}}
>     {"return": {}}
>     QMP> {"execute": "query-iothreads"}
>     {"return": [{"poll-shrink": 0, "thread-id": 2140323, "aio-max-batch": 0, "attached-dev": "none", "poll-grow": 0, "attached-cnt": 0, "poll-max-ns": 32768, "id": "iot0"}]}
>     QMP> {"execute": "quit"}
>     {"timestamp": {"seconds": 1771922506, "microseconds": 801687}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
>     {"return": {}}
>

Got it, will double check the QMP.
Thank you for the detailed description.


Thanks
Chen

>
> >> >  #                 "poll-max-ns":32768,
> >> >  #                 "poll-grow":0,
> >> >  #                 "poll-shrink":0,
> >> > @@ -126,6 +143,8 @@
> >> >  #              {
> >> >  #                 "id":"iothread1",
> >> >  #                 "thread-id":3135,
> >> > +#                 "attached-cnt":1,
> >> > +#                 "attached-dev":/machine/peripheral/blk3/virtio-backend,
> >>
> >> Likewise.
> >
> > Thanks
> > Chen
> >
> >>
> >> >  #                 "poll-max-ns":32768,
> >> >  #                 "poll-grow":0,
> >> >  #                 "poll-shrink":0,
> >>
>


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH V4 4/4] qapi: examine IOThread attachment status via query-iothreads
  2026-02-25 10:29         ` Zhang Chen
@ 2026-02-25 10:54           ` Markus Armbruster
  2026-02-25 11:39             ` Zhang Chen
  0 siblings, 1 reply; 14+ messages in thread
From: Markus Armbruster @ 2026-02-25 10:54 UTC (permalink / raw)
  To: Zhang Chen
  Cc: qemu-devel, Dr . David Alan Gilbert, Eric Blake,
	Michael S . Tsirkin, Stefan Hajnoczi

Zhang Chen <zhangckid@gmail.com> writes:

> On Tue, Feb 24, 2026 at 4:42 PM Markus Armbruster <armbru@redhat.com> wrote:
>>
>> Zhang Chen <zhangckid@gmail.com> writes:
>>
>> > On Tue, Feb 17, 2026 at 3:51 PM Markus Armbruster <armbru@redhat.com> wrote:
>> >>
>> >> Zhang Chen <zhangckid@gmail.com> writes:
>> >>
>> >> > Extend the 'IOThreadInfo' structure to include attachment metrics.
>> >> > This allows users to monitor how many devices are associated with
>> >> > a specific IOThread and identify them by their QOM paths.
>> >> >
>> >> > New fields added to IOThreadInfo:
>> >> > - @attached-cnt: An integer representing the number of devices
>> >> >   currently using this IOThread's AioContext.
>> >> > - @attached-dev: A string containing a delimited list ("|") of
>> >> >   QOM paths for the attached devices.
>> >> >
>> >> > These fields are also exposed via the Human Monitor Interface (HMP)
>> >> > command 'info iothreads' to assist with manual debugging and
>> >> > performance tuning.
>> >> >
>> >> > Example QMP output:
>> >> > {
>> >> >     "id": "iothread0",
>> >> >     "thread-id": 3134,
>> >> >     "attached-cnt": 2,
>> >> >     "attached-dev": "/machine/peripheral/blk1/virtio-backend | /machine/peripheral/blk0/virtio-backend",
>> >> >     ...
>> >> > }
>> >> >
>> >> > Signed-off-by: Zhang Chen <zhangckid@gmail.com>
>> >>
>> >> [...]
>> >>
>> >> > diff --git a/qapi/misc.json b/qapi/misc.json
>> >> > index 1f5062df2a..ca53638684 100644
>> >> > --- a/qapi/misc.json
>> >> > +++ b/qapi/misc.json
>> >> > @@ -76,6 +76,19 @@
>> >> >  #
>> >> >  # @thread-id: ID of the underlying host thread
>> >> >  #
>> >> > +# @attached-cnt: The parameter is a counter indicating how many
>> >> > +#     active devices are currently associated with this iothread
>> >> > +#     (e.g. virtio-blk).  In hotplug scenarios, users can
>> >> > +#     pre-allocate multiple iothread objects to serve as a persistent
>> >> > +#     thread pool.  When a device is hot-unplugged, the corresponding
>> >> > +#     IOThread is released but remains available, allowing subsequent
>> >> > +#     hot-plugged devices to attach to and reuse the existing thread.
>> >> > +#     (since 11.0)
>> >> > +#
>> >> > +# @attached-dev: A list of QOM paths for the devices currently
>> >> > +#     associated with this IOThread, delimited by " | ".
>> >> > +#     Returns "none" if no devices are attached. (since 11.0)

[...]

>> >>
>> >> QAPI schema design maxim: do not encode structured data as strings.
>> >> @attached-devs should be an array of QOM paths instead.
>> >
>> > OK, will fix in next version.
>>
>> Thanks!
>>
>> >> Unless I misunderstand your docs, @attached-cnt is the number of QOM
>> >> paths in @attached-dev, i.e. @attached-dev is redundant.  If this is the
>> >> case, drop it.  If it isn't, educate me :)
>> >
>> > As Stefan's comments, I try to address more specific needs:
>> > https://mail.gnu.org/archive/html/qemu-devel/2026-02/msg01892.html
>>
>> As far as I can tell, Stefan asked for the QOM paths of attached
>> devices.  @attached-dev provides it.  Good.  Why have @attached-cnt as
>> well?
>>
>
> Users can obtain the quantity more conveniently, avoiding the need to
> count the number of @attached-dev.
> If you think the @attached-cnt is redundant, I will remove it in next version.

Please do.

[...]



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH V4 2/4] iothread: introduce iothread_ref/unref to track attached devices
  2026-02-18 20:53   ` Stefan Hajnoczi
@ 2026-02-25 11:38     ` Zhang Chen
  0 siblings, 0 replies; 14+ messages in thread
From: Zhang Chen @ 2026-02-25 11:38 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: qemu-devel, Dr . David Alan Gilbert, Eric Blake,
	Markus Armbruster, Michael S . Tsirkin

On Thu, Feb 19, 2026 at 4:53 AM Stefan Hajnoczi <stefanha@redhat.com> wrote:
>
> On Sat, Feb 14, 2026 at 01:16:20AM +0800, Zhang Chen wrote:
> > Currently, IOThreads do not maintain a record of which devices are
> > associated with them. This makes it difficult to monitor the
> > workload distribution of IOThreads, especially in complex
> > hotplug scenarios involving multiple virtio-blk or virtio-scsi devices.
> >
> > This patch introduces a reference counting and tracking mechanism
> > within the IOThread object:
> >
> > - iothread_ref(): Increments the attachment counter and prepends the
> >   device's QOM path to a list. Note: The IOThread takes ownership of
> >   the passed 'holder' string.
> > - iothread_unref(): Searches for the device path using a custom
> >   string comparison (g_strcmp0), decrements the counter, and
> >   releases the associated memory upon a successful match.
> > - attached_cnt: Tracks the number of active device attachments.
> > - attached_dev: A GList storing the QOM paths of attached devices
> >   for runtime introspection.
> >
> > This infrastructure allows management tools and QMP commands to
> > query the attachment status of IOThreads.
> >
> > Signed-off-by: Zhang Chen <zhangckid@gmail.com>
> > ---
> >  include/system/iothread.h |  4 ++++
> >  iothread.c                | 35 +++++++++++++++++++++++++++++++++++
> >  2 files changed, 39 insertions(+)
> >
> > diff --git a/include/system/iothread.h b/include/system/iothread.h
> > index e26d13c6c7..4a2ffdb9bd 100644
> > --- a/include/system/iothread.h
> > +++ b/include/system/iothread.h
> > @@ -33,6 +33,8 @@ struct IOThread {
> >      bool stopping;              /* has iothread_stop() been called? */
> >      bool running;               /* should iothread_run() continue? */
> >      int thread_id;
> > +    int attached_cnt;
>
> Is this field necessary given that the user can see the list of holders?

Will remove it in next version.

>
> > +    GList *attached_dev;
>
> IOThreads are general eventloop concept in QEMU and not limited to
> device emulation. Non-device code may also wish to add itself (e.g.
> block/export/export.c). Please call this GList *holders.

OK, will change the name next version.


>
> This raises questions:
> - Is it mandatory for users of the IOThread's AioContext to add
>   themselves?
> - How does it relate to object_ref()/object_unref()?
>
> I would prefer to set things up as follows:
>
> It is mandatory for users of the IOThread's AioContext to add
> themselves. This is enforced by modifying iothread_get_aio_context() to
> take a string argument with the name of the holder.
>
> iothread_get_aio_context() is also extended to call
> object_ref(OBJECT(iothread)). This guarantees that the IOThread and its
> AioContext remain alive as long as there is a holder. (Some users
> already do this themselves, so I think it makes sense to build this
> behavior into the API so that all users get it automatically.)
>
> A new iothread_put_aio_context() function is introduced to remove the
> hold and object_unref(OBJECT(iothread)).
>
> All existing callers of iothread_get_aio_context() need to be updated to
> pass in their QOM object path as the name of the holder, remove their own
> object_ref() call (if present), and call iothread_put_aio_context() at
> the appropriate point.

Make sense, I will implement it in next version.

>
> >
> >      /* AioContext poll parameters */
> >      int64_t poll_max_ns;
> > @@ -48,6 +50,8 @@ char *iothread_get_id(IOThread *iothread);
> >  IOThread *iothread_by_id(const char *id);
> >  AioContext *iothread_get_aio_context(IOThread *iothread);
> >  GMainContext *iothread_get_g_main_context(IOThread *iothread);
> > +void iothread_ref(IOThread *iothread, const char* holder);
> > +void iothread_unref(IOThread *iothread, const char* holder);
> >
> >  /*
> >   * Helpers used to allocate iothreads for internal use.  These
> > diff --git a/iothread.c b/iothread.c
> > index caf68e0764..b869637497 100644
> > --- a/iothread.c
> > +++ b/iothread.c
> > @@ -36,6 +36,41 @@
> >  #define IOTHREAD_POLL_MAX_NS_DEFAULT 0ULL
> >  #endif
> >
> > +/*
> > + * Increment iothread's reference count,
> > + * and add holder device path to the list.
> > + */
> > +void iothread_ref(IOThread *iothread, const char *holder)
> > +{
> > +    iothread->attached_cnt++;
> > +    iothread->attached_dev = g_list_prepend(iothread->attached_dev,
> > +                                           (gpointer)holder);
>
> It's safer to g_strdup(holder) so the caller doesn't need to worry about
> the lifetime of the argument. This is not a performance-critical code
> path so the cost of the strdup is acceptable.

OK.

>
> > +}
> > +
> > +/*
> > + * Decrement iothread's reference count,
> > + * and delete holder device path from the list.
> > + */
> > +void iothread_unref(IOThread *iothread, const char *holder)
> > +{
> > +    if (iothread->attached_cnt > 0) {
> > +        GList *link = g_list_find_custom(iothread->attached_dev,
> > +                                         holder, (GCompareFunc)g_strcmp0);
> > +
> > +        if (link) {
> > +            g_free(link->data);
>
> iothread_ref() originally took a _const_ char * so it must not free the
> pointer here. The reason why the compiler didn't complain was because
> iothread_ref() cast the pointer to non-const gpointer. In any case, as
> mentioned above, it's probably best to use g_strdup() and avoid placing
> constraints on the lifetime of the caller's string.

OK, will use the g_strdup() in ref side next version.

>
> > +            iothread->attached_dev = g_list_delete_link(iothread->attached_dev,
> > +                                                        link);
> > +            iothread->attached_cnt--;
> > +        } else {
> > +            error_report("iohtread_unref can't find device. attached_dev=%s",
>
> "iohtread" typo here and in the line below.

Good catch.

Thanks
Chen

>
> > +                        holder);
> > +        }
> > +    } else {
> > +        error_report("iohtread_unref counter error. attached_dev=%s", holder);
> > +    }
> > +}
> > +
> >  static void *iothread_run(void *opaque)
> >  {
> >      IOThread *iothread = opaque;
> > --
> > 2.49.0
> >


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH V4 4/4] qapi: examine IOThread attachment status via query-iothreads
  2026-02-25 10:54           ` Markus Armbruster
@ 2026-02-25 11:39             ` Zhang Chen
  0 siblings, 0 replies; 14+ messages in thread
From: Zhang Chen @ 2026-02-25 11:39 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, Dr . David Alan Gilbert, Eric Blake,
	Michael S . Tsirkin, Stefan Hajnoczi

On Wed, Feb 25, 2026 at 6:55 PM Markus Armbruster <armbru@redhat.com> wrote:
>
> Zhang Chen <zhangckid@gmail.com> writes:
>
> > On Tue, Feb 24, 2026 at 4:42 PM Markus Armbruster <armbru@redhat.com> wrote:
> >>
> >> Zhang Chen <zhangckid@gmail.com> writes:
> >>
> >> > On Tue, Feb 17, 2026 at 3:51 PM Markus Armbruster <armbru@redhat.com> wrote:
> >> >>
> >> >> Zhang Chen <zhangckid@gmail.com> writes:
> >> >>
> >> >> > Extend the 'IOThreadInfo' structure to include attachment metrics.
> >> >> > This allows users to monitor how many devices are associated with
> >> >> > a specific IOThread and identify them by their QOM paths.
> >> >> >
> >> >> > New fields added to IOThreadInfo:
> >> >> > - @attached-cnt: An integer representing the number of devices
> >> >> >   currently using this IOThread's AioContext.
> >> >> > - @attached-dev: A string containing a delimited list ("|") of
> >> >> >   QOM paths for the attached devices.
> >> >> >
> >> >> > These fields are also exposed via the Human Monitor Interface (HMP)
> >> >> > command 'info iothreads' to assist with manual debugging and
> >> >> > performance tuning.
> >> >> >
> >> >> > Example QMP output:
> >> >> > {
> >> >> >     "id": "iothread0",
> >> >> >     "thread-id": 3134,
> >> >> >     "attached-cnt": 2,
> >> >> >     "attached-dev": "/machine/peripheral/blk1/virtio-backend | /machine/peripheral/blk0/virtio-backend",
> >> >> >     ...
> >> >> > }
> >> >> >
> >> >> > Signed-off-by: Zhang Chen <zhangckid@gmail.com>
> >> >>
> >> >> [...]
> >> >>
> >> >> > diff --git a/qapi/misc.json b/qapi/misc.json
> >> >> > index 1f5062df2a..ca53638684 100644
> >> >> > --- a/qapi/misc.json
> >> >> > +++ b/qapi/misc.json
> >> >> > @@ -76,6 +76,19 @@
> >> >> >  #
> >> >> >  # @thread-id: ID of the underlying host thread
> >> >> >  #
> >> >> > +# @attached-cnt: The parameter is a counter indicating how many
> >> >> > +#     active devices are currently associated with this iothread
> >> >> > +#     (e.g. virtio-blk).  In hotplug scenarios, users can
> >> >> > +#     pre-allocate multiple iothread objects to serve as a persistent
> >> >> > +#     thread pool.  When a device is hot-unplugged, the corresponding
> >> >> > +#     IOThread is released but remains available, allowing subsequent
> >> >> > +#     hot-plugged devices to attach to and reuse the existing thread.
> >> >> > +#     (since 11.0)
> >> >> > +#
> >> >> > +# @attached-dev: A list of QOM paths for the devices currently
> >> >> > +#     associated with this IOThread, delimited by " | ".
> >> >> > +#     Returns "none" if no devices are attached. (since 11.0)
>
> [...]
>
> >> >>
> >> >> QAPI schema design maxim: do not encode structured data as strings.
> >> >> @attached-devs should be an array of QOM paths instead.
> >> >
> >> > OK, will fix in next version.
> >>
> >> Thanks!
> >>
> >> >> Unless I misunderstand your docs, @attached-cnt is the number of QOM
> >> >> paths in @attached-dev, i.e. @attached-dev is redundant.  If this is the
> >> >> case, drop it.  If it isn't, educate me :)
> >> >
> >> > As Stefan's comments, I try to address more specific needs:
> >> > https://mail.gnu.org/archive/html/qemu-devel/2026-02/msg01892.html
> >>
> >> As far as I can tell, Stefan asked for the QOM paths of attached
> >> devices.  @attached-dev provides it.  Good.  Why have @attached-cnt as
> >> well?
> >>
> >
> > Users can obtain the quantity more conveniently, avoiding the need to
> > count the number of @attached-dev.
> > If you think the @attached-cnt is redundant, I will remove it in next version.
>
> Please do.

OK~ Thank you for the suggestion.

Thanks
Chen

>
> [...]
>


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2026-02-25 11:40 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-13 17:16 [PATCH V4 1/4] qapi/misc: Fix missed query-iothreads items Zhang Chen
2026-02-13 17:16 ` [PATCH V4 2/4] iothread: introduce iothread_ref/unref to track attached devices Zhang Chen
2026-02-18 20:53   ` Stefan Hajnoczi
2026-02-25 11:38     ` Zhang Chen
2026-02-13 17:16 ` [PATCH V4 3/4] iothread: track virtio-blk devices using IOThread reference counting Zhang Chen
2026-02-18 20:55   ` Stefan Hajnoczi
2026-02-24  2:55     ` Zhang Chen
2026-02-13 17:16 ` [PATCH V4 4/4] qapi: examine IOThread attachment status via query-iothreads Zhang Chen
2026-02-17  7:51   ` Markus Armbruster
2026-02-24  2:42     ` Zhang Chen
2026-02-24  8:42       ` Markus Armbruster
2026-02-25 10:29         ` Zhang Chen
2026-02-25 10:54           ` Markus Armbruster
2026-02-25 11:39             ` Zhang Chen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.