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.

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

Attachment: signature.asc
Description: PGP signature

Reply via email to