+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Hanna Reitz <hreitz@redhat.com>
+Date: Wed, 9 Feb 2022 15:02:57 +0100
+Subject: [PATCH] block/nbd: Move s->ioc on AioContext change
+
+s->ioc must always be attached to the NBD node's AioContext. If that
+context changes, s->ioc must be attached to the new context.
+
+Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2033626
+Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+Signed-off-by: Hanna Reitz <hreitz@redhat.com>
+[FE: backport (open_timer doesn't exist yet in 6.2.0)]
+Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
+---
+ block/nbd.c | 41 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 41 insertions(+)
+
+diff --git a/block/nbd.c b/block/nbd.c
+index aab20125d8..a3896c7f5f 100644
+--- a/block/nbd.c
++++ b/block/nbd.c
+@@ -2003,6 +2003,38 @@ static void nbd_cancel_in_flight(BlockDriverState *bs)
+ nbd_co_establish_connection_cancel(s->conn);
+ }
+
++static void nbd_attach_aio_context(BlockDriverState *bs,
++ AioContext *new_context)
++{
++ BDRVNBDState *s = bs->opaque;
++
++ /*
++ * The reconnect_delay_timer is scheduled in I/O paths when the
++ * connection is lost, to cancel the reconnection attempt after a
++ * given time. Once this attempt is done (successfully or not),
++ * nbd_reconnect_attempt() ensures the timer is deleted before the
++ * respective I/O request is resumed.
++ * Since the AioContext can only be changed when a node is drained,
++ * the reconnect_delay_timer cannot be active here.
++ */
++ assert(!s->reconnect_delay_timer);
++
++ if (s->ioc) {
++ qio_channel_attach_aio_context(s->ioc, new_context);
++ }
++}
++
++static void nbd_detach_aio_context(BlockDriverState *bs)
++{
++ BDRVNBDState *s = bs->opaque;
++
++ assert(!s->reconnect_delay_timer);
++
++ if (s->ioc) {
++ qio_channel_detach_aio_context(s->ioc);
++ }
++}
++
+ static BlockDriver bdrv_nbd = {
+ .format_name = "nbd",
+ .protocol_name = "nbd",
+@@ -2026,6 +2058,9 @@ static BlockDriver bdrv_nbd = {
+ .bdrv_dirname = nbd_dirname,
+ .strong_runtime_opts = nbd_strong_runtime_opts,
+ .bdrv_cancel_in_flight = nbd_cancel_in_flight,
++
++ .bdrv_attach_aio_context = nbd_attach_aio_context,
++ .bdrv_detach_aio_context = nbd_detach_aio_context,
+ };
+
+ static BlockDriver bdrv_nbd_tcp = {
+@@ -2051,6 +2086,9 @@ static BlockDriver bdrv_nbd_tcp = {
+ .bdrv_dirname = nbd_dirname,
+ .strong_runtime_opts = nbd_strong_runtime_opts,
+ .bdrv_cancel_in_flight = nbd_cancel_in_flight,
++
++ .bdrv_attach_aio_context = nbd_attach_aio_context,
++ .bdrv_detach_aio_context = nbd_detach_aio_context,
+ };
+
+ static BlockDriver bdrv_nbd_unix = {
+@@ -2076,6 +2114,9 @@ static BlockDriver bdrv_nbd_unix = {
+ .bdrv_dirname = nbd_dirname,
+ .strong_runtime_opts = nbd_strong_runtime_opts,
+ .bdrv_cancel_in_flight = nbd_cancel_in_flight,
++
++ .bdrv_attach_aio_context = nbd_attach_aio_context,
++ .bdrv_detach_aio_context = nbd_detach_aio_context,
+ };
+
+ static void bdrv_nbd_init(void)