All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: Alberto Garcia <berto@igalia.com>
Cc: Max Reitz <mreitz@redhat.com>,
	qemu-devel@nongnu.org, qemu-block@nongnu.org,
	Eric Blake <eblake@redhat.com>,
	Stefan Hajnoczi <stefanha@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v9 07/11] block: Add QMP support for streaming to an intermediate layer
Date: Thu, 12 May 2016 17:28:34 +0200	[thread overview]
Message-ID: <20160512152834.GG4794@noname.redhat.com> (raw)
In-Reply-To: <w514ma3nwbl.fsf@maestria.local.igalia.com>

Am 12.05.2016 um 17:13 hat Alberto Garcia geschrieben:
> On Thu 12 May 2016 05:04:51 PM CEST, Kevin Wolf wrote:
> > Am 12.05.2016 um 15:47 hat Alberto Garcia geschrieben:
> >> On Tue 03 May 2016 03:48:47 PM CEST, Kevin Wolf wrote:
> >> > Am 03.05.2016 um 15:33 hat Alberto Garcia geschrieben:
> >> >> On Tue 03 May 2016 03:23:24 PM CEST, Kevin Wolf wrote:
> >> >> >> c) we fix bdrv_reopen() so we can actually run both jobs at the same
> >> >> >>    time. I'm wondering if pausing all block jobs between
> >> >> >>    bdrv_reopen_prepare() and bdrv_reopen_commit() would do the
> >> >> >>    trick. Opinions?
> >> >> >
> >> >> > I would have to read up the details of the problem again, but I think
> >> >> > with bdrv_drained_begin/end() we actually have the right tool now to fix
> >> >> > it properly. We may need to pull up the drain (bdrv_drain_all() today)
> >> >> > from bdrv_reopen_multiple() to its caller and just assert it in the
> >> >> > function itself, but there shouldn't be much more to it than that.
> >> >> 
> >> >> I think that's not enough, see point 2) here:
> >> >> 
> >> >> https://lists.gnu.org/archive/html/qemu-block/2015-12/msg00180.html
> >> >> 
> >> >>   "I've been taking a look at the bdrv_drained_begin/end() API, but as I
> >> >>    understand it it prevents requests from a different AioContext.
> >> >>    Since all BDS in the same chain share the same context it does not
> >> >>    really help here."
> >> >
> >> > Yes, that's the part I meant with pulling up the calls.
> >> >
> >> > If I understand correctly, the problem is that first bdrv_reopen_queue()
> >> > queues a few BDSes for reopen, then bdrv_drain_all() completes all
> >> > running requests and can indirectly trigger a graph modification, and
> >> > then bdrv_reopen_multiple() uses the queue which doesn't match reality
> >> > any more.
> >> >
> >> > The solution to that should be simply changing the order of things:
> >> >
> >> > 1. bdrv_drained_begin()
> >> > 2. bdrv_reopen_queue()
> >> > 3. bdrv_reopen_multiple()
> >> >     * Instead of bdrv_drain_all(), assert that no requests are pending
> >> >     * We don't run requests, so we can't complete a block job and
> >> >       manipulate the graph any more
> >> > 4. then bdrv_drained_end()
> >> 
> >> This doesn't work. Here's what happens:
> >> 
> >> 1) Block job (a) starts (block-stream).
> >> 
> >> 2) Block job (b) starts (block-stream, or block-commit).
> >> 
> >> 3) job (b) calls bdrv_reopen() and does the drain call.
> >> 
> >> 4) job (b) creates reopen_queue and calls bdrv_reopen_multiple().
> >>    There are no pending requests at this point, but job (a) is sleeping.
> >> 
> >> 5) bdrv_reopen_multiple() iterates over reopen_queue and calls
> >>    bdrv_reopen_prepare() -> bdrv_flush() -> bdrv_co_flush() ->
> >>    qemu_coroutine_yield().
> >
> > I think between here and the next step is what I don't understand.
> >
> > bdrv_reopen_multiple() is not called in coroutine context, right? All
> > block jobs use block_job_defer_to_main_loop() before they call
> > bdrv_reopen(), as far as I can see. So bdrv_flush() shouldn't take the
> > shortcut, but use a nested event loop.
> 
> When bdrv_flush() is not called in coroutine context it does
> qemu_coroutine_create() + qemu_coroutine_enter().

Right, but if the coroutine yields, we jump back to the caller, which
looks like this:

    co = qemu_coroutine_create(bdrv_flush_co_entry);
    qemu_coroutine_enter(co, &rwco);
    while (rwco.ret == NOT_DONE) {
        aio_poll(aio_context, true);
    }

So this loops until the flush has completed. The only way I can see how
something else (job (a)) can run is if aio_poll() calls it.

> > What is it that calls into job (a) from that event loop? It can't be a
> > request completion because we already drained all requests. Is it a
> > timer?
> 
> If I didn't get it wrong it's this bit in bdrv_co_flush()
> [...]

That's the place that yields from (b), but it's not the place that calls
into (a).

> >> 6) job (a) resumes, finishes the job and removes nodes from the graph.
> >> 
> >> 7) job (b) continues with bdrv_reopen_multiple() but now reopen_queue
> >>    contains invalid pointers.
> >
> > I don't fully understand the problem yet, but as a shot in the dark,
> > would pausing block jobs in bdrv_drained_begin() help?
> 
> Yeah, my impression is that pausing all jobs during bdrv_reopen() should
> be enough.

If you base your patches on top of my queue (which I think you already
do for the greatest part), the nicest way to implement this would
probably be that BlockBackends give their users a callback for
.drained_begin/end and the jobs implement that as pausing themselves.

We could, of course, directly pause block jobs in bdrv_drained_begin(),
but that would feel a bit hackish. So maybe do that for a quick attempt
whether it helps, and if it does, we can write the real thing then.

Kevin

  parent reply	other threads:[~2016-05-12 15:28 UTC|newest]

Thread overview: 56+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-04 13:43 [Qemu-devel] [PATCH for-2.7 v9 00/11] Support streaming to an intermediate layer Alberto Garcia
2016-04-04 13:43 ` [Qemu-devel] [PATCH v9 01/11] block: keep a list of block jobs Alberto Garcia
2016-04-27 11:59   ` Max Reitz
2016-04-29 14:22   ` Kevin Wolf
2016-04-04 13:43 ` [Qemu-devel] [PATCH v9 02/11] block: use the block job list in bdrv_drain_all() Alberto Garcia
2016-04-27 12:04   ` Max Reitz
2016-04-27 12:08     ` Alberto Garcia
2016-04-29 14:25   ` Kevin Wolf
2016-04-04 13:43 ` [Qemu-devel] [PATCH v9 03/11] block: use the block job list in qmp_query_block_jobs() Alberto Garcia
2016-04-27 12:09   ` Max Reitz
2016-04-29 14:32   ` Kevin Wolf
2016-05-02 13:06     ` Alberto Garcia
2016-04-04 13:43 ` [Qemu-devel] [PATCH v9 04/11] block: use the block job list in bdrv_close() Alberto Garcia
2016-04-27 12:14   ` Max Reitz
2016-04-29 14:38   ` Kevin Wolf
2016-05-02 13:42     ` Alberto Garcia
2016-04-04 13:43 ` [Qemu-devel] [PATCH v9 05/11] block: allow block jobs in any arbitrary node Alberto Garcia
2016-04-27 12:30   ` Max Reitz
2016-04-27 14:59     ` Alberto Garcia
2016-04-29 15:00   ` Kevin Wolf
2016-05-06 10:00     ` Alberto Garcia
2016-05-06 17:54       ` John Snow
2016-05-09  7:06         ` Kevin Wolf
2016-05-09 11:59         ` Alberto Garcia
2016-04-29 15:25   ` Eric Blake
2016-04-04 13:43 ` [Qemu-devel] [PATCH v9 06/11] block: Support streaming to an intermediate layer Alberto Garcia
2016-04-27 13:04   ` Max Reitz
2016-04-28  9:23     ` Alberto Garcia
2016-04-29 15:07   ` Kevin Wolf
2016-04-04 13:43 ` [Qemu-devel] [PATCH v9 07/11] block: Add QMP support for " Alberto Garcia
2016-04-27 13:34   ` Max Reitz
2016-04-28 12:20     ` Alberto Garcia
2016-04-29 15:18       ` Kevin Wolf
2016-05-03 12:50         ` Alberto Garcia
2016-05-03 13:23           ` Kevin Wolf
2016-05-03 13:33             ` Alberto Garcia
2016-05-03 13:48               ` Kevin Wolf
2016-05-03 15:09                 ` Alberto Garcia
     [not found]                 ` <w517fezo0al.fsf@maestria.local.igalia.com>
2016-05-12 15:04                   ` Kevin Wolf
     [not found]                     ` <w514ma3nwbl.fsf@maestria.local.igalia.com>
2016-05-12 15:28                       ` Kevin Wolf [this message]
2016-05-17 14:26                         ` Alberto Garcia
2016-05-17 14:47                           ` Kevin Wolf
2016-05-17 14:54                             ` Alberto Garcia
2016-04-29 15:11   ` Kevin Wolf
2016-05-03 12:53     ` Alberto Garcia
2016-05-03 13:18       ` Kevin Wolf
2016-05-03 13:29         ` Alberto Garcia
2016-04-29 15:29   ` Eric Blake
2016-04-04 13:43 ` [Qemu-devel] [PATCH v9 08/11] docs: Document how to stream " Alberto Garcia
2016-04-04 13:43 ` [Qemu-devel] [PATCH v9 09/11] qemu-iotests: test streaming " Alberto Garcia
2016-04-04 13:44 ` [Qemu-devel] [PATCH v9 10/11] qemu-iotests: test overlapping block-stream operations Alberto Garcia
2016-04-27 13:48   ` Max Reitz
2016-04-27 15:02     ` Alberto Garcia
2016-04-04 13:44 ` [Qemu-devel] [PATCH v9 11/11] qemu-iotests: test non-overlapping " Alberto Garcia
2016-04-27 13:50   ` Max Reitz
2016-04-08 10:00 ` [Qemu-devel] [PATCH for-2.7 v9 00/11] Support streaming to an intermediate layer 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=20160512152834.GG4794@noname.redhat.com \
    --to=kwolf@redhat.com \
    --cc=berto@igalia.com \
    --cc=eblake@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.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.