From: Peter Xu <peterx@redhat.com>
To: Markus Armbruster <armbru@redhat.com>
Cc: qemu-devel@nongnu.org, "Marc-André Lureau" <marcandre.lureau@redhat.com>
Subject: Re: [Qemu-devel] monitor: enable OOB by default
Date: Thu, 19 Jul 2018 21:00:30 +0800 [thread overview]
Message-ID: <20180719130030.GL4071@xz-mi> (raw)
In-Reply-To: <87d0vkh996.fsf@dusky.pond.sub.org>
On Wed, Jul 18, 2018 at 05:08:21PM +0200, Markus Armbruster wrote:
> Marc-André, one question for you inline. Search for your name.
>
> Peter Xu <peterx@redhat.com> writes:
>
> > On Thu, Jun 28, 2018 at 03:20:41PM +0200, Markus Armbruster wrote:
> >> Peter Xu <peterx@redhat.com> writes:
> >>
> >> > On Wed, Jun 27, 2018 at 03:13:57PM +0200, Markus Armbruster wrote:
> >> >> Monitor behavior changes even when the client rejects capability "oob".
> >> >>
> >> >> Traditionally, the monitor reads, executes and responds to one command
> >> >> after the other. If the client sends in-band commands faster than the
> >> >> server can execute them, the kernel will eventually refuse to buffer
> >> >> more, and sending blocks or fails with EAGAIN.
> >> >>
> >> >> To make OOB possible, we need to read and queue commands as we receive
> >> >> them. If the client sends in-band commands faster than the server can
> >> >> execute them, the server will eventually drop commands to limit the
> >> >> queue length. The sever sends event COMMAND_DROPPED then.
> >> >>
> >> >> However, we get the new behavior even when the client rejects capability
> >> >> "oob". We get the traditional behavior only when the server doesn't
> >> >> offer "oob".
> >> >>
> >> >> Is this what we want?
> >> >
> >> > Not really. But I thought we kept that old behavior, haven't we?
> >> >
> >> > In handle_qmp_command() we have this:
> >> >
> >> > /*
> >> > * If OOB is not enabled on the current monitor, we'll emulate the
> >> > * old behavior that we won't process the current monitor any more
> >> > * until it has responded. This helps make sure that as long as
> >> > * OOB is not enabled, the server will never drop any command.
> >> > */
> >> > if (!qmp_oob_enabled(mon)) {
> >> > monitor_suspend(mon);
> >> > req_obj->need_resume = true;
> >> > } else {
> >> > /* Drop the request if queue is full. */
> >> > if (mon->qmp.qmp_requests->length >= QMP_REQ_QUEUE_LEN_MAX) {
> >> > qemu_mutex_unlock(&mon->qmp.qmp_queue_lock);
> >> > qapi_event_send_command_dropped(id,
> >> > COMMAND_DROP_REASON_QUEUE_FULL,
> >> > &error_abort);
> >> > qmp_request_free(req_obj);
> >> > return;
> >> > }
> >> > }
> >> >
> >> > Here assuming that we are not enabling OOB, then since we will suspend
> >> > the monitor when we receive one command, then monitor_can_read() later
> >> > will check with a result that "we should not read the chardev", then
> >> > it'll leave all the data in the input buffer. Then AFAIU the QMP
> >> > client that didn't enable OOB will have similar behavior as before.
> >> >
> >> > Also, we will never receive a COMMAND_DROPPED event in that legacy
> >> > mode as well since it's in the "else" block. Am I right?
> >>
> >> Hmm. Did I get confused? Let me look again.
> >>
> >> Some places check qmp_oob_enabled(), which is true when the server
> >> offered capability "oob" and the client accepted. In terms of my reply
> >> to Daniel, it distinguishes the two run time cases "OOB off" and "OOB
> >> on".
> >
> > Exactly.
> >
> >>
> >> Other places check ->use_io_thr, which is true when
> >>
> >> (flags & MONITOR_USE_CONTROL) && !CHARDEV_IS_MUX(chr)
> >>
> >> in monitor_init().
>
> ->use_io_thr is now spelled ->use_io_thread.
>
> >> One of these places is get_qmp_greeting(). It makes the server offer
> >> "oob" when ->use_io_thr. Makes sense.
> >>
> >> In terms of my reply to Daniel, ->use_io_thr distinguishes between "OOB
> >> not offered" and ("OOB offered, but rejected by client" or "OOB offered
> >> and accepted").
> >
> > Exactly.
> >
> > To be more clear, let's name the three cases (as you mentioned):
> >
> > (A) OOB not offered
> > (B) OOB offered, but rejected by client
> > (C) OOB offered, and accepted
> >
> > Then:
> >
> > (1) qmp_oob_enabled() will only be return true if (C).
> > (2) ->use_io_thr will only be true if (B) or (C).
>
> Notes on (A) to be kept in mind for the remainder of the discussion:
>
> * I don't expect (A) to occur in production
>
> (A) means the monitor has a chardev-mux backend. chardev-mux
> multiplexes multiple character backends, e.g. multiplex a monitor and
> a console on stdio. C-a c switches focus. While such multiplexing
> may be convenient for humans, it's an unnecessary complication for
> machines, which could just as well use two UNIX domain sockets and not
> have to worry about focus and escape sequences.
>
> * I do expect (A) to go away eventually
>
> (A) exists only because "not all the chardev frontends can run without
> main thread, or can run in multiple threads" [PATCH 6]. Hopefully,
> that'll be fixed eventually, so (A) can go away.
>
> Marc-André, your "[PATCH 04/12] Revert "qmp: isolate responses into io
> thread" states the "chardev write path is thread safe". What's
> missing to make chardev-mux capable of supporting OOB?
>
> >> Uses could to violate 'may use "server offered OOB" only for
> >> configuration purposes', so let's check them:
> >>
> >> * monitor_json_emitter()
>
> This is now qmp_queue_response()
>
> >> If mon->use_io_thr, push to response queue. Else emit directly.
> >>
> >> I'm afraid run time behavior differs for "OOB not offered" (emit
> >> directly) and "OOB offered by rejected" (queue).
> >
> > Yeah it's different, but logically it's the same. IMHO it's only a
> > fast path for main thread. In other word, I think it can still work
> > correctly if we remove that else clause. In that sense, it's not
> > really a "true" behavior change.
>
> Remember that (A) should not occur in production, and should go away
> eventually. Maintaining a fast path just for that feels unjustified.
>
> >> * qmp_caps_check()
> >>
> >> If !mon->use_io_thr, reject client's acceptance of "oob". Implicitly
> >> recomputing the set of offered capabilities here is less than elegant,
> >> but it's not wrong.
>
> This has been replaced by monitor_qmp_caps_reset().
>
> If mon->use_io_thread, offer OOB. Makes sense.
>
> >> * monitor_resume()
> >>
> >> If mon->use_io_thr(), kick the monitor I/O thread.
> >>
> >> Again, different behavior for the two variations of "OOB off".
> >
> > This is another example like above - IMHO we can just kick it no
> > matter what, but we just don't need to do that for main thread (since
> > we are in main thread so we are sure it is not asleep). It's just
> > another trivial enhancement on top of the main logic.
>
> Again, maintaining a special case just for (A) feels unjustified.
>
> >> * get_qmp_greeting()
> >>
> >> Covered above, looks good to me.
>
> Also replaced by monitor_qmp_caps_reset().
>
> >> * monitor_qmp_setup_handlers_bh()
> >>
> >> If mon->use_io_thr(), pass the monitor I/O thread's AIOContext to
> >> qemu_chr_fe_set_handlers(), else pass NULL.
> >>
> >> Again, different behavior for the two variations of "OOB off".
> >
> > This is different indeed, but IMHO it's not really "behavior
> > difference", it's just the context (thread to run the code) that is
> > different. The major code path for case (A) and (B) (which are the
> > two "off" cases) should be the same (when I say "major", I excluded
> > those trivial enhancements that I mentioned).
>
> As far as I can tell, monitor_qmp_setup_handlers_bh() can run only if
> scheduled by monitor_init() when mon->use_io_thread. If that's true,
> then the !mon->use_io_thread case is unreachable. Ah, I see you've also
> noticed that, and you're proposing a patch below.
Yeah, and...
>
> >> * monitor_init()
> >>
> >> If mon->use_io_thr, set up bottom half
> >> monitor_qmp_setup_handlers_bh(), else call qemu_chr_fe_set_handlers()
> >> directly.
> >
> > This is indeed a bit tricky (to avoid a potential race that Stefan has
> > pointed out), however after things are setup it'll be exactly the same
> > code path for both OFF cases.
> >
> > And actually when I read the code I noticed that we can actually
> > simplify the code with this:
> >
> > diff --git a/monitor.c b/monitor.c
> > index 0730a27172..5d6bff8d51 100644
> > --- a/monitor.c
> > +++ b/monitor.c
> > @@ -4635,18 +4635,14 @@ static void monitor_qmp_setup_handlers_bh(void *opaque)
> > Monitor *mon = opaque;
> > GMainContext *context;
> >
> > - if (mon->use_io_thr) {
> > - /*
> > - * When use_io_thr is set, we use the global shared dedicated
> > - * IO thread for this monitor to handle input/output.
> > - */
> > - context = monitor_get_io_context();
> > - /* We should have inited globals before reaching here. */
> > - assert(context);
> > - } else {
> > - /* The default main loop, which is the main thread */
> > - context = NULL;
> > - }
> > + assert(mon->use_io_thr);
> > + /*
> > + * When use_io_thr is set, we use the global shared dedicated
> > + * IO thread for this monitor to handle input/output.
> > + */
> > + context = monitor_get_io_context();
> > + /* We should have inited globals before reaching here. */
> > + assert(context);
> >
> > qemu_chr_fe_set_handlers(&mon->chr, monitor_can_read, monitor_qmp_read,
> > monitor_qmp_event, NULL, mon, context, true);
> >
> > Since monitor_qmp_setup_handlers_bh() will only be used for IOThread
> > case. I can post a patch for that.
>
> Yes, please.
... actually I have had that patch in my "turn-oob-on-default" series,
and even with your Reviewed-by. :)
https://patchwork.kernel.org/patch/10506173/
I suppose I'll just repost it and the series after the release.
>
> >>
> >> Again, different behavior for the two variations of "OOB off".
>
> The difference is
>
> * timing: right away for (A) vs. bottom half for (B) and (C)
>
> * context argument for qemu_chr_fe_set_handlers(): NULL, i.e. main loop
> thread for (A), monitor_get_io_context(), i.e. the I/O thread for (B)
> and (C)
>
> Okay, I think.
>
> >> Either I am confused now, or the two variations of "OOB off" execute
> >> different code at run time. Which is it?
> >
> > As mentioned, they should be running the same code at run time.
> > Though with some trivial differences, but if you see above most of
> > them should only be small enhancements which can actually be removed.
>
> Please do.
>
> >> If it's different code, are the differences observable for the client?
> >
> > AFAIU since the code path should mostly be the same for the two OOF
> > cases, IMHO there should have no difference observable from the
> > client, otherwise it's buggy and I'd be willing to fix it.
> >
> >>
> >> Observable or not, I suspect the differences should not exist.
> >
> > We can remove those "trivial enhancements" if we want to make sure the
> > code paths are exactly the same, but I'm not sure whether that's
> > really what we need (or we just need to make sure it's unobservable).
>
> As long as we're running separate code for (A), "unobservable
> difference" is a proposition we need to prove.
>
> Reducing separate code should simplify the proof.
>
> Eliminiating it will simplify it maximally :)
Ok, this I can try to do too after the release.
>
> > Thanks!
>
> Thank *you* for persevering :)
I should thank you for your continuous support on out-of-band (or even
before it was proposed and named by you :).
(I hope I didn't miss anything that I should comment on; let me know
if I have)
Regards,
--
Peter Xu
next prev parent reply other threads:[~2018-07-19 13:04 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-06-20 7:32 [Qemu-devel] [PATCH v5 0/7] monitor: enable OOB by default Peter Xu
2018-06-20 7:32 ` [Qemu-devel] [PATCH v5 1/7] chardev: comment details for CLOSED event Peter Xu
2018-06-20 7:32 ` [Qemu-devel] [PATCH v5 2/7] monitor: rename *_pop_one to *_pop_any Peter Xu
2018-06-20 7:32 ` [Qemu-devel] [PATCH v5 3/7] monitor: flush qmp responses when CLOSED Peter Xu
2018-06-20 8:33 ` Markus Armbruster
2018-06-20 8:38 ` Peter Xu
2018-06-20 9:50 ` Markus Armbruster
2018-06-20 7:32 ` [Qemu-devel] [PATCH v5 4/7] tests: iotests: drop some stderr line Peter Xu
2018-06-20 8:35 ` Markus Armbruster
2018-06-20 7:32 ` [Qemu-devel] [PATCH v5 5/7] docs: mention shared state protect for OOB Peter Xu
2018-06-20 7:32 ` [Qemu-devel] [PATCH v5 6/7] monitor: remove "x-oob", turn oob on by default Peter Xu
2018-06-20 7:32 ` [Qemu-devel] [PATCH v5 7/7] Revert "tests: Add parameter to qtest_init_without_qmp_handshake" Peter Xu
2018-06-26 17:21 ` [Qemu-devel] (no subject) Markus Armbruster
2018-06-27 7:38 ` [Qemu-devel] monitor: enable OOB by default Markus Armbruster
2018-06-27 8:41 ` Markus Armbruster
2018-06-27 10:20 ` Daniel P. Berrangé
2018-06-27 11:23 ` Markus Armbruster
2018-06-27 12:07 ` Peter Xu
2018-06-27 12:37 ` Eric Blake
2018-06-28 7:04 ` Markus Armbruster
2018-06-29 7:20 ` Peter Xu
2018-06-28 6:55 ` Markus Armbruster
2018-06-28 11:43 ` Eric Blake
2018-06-29 8:18 ` Peter Xu
2018-06-27 13:13 ` Markus Armbruster
2018-06-27 13:28 ` Daniel P. Berrangé
2018-06-28 13:02 ` Markus Armbruster
2018-06-27 13:34 ` Peter Xu
2018-06-28 13:20 ` Markus Armbruster
2018-06-29 9:01 ` Peter Xu
2018-07-18 15:08 ` Markus Armbruster
2018-07-19 13:00 ` Peter Xu [this message]
2018-06-27 7:40 ` Markus Armbruster
2018-06-27 8:35 ` Markus Armbruster
2018-06-27 12:32 ` Peter Xu
2018-06-28 9:29 ` Markus Armbruster
2018-06-29 9:42 ` Peter Xu
2018-06-27 13:36 ` Peter Xu
2018-06-27 11:59 ` [Qemu-devel] your mail Peter Xu
2018-06-28 8:31 ` Markus Armbruster
2018-06-28 11:51 ` Eric Blake
2018-06-28 12:00 ` Daniel P. Berrangé
2018-06-29 9:57 ` Peter Xu
2018-06-29 15:40 ` Eric Blake
2018-07-02 5:43 ` [Qemu-devel] monitor: enable OOB by default Markus Armbruster
2018-07-04 5:44 ` Peter Xu
2018-07-04 7:03 ` Markus Armbruster
2018-06-30 16:26 ` [Qemu-devel] [PATCH v5 0/7] " Markus Armbruster
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=20180719130030.GL4071@xz-mi \
--to=peterx@redhat.com \
--cc=armbru@redhat.com \
--cc=marcandre.lureau@redhat.com \
--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).