From patchwork Tue Feb 18 15:40:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kevin Wolf X-Patchwork-Id: 11388829 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 08B411395 for ; Tue, 18 Feb 2020 15:41:36 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C37CB2176D for ; Tue, 18 Feb 2020 15:41:35 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="azjxofrt" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C37CB2176D Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:37292 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j450B-0008RB-0R for patchwork-qemu-devel@patchwork.kernel.org; Tue, 18 Feb 2020 10:41:35 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:38982) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j44zT-0006bF-De for qemu-devel@nongnu.org; Tue, 18 Feb 2020 10:40:53 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1j44zR-0001dG-DX for qemu-devel@nongnu.org; Tue, 18 Feb 2020 10:40:51 -0500 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:21601 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1j44zR-0001cm-8X for qemu-devel@nongnu.org; Tue, 18 Feb 2020 10:40:49 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1582040448; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=0fofnXmzWwoAoZLNHsCrqCblbFUzE3zF3J43i4iej00=; b=azjxofrtvG9ZwuD20bdymBetUsHN3tbBlda+711R6aD7nwodr+m3hgJzaTADhgHuGl76J9 UHIGELkZg+C8HQrJSmtpTXGJc/u6W/pbyysFy2YftpYLTYxrHGXcXhblft4wPzcYFQLdcG TIoSXJsboVrT444QE4UhzHZxa+ROvwc= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-50-VN7cczDzN_aCgKUP6-hJ0Q-1; Tue, 18 Feb 2020 10:40:46 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 64C7E800D48; Tue, 18 Feb 2020 15:40:45 +0000 (UTC) Received: from linux.fritz.box.com (ovpn-117-181.ams2.redhat.com [10.36.117.181]) by smtp.corp.redhat.com (Postfix) with ESMTP id 108F71BC6D; Tue, 18 Feb 2020 15:40:43 +0000 (UTC) From: Kevin Wolf To: qemu-devel@nongnu.org Subject: [PATCH v5 1/4] qapi: Add a 'coroutine' flag for commands Date: Tue, 18 Feb 2020 16:40:33 +0100 Message-Id: <20200218154036.28562-2-kwolf@redhat.com> In-Reply-To: <20200218154036.28562-1-kwolf@redhat.com> References: <20200218154036.28562-1-kwolf@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-MC-Unique: VN7cczDzN_aCgKUP6-hJ0Q-1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 205.139.110.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, marcandre.lureau@gmail.com, armbru@redhat.com, qemu-block@nongnu.org Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" This patch adds a new 'coroutine' flag to QMP command definitions that tells the QMP dispatcher that the command handler is safe to be run in a coroutine. The documentation of the new flag pretends that this flag is already used as intended, which it isn't yet after this patch. We'll implement this in another patch in this series. Signed-off-by: Kevin Wolf Reviewed-by: Marc-André Lureau Reviewed-by: Markus Armbruster --- docs/devel/qapi-code-gen.txt | 11 +++++++++++ include/qapi/qmp/dispatch.h | 1 + tests/test-qmp-cmds.c | 4 ++++ scripts/qapi/commands.py | 10 +++++++--- scripts/qapi/doc.py | 2 +- scripts/qapi/expr.py | 10 ++++++++-- scripts/qapi/introspect.py | 2 +- scripts/qapi/schema.py | 9 ++++++--- tests/qapi-schema/test-qapi.py | 7 ++++--- tests/Makefile.include | 1 + tests/qapi-schema/oob-coroutine.err | 2 ++ tests/qapi-schema/oob-coroutine.json | 2 ++ tests/qapi-schema/oob-coroutine.out | 0 tests/qapi-schema/qapi-schema-test.json | 1 + tests/qapi-schema/qapi-schema-test.out | 2 ++ 15 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 tests/qapi-schema/oob-coroutine.err create mode 100644 tests/qapi-schema/oob-coroutine.json create mode 100644 tests/qapi-schema/oob-coroutine.out diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt index 59d6973e1e..df01bd852b 100644 --- a/docs/devel/qapi-code-gen.txt +++ b/docs/devel/qapi-code-gen.txt @@ -457,6 +457,7 @@ Syntax: '*gen': false, '*allow-oob': true, '*allow-preconfig': true, + '*coroutine': true, '*if': COND, '*features': FEATURES } @@ -581,6 +582,16 @@ before the machine is built. It defaults to false. For example: QMP is available before the machine is built only when QEMU was started with --preconfig. +Member 'coroutine' tells the QMP dispatcher whether the command handler +is safe to be run in a coroutine. It defaults to false. If it is true, +the command handler is called from coroutine context and may yield while +waiting for an external event (such as I/O completion) in order to avoid +blocking the guest and other background operations. + +It is an error to specify both 'coroutine': true and 'allow-oob': true +for a command. (We don't currently have a use case for both together and +without a use case, it's not entirely clear what the semantics should be.) + The optional 'if' member specifies a conditional. See "Configuring the schema" below for more on this. diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 9aa426a398..d6ce9efc8e 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -24,6 +24,7 @@ typedef enum QmpCommandOptions QCO_NO_SUCCESS_RESP = (1U << 0), QCO_ALLOW_OOB = (1U << 1), QCO_ALLOW_PRECONFIG = (1U << 2), + QCO_COROUTINE = (1U << 3), } QmpCommandOptions; typedef struct QmpCommand diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index 79507d9e54..6359cc28c7 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -35,6 +35,10 @@ void qmp_cmd_success_response(Error **errp) { } +void qmp_coroutine_cmd(Error **errp) +{ +} + Empty2 *qmp_user_def_cmd0(Error **errp) { return g_new0(Empty2, 1); diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py index afa55b055c..f2f2f8948d 100644 --- a/scripts/qapi/commands.py +++ b/scripts/qapi/commands.py @@ -194,7 +194,8 @@ out: return ret -def gen_register_command(name, success_response, allow_oob, allow_preconfig): +def gen_register_command(name, success_response, allow_oob, allow_preconfig, + coroutine): options = [] if not success_response: @@ -203,6 +204,8 @@ def gen_register_command(name, success_response, allow_oob, allow_preconfig): options += ['QCO_ALLOW_OOB'] if allow_preconfig: options += ['QCO_ALLOW_PRECONFIG'] + if coroutine: + options += ['QCO_COROUTINE'] if not options: options = ['QCO_NO_OPTIONS'] @@ -285,7 +288,7 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds); def visit_command(self, name, info, ifcond, arg_type, ret_type, gen, success_response, boxed, allow_oob, allow_preconfig, - features): + coroutine, features): if not gen: return # FIXME: If T is a user-defined type, the user is responsible @@ -303,7 +306,8 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds); self._genh.add(gen_marshal_decl(name)) self._genc.add(gen_marshal(name, arg_type, boxed, ret_type)) self._regy.add(gen_register_command(name, success_response, - allow_oob, allow_preconfig)) + allow_oob, allow_preconfig, + coroutine)) def gen_commands(schema, output_dir, prefix): diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py index 1787a53d91..69f971e427 100644 --- a/scripts/qapi/doc.py +++ b/scripts/qapi/doc.py @@ -264,7 +264,7 @@ class QAPISchemaGenDocVisitor(QAPISchemaVisitor): def visit_command(self, name, info, ifcond, arg_type, ret_type, gen, success_response, boxed, allow_oob, allow_preconfig, - features): + coroutine, features): doc = self.cur_doc self._gen.add(texi_msg('Command', doc, ifcond, texi_arguments(doc, diff --git a/scripts/qapi/expr.py b/scripts/qapi/expr.py index d7a289eded..95cc006cae 100644 --- a/scripts/qapi/expr.py +++ b/scripts/qapi/expr.py @@ -89,10 +89,16 @@ def check_flags(expr, info): if key in expr and expr[key] is not False: raise QAPISemError( info, "flag '%s' may only use false value" % key) - for key in ['boxed', 'allow-oob', 'allow-preconfig']: + for key in ['boxed', 'allow-oob', 'allow-preconfig', 'coroutine']: if key in expr and expr[key] is not True: raise QAPISemError( info, "flag '%s' may only use true value" % key) + if 'allow-oob' in expr and 'coroutine' in expr: + # This is not necessarily a fundamental incompatibility, but we don't + # have a use case and the desired semantics isn't obvious. The simplest + # solution is to forbid it until we get a use case for it. + raise QAPISemError(info, "flags 'allow-oob' and 'coroutine' " + "are incompatible") def check_if(expr, info, source): @@ -344,7 +350,7 @@ def check_exprs(exprs): ['command'], ['data', 'returns', 'boxed', 'if', 'features', 'gen', 'success-response', 'allow-oob', - 'allow-preconfig']) + 'allow-preconfig', 'coroutine']) normalize_members(expr.get('data')) check_command(expr, info) elif meta == 'event': diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py index b3a463dd8b..8a296a69d6 100644 --- a/scripts/qapi/introspect.py +++ b/scripts/qapi/introspect.py @@ -212,7 +212,7 @@ const QLitObject %(c_name)s = %(c_string)s; def visit_command(self, name, info, ifcond, arg_type, ret_type, gen, success_response, boxed, allow_oob, allow_preconfig, - features): + coroutine, features): arg_type = arg_type or self._schema.the_empty_object_type ret_type = ret_type or self._schema.the_empty_object_type obj = {'arg-type': self._use_type(arg_type), diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py index 5100110fa2..8fbfa42e8e 100644 --- a/scripts/qapi/schema.py +++ b/scripts/qapi/schema.py @@ -128,7 +128,7 @@ class QAPISchemaVisitor(object): def visit_command(self, name, info, ifcond, arg_type, ret_type, gen, success_response, boxed, allow_oob, allow_preconfig, - features): + coroutine, features): pass def visit_event(self, name, info, ifcond, arg_type, boxed): @@ -690,7 +690,7 @@ class QAPISchemaCommand(QAPISchemaEntity): def __init__(self, name, info, doc, ifcond, arg_type, ret_type, gen, success_response, boxed, allow_oob, allow_preconfig, - features): + coroutine, features): QAPISchemaEntity.__init__(self, name, info, doc, ifcond, features) assert not arg_type or isinstance(arg_type, str) assert not ret_type or isinstance(ret_type, str) @@ -703,6 +703,7 @@ class QAPISchemaCommand(QAPISchemaEntity): self.boxed = boxed self.allow_oob = allow_oob self.allow_preconfig = allow_preconfig + self.coroutine = coroutine def check(self, schema): QAPISchemaEntity.check(self, schema) @@ -745,7 +746,7 @@ class QAPISchemaCommand(QAPISchemaEntity): self.arg_type, self.ret_type, self.gen, self.success_response, self.boxed, self.allow_oob, - self.allow_preconfig, + self.allow_preconfig, self.coroutine, self.features) @@ -1043,6 +1044,7 @@ class QAPISchema(object): boxed = expr.get('boxed', False) allow_oob = expr.get('allow-oob', False) allow_preconfig = expr.get('allow-preconfig', False) + coroutine = expr.get('coroutine', False) ifcond = expr.get('if') features = expr.get('features', []) if isinstance(data, OrderedDict): @@ -1054,6 +1056,7 @@ class QAPISchema(object): self._def_entity(QAPISchemaCommand(name, info, doc, ifcond, data, rets, gen, success_response, boxed, allow_oob, allow_preconfig, + coroutine, self._make_features(features, info))) def _def_event(self, expr, info, doc): diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py index 41232c11a3..dcb922755d 100755 --- a/tests/qapi-schema/test-qapi.py +++ b/tests/qapi-schema/test-qapi.py @@ -69,12 +69,13 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor): def visit_command(self, name, info, ifcond, arg_type, ret_type, gen, success_response, boxed, allow_oob, allow_preconfig, - features): + coroutine, features): print('command %s %s -> %s' % (name, arg_type and arg_type.name, ret_type and ret_type.name)) - print(' gen=%s success_response=%s boxed=%s oob=%s preconfig=%s' - % (gen, success_response, boxed, allow_oob, allow_preconfig)) + print(' gen=%s success_response=%s boxed=%s oob=%s preconfig=%s%s' + % (gen, success_response, boxed, allow_oob, allow_preconfig, + " coroutine=True" if coroutine else "")) self._print_if(ifcond) self._print_features(features) diff --git a/tests/Makefile.include b/tests/Makefile.include index 2f1cafed72..893540f5a3 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -286,6 +286,7 @@ qapi-schema += missing-type.json qapi-schema += nested-struct-data.json qapi-schema += nested-struct-data-invalid-dict.json qapi-schema += non-objects.json +qapi-schema += oob-coroutine.json qapi-schema += oob-test.json qapi-schema += allow-preconfig-test.json qapi-schema += pragma-doc-required-crap.json diff --git a/tests/qapi-schema/oob-coroutine.err b/tests/qapi-schema/oob-coroutine.err new file mode 100644 index 0000000000..c01a4992bd --- /dev/null +++ b/tests/qapi-schema/oob-coroutine.err @@ -0,0 +1,2 @@ +oob-coroutine.json: In command 'oob-command-1': +oob-coroutine.json:2: flags 'allow-oob' and 'coroutine' are incompatible diff --git a/tests/qapi-schema/oob-coroutine.json b/tests/qapi-schema/oob-coroutine.json new file mode 100644 index 0000000000..0f67663bcd --- /dev/null +++ b/tests/qapi-schema/oob-coroutine.json @@ -0,0 +1,2 @@ +# Check that incompatible flags allow-oob and coroutine are rejected +{ 'command': 'oob-command-1', 'allow-oob': true, 'coroutine': true } diff --git a/tests/qapi-schema/oob-coroutine.out b/tests/qapi-schema/oob-coroutine.out new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json index 9abf175fe0..1a850fe171 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -147,6 +147,7 @@ 'returns': 'UserDefTwo' } { 'command': 'cmd-success-response', 'data': {}, 'success-response': false } +{ 'command': 'coroutine-cmd', 'data': {}, 'coroutine': true } # Returning a non-dictionary requires a name from the whitelist { 'command': 'guest-get-time', 'data': {'a': 'int', '*b': 'int' }, diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out index 9bd3c4a490..fdc349991a 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -203,6 +203,8 @@ command user_def_cmd2 q_obj_user_def_cmd2-arg -> UserDefTwo gen=True success_response=True boxed=False oob=False preconfig=False command cmd-success-response None -> None gen=True success_response=False boxed=False oob=False preconfig=False +command coroutine-cmd None -> None + gen=True success_response=True boxed=False oob=False preconfig=False coroutine=True object q_obj_guest-get-time-arg member a: int optional=False member b: int optional=True From patchwork Tue Feb 18 15:40:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kevin Wolf X-Patchwork-Id: 11388831 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 77B891395 for ; Tue, 18 Feb 2020 15:41:38 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4F1612176D for ; Tue, 18 Feb 2020 15:41:38 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Z/O1ipb2" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4F1612176D Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:37294 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j450D-00005c-Fd for patchwork-qemu-devel@patchwork.kernel.org; Tue, 18 Feb 2020 10:41:37 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:39039) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j44zX-0006iv-RR for qemu-devel@nongnu.org; Tue, 18 Feb 2020 10:40:56 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1j44zW-0001ge-Rr for qemu-devel@nongnu.org; Tue, 18 Feb 2020 10:40:55 -0500 Received: from us-smtp-delivery-1.mimecast.com ([207.211.31.120]:30454 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1j44zW-0001g0-OK for qemu-devel@nongnu.org; Tue, 18 Feb 2020 10:40:54 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1582040454; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=qYdW57Gi4VWogYvFlCc6iuJ0jzLDS0PDclWM8DpwXMQ=; b=Z/O1ipb2GHOK2W/+WbOcDiKW/zkLYZKFZfPBAUp5jOK7tinFf1UciVKLFGQBoC1qBPn+oz Em0WgoorUFP9fmEmIRxn5PCItc1eNM9ecCyK6W3E5PTG1LcxwPeGeK0qe0hSjRY+jzbCsM xROKM9yFXZurAyy14gva/6qlpDUbzyw= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-237-C2moIUXeMQGqdp0oiNDJpg-1; Tue, 18 Feb 2020 10:40:48 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 1EE9D800EB2; Tue, 18 Feb 2020 15:40:47 +0000 (UTC) Received: from linux.fritz.box.com (ovpn-117-181.ams2.redhat.com [10.36.117.181]) by smtp.corp.redhat.com (Postfix) with ESMTP id B1BF287056; Tue, 18 Feb 2020 15:40:45 +0000 (UTC) From: Kevin Wolf To: qemu-devel@nongnu.org Subject: [PATCH v5 2/4] vl: Initialise main loop earlier Date: Tue, 18 Feb 2020 16:40:34 +0100 Message-Id: <20200218154036.28562-3-kwolf@redhat.com> In-Reply-To: <20200218154036.28562-1-kwolf@redhat.com> References: <20200218154036.28562-1-kwolf@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-MC-Unique: C2moIUXeMQGqdp0oiNDJpg-1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 207.211.31.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, marcandre.lureau@gmail.com, armbru@redhat.com, qemu-block@nongnu.org Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" We want to be able to use qemu_aio_context in the monitor initialisation. Signed-off-by: Kevin Wolf Reviewed-by: Marc-André Lureau Reviewed-by: Markus Armbruster --- vl.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/vl.c b/vl.c index 794f2e5733..98bc51e089 100644 --- a/vl.c +++ b/vl.c @@ -2894,6 +2894,11 @@ int main(int argc, char **argv, char **envp) runstate_init(); precopy_infrastructure_init(); postcopy_infrastructure_init(); + + if (qemu_init_main_loop(&main_loop_err)) { + error_report_err(main_loop_err); + exit(1); + } monitor_init_globals(); if (qcrypto_init(&err) < 0) { @@ -3811,11 +3816,6 @@ int main(int argc, char **argv, char **envp) qemu_unlink_pidfile_notifier.notify = qemu_unlink_pidfile; qemu_add_exit_notifier(&qemu_unlink_pidfile_notifier); - if (qemu_init_main_loop(&main_loop_err)) { - error_report_err(main_loop_err); - exit(1); - } - #ifdef CONFIG_SECCOMP olist = qemu_find_opts_err("sandbox", NULL); if (olist) { From patchwork Tue Feb 18 15:40:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Wolf X-Patchwork-Id: 11388833 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4D76B1395 for ; Tue, 18 Feb 2020 15:42:51 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 13A3422527 for ; Tue, 18 Feb 2020 15:42:51 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="dgIuGhwj" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 13A3422527 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:37314 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j451O-0002Uf-9f for patchwork-qemu-devel@patchwork.kernel.org; Tue, 18 Feb 2020 10:42:50 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:39013) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j44zW-0006gF-VB for qemu-devel@nongnu.org; Tue, 18 Feb 2020 10:40:57 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1j44zU-0001ew-MZ for qemu-devel@nongnu.org; Tue, 18 Feb 2020 10:40:54 -0500 Received: from us-smtp-delivery-1.mimecast.com ([207.211.31.120]:34124 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1j44zU-0001ej-H9 for qemu-devel@nongnu.org; Tue, 18 Feb 2020 10:40:52 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1582040452; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=a2nJJibWr+MWF10oEnk54fPJyk9Rolq9tmMWulfdPvw=; b=dgIuGhwjj87rhfO8C6CcL0CoDMeNUgd543an7PF/gDxpzSopRx0aKVA1Q7X5sFTp1PsLz/ 6I6576UQCa/02axsZIW/PSCBS1VfOjceQ/JL0cmq+ZfjTZbfmVUPnJwKlhGApz58i/VsFe KhND42qrW3LwC76DldImD50KgU3dXvo= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-365-Qp2Ics0aP-mi_3ucMGTzzQ-1; Tue, 18 Feb 2020 10:40:49 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id A15A5800D48; Tue, 18 Feb 2020 15:40:48 +0000 (UTC) Received: from linux.fritz.box.com (ovpn-117-181.ams2.redhat.com [10.36.117.181]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6F2AB5C13B; Tue, 18 Feb 2020 15:40:47 +0000 (UTC) From: Kevin Wolf To: qemu-devel@nongnu.org Subject: [PATCH v5 3/4] qmp: Move dispatcher to a coroutine Date: Tue, 18 Feb 2020 16:40:35 +0100 Message-Id: <20200218154036.28562-4-kwolf@redhat.com> In-Reply-To: <20200218154036.28562-1-kwolf@redhat.com> References: <20200218154036.28562-1-kwolf@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-MC-Unique: Qp2Ics0aP-mi_3ucMGTzzQ-1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 207.211.31.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, marcandre.lureau@gmail.com, armbru@redhat.com, qemu-block@nongnu.org Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" This moves the QMP dispatcher to a coroutine and runs all QMP command handlers that declare 'coroutine': true in coroutine context so they can avoid blocking the main loop while doing I/O or waiting for other events. For commands that are not declared safe to run in a coroutine, the dispatcher drops out of coroutine context by calling the QMP command handler from a bottom half. Signed-off-by: Kevin Wolf Reviewed-by: Markus Armbruster --- include/qapi/qmp/dispatch.h | 1 + monitor/monitor-internal.h | 6 +- monitor/monitor.c | 55 +++++++++++++--- monitor/qmp.c | 122 +++++++++++++++++++++++++++--------- qapi/qmp-dispatch.c | 44 ++++++++++++- qapi/qmp-registry.c | 3 + util/aio-posix.c | 7 ++- 7 files changed, 196 insertions(+), 42 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index d6ce9efc8e..6812e49b5f 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -30,6 +30,7 @@ typedef enum QmpCommandOptions typedef struct QmpCommand { const char *name; + /* Runs in coroutine context if QCO_COROUTINE is set */ QmpCommandFunc *fn; QmpCommandOptions options; QTAILQ_ENTRY(QmpCommand) node; diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h index 3e6baba88f..f8123b151a 100644 --- a/monitor/monitor-internal.h +++ b/monitor/monitor-internal.h @@ -155,7 +155,9 @@ static inline bool monitor_is_qmp(const Monitor *mon) typedef QTAILQ_HEAD(MonitorList, Monitor) MonitorList; extern IOThread *mon_iothread; -extern QEMUBH *qmp_dispatcher_bh; +extern Coroutine *qmp_dispatcher_co; +extern bool qmp_dispatcher_co_shutdown; +extern bool qmp_dispatcher_co_busy; extern QmpCommandList qmp_commands, qmp_cap_negotiation_commands; extern QemuMutex monitor_lock; extern MonitorList mon_list; @@ -173,7 +175,7 @@ void monitor_fdsets_cleanup(void); void qmp_send_response(MonitorQMP *mon, const QDict *rsp); void monitor_data_destroy_qmp(MonitorQMP *mon); -void monitor_qmp_bh_dispatcher(void *data); +void coroutine_fn monitor_qmp_dispatcher_co(void *data); int get_monitor_def(int64_t *pval, const char *name); void help_cmd(Monitor *mon, const char *name); diff --git a/monitor/monitor.c b/monitor/monitor.c index c1a6c4460f..72d57b5cd2 100644 --- a/monitor/monitor.c +++ b/monitor/monitor.c @@ -53,8 +53,32 @@ typedef struct { /* Shared monitor I/O thread */ IOThread *mon_iothread; -/* Bottom half to dispatch the requests received from I/O thread */ -QEMUBH *qmp_dispatcher_bh; +/* Coroutine to dispatch the requests received from I/O thread */ +Coroutine *qmp_dispatcher_co; + +/* Set to true when the dispatcher coroutine should terminate */ +bool qmp_dispatcher_co_shutdown; + +/* + * qmp_dispatcher_co_busy is used for synchronisation between the + * monitor thread and the main thread to ensure that the dispatcher + * coroutine never gets scheduled a second time when it's already + * scheduled (scheduling the same coroutine twice is forbidden). + * + * It is true if the coroutine is active and processing requests. + * Additional requests may then be pushed onto a mon->qmp_requests, + * and @qmp_dispatcher_co_shutdown may be set without further ado. + * @qmp_dispatcher_co_busy must not be woken up in this case. + * + * If false, you also have to set @qmp_dispatcher_co_busy to true and + * wake up @qmp_dispatcher_co after pushing the new requests. + * + * The coroutine will automatically change this variable back to false + * before it yields. Nobody else may set the variable to false. + * + * Access must be atomic for thread safety. + */ +bool qmp_dispatcher_co_busy; /* Protects mon_list, monitor_qapi_event_state, monitor_destroyed. */ QemuMutex monitor_lock; @@ -579,9 +603,24 @@ void monitor_cleanup(void) } qemu_mutex_unlock(&monitor_lock); - /* QEMUBHs needs to be deleted before destroying the I/O thread */ - qemu_bh_delete(qmp_dispatcher_bh); - qmp_dispatcher_bh = NULL; + /* + * The dispatcher needs to stop before destroying the I/O thread. + * + * We need to poll both qemu_aio_context and iohandler_ctx to make + * sure that the dispatcher coroutine keeps making progress and + * eventually terminates. qemu_aio_context is automatically + * polled by calling AIO_WAIT_WHILE on it, but we must poll + * iohandler_ctx manually. + */ + qmp_dispatcher_co_shutdown = true; + if (!atomic_xchg(&qmp_dispatcher_co_busy, true)) { + aio_co_wake(qmp_dispatcher_co); + } + + AIO_WAIT_WHILE(qemu_get_aio_context(), + (aio_poll(iohandler_get_aio_context(), false), + atomic_mb_read(&qmp_dispatcher_co_busy))); + if (mon_iothread) { iothread_destroy(mon_iothread); mon_iothread = NULL; @@ -604,9 +643,9 @@ void monitor_init_globals_core(void) * have commands assuming that context. It would be nice to get * rid of those assumptions. */ - qmp_dispatcher_bh = aio_bh_new(iohandler_get_aio_context(), - monitor_qmp_bh_dispatcher, - NULL); + qmp_dispatcher_co = qemu_coroutine_create(monitor_qmp_dispatcher_co, NULL); + atomic_mb_set(&qmp_dispatcher_co_busy, true); + aio_co_schedule(iohandler_get_aio_context(), qmp_dispatcher_co); } int monitor_init_opts(QemuOpts *opts, Error **errp) diff --git a/monitor/qmp.c b/monitor/qmp.c index 8379c8f96e..d572d92e09 100644 --- a/monitor/qmp.c +++ b/monitor/qmp.c @@ -133,6 +133,10 @@ static void monitor_qmp_respond(MonitorQMP *mon, QDict *rsp) } } +/* + * Runs outside of coroutine context for OOB commands, but in + * coroutine context for everything else. + */ static void monitor_qmp_dispatch(MonitorQMP *mon, QObject *req) { Monitor *old_mon; @@ -211,43 +215,99 @@ static QMPRequest *monitor_qmp_requests_pop_any_with_lock(void) return req_obj; } -void monitor_qmp_bh_dispatcher(void *data) +void coroutine_fn monitor_qmp_dispatcher_co(void *data) { - QMPRequest *req_obj = monitor_qmp_requests_pop_any_with_lock(); + QMPRequest *req_obj = NULL; QDict *rsp; bool need_resume; MonitorQMP *mon; - if (!req_obj) { - return; - } + while (true) { + assert(atomic_mb_read(&qmp_dispatcher_co_busy) == true); - mon = req_obj->mon; - /* qmp_oob_enabled() might change after "qmp_capabilities" */ - need_resume = !qmp_oob_enabled(mon) || - mon->qmp_requests->length == QMP_REQ_QUEUE_LEN_MAX - 1; - qemu_mutex_unlock(&mon->qmp_queue_lock); - if (req_obj->req) { - QDict *qdict = qobject_to(QDict, req_obj->req); - QObject *id = qdict ? qdict_get(qdict, "id") : NULL; - trace_monitor_qmp_cmd_in_band(qobject_get_try_str(id) ?: ""); - monitor_qmp_dispatch(mon, req_obj->req); - } else { - assert(req_obj->err); - rsp = qmp_error_response(req_obj->err); - req_obj->err = NULL; - monitor_qmp_respond(mon, rsp); - qobject_unref(rsp); - } + /* + * Mark the dispatcher as not busy already here so that we + * don't miss any new requests coming in the middle of our + * processing. + */ + atomic_mb_set(&qmp_dispatcher_co_busy, false); + + while (!(req_obj = monitor_qmp_requests_pop_any_with_lock())) { + /* + * No more requests to process. Wait to be reentered from + * handle_qmp_command() when it pushes more requests, or + * from monitor_cleanup() when it requests shutdown. + */ + if (!qmp_dispatcher_co_shutdown) { + qemu_coroutine_yield(); + + /* + * busy must be set to true again by whoever + * rescheduled us to avoid double scheduling + */ + assert(atomic_xchg(&qmp_dispatcher_co_busy, false) == true); + } + + /* + * qmp_dispatcher_co_shutdown may have changed if we + * yielded and were reentered from monitor_cleanup() + */ + if (qmp_dispatcher_co_shutdown) { + return; + } + } - if (need_resume) { - /* Pairs with the monitor_suspend() in handle_qmp_command() */ - monitor_resume(&mon->common); - } - qmp_request_free(req_obj); + if (atomic_xchg(&qmp_dispatcher_co_busy, true) == true) { + /* + * Someone rescheduled us (probably because a new requests + * came in), but we didn't actually yield. Do that now, + * only to be immediately reentered and removed from the + * list of scheduled coroutines. + */ + qemu_coroutine_yield(); + } - /* Reschedule instead of looping so the main loop stays responsive */ - qemu_bh_schedule(qmp_dispatcher_bh); + /* + * Move the coroutine from iohandler_ctx to qemu_aio_context for + * executing the command handler so that it can make progress if it + * involves an AIO_WAIT_WHILE(). + */ + aio_co_schedule(qemu_get_aio_context(), qmp_dispatcher_co); + qemu_coroutine_yield(); + + mon = req_obj->mon; + /* qmp_oob_enabled() might change after "qmp_capabilities" */ + need_resume = !qmp_oob_enabled(mon) || + mon->qmp_requests->length == QMP_REQ_QUEUE_LEN_MAX - 1; + qemu_mutex_unlock(&mon->qmp_queue_lock); + if (req_obj->req) { + QDict *qdict = qobject_to(QDict, req_obj->req); + QObject *id = qdict ? qdict_get(qdict, "id") : NULL; + trace_monitor_qmp_cmd_in_band(qobject_get_try_str(id) ?: ""); + monitor_qmp_dispatch(mon, req_obj->req); + } else { + assert(req_obj->err); + rsp = qmp_error_response(req_obj->err); + req_obj->err = NULL; + monitor_qmp_respond(mon, rsp); + qobject_unref(rsp); + } + + if (need_resume) { + /* Pairs with the monitor_suspend() in handle_qmp_command() */ + monitor_resume(&mon->common); + } + qmp_request_free(req_obj); + + /* + * Yield and reschedule so the main loop stays responsive. + * + * Move back to iohandler_ctx so that nested event loops for + * qemu_aio_context don't start new monitor commands. + */ + aio_co_schedule(iohandler_get_aio_context(), qmp_dispatcher_co); + qemu_coroutine_yield(); + } } static void handle_qmp_command(void *opaque, QObject *req, Error *err) @@ -308,7 +368,9 @@ static void handle_qmp_command(void *opaque, QObject *req, Error *err) qemu_mutex_unlock(&mon->qmp_queue_lock); /* Kick the dispatcher routine */ - qemu_bh_schedule(qmp_dispatcher_bh); + if (!atomic_xchg(&qmp_dispatcher_co_busy, true)) { + aio_co_wake(qmp_dispatcher_co); + } } static void monitor_qmp_read(void *opaque, const uint8_t *buf, int size) diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index bc264b3c9b..eef09d15bc 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -12,12 +12,16 @@ */ #include "qemu/osdep.h" + +#include "block/aio.h" #include "qapi/error.h" #include "qapi/qmp/dispatch.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qjson.h" #include "sysemu/runstate.h" #include "qapi/qmp/qbool.h" +#include "qemu/coroutine.h" +#include "qemu/main-loop.h" static QDict *qmp_dispatch_check_obj(const QObject *request, bool allow_oob, Error **errp) @@ -75,6 +79,25 @@ static QDict *qmp_dispatch_check_obj(const QObject *request, bool allow_oob, return dict; } +typedef struct QmpDispatchBH { + QmpCommand *cmd; + QDict *args; + QObject **ret; + Error **errp; + Coroutine *co; +} QmpDispatchBH; + +static void do_qmp_dispatch_bh(void *opaque) +{ + QmpDispatchBH *data = opaque; + data->cmd->fn(data->args, data->ret, data->errp); + aio_co_wake(data->co); +} + +/* + * Runs outside of coroutine context for OOB commands, but in coroutine context + * for everything else. + */ static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request, bool allow_oob, Error **errp) { @@ -129,7 +152,22 @@ static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request, qobject_ref(args); } - cmd->fn(args, &ret, &local_err); + assert(!(oob && qemu_in_coroutine())); + if ((cmd->options & QCO_COROUTINE) || !qemu_in_coroutine()) { + cmd->fn(args, &ret, &local_err); + } else { + /* Must drop out of coroutine context for this one */ + QmpDispatchBH data = { + .cmd = cmd, + .args = args, + .ret = &ret, + .errp = &local_err, + .co = qemu_coroutine_self(), + }; + aio_bh_schedule_oneshot(qemu_get_aio_context(), do_qmp_dispatch_bh, + &data); + qemu_coroutine_yield(); + } if (local_err) { error_propagate(errp, local_err); } else if (cmd->options & QCO_NO_SUCCESS_RESP) { @@ -164,6 +202,10 @@ bool qmp_is_oob(const QDict *dict) && !qdict_haskey(dict, "execute"); } +/* + * Runs outside of coroutine context for OOB commands, but in coroutine context + * for everything else. + */ QDict *qmp_dispatch(QmpCommandList *cmds, QObject *request, bool allow_oob) { diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c index ca00f74795..1b5b9f1ccc 100644 --- a/qapi/qmp-registry.c +++ b/qapi/qmp-registry.c @@ -20,6 +20,9 @@ void qmp_register_command(QmpCommandList *cmds, const char *name, { QmpCommand *cmd = g_malloc0(sizeof(*cmd)); + /* QCO_COROUTINE and QCO_ALLOW_OOB are incompatible for now */ + assert(!((options & QCO_COROUTINE) && (options & QCO_ALLOW_OOB))); + cmd->name = name; cmd->fn = fn; cmd->enabled = true; diff --git a/util/aio-posix.c b/util/aio-posix.c index a4977f538e..223de08b91 100644 --- a/util/aio-posix.c +++ b/util/aio-posix.c @@ -15,6 +15,7 @@ #include "qemu/osdep.h" #include "block/block.h" +#include "qemu/main-loop.h" #include "qemu/rcu_queue.h" #include "qemu/sockets.h" #include "qemu/cutils.h" @@ -616,7 +617,11 @@ bool aio_poll(AioContext *ctx, bool blocking) int64_t timeout; int64_t start = 0; - assert(in_aio_context_home_thread(ctx)); + /* aio_poll() may only be called in the AioContext's thread. iohandler_ctx + * is special in that it runs in the main thread, but that thread's context + * is qemu_aio_context. */ + assert(in_aio_context_home_thread(ctx == iohandler_get_aio_context() ? + qemu_get_aio_context() : ctx)); /* aio_notify can avoid the expensive event_notifier_set if * everything (file descriptors, bottom halves, timers) will From patchwork Tue Feb 18 15:40:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kevin Wolf X-Patchwork-Id: 11388835 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 82C3D1395 for ; Tue, 18 Feb 2020 15:43:00 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5A58A2176D for ; Tue, 18 Feb 2020 15:43:00 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="XMtlLAjw" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5A58A2176D Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:37316 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j451X-0002oG-J8 for patchwork-qemu-devel@patchwork.kernel.org; Tue, 18 Feb 2020 10:42:59 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:39009) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j44zW-0006g2-Pp for qemu-devel@nongnu.org; Tue, 18 Feb 2020 10:40:55 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1j44zV-0001fP-HD for qemu-devel@nongnu.org; Tue, 18 Feb 2020 10:40:54 -0500 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:27934 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1j44zV-0001fA-DU for qemu-devel@nongnu.org; Tue, 18 Feb 2020 10:40:53 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1582040452; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=j+Bthn2VUai9+SGIYG/1resgzBfRQmNsiV8KM6o5IWY=; b=XMtlLAjwkW0MhnvhBsAcbDqg77YcQbDPBM8/k4ydq2Kmb/2RoybaJtNiHP6FNeEhRKQr3R DIo3+ojbEk0baw3H0WfzVR0Rd8Aa41G89++9gdb+1bMJqT9nyShRJ/yxt1e098zouN/iAe dd6PqCKvZ2PuAplPDDTcAq/SOzthCPk= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-26-XR49gvoGMQWw8rr5AvPPrA-1; Tue, 18 Feb 2020 10:40:51 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 2B718107ACCC; Tue, 18 Feb 2020 15:40:50 +0000 (UTC) Received: from linux.fritz.box.com (ovpn-117-181.ams2.redhat.com [10.36.117.181]) by smtp.corp.redhat.com (Postfix) with ESMTP id EDFC01BC6D; Tue, 18 Feb 2020 15:40:48 +0000 (UTC) From: Kevin Wolf To: qemu-devel@nongnu.org Subject: [PATCH v5 4/4] block: Mark 'block_resize' as coroutine Date: Tue, 18 Feb 2020 16:40:36 +0100 Message-Id: <20200218154036.28562-5-kwolf@redhat.com> In-Reply-To: <20200218154036.28562-1-kwolf@redhat.com> References: <20200218154036.28562-1-kwolf@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-MC-Unique: XR49gvoGMQWw8rr5AvPPrA-1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 205.139.110.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, marcandre.lureau@gmail.com, armbru@redhat.com, qemu-block@nongnu.org Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" block_resize is safe to run in a coroutine, and it does some I/O that could potentially take quite some time, so use it as an example for the new 'coroutine': true annotation in the QAPI schema. Signed-off-by: Kevin Wolf Reviewed-by: Marc-André Lureau Reviewed-by: Markus Armbruster --- qapi/block-core.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index 37d7ea7295..077b721d01 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1344,7 +1344,8 @@ { 'command': 'block_resize', 'data': { '*device': 'str', '*node-name': 'str', - 'size': 'int' } } + 'size': 'int' }, + 'coroutine': true } ## # @NewImageMode: