From: Stefan Hajnoczi <stefanha@gmail.com>
To: Kevin Wolf <kwolf@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
qemu-devel@nongnu.org, famz@redhat.com, qemu-block@nongnu.org
Subject: Re: [Qemu-devel] [Qemu-block] [PATCH 1/4] block: Expect graph changes in bdrv_parent_drained_begin/end
Date: Fri, 1 Dec 2017 10:13:21 +0000 [thread overview]
Message-ID: <20171201101321.GG23501@stefanha-x1.localdomain> (raw)
In-Reply-To: <20171129135528.GD3753@localhost.localdomain>
[-- Attachment #1: Type: text/plain, Size: 3769 bytes --]
On Wed, Nov 29, 2017 at 02:55:28PM +0100, Kevin Wolf wrote:
> Am 29.11.2017 um 14:44 hat Stefan Hajnoczi geschrieben:
> > On Wed, Nov 29, 2017 at 11:25:10AM +0100, Paolo Bonzini wrote:
> > > From: Kevin Wolf <kwolf@redhat.com>
> > >
> > > The .drained_begin/end callbacks can (directly or indirectly via
> > > aio_poll()) cause block nodes to be removed or the current BdrvChild to
> > > point to a different child node.
> > >
> > > Use QLIST_FOREACH_SAFE() to make sure we don't access invalid
> > > BlockDriverStates or accidentally continue iterating the parents of the
> > > new child node instead of the node we actually came from.
> > >
> > > Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> > > Tested-by: Jeff Cody <jcody@redhat.com>
> > > Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
> > > Reviewed-by: Jeff Cody <jcody@redhat.com>
> > > ---
> > > block/io.c | 8 ++++----
> > > 1 file changed, 4 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/block/io.c b/block/io.c
> > > index 4fdf93a014..6773926fc1 100644
> > > --- a/block/io.c
> > > +++ b/block/io.c
> > > @@ -42,9 +42,9 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
> > >
> > > void bdrv_parent_drained_begin(BlockDriverState *bs)
> > > {
> > > - BdrvChild *c;
> > > + BdrvChild *c, *next;
> > >
> > > - QLIST_FOREACH(c, &bs->parents, next_parent) {
> > > + QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) {
> > > if (c->role->drained_begin) {
> > > c->role->drained_begin(c);
> > > }
> > > @@ -53,9 +53,9 @@ void bdrv_parent_drained_begin(BlockDriverState *bs)
> > >
> > > void bdrv_parent_drained_end(BlockDriverState *bs)
> > > {
> > > - BdrvChild *c;
> > > + BdrvChild *c, *next;
> > >
> > > - QLIST_FOREACH(c, &bs->parents, next_parent) {
> > > + QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) {
> > > if (c->role->drained_end) {
> > > c->role->drained_end(c);
> > > }
> >
> > Hmm...not sure if this patch is enough.
>
> Depends on what you have in mind, but generally, no, it's certainly not
> enough to fix all bad things that can happen during drain...
>
> > Thinking about this more, if this sub-graph changes then
> > .drained_begin() callbacks are not necessarily paired with
> > .drained_end() callbacks.
> >
> > In other words, all of the following are possible:
> >
> > 1. Only .drained_begin() is called
> > 2. .drained_begin() is called, then .drained_end()
> > 3. Only .drained_end() is called
>
> bdrv_replace_child_noperm() makes sure to call .drained_end() and
> .drained_begin() depending on whether the old and new child node are
> currently drained. So I think this might actually work.
>
> > It makes me wonder if we need to either:
> >
> > Take references and ensure .drained_end() gets called if and only if
> > .drained_begin() was also called.
> >
> > OR
> >
> > Document that .drained_begin/end() calls may not be paired and audit
> > existing code to check that this is safe.
>
> How would the latter even possibly work? If the .drained_end is missing,
> the parent would never know that it can send new requests again. A
> missing .drained_begin could be ignored in the .drained_end callback,
> but it wouldn't be safe because the parent wouldn't actually stop to
> send new requests.
Yesterday I looked at a similar issue in Fam's new RFC that moves
.drained_begin()/.drained_end() to AioContext. I came to the conclusion
that while it's easy to implement unmatched begin/end calls (as we do
today) it's not possible to get useful semantics out of them :). So we
have to ensure the the begin/end calls match.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]
next prev parent reply other threads:[~2017-12-01 15:44 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-11-29 10:25 [Qemu-devel] [PATCH 0/4] blockjob: reinstate busy=false/busy=true in block_job_sleep_ns Paolo Bonzini
2017-11-29 10:25 ` [Qemu-devel] [PATCH 1/4] block: Expect graph changes in bdrv_parent_drained_begin/end Paolo Bonzini
2017-11-29 12:27 ` [Qemu-devel] [Qemu-block] " Alberto Garcia
2017-11-29 13:44 ` Stefan Hajnoczi
2017-11-29 13:55 ` Kevin Wolf
2017-12-01 10:13 ` Stefan Hajnoczi [this message]
2017-11-29 10:25 ` [Qemu-devel] [PATCH 2/4] blockjob: remove clock argument from block_job_sleep_ns Paolo Bonzini
2017-11-29 12:45 ` [Qemu-devel] [Qemu-block] " Alberto Garcia
2017-11-29 13:14 ` [Qemu-devel] " Jeff Cody
2017-11-29 13:55 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi
2017-11-29 10:25 ` [Qemu-devel] [PATCH 3/4] blockjob: introduce block_job_do_yield Paolo Bonzini
2017-11-29 13:30 ` Jeff Cody
2017-11-29 13:55 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi
2017-11-29 10:25 ` [Qemu-devel] [PATCH 4/4] blockjob: reimplement block_job_sleep_ns to allow cancellation Paolo Bonzini
2017-11-29 12:54 ` Kevin Wolf
2017-11-29 13:52 ` Jeff Cody
2017-11-29 13:56 ` Jeff Cody
2017-11-29 14:21 ` Kevin Wolf
2017-11-29 14:25 ` Jeff Cody
2017-11-29 14:07 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi
2017-11-29 21:12 ` [Qemu-devel] " Eric Blake
2017-11-29 13:13 ` [Qemu-devel] [PATCH 0/4] blockjob: reinstate busy=false/busy=true in block_job_sleep_ns Jeff Cody
2017-11-29 13:14 ` Fam Zheng
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=20171201101321.GG23501@stefanha-x1.localdomain \
--to=stefanha@gmail.com \
--cc=famz@redhat.com \
--cc=kwolf@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).