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
> >

Reply via email to