From: Stefan Hajnoczi <stefanha@redhat.com>
To: Kevin Wolf <kwolf@redhat.com>
Cc: qemu-devel@nongnu.org, "Daniel P. Berrangé" <berrange@redhat.com>,
"Juan Quintela" <quintela@redhat.com>,
"Julia Suvorova" <jusual@redhat.com>,
xen-devel@lists.xenproject.org, eesposit@redhat.com,
"Richard Henderson" <richard.henderson@linaro.org>,
"Fam Zheng" <fam@euphon.net>,
"Michael S. Tsirkin" <mst@redhat.com>,
"Coiby Xu" <Coiby.Xu@gmail.com>,
"David Woodhouse" <dwmw2@infradead.org>,
"Marcel Apfelbaum" <marcel.apfelbaum@gmail.com>,
"Peter Lieven" <pl@kamp.de>, "Paul Durrant" <paul@xen.org>,
"Richard W.M. Jones" <rjones@redhat.com>,
qemu-block@nongnu.org, "Stefano Garzarella" <sgarzare@redhat.com>,
"Anthony Perard" <anthony.perard@citrix.com>,
"Stefan Weil" <sw@weilnetz.de>,
"Xie Yongji" <xieyongji@bytedance.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Aarushi Mehta" <mehta.aaru20@gmail.com>,
"Philippe Mathieu-Daudé" <philmd@linaro.org>,
"Eduardo Habkost" <eduardo@habkost.net>,
"Stefano Stabellini" <sstabellini@kernel.org>,
"Hanna Reitz" <hreitz@redhat.com>,
"Ronnie Sahlberg" <ronniesahlberg@gmail.com>
Subject: Re: [PATCH v4 06/20] block/export: wait for vhost-user-blk requests when draining
Date: Tue, 2 May 2023 15:40:45 -0400 [thread overview]
Message-ID: <20230502194045.GC535070@fedora> (raw)
In-Reply-To: <ZFEve2GfI0TqsItA@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 6898 bytes --]
On Tue, May 02, 2023 at 05:42:51PM +0200, Kevin Wolf wrote:
> Am 25.04.2023 um 19:27 hat Stefan Hajnoczi geschrieben:
> > Each vhost-user-blk request runs in a coroutine. When the BlockBackend
> > enters a drained section we need to enter a quiescent state. Currently
> > any in-flight requests race with bdrv_drained_begin() because it is
> > unaware of vhost-user-blk requests.
> >
> > When blk_co_preadv/pwritev()/etc returns it wakes the
> > bdrv_drained_begin() thread but vhost-user-blk request processing has
> > not yet finished. The request coroutine continues executing while the
> > main loop thread thinks it is in a drained section.
> >
> > One example where this is unsafe is for blk_set_aio_context() where
> > bdrv_drained_begin() is called before .aio_context_detached() and
> > .aio_context_attach(). If request coroutines are still running after
> > bdrv_drained_begin(), then the AioContext could change underneath them
> > and they race with new requests processed in the new AioContext. This
> > could lead to virtqueue corruption, for example.
> >
> > (This example is theoretical, I came across this while reading the
> > code and have not tried to reproduce it.)
> >
> > It's easy to make bdrv_drained_begin() wait for in-flight requests: add
> > a .drained_poll() callback that checks the VuServer's in-flight counter.
> > VuServer just needs an API that returns true when there are requests in
> > flight. The in-flight counter needs to be atomic.
> >
> > Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> > ---
> > include/qemu/vhost-user-server.h | 4 +++-
> > block/export/vhost-user-blk-server.c | 16 ++++++++++++++++
> > util/vhost-user-server.c | 14 ++++++++++----
> > 3 files changed, 29 insertions(+), 5 deletions(-)
> >
> > diff --git a/include/qemu/vhost-user-server.h b/include/qemu/vhost-user-server.h
> > index bc0ac9ddb6..b1c1cda886 100644
> > --- a/include/qemu/vhost-user-server.h
> > +++ b/include/qemu/vhost-user-server.h
> > @@ -40,8 +40,9 @@ typedef struct {
> > int max_queues;
> > const VuDevIface *vu_iface;
> >
> > + unsigned int in_flight; /* atomic */
> > +
> > /* Protected by ctx lock */
> > - unsigned int in_flight;
> > bool wait_idle;
> > VuDev vu_dev;
> > QIOChannel *ioc; /* The I/O channel with the client */
> > @@ -62,6 +63,7 @@ void vhost_user_server_stop(VuServer *server);
> >
> > void vhost_user_server_inc_in_flight(VuServer *server);
> > void vhost_user_server_dec_in_flight(VuServer *server);
> > +bool vhost_user_server_has_in_flight(VuServer *server);
> >
> > void vhost_user_server_attach_aio_context(VuServer *server, AioContext *ctx);
> > void vhost_user_server_detach_aio_context(VuServer *server);
> > diff --git a/block/export/vhost-user-blk-server.c b/block/export/vhost-user-blk-server.c
> > index 841acb36e3..092b86aae4 100644
> > --- a/block/export/vhost-user-blk-server.c
> > +++ b/block/export/vhost-user-blk-server.c
> > @@ -272,7 +272,20 @@ static void vu_blk_exp_resize(void *opaque)
> > vu_config_change_msg(&vexp->vu_server.vu_dev);
> > }
> >
> > +/*
> > + * Ensures that bdrv_drained_begin() waits until in-flight requests complete.
> > + *
> > + * Called with vexp->export.ctx acquired.
> > + */
> > +static bool vu_blk_drained_poll(void *opaque)
> > +{
> > + VuBlkExport *vexp = opaque;
> > +
> > + return vhost_user_server_has_in_flight(&vexp->vu_server);
> > +}
> > +
> > static const BlockDevOps vu_blk_dev_ops = {
> > + .drained_poll = vu_blk_drained_poll,
> > .resize_cb = vu_blk_exp_resize,
> > };
>
> You're adding a new function pointer to an existing BlockDevOps...
>
> > @@ -314,6 +327,7 @@ static int vu_blk_exp_create(BlockExport *exp, BlockExportOptions *opts,
> > vu_blk_initialize_config(blk_bs(exp->blk), &vexp->blkcfg,
> > logical_block_size, num_queues);
> >
> > + blk_set_dev_ops(exp->blk, &vu_blk_dev_ops, vexp);
> > blk_add_aio_context_notifier(exp->blk, blk_aio_attached, blk_aio_detach,
> > vexp);
> >
> > blk_set_dev_ops(exp->blk, &vu_blk_dev_ops, vexp);
>
> ..but still add a second blk_set_dev_ops(). Maybe a bad merge conflict
> resolution with commit ca858a5fe94?
Thanks, I probably didn't have ca858a5fe94 in my tree when writing this
code.
> > @@ -323,6 +337,7 @@ static int vu_blk_exp_create(BlockExport *exp, BlockExportOptions *opts,
> > num_queues, &vu_blk_iface, errp)) {
> > blk_remove_aio_context_notifier(exp->blk, blk_aio_attached,
> > blk_aio_detach, vexp);
> > + blk_set_dev_ops(exp->blk, NULL, NULL);
> > g_free(vexp->handler.serial);
> > return -EADDRNOTAVAIL;
> > }
> > @@ -336,6 +351,7 @@ static void vu_blk_exp_delete(BlockExport *exp)
> >
> > blk_remove_aio_context_notifier(exp->blk, blk_aio_attached, blk_aio_detach,
> > vexp);
> > + blk_set_dev_ops(exp->blk, NULL, NULL);
> > g_free(vexp->handler.serial);
> > }
>
> These two hunks are then probably already fixes for ca858a5fe94 and
> should be a separate patch if so.
Sure, I can split them out.
hw/ doesn't need to call blk_set_dev_ops(blk, NULL, NULL) because
hw/core/qdev-properties-system.c:release_drive() -> blk_detach_dev()
does it automatically, but block/export does. It's easy to overlook and
that's probably why ca858a5fe94 didn't include it.
> > diff --git a/util/vhost-user-server.c b/util/vhost-user-server.c
> > index 1622f8cfb3..2e6b640050 100644
> > --- a/util/vhost-user-server.c
> > +++ b/util/vhost-user-server.c
> > @@ -78,17 +78,23 @@ static void panic_cb(VuDev *vu_dev, const char *buf)
> > void vhost_user_server_inc_in_flight(VuServer *server)
> > {
> > assert(!server->wait_idle);
> > - server->in_flight++;
> > + qatomic_inc(&server->in_flight);
> > }
> >
> > void vhost_user_server_dec_in_flight(VuServer *server)
> > {
> > - server->in_flight--;
> > - if (server->wait_idle && !server->in_flight) {
> > - aio_co_wake(server->co_trip);
> > + if (qatomic_fetch_dec(&server->in_flight) == 1) {
> > + if (server->wait_idle) {
> > + aio_co_wake(server->co_trip);
> > + }
> > }
> > }
> >
> > +bool vhost_user_server_has_in_flight(VuServer *server)
> > +{
> > + return qatomic_load_acquire(&server->in_flight) > 0;
> > +}
> > +
>
> Any reason why you left the server->in_flight accesses in
> vu_client_trip() non-atomic?
I don't remember if it was a mistake or if there is a reason why it's
safe. I'll replace those accesses with calls to
vhost_user_server_has_in_flight().
Stefan
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
next prev parent reply other threads:[~2023-05-02 19:41 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-04-25 17:26 [PATCH v4 00/20] block: remove aio_disable_external() API Stefan Hajnoczi
2023-04-25 17:26 ` [PATCH v4 01/20] block-backend: split blk_do_set_aio_context() Stefan Hajnoczi
2023-04-25 17:26 ` [PATCH v4 02/20] hw/qdev: introduce qdev_is_realized() helper Stefan Hajnoczi
2023-04-25 17:26 ` [PATCH v4 03/20] virtio-scsi: avoid race between unplug and transport event Stefan Hajnoczi
2023-05-02 15:19 ` Kevin Wolf
2023-05-02 18:56 ` Stefan Hajnoczi
2023-05-03 8:00 ` Kevin Wolf
2023-05-03 13:12 ` Stefan Hajnoczi
2023-04-25 17:27 ` [PATCH v4 04/20] virtio-scsi: stop using aio_disable_external() during unplug Stefan Hajnoczi
2023-04-28 14:22 ` Kevin Wolf
2023-05-01 15:09 ` Stefan Hajnoczi
2023-05-02 13:19 ` Kevin Wolf
2023-05-02 20:02 ` Stefan Hajnoczi
2023-05-03 11:40 ` Kevin Wolf
2023-05-03 13:05 ` Stefan Hajnoczi
2023-04-25 17:27 ` [PATCH v4 05/20] util/vhost-user-server: rename refcount to in_flight counter Stefan Hajnoczi
2023-04-25 17:27 ` [PATCH v4 06/20] block/export: wait for vhost-user-blk requests when draining Stefan Hajnoczi
2023-05-02 15:42 ` Kevin Wolf
2023-05-02 19:40 ` Stefan Hajnoczi [this message]
2023-04-25 17:27 ` [PATCH v4 07/20] block/export: stop using is_external in vhost-user-blk server Stefan Hajnoczi
2023-05-02 16:04 ` Kevin Wolf
2023-05-02 20:06 ` Stefan Hajnoczi
2023-05-03 8:08 ` Kevin Wolf
2023-05-03 13:11 ` Stefan Hajnoczi
2023-05-03 13:43 ` Kevin Wolf
2023-04-25 17:27 ` [PATCH v4 08/20] hw/xen: do not use aio_set_fd_handler(is_external=true) in xen_xenstore Stefan Hajnoczi
2023-04-25 17:27 ` [PATCH v4 09/20] block: add blk_in_drain() API Stefan Hajnoczi
2023-04-25 17:27 ` [PATCH v4 10/20] block: drain from main loop thread in bdrv_co_yield_to_drain() Stefan Hajnoczi
2023-05-02 16:21 ` Kevin Wolf
2023-05-02 20:10 ` Stefan Hajnoczi
2023-04-25 17:27 ` [PATCH v4 11/20] xen-block: implement BlockDevOps->drained_begin() Stefan Hajnoczi
2023-04-25 17:27 ` [PATCH v4 12/20] hw/xen: do not set is_external=true on evtchn fds Stefan Hajnoczi
2023-04-25 17:27 ` [PATCH v4 13/20] block/export: rewrite vduse-blk drain code Stefan Hajnoczi
2023-04-25 17:27 ` [PATCH v4 14/20] block/export: don't require AioContext lock around blk_exp_ref/unref() Stefan Hajnoczi
2023-04-25 17:27 ` [PATCH v4 15/20] block/fuse: do not set is_external=true on FUSE fd Stefan Hajnoczi
2023-04-25 17:27 ` [PATCH v4 16/20] virtio: make it possible to detach host notifier from any thread Stefan Hajnoczi
2023-05-04 21:00 ` Kevin Wolf
2023-05-10 21:40 ` Stefan Hajnoczi
2023-04-25 17:27 ` [PATCH v4 17/20] virtio-blk: implement BlockDevOps->drained_begin() Stefan Hajnoczi
2023-05-04 21:13 ` Kevin Wolf
2023-05-11 20:54 ` Stefan Hajnoczi
2023-05-11 21:22 ` Stefan Hajnoczi
2023-04-25 17:27 ` [PATCH v4 18/20] virtio-scsi: " Stefan Hajnoczi
2023-05-04 21:25 ` Kevin Wolf
2023-04-25 17:27 ` [PATCH v4 19/20] virtio: do not set is_external=true on host notifiers Stefan Hajnoczi
2023-04-25 17:27 ` [PATCH v4 20/20] aio: remove aio_disable_external() API Stefan Hajnoczi
2023-05-04 21:34 ` Kevin Wolf
2023-05-11 21:24 ` Stefan Hajnoczi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230502194045.GC535070@fedora \
--to=stefanha@redhat.com \
--cc=Coiby.Xu@gmail.com \
--cc=anthony.perard@citrix.com \
--cc=berrange@redhat.com \
--cc=dwmw2@infradead.org \
--cc=eduardo@habkost.net \
--cc=eesposit@redhat.com \
--cc=fam@euphon.net \
--cc=hreitz@redhat.com \
--cc=jusual@redhat.com \
--cc=kwolf@redhat.com \
--cc=marcel.apfelbaum@gmail.com \
--cc=mehta.aaru20@gmail.com \
--cc=mst@redhat.com \
--cc=paul@xen.org \
--cc=pbonzini@redhat.com \
--cc=philmd@linaro.org \
--cc=pl@kamp.de \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=quintela@redhat.com \
--cc=richard.henderson@linaro.org \
--cc=rjones@redhat.com \
--cc=ronniesahlberg@gmail.com \
--cc=sgarzare@redhat.com \
--cc=sstabellini@kernel.org \
--cc=sw@weilnetz.de \
--cc=xen-devel@lists.xenproject.org \
--cc=xieyongji@bytedance.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.