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 <[email protected]>
---
 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


Reply via email to