On Tue, May 12, 2026 at 3:05 AM Stefan Hajnoczi <[email protected]> wrote:
>
> On Mon, May 11, 2026 at 10:04:06PM +0800, Zhang Chen wrote:
> > Currently, x-blockdev-set-iothread changes the AioContext but does not
> > track the IOThread object itself within the block layer. This makes it
> > difficult to manage IOThread reference counting (put/get) during
> > dynamic context switching.
> >
> > Introduce an 'iothread' field to BlockDriverState to store the current
> > assigned IOThread. Update qmp_x_blockdev_set_iothread to perform
> > proper reference counting using iothread_ref/put when moving nodes
> > between an IOThread and the main loop.
> >
> > This ensures 'info iothreads' (holders) accurately reflects the block
> > device attachment state after dynamic migrations.
> >
> > Signed-off-by: Zhang Chen <[email protected]>
> > ---
> > blockdev.c | 6 +++++-
> > include/block/block_int-common.h | 5 +++++
> > 2 files changed, 10 insertions(+), 1 deletion(-)
> >
> > diff --git a/blockdev.c b/blockdev.c
> > index 6e86c6262f..6e20579187 100644
> > --- a/blockdev.c
> > +++ b/blockdev.c
> > @@ -3683,8 +3683,12 @@ void qmp_x_blockdev_set_iothread(const char
> > *node_name, StrOrNull *iothread,
> > goto out;
> > }
> >
> > - new_context = iothread_get_aio_context(obj);
> > + new_context = iothread_ref_and_get_aio_context(obj, node_name);
> > + bs->iothread = obj;
> > } else {
> > + if (bs->iothread) {
> > + iothread_put_aio_context(bs->iothread, node_name);
> > + }
> > new_context = qemu_get_aio_context();
> > }
>
> This command is the wrong place to associate an IOThread with a
> BlockDriverState:
> 1. Do we need to call iothread_put_aio_context() on the current IOThread
> when x-blockdev-set-iothread is called with a new IOThread?
> 2. Is the AioContext leaked when x-blockdev-set-iothread iothread=null
> is not called before the BlockDriverState is freed?
>
> Every BlockDriverState would need to get/put the IOThread AioContext in
> bdrv_change_aio_context() or related functions.
>
> However, the QEMU block layer has been moving away from having a
> per-BlockDriverState AioContext. It is possible to use a
> BlockDriverState from any AioContext (including multiple AioContexts at
> the same time). I'm in favor of not associating BlockDriverStates with
> IOThreads and instead relying on their device owners (e.g. emulated
> storage controllers) to be the IOThread holders. That means you could
> use iothread->ctx directly or create an
> iothread_unsafe_get_aio_context() API to document that this is a
> low-level unsafe way of getting the AioContext.
It's fine for me, I was troubled for a long time by the specific
implementation of this problem.
Thanks
Chen
>
> >
> > diff --git a/include/block/block_int-common.h
> > b/include/block/block_int-common.h
> > index 147c08155f..6edaf53377 100644
> > --- a/include/block/block_int-common.h
> > +++ b/include/block/block_int-common.h
> > @@ -1101,6 +1101,8 @@ typedef struct BdrvBlockStatusCache {
> > int64_t data_end;
> > } BdrvBlockStatusCache;
> >
> > +typedef struct IOThread IOThread;
> > +
> > struct BlockDriverState {
> > /*
> > * Protected by big QEMU lock or read-only after opening. No special
> > @@ -1289,6 +1291,9 @@ struct BlockDriverState {
> >
> > /* array of write pointers' location of each zone in the zoned device.
> > */
> > BlockZoneWps *wps;
> > +
> > + /* Track the iothread for detach aio context*/
> > + IOThread *iothread;
> > };
> >
> > struct BlockBackendRootState {
> > --
> > 2.49.0
> >