Re: [PATCH v5 12/21] xen-block: implement BlockDevOps->drained_begin()

2023-05-16 Thread Anthony PERARD via
On Thu, May 04, 2023 at 03:53:18PM -0400, Stefan Hajnoczi wrote:
> @@ -819,11 +841,9 @@ void xen_block_dataplane_start(XenBlockDataPlane 
> *dataplane,
>  blk_set_aio_context(dataplane->blk, dataplane->ctx, NULL);
>  aio_context_release(old_context);
>  
> -/* Only reason for failure is a NULL channel */
> -aio_context_acquire(dataplane->ctx);
> -xen_device_set_event_channel_context(xendev, dataplane->event_channel,
> - dataplane->ctx, _abort);
> -aio_context_release(dataplane->ctx);
> +if (!blk_in_drain(dataplane->blk)) {

There's maybe something missing in the patch.
xen_block_dataplane_start() calls xen_device_bind_event_channel() just
before xen_block_dataplane_attach().

And xen_device_bind_event_channel() sets the event context to
qemu_get_aio_context() instead of NULL.

So, even if we don't call xen_block_dataplane_attach() while in drain,
there's already a fd_handler attach to the fd. So should
xen_device_bind_event_channel() be changed as well? Or maybe a call to
xen_block_dataplane_detach() would be enough.

(There's only one user of xen_device_bind_event_channel() at the moment
so I don't know if other implementation making use of this API will want
to call set_event_channel_context or not.)

> +xen_block_dataplane_attach(dataplane);
> +}
>  
>  return;
>  

-- 
Anthony PERARD



Re: [PATCH v5 12/21] xen-block: implement BlockDevOps->drained_begin()

2023-05-16 Thread Anthony PERARD via
On Thu, May 04, 2023 at 03:53:18PM -0400, Stefan Hajnoczi wrote:
> Detach event channels during drained sections to stop I/O submission
> from the ring. xen-block is no longer reliant on aio_disable_external()
> after this patch. This will allow us to remove the
> aio_disable_external() API once all other code that relies on it is
> converted.
> 
> Extend xen_device_set_event_channel_context() to allow ctx=NULL. The
> event channel still exists but the event loop does not monitor the file
> descriptor. Event channel processing can resume by calling
> xen_device_set_event_channel_context() with a non-NULL ctx.
> 
> Factor out xen_device_set_event_channel_context() calls in
> hw/block/dataplane/xen-block.c into attach/detach helper functions.
> Incidentally, these don't require the AioContext lock because
> aio_set_fd_handler() is thread-safe.
> 
> It's safer to register BlockDevOps after the dataplane instance has been
> created. The BlockDevOps .drained_begin/end() callbacks depend on the
> dataplane instance, so move the blk_set_dev_ops() call after
> xen_block_dataplane_create().
> 
> Signed-off-by: Stefan Hajnoczi 

Reviewed-by: Anthony PERARD 

Thanks,

-- 
Anthony PERARD



[PATCH v5 12/21] xen-block: implement BlockDevOps->drained_begin()

2023-05-04 Thread Stefan Hajnoczi
Detach event channels during drained sections to stop I/O submission
from the ring. xen-block is no longer reliant on aio_disable_external()
after this patch. This will allow us to remove the
aio_disable_external() API once all other code that relies on it is
converted.

Extend xen_device_set_event_channel_context() to allow ctx=NULL. The
event channel still exists but the event loop does not monitor the file
descriptor. Event channel processing can resume by calling
xen_device_set_event_channel_context() with a non-NULL ctx.

Factor out xen_device_set_event_channel_context() calls in
hw/block/dataplane/xen-block.c into attach/detach helper functions.
Incidentally, these don't require the AioContext lock because
aio_set_fd_handler() is thread-safe.

It's safer to register BlockDevOps after the dataplane instance has been
created. The BlockDevOps .drained_begin/end() callbacks depend on the
dataplane instance, so move the blk_set_dev_ops() call after
xen_block_dataplane_create().

Signed-off-by: Stefan Hajnoczi 
---
 hw/block/dataplane/xen-block.h |  2 ++
 hw/block/dataplane/xen-block.c | 42 +-
 hw/block/xen-block.c   | 24 ---
 hw/xen/xen-bus.c   |  7 --
 4 files changed, 59 insertions(+), 16 deletions(-)

diff --git a/hw/block/dataplane/xen-block.h b/hw/block/dataplane/xen-block.h
index 76dcd51c3d..7b8e9df09f 100644
--- a/hw/block/dataplane/xen-block.h
+++ b/hw/block/dataplane/xen-block.h
@@ -26,5 +26,7 @@ void xen_block_dataplane_start(XenBlockDataPlane *dataplane,
unsigned int protocol,
Error **errp);
 void xen_block_dataplane_stop(XenBlockDataPlane *dataplane);
+void xen_block_dataplane_attach(XenBlockDataPlane *dataplane);
+void xen_block_dataplane_detach(XenBlockDataPlane *dataplane);
 
 #endif /* HW_BLOCK_DATAPLANE_XEN_BLOCK_H */
diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c
index d8bc39d359..2597f38805 100644
--- a/hw/block/dataplane/xen-block.c
+++ b/hw/block/dataplane/xen-block.c
@@ -664,6 +664,30 @@ void xen_block_dataplane_destroy(XenBlockDataPlane 
*dataplane)
 g_free(dataplane);
 }
 
+void xen_block_dataplane_detach(XenBlockDataPlane *dataplane)
+{
+if (!dataplane || !dataplane->event_channel) {
+return;
+}
+
+/* Only reason for failure is a NULL channel */
+xen_device_set_event_channel_context(dataplane->xendev,
+ dataplane->event_channel,
+ NULL, _abort);
+}
+
+void xen_block_dataplane_attach(XenBlockDataPlane *dataplane)
+{
+if (!dataplane || !dataplane->event_channel) {
+return;
+}
+
+/* Only reason for failure is a NULL channel */
+xen_device_set_event_channel_context(dataplane->xendev,
+ dataplane->event_channel,
+ dataplane->ctx, _abort);
+}
+
 void xen_block_dataplane_stop(XenBlockDataPlane *dataplane)
 {
 XenDevice *xendev;
@@ -674,13 +698,11 @@ void xen_block_dataplane_stop(XenBlockDataPlane 
*dataplane)
 
 xendev = dataplane->xendev;
 
-aio_context_acquire(dataplane->ctx);
-if (dataplane->event_channel) {
-/* Only reason for failure is a NULL channel */
-xen_device_set_event_channel_context(xendev, dataplane->event_channel,
- qemu_get_aio_context(),
- _abort);
+if (!blk_in_drain(dataplane->blk)) {
+xen_block_dataplane_detach(dataplane);
 }
+
+aio_context_acquire(dataplane->ctx);
 /* Xen doesn't have multiple users for nodes, so this can't fail */
 blk_set_aio_context(dataplane->blk, qemu_get_aio_context(), _abort);
 aio_context_release(dataplane->ctx);
@@ -819,11 +841,9 @@ void xen_block_dataplane_start(XenBlockDataPlane 
*dataplane,
 blk_set_aio_context(dataplane->blk, dataplane->ctx, NULL);
 aio_context_release(old_context);
 
-/* Only reason for failure is a NULL channel */
-aio_context_acquire(dataplane->ctx);
-xen_device_set_event_channel_context(xendev, dataplane->event_channel,
- dataplane->ctx, _abort);
-aio_context_release(dataplane->ctx);
+if (!blk_in_drain(dataplane->blk)) {
+xen_block_dataplane_attach(dataplane);
+}
 
 return;
 
diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c
index f5a744589d..f099914831 100644
--- a/hw/block/xen-block.c
+++ b/hw/block/xen-block.c
@@ -189,8 +189,26 @@ static void xen_block_resize_cb(void *opaque)
 xen_device_backend_printf(xendev, "state", "%u", state);
 }
 
+/* Suspend request handling */
+static void xen_block_drained_begin(void *opaque)
+{
+XenBlockDevice *blockdev = opaque;
+
+xen_block_dataplane_detach(blockdev->dataplane);
+}
+
+/* Resume request handling */
+static void xen_block_drained_end(void *opaque)