On Mon, Mar 9, 2026 at 4:02 PM Stefan Hajnoczi <[email protected]> wrote:
>
> On Thu, Mar 05, 2026 at 10:24:49PM +0800, Zhang Chen wrote:
> > Introduce iothread_get_aio_context() with a 'holder' argument and its
> > counterpart iothread_put_aio_context().
> >
> > Previously, users of an IOThread's AioContext did not explicitly
> > record their identity, making it difficult to debug which devices or
> > subsystems were pinning an IOThread.
> >
> > This patch enhances the reference counting mechanism by:
> > 1. Automatically incrementing the object reference count when a context
> > is retrieved.
> > 2. Tracking holders by name using iothread_ref() and iothread_unref().
> >
> > In iothread_instance_finalize(), we now retrieve the source name from
> > the GMainContext to correctly unref the initial internal holder.
> >
> > Signed-off-by: Zhang Chen <[email protected]>
> > ---
> > include/system/iothread.h | 3 ++-
> > iothread.c | 28 ++++++++++++++++++++++++++--
> > 2 files changed, 28 insertions(+), 3 deletions(-)
> >
> > diff --git a/include/system/iothread.h b/include/system/iothread.h
> > index 21a76bd70d..595abeefbe 100644
> > --- a/include/system/iothread.h
> > +++ b/include/system/iothread.h
> > @@ -47,7 +47,8 @@ DECLARE_INSTANCE_CHECKER(IOThread, IOTHREAD,
> >
> > char *iothread_get_id(IOThread *iothread);
> > IOThread *iothread_by_id(const char *id);
> > -AioContext *iothread_get_aio_context(IOThread *iothread);
> > +AioContext *iothread_get_aio_context(IOThread *iothread, const char
> > *holder);
> > +void iothread_put_aio_context(IOThread *iothread, const char *holder);
> > GMainContext *iothread_get_g_main_context(IOThread *iothread);
> >
> > /*
> > diff --git a/iothread.c b/iothread.c
> > index 80a8cf4b32..da98fbb9ad 100644
> > --- a/iothread.c
> > +++ b/iothread.c
> > @@ -172,7 +172,8 @@ static void iothread_init_gcontext(IOThread *iothread,
> > const char *thread_name)
> > g_autofree char *name = g_strdup_printf("%s aio-context", thread_name);
> >
> > iothread->worker_context = g_main_context_new();
> > - source = aio_get_g_source(iothread_get_aio_context(iothread));
> > + /* No need setup itself as the init holder */
> > + source = aio_get_g_source(iothread_get_aio_context(iothread, NULL));
>
> This is cleaner:
>
> source = aio_get_g_source(iothread->ctx);
>
> That way iothread_get_aio_context() doesn't need a special case for
> NULL.
OK for here. But according to the following patch we try to use the
NULL to handle
problems that cannot be easily solved using ref/unref or get/put.
For example the patch 7 and 9. We can discuss the details in that mail threads.
>
> > g_source_set_name(source, name);
> > g_source_attach(source, iothread->worker_context);
> > g_source_unref(source);
> > @@ -362,11 +363,34 @@ char *iothread_get_id(IOThread *iothread)
> > return g_strdup(object_get_canonical_path_component(OBJECT(iothread)));
> > }
> >
> > -AioContext *iothread_get_aio_context(IOThread *iothread)
> > +AioContext *iothread_get_aio_context(IOThread *iothread, const char
> > *holder)
> > {
> > + /*
> > + * In some cases, iothread user need the ctx to clearup other resource.
> > + * When holder is empty, back to the legacy way.
> > + */
> > + if (holder) {
> > + /*
> > + * This guarantees that the IOThread and its AioContext remain
> > alive
> > + * as long as there is a holder.
> > + */
> > + object_ref(OBJECT(iothread));
>
> Can this be done in iothread_ref()/iothread_unref()? That would ensure
> that callers always increment the QOM reference count regardless of
> whether the iothread_ref() or iothread_get_aio_context() API is used.
Sure, will move it into iothread_ref()/iothread_unref().
Thanks
Chen
>
> > +
> > + /* Add holder device path to the list */
> > + iothread_ref(iothread, holder);
> > + }
> > +
> > return iothread->ctx;
> > }
> >
> > +void iothread_put_aio_context(IOThread *iothread, const char *holder)
> > +{
> > + object_unref(OBJECT(iothread));
> > +
> > + /* Delete holder device path from the list */
> > + iothread_unref(iothread, holder);
> > +}
> > +
> > static int query_one_iothread(Object *object, void *opaque)
> > {
> > IOThreadInfoList ***tail = opaque;
> > --
> > 2.49.0
> >