From patchwork Wed Oct 16 10:25:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13838177 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id DF88DD1AD42 for ; Wed, 16 Oct 2024 10:29:26 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t11GU-0003i0-0E; Wed, 16 Oct 2024 06:28:26 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1t11GR-0003hF-PA for qemu-devel@nongnu.org; Wed, 16 Oct 2024 06:28:24 -0400 Received: from mail-lf1-x136.google.com ([2a00:1450:4864:20::136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1t11GP-00048r-Jj for qemu-devel@nongnu.org; Wed, 16 Oct 2024 06:28:23 -0400 Received: by mail-lf1-x136.google.com with SMTP id 2adb3069b0e04-5389917ef34so7079602e87.2 for ; Wed, 16 Oct 2024 03:28:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1729074500; x=1729679300; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=H3MhWVz35MEVxLAgf+2Rpi6iKRqTz/Rily/8Q2fKy2U=; b=hoJ33OnU7/NWtXp/SxKPzObRsfFFKvH5Ym8sa7/JcvhJ841ER8NX+XyLPWpQkKGZQQ Kl4n0RAESoetwLG9v0ulKIzJLxr9tHuJfw30yi/ABUflpDqkhu31d3qkq5GhPsVqTk07 bK0rSVvJGFHs9U4qLLDkw7fsBA7iC+6jyLQ0spTMfEtqMFSY1mzZlaBZa5+EjrKGMYCb UrchSg4iQT23ve71SX+hHhEiSh4fH9dpef6G+39WPZ6iveIprzol75wRtcSteAolZPOJ UcduYWbVNaaO3c0Fqb0D0DIZvMibAtUKFxoDQjn7mJWlUFeMpAdK+U+ScpJQDSHK1PLS JxdQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729074500; x=1729679300; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=H3MhWVz35MEVxLAgf+2Rpi6iKRqTz/Rily/8Q2fKy2U=; b=jawa5WXPlD3oE19Jxx0p/rLJFExv/dO0M+jvBa55HecNFh3fldx9SVM1YnvTqyJCkR jVjrJGGJElJZoEvcJQYYv/l2pt5xysXzSuF+9n86C5G4NJmj24KuN4O1ETKJqOEF26D7 9Jze0tW3i1x+yyCnIaNVoKDFVmb+pxuqhQ8vItDborswtK1SL1sra7WGdTQjSD/Gl81Y gpe7C21XLcBogkM2WFAQ+QY2ugdggd7v9W2bALWPWCRg+AgA0dzoS5B8qmgygGI5zkfT NUFcDg+Zz1oTtFV1shCaidnOzwfBKyNi5HPm43qAEAGuyBv82rsz80iUxqgUHTktsLkJ xMbg== X-Forwarded-Encrypted: i=1; AJvYcCWDGntbJ2UA14xCX3bmWOXC6PBvNykE0EwSnQB1uf+uvNou+L80MQurXysPjz73v9TVC053835HzrN4@nongnu.org X-Gm-Message-State: AOJu0YypqEXiiYcjhttFqFev33zR3cvrTgxNGJ+UtXCdlVHscd0AtrR4 kOGKUf4odckhbZfPSB7tvLkcjDDLO7y/WX8QCQHP+sJKRJfnMFmd X-Google-Smtp-Source: AGHT+IEOgoChLjslxPUa7I5tQjQ9R7XpIYpNKTWBNZ+ojPjHJ90M/IeAErD/1wFYtEupcHFhe5IAdA== X-Received: by 2002:a05:6512:31d2:b0:539:9645:97ab with SMTP id 2adb3069b0e04-539e5620d80mr6762823e87.33.1729074499285; Wed, 16 Oct 2024 03:28:19 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:eb7f:8fd0:f96c:766b]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5c98d4f85dcsm1566680a12.22.2024.10.16.03.28.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Oct 2024 03:28:18 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v4 1/8] chardev/char: rename `MuxChardev` struct to `MuxFeChardev` Date: Wed, 16 Oct 2024 12:25:58 +0200 Message-Id: <20241016102605.459395-2-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241016102605.459395-1-r.peniaev@gmail.com> References: <20241016102605.459395-1-r.peniaev@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::136; envelope-from=r.peniaev@gmail.com; helo=mail-lf1-x136.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org In the following patches backend multiplexer will be introduced. This patch renames the structure and a few mux macros to reflect that this mux is responsible only for multiplexing of frontend devices. This patch does the following: s/MuxChardev/MuxFeChardev/g s/CHARDEV_IS_MUX/CHARDEV_IS_MUX_FE/g s/MUX_CHARDEV/MUX_FE_CHARDEV/g s/TYPE_CHARDEV_MUX/TYPE_CHARDEV_MUX_FE/g No json or string types are changed for the sake of compatibility. Signed-off-by: Roman Penyaev Cc: "Marc-André Lureau" Cc: qemu-devel@nongnu.org --- chardev/char-fe.c | 10 +++++----- chardev/char-mux.c | 36 ++++++++++++++++++------------------ chardev/char.c | 8 ++++---- chardev/chardev-internal.h | 16 ++++++++-------- include/chardev/char.h | 2 +- 5 files changed, 36 insertions(+), 36 deletions(-) diff --git a/chardev/char-fe.c b/chardev/char-fe.c index 8ac6bebb6f74..7b1ae16c62a4 100644 --- a/chardev/char-fe.c +++ b/chardev/char-fe.c @@ -194,8 +194,8 @@ bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp) unsigned int tag = 0; if (s) { - if (CHARDEV_IS_MUX(s)) { - MuxChardev *d = MUX_CHARDEV(s); + if (CHARDEV_IS_MUX_FE(s)) { + MuxFeChardev *d = MUX_FE_CHARDEV(s); if (!mux_chr_attach_frontend(d, b, &tag, errp)) { return false; @@ -223,8 +223,8 @@ void qemu_chr_fe_deinit(CharBackend *b, bool del) if (b->chr->be == b) { b->chr->be = NULL; } - if (CHARDEV_IS_MUX(b->chr)) { - MuxChardev *d = MUX_CHARDEV(b->chr); + if (CHARDEV_IS_MUX_FE(b->chr)) { + MuxFeChardev *d = MUX_FE_CHARDEV(b->chr); mux_chr_detach_frontend(d, b->tag); } if (del) { @@ -305,7 +305,7 @@ void qemu_chr_fe_take_focus(CharBackend *b) return; } - if (CHARDEV_IS_MUX(b->chr)) { + if (CHARDEV_IS_MUX_FE(b->chr)) { mux_set_focus(b->chr, b->tag); } } diff --git a/chardev/char-mux.c b/chardev/char-mux.c index bda5c45e6058..dfaea5aefac3 100644 --- a/chardev/char-mux.c +++ b/chardev/char-mux.c @@ -44,7 +44,7 @@ static bool muxes_opened = true; /* Called with chr_write_lock held. */ static int mux_chr_write(Chardev *chr, const uint8_t *buf, int len) { - MuxChardev *d = MUX_CHARDEV(chr); + MuxFeChardev *d = MUX_FE_CHARDEV(chr); int ret; if (!d->timestamps) { ret = qemu_chr_fe_write(&d->chr, buf, len); @@ -125,7 +125,7 @@ static void mux_print_help(Chardev *chr) } } -static void mux_chr_send_event(MuxChardev *d, unsigned int mux_nr, +static void mux_chr_send_event(MuxFeChardev *d, unsigned int mux_nr, QEMUChrEvent event) { CharBackend *be = d->backends[mux_nr]; @@ -137,14 +137,14 @@ static void mux_chr_send_event(MuxChardev *d, unsigned int mux_nr, static void mux_chr_be_event(Chardev *chr, QEMUChrEvent event) { - MuxChardev *d = MUX_CHARDEV(chr); + MuxFeChardev *d = MUX_FE_CHARDEV(chr); if (d->focus != -1) { mux_chr_send_event(d, d->focus, event); } } -static int mux_proc_byte(Chardev *chr, MuxChardev *d, int ch) +static int mux_proc_byte(Chardev *chr, MuxFeChardev *d, int ch) { if (d->term_got_escape) { d->term_got_escape = false; @@ -198,7 +198,7 @@ static int mux_proc_byte(Chardev *chr, MuxChardev *d, int ch) static void mux_chr_accept_input(Chardev *chr) { - MuxChardev *d = MUX_CHARDEV(chr); + MuxFeChardev *d = MUX_FE_CHARDEV(chr); int m = d->focus; CharBackend *be = d->backends[m]; @@ -211,7 +211,7 @@ static void mux_chr_accept_input(Chardev *chr) static int mux_chr_can_read(void *opaque) { - MuxChardev *d = MUX_CHARDEV(opaque); + MuxFeChardev *d = MUX_FE_CHARDEV(opaque); int m = d->focus; CharBackend *be = d->backends[m]; @@ -229,7 +229,7 @@ static int mux_chr_can_read(void *opaque) static void mux_chr_read(void *opaque, const uint8_t *buf, int size) { Chardev *chr = CHARDEV(opaque); - MuxChardev *d = MUX_CHARDEV(opaque); + MuxFeChardev *d = MUX_FE_CHARDEV(opaque); int m = d->focus; CharBackend *be = d->backends[m]; int i; @@ -250,7 +250,7 @@ static void mux_chr_read(void *opaque, const uint8_t *buf, int size) void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event) { - MuxChardev *d = MUX_CHARDEV(chr); + MuxFeChardev *d = MUX_FE_CHARDEV(chr); int bit; if (!muxes_opened) { @@ -271,7 +271,7 @@ static void mux_chr_event(void *opaque, QEMUChrEvent event) static GSource *mux_chr_add_watch(Chardev *s, GIOCondition cond) { - MuxChardev *d = MUX_CHARDEV(s); + MuxFeChardev *d = MUX_FE_CHARDEV(s); Chardev *chr = qemu_chr_fe_get_driver(&d->chr); ChardevClass *cc = CHARDEV_GET_CLASS(chr); @@ -284,7 +284,7 @@ static GSource *mux_chr_add_watch(Chardev *s, GIOCondition cond) static void char_mux_finalize(Object *obj) { - MuxChardev *d = MUX_CHARDEV(obj); + MuxFeChardev *d = MUX_FE_CHARDEV(obj); int bit; bit = -1; @@ -299,7 +299,7 @@ static void char_mux_finalize(Object *obj) static void mux_chr_update_read_handlers(Chardev *chr) { - MuxChardev *d = MUX_CHARDEV(chr); + MuxFeChardev *d = MUX_FE_CHARDEV(chr); /* Fix up the real driver with mux routines */ qemu_chr_fe_set_handlers_full(&d->chr, @@ -311,7 +311,7 @@ static void mux_chr_update_read_handlers(Chardev *chr) chr->gcontext, true, false); } -bool mux_chr_attach_frontend(MuxChardev *d, CharBackend *b, +bool mux_chr_attach_frontend(MuxFeChardev *d, CharBackend *b, unsigned int *tag, Error **errp) { unsigned int bit; @@ -332,7 +332,7 @@ bool mux_chr_attach_frontend(MuxChardev *d, CharBackend *b, return true; } -bool mux_chr_detach_frontend(MuxChardev *d, unsigned int tag) +bool mux_chr_detach_frontend(MuxFeChardev *d, unsigned int tag) { unsigned int bit; @@ -349,7 +349,7 @@ bool mux_chr_detach_frontend(MuxChardev *d, unsigned int tag) void mux_set_focus(Chardev *chr, unsigned int focus) { - MuxChardev *d = MUX_CHARDEV(chr); + MuxFeChardev *d = MUX_FE_CHARDEV(chr); assert(find_next_bit(&d->mux_bitset, MAX_MUX, focus) == focus); @@ -369,7 +369,7 @@ static void qemu_chr_open_mux(Chardev *chr, { ChardevMux *mux = backend->u.mux.data; Chardev *drv; - MuxChardev *d = MUX_CHARDEV(chr); + MuxFeChardev *d = MUX_FE_CHARDEV(chr); drv = qemu_chr_find(mux->chardev); if (drv == NULL) { @@ -434,7 +434,7 @@ static int chardev_options_parsed_cb(Object *child, void *opaque) { Chardev *chr = (Chardev *)child; - if (!chr->be_open && CHARDEV_IS_MUX(chr)) { + if (!chr->be_open && CHARDEV_IS_MUX_FE(chr)) { open_muxes(chr); } @@ -462,10 +462,10 @@ static void char_mux_class_init(ObjectClass *oc, void *data) } static const TypeInfo char_mux_type_info = { - .name = TYPE_CHARDEV_MUX, + .name = TYPE_CHARDEV_MUX_FE, .parent = TYPE_CHARDEV, .class_init = char_mux_class_init, - .instance_size = sizeof(MuxChardev), + .instance_size = sizeof(MuxFeChardev), .instance_finalize = char_mux_finalize, }; diff --git a/chardev/char.c b/chardev/char.c index a1722aa076d9..e077773cdece 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -331,8 +331,8 @@ static const TypeInfo char_type_info = { static bool qemu_chr_is_busy(Chardev *s) { - if (CHARDEV_IS_MUX(s)) { - MuxChardev *d = MUX_CHARDEV(s); + if (CHARDEV_IS_MUX_FE(s)) { + MuxFeChardev *d = MUX_FE_CHARDEV(s); return d->mux_bitset != 0; } else { return s->be != NULL; @@ -687,7 +687,7 @@ static Chardev *__qemu_chr_new_from_opts(QemuOpts *opts, GMainContext *context, backend->type = CHARDEV_BACKEND_KIND_MUX; backend->u.mux.data = g_new0(ChardevMux, 1); backend->u.mux.data->chardev = g_strdup(bid); - mux = qemu_chardev_new(id, TYPE_CHARDEV_MUX, backend, context, errp); + mux = qemu_chardev_new(id, TYPE_CHARDEV_MUX_FE, backend, context, errp); if (mux == NULL) { object_unparent(OBJECT(chr)); chr = NULL; @@ -1104,7 +1104,7 @@ ChardevReturn *qmp_chardev_change(const char *id, ChardevBackend *backend, return NULL; } - if (CHARDEV_IS_MUX(chr)) { + if (CHARDEV_IS_MUX_FE(chr)) { error_setg(errp, "Mux device hotswap not supported yet"); return NULL; } diff --git a/chardev/chardev-internal.h b/chardev/chardev-internal.h index 853807f3cb88..321051bb9cc5 100644 --- a/chardev/chardev-internal.h +++ b/chardev/chardev-internal.h @@ -33,7 +33,7 @@ #define MUX_BUFFER_SIZE 32 /* Must be a power of 2. */ #define MUX_BUFFER_MASK (MUX_BUFFER_SIZE - 1) -struct MuxChardev { +struct MuxFeChardev { Chardev parent; CharBackend *backends[MAX_MUX]; CharBackend chr; @@ -52,16 +52,16 @@ struct MuxChardev { bool linestart; int64_t timestamps_start; }; -typedef struct MuxChardev MuxChardev; +typedef struct MuxFeChardev MuxFeChardev; -DECLARE_INSTANCE_CHECKER(MuxChardev, MUX_CHARDEV, - TYPE_CHARDEV_MUX) -#define CHARDEV_IS_MUX(chr) \ - object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_MUX) +DECLARE_INSTANCE_CHECKER(MuxFeChardev, MUX_FE_CHARDEV, + TYPE_CHARDEV_MUX_FE) +#define CHARDEV_IS_MUX_FE(chr) \ + object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_MUX_FE) -bool mux_chr_attach_frontend(MuxChardev *d, CharBackend *b, +bool mux_chr_attach_frontend(MuxFeChardev *d, CharBackend *b, unsigned int *tag, Error **errp); -bool mux_chr_detach_frontend(MuxChardev *d, unsigned int tag); +bool mux_chr_detach_frontend(MuxFeChardev *d, unsigned int tag); void mux_set_focus(Chardev *chr, unsigned int focus); void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event); diff --git a/include/chardev/char.h b/include/chardev/char.h index 01df55f9e8c8..d9d23b6232db 100644 --- a/include/chardev/char.h +++ b/include/chardev/char.h @@ -231,7 +231,7 @@ int qemu_chr_wait_connected(Chardev *chr, Error **errp); OBJECT_DECLARE_TYPE(Chardev, ChardevClass, CHARDEV) #define TYPE_CHARDEV_NULL "chardev-null" -#define TYPE_CHARDEV_MUX "chardev-mux" +#define TYPE_CHARDEV_MUX_FE "chardev-mux" #define TYPE_CHARDEV_RINGBUF "chardev-ringbuf" #define TYPE_CHARDEV_PTY "chardev-pty" #define TYPE_CHARDEV_CONSOLE "chardev-console" From patchwork Wed Oct 16 10:25:59 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13838178 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id F234AD1AD42 for ; Wed, 16 Oct 2024 10:29:29 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t11GU-0003i5-Gi; Wed, 16 Oct 2024 06:28:26 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1t11GR-0003hJ-Ui for qemu-devel@nongnu.org; Wed, 16 Oct 2024 06:28:24 -0400 Received: from mail-ed1-x532.google.com ([2a00:1450:4864:20::532]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1t11GP-00048u-Qa for qemu-devel@nongnu.org; Wed, 16 Oct 2024 06:28:23 -0400 Received: by mail-ed1-x532.google.com with SMTP id 4fb4d7f45d1cf-5c937b5169cso1189611a12.1 for ; Wed, 16 Oct 2024 03:28:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1729074500; x=1729679300; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=wZr22C6GyP2zNyIOBJrfarPfi36zfJfEl98MesRI/BA=; b=lf7Xaia6tmnLRzlYAcbbDkJ649pLHVHjo0Q5RxanuPOY1ok9dvUf6HZrjcTnfN4DM5 zF2/ChA2ePazWr5zt6o3wD+ADxODRtfDRlYmmj9OLS7Y2pFqLumexaV4OVxNfKFaK39r WrUBaGHokfuILV2UsAuCXDZ3Z0ubILZxxO1Ma+o/fUvpdoUE/e1wRaGoBy66CJ2B5cxi OBjmXSyRwrCAlLA0wtMNKLvPuGG+6kcDv4KA2Vravryk703B5JkgviAoKrvuAaojMJ2O bKR+wa6u00Ur/bb7Ud+lRuicfKlJDRhc1ok0DXSFLoECrHL42NSqNgPV2HJe+sOnFEtt tERg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729074500; x=1729679300; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=wZr22C6GyP2zNyIOBJrfarPfi36zfJfEl98MesRI/BA=; b=SA5JFRMYZ4o0ol2sZl5uLDZU6kK3YS2Vx27qqVVtnDqCk/GfTx2vHjGX3Pv+9ceT4N s07GgGifjYb3C1H01K4R2HAv45AEpbNFDJ9DO0qYzxZjEoFAkYU4H1d8zvNnEVGduDI+ 5FMlysdvV4Byqt7Aku6/ltUcL+q0sxgeawSoOOl9usUq0vWQkiUedG64s4ugG/2yIgoV AIJJ15HgSXerhKfBByNWyceERQwqB7jnIcDqEj13UkFCQhPUOXe9emqGl67F1cB2MPm6 MzvXTxg4CCGTCiHoO1TGNc7Le9wbQt2Urk0TqqXsn/b+4N2eQrSsX6kLXUcw8Xd36FQD vAyQ== X-Forwarded-Encrypted: i=1; AJvYcCUgEgJSfxhlv3g+WZ4jk1gnDVwdjPfawUjprenqdI+Udd37xzGzbMJF5Nw6E9xKBDduS01olLSW2haT@nongnu.org X-Gm-Message-State: AOJu0Ywm9ShmBZdBBashq3c9njzlECmAfnyIowMChkxJSyU4p1VLn8SJ YraTf9xtk1B5vE6ydASRHYMd549oSMi/bkRFF86PPRjKxY228Kkazz4vRw== X-Google-Smtp-Source: AGHT+IHBUPL5nz7OqvsUPE8Y1i5VLjcvSprM81EOfQEbK6fjcc/rFdyFy/rWCu9mivWCXbT6kh6Z8g== X-Received: by 2002:a05:6402:42ca:b0:5c9:85ce:d9cd with SMTP id 4fb4d7f45d1cf-5c985cedb2cmr8335958a12.3.1729074499927; Wed, 16 Oct 2024 03:28:19 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:eb7f:8fd0:f96c:766b]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5c98d4f85dcsm1566680a12.22.2024.10.16.03.28.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Oct 2024 03:28:19 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v4 2/8] chardev/char: rename `char-mux.c` to `char-mux-fe.c` Date: Wed, 16 Oct 2024 12:25:59 +0200 Message-Id: <20241016102605.459395-3-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241016102605.459395-1-r.peniaev@gmail.com> References: <20241016102605.459395-1-r.peniaev@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::532; envelope-from=r.peniaev@gmail.com; helo=mail-ed1-x532.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org In the following patches backend multiplexer will be introduced and the implementation will be named as follows: `char-mux-be.c`. This patch renames the frontend multiplexer from `char-mux.c` to `char-mux-fe.c`. Signed-off-by: Roman Penyaev Cc: "Marc-André Lureau" Cc: qemu-devel@nongnu.org --- chardev/{char-mux.c => char-mux-fe.c} | 0 chardev/meson.build | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename chardev/{char-mux.c => char-mux-fe.c} (100%) diff --git a/chardev/char-mux.c b/chardev/char-mux-fe.c similarity index 100% rename from chardev/char-mux.c rename to chardev/char-mux-fe.c diff --git a/chardev/meson.build b/chardev/meson.build index 70070a8279a9..778444a00ca6 100644 --- a/chardev/meson.build +++ b/chardev/meson.build @@ -2,7 +2,7 @@ chardev_ss.add(files( 'char-fe.c', 'char-file.c', 'char-io.c', - 'char-mux.c', + 'char-mux-fe.c', 'char-null.c', 'char-pipe.c', 'char-ringbuf.c', From patchwork Wed Oct 16 10:26:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13838179 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 90506D1AD43 for ; Wed, 16 Oct 2024 10:29:46 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t11GV-0003ip-OV; Wed, 16 Oct 2024 06:28:27 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1t11GS-0003hm-U0 for qemu-devel@nongnu.org; Wed, 16 Oct 2024 06:28:24 -0400 Received: from mail-lf1-x12e.google.com ([2a00:1450:4864:20::12e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1t11GQ-00048y-ME for qemu-devel@nongnu.org; Wed, 16 Oct 2024 06:28:24 -0400 Received: by mail-lf1-x12e.google.com with SMTP id 2adb3069b0e04-539f0f9ee49so3968885e87.1 for ; Wed, 16 Oct 2024 03:28:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1729074501; x=1729679301; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=qBhjMyaS7m28UKrmGr2wsVJl2lrhr5g7YG4lTUQ0QeA=; b=ayM1WTO1dCly4YZ4RdSrp4V24x5+JUt+qZhOUwf02PfKKtNTWEC+I65WwdxVuW+PDJ VkRyMlQzzDbASf/paTAdh2NXcBbYGtoOJgCyk8IV8KTPOUbCrUfqm5KOziCxVwZFRcbp UNNur3elR0fj2oDFrJJdIRE5MFEGoNqDRfhHh04iFCrxYlYwSiV5chEjNuoAu6sE/pr7 dqp9FiMv7dD4BSx5zYpTIrOlkRje2v8bKLsRACOUMiGmsxurbuhW+4+RTyvVOh+sZq9q 3VpI/74UkZAtCv8hvk8AMN98SJRWfpfo6WXitYKZ3dqKivsKxwijosGrYEgBDsuRt3WX DVkg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729074501; x=1729679301; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=qBhjMyaS7m28UKrmGr2wsVJl2lrhr5g7YG4lTUQ0QeA=; b=OKKRxOTuQY9eUvVd35wXPMkr2nLZQkinNeqtT2D04NdEA8rraJ9UPivZK2VF9coCS/ InoVWm8b0ADSxKI9Zf7Jr68SvOsx5xZfykbecIGZAjfyYOHCSTeXUiMOWnh8/iRTbTAS RCUDHwMZyReP8vGpiTiq3k7Nq6apo1x11tqFhfAf9aWD3Y39kV5UBYNOizegtPoJv+21 L++JG+yY06fubj0aQ+PuUvylGIjvmkhtVtKddTG12ulb3e6FQhOujCkpU/I2b223dMFF HZjB68Cna4xmGr8wDSVMThhGVHwTz40MjuNfSeFEjgDN+Ma8RApaUTWUNlpPNC/pCvT8 AAFw== X-Forwarded-Encrypted: i=1; AJvYcCXwSJzmykssa6xQH3tdmIumHmqC2GoIoMCZl8NeMC11C4am87Sm1g9u2A+X19h7dYECi7MDJmyHL2O9@nongnu.org X-Gm-Message-State: AOJu0Yz3DtVGriYgZYPUCArNGDBfDRnewQ5E2p5TD4emRWTpLjwboZaa d7ezFWLwQ8JyilQOEKWdD+jdxoLypwQ8hqaFgHNhSNKxnxaaUhpL X-Google-Smtp-Source: AGHT+IGlJqsEODxYMPoj0SCj/kWFNA14FL0D/CDM93fwsXU6/6fuvTCbzwp9dbUMjDR96Qv7S+hqPg== X-Received: by 2002:a05:6512:b1c:b0:539:9524:92bc with SMTP id 2adb3069b0e04-53a03f826f9mr2195662e87.55.1729074500412; Wed, 16 Oct 2024 03:28:20 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:eb7f:8fd0:f96c:766b]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5c98d4f85dcsm1566680a12.22.2024.10.16.03.28.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Oct 2024 03:28:20 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v4 3/8] chardev/char: move away mux suspend/resume calls Date: Wed, 16 Oct 2024 12:26:00 +0200 Message-Id: <20241016102605.459395-4-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241016102605.459395-1-r.peniaev@gmail.com> References: <20241016102605.459395-1-r.peniaev@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::12e; envelope-from=r.peniaev@gmail.com; helo=mail-lf1-x12e.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org The suspend/resume open multiplexer calls are generic and will be used for frontend (current mux) and backend (will follow) implementations. Move them away from the `char-mux-fe.c` to more generic `char.c` file. Also for the sake of clarity these renames were made: s/suspend_mux_open/mux_suspend_open/g s/resume_mux_open/mux_resume_open/g No functional changes are made. Signed-off-by: Roman Penyaev Cc: "Marc-André Lureau" Cc: qemu-devel@nongnu.org --- chardev/char-mux-fe.c | 63 ++------------------------------- chardev/char.c | 72 ++++++++++++++++++++++++++++++++++++++ chardev/chardev-internal.h | 3 ++ include/chardev/char.h | 5 +-- system/vl.c | 4 +-- 5 files changed, 82 insertions(+), 65 deletions(-) diff --git a/chardev/char-mux-fe.c b/chardev/char-mux-fe.c index dfaea5aefac3..6a195390a3c9 100644 --- a/chardev/char-mux-fe.c +++ b/chardev/char-mux-fe.c @@ -34,13 +34,6 @@ /* MUX driver for serial I/O splitting */ -/* - * Set to false by suspend_mux_open. Open events are delayed until - * resume_mux_open. Usually suspend_mux_open is called before - * command line processing and resume_mux_open afterwards. - */ -static bool muxes_opened = true; - /* Called with chr_write_lock held. */ static int mux_chr_write(Chardev *chr, const uint8_t *buf, int len) { @@ -248,15 +241,10 @@ static void mux_chr_read(void *opaque, const uint8_t *buf, int size) } } -void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event) +void mux_fe_chr_send_all_event(MuxFeChardev *d, QEMUChrEvent event) { - MuxFeChardev *d = MUX_FE_CHARDEV(chr); int bit; - if (!muxes_opened) { - return; - } - /* Send the event to all registered listeners */ bit = -1; while ((bit = find_next_bit(&d->mux_bitset, MAX_MUX, bit + 1)) < MAX_MUX) { @@ -381,7 +369,7 @@ static void qemu_chr_open_mux(Chardev *chr, /* only default to opened state if we've realized the initial * set of muxes */ - *be_opened = muxes_opened; + *be_opened = mux_is_opened(); qemu_chr_fe_init(&d->chr, drv, errp); } @@ -401,53 +389,6 @@ static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend, mux->chardev = g_strdup(chardev); } -/** - * Called after processing of default and command-line-specified - * chardevs to deliver CHR_EVENT_OPENED events to any FEs attached - * to a mux chardev. This is done here to ensure that - * output/prompts/banners are only displayed for the FE that has - * focus when initial command-line processing/machine init is - * completed. - * - * After this point, any new FE attached to any new or existing - * mux will receive CHR_EVENT_OPENED notifications for the BE - * immediately. - */ -static void open_muxes(Chardev *chr) -{ - /* send OPENED to all already-attached FEs */ - mux_chr_send_all_event(chr, CHR_EVENT_OPENED); - - /* - * mark mux as OPENED so any new FEs will immediately receive - * OPENED event - */ - chr->be_open = 1; -} - -void suspend_mux_open(void) -{ - muxes_opened = false; -} - -static int chardev_options_parsed_cb(Object *child, void *opaque) -{ - Chardev *chr = (Chardev *)child; - - if (!chr->be_open && CHARDEV_IS_MUX_FE(chr)) { - open_muxes(chr); - } - - return 0; -} - -void resume_mux_open(void) -{ - muxes_opened = true; - object_child_foreach(get_chardevs_root(), - chardev_options_parsed_cb, NULL); -} - static void char_mux_class_init(ObjectClass *oc, void *data) { ChardevClass *cc = CHARDEV_CLASS(oc); diff --git a/chardev/char.c b/chardev/char.c index e077773cdece..d8dbdb6f84f1 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -43,6 +43,13 @@ #include "chardev-internal.h" +/* + * Set to false by mux_suspend_open(). Open events are delayed until + * mux_resume_open(). Usually mux_suspend_open() is called before + * command line processing and mux_resume_open() afterwards. + */ +static bool muxes_opened = true; + /***********************************************************/ /* character device */ @@ -1259,6 +1266,71 @@ void qemu_chr_cleanup(void) object_unparent(get_chardevs_root()); } +/** + * Called after processing of default and command-line-specified + * chardevs to deliver CHR_EVENT_OPENED events to any FEs attached + * to a mux chardev. This is done here to ensure that + * output/prompts/banners are only displayed for the FE that has + * focus when initial command-line processing/machine init is + * completed. + * + * After this point, any new FE attached to any new or existing + * mux will receive CHR_EVENT_OPENED notifications for the BE + * immediately. + */ +static void open_muxes(Chardev *chr) +{ + /* send OPENED to all already-attached FEs */ + mux_chr_send_all_event(chr, CHR_EVENT_OPENED); + + /* + * mark mux as OPENED so any new FEs will immediately receive + * OPENED event + */ + chr->be_open = 1; +} + +void mux_suspend_open(void) +{ + muxes_opened = false; +} + +static int chardev_options_parsed_cb(Object *child, void *opaque) +{ + Chardev *chr = (Chardev *)child; + + if (!chr->be_open && CHARDEV_IS_MUX_FE(chr)) { + open_muxes(chr); + } + + return 0; +} + +void mux_resume_open(void) +{ + muxes_opened = true; + object_child_foreach(get_chardevs_root(), + chardev_options_parsed_cb, NULL); +} + +bool mux_is_opened(void) +{ + return muxes_opened; +} + +void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event) +{ + if (!mux_is_opened()) { + return; + } + + if (CHARDEV_IS_MUX_FE(chr)) { + MuxFeChardev *d = MUX_FE_CHARDEV(chr); + + mux_fe_chr_send_all_event(d, event); + } +} + static void register_types(void) { type_register_static(&char_type_info); diff --git a/chardev/chardev-internal.h b/chardev/chardev-internal.h index 321051bb9cc5..c874850a41ad 100644 --- a/chardev/chardev-internal.h +++ b/chardev/chardev-internal.h @@ -65,6 +65,9 @@ bool mux_chr_detach_frontend(MuxFeChardev *d, unsigned int tag); void mux_set_focus(Chardev *chr, unsigned int focus); void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event); +/* Mux type dependent calls */ +void mux_fe_chr_send_all_event(MuxFeChardev *d, QEMUChrEvent event); + Object *get_chardevs_root(void); #endif /* CHARDEV_INTERNAL_H */ diff --git a/include/chardev/char.h b/include/chardev/char.h index d9d23b6232db..0bec974f9d73 100644 --- a/include/chardev/char.h +++ b/include/chardev/char.h @@ -317,7 +317,8 @@ extern int term_escape_char; GSource *qemu_chr_timeout_add_ms(Chardev *chr, guint ms, GSourceFunc func, void *private); -void suspend_mux_open(void); -void resume_mux_open(void); +bool mux_is_opened(void); +void mux_suspend_open(void); +void mux_resume_open(void); #endif diff --git a/system/vl.c b/system/vl.c index e83b3b2608bf..b3cbfe2c0f84 100644 --- a/system/vl.c +++ b/system/vl.c @@ -3679,7 +3679,7 @@ void qemu_init(int argc, char **argv) qemu_create_machine(machine_opts_dict); - suspend_mux_open(); + mux_suspend_open(); qemu_disable_default_devices(); qemu_setup_display(); @@ -3757,5 +3757,5 @@ void qemu_init(int argc, char **argv) qemu_init_displays(); accel_setup_post(current_machine); os_setup_post(); - resume_mux_open(); + mux_resume_open(); } From patchwork Wed Oct 16 10:26:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13838176 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id F3544D1AD42 for ; Wed, 16 Oct 2024 10:29:04 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t11GW-0003j7-IE; Wed, 16 Oct 2024 06:28:28 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1t11GV-0003iX-19 for qemu-devel@nongnu.org; Wed, 16 Oct 2024 06:28:27 -0400 Received: from mail-ed1-x52f.google.com ([2a00:1450:4864:20::52f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1t11GT-00049X-3M for qemu-devel@nongnu.org; Wed, 16 Oct 2024 06:28:26 -0400 Received: by mail-ed1-x52f.google.com with SMTP id 4fb4d7f45d1cf-5c94c4ad9d8so7269112a12.2 for ; Wed, 16 Oct 2024 03:28:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1729074504; x=1729679304; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=GanDoQPe72SVPSkPSldUjnclOENoEQhhoRjErfVjJmU=; b=YaIl0Ecd3kSlpw0FVWHLsaClbz02lJ9Fw6LV1Pg4AmutgitmZgOQR2aqBOZgXFT9tw ubNmCWHiR0dce9qzPIXeAZRjudZpd58xSmHWtYFp/+oKA32toUGXHoxh5p2BLqpbz9WL N8L0DLaU7j/dZkHljOIvN7kf7rfNfSPSTXyDgX06FAz3LPWN0bUbtxLAeqw7zwflpqnm 5yc7dzs+75PITFVgkAGtqCEJwoKr5AVyDISysoEsETe0ttByIag2NTaSIfWC0pXiBT2q et+WTsqQmNEkc9yhuekU8qPy7AB985tRzHqPtUXGy3rh671aTyHfL4ffZPbp1Vj/24SI ZFTA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729074504; x=1729679304; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=GanDoQPe72SVPSkPSldUjnclOENoEQhhoRjErfVjJmU=; b=fub4TDO9jnqD957BUMhN+GOUd6WDcKgQu0h1H1YmuQ6TaVFWJhsPNmAlcQ12wSPZKU hix0HPARtHqdz9xd6LMZ4lzNR4ckIV6xHaYreevV1aifs358qskcciMAZiGr1yAlH4qv weTuvhrmAEusvZxVTJPqPA6KfDJ7RhsikZNnvcVzzb9ZQ/U/Vj7ktyw5a+ltIWKu0TJe v+4mZiBRGRKYlIFfxZ3FBwcO1/XtUE4WhVN4thfkM05CWXZclJtoYq6e9yM9+dQFWeKl 5Lvjs3/CgjFqZHLZqvMmUoh8kc4M6189/GocngWiXtsqOktcetCX3QO0NhEpRtE+KnKT Ijgg== X-Forwarded-Encrypted: i=1; AJvYcCXAPvA8kZiw/VJs3IckOY8IdSyKcxSwPAOpV/jMfWZbUe3XTozbOdCderAOZq12+ew++81jva8wPuKW@nongnu.org X-Gm-Message-State: AOJu0YyeLWWlt026yYoH+1VihMp5QrhNV0crTxKk+dFG0MqHwLKGpn0I e4L/cZIyzVALGGY71BB4kBF7V2yJNHV5MZqN2tH/vc4s2UYH67xo X-Google-Smtp-Source: AGHT+IEH8HLAGAgOv4F0RXAd+jPdmK9knmIvKeNC8AG/hVK2E7zd9R+5C/CuLnjkscEcAhSmN6dxtw== X-Received: by 2002:a05:6402:2804:b0:5c9:29f3:fba3 with SMTP id 4fb4d7f45d1cf-5c948cca98bmr15536176a12.20.1729074503333; Wed, 16 Oct 2024 03:28:23 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:eb7f:8fd0:f96c:766b]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5c98d4f85dcsm1566680a12.22.2024.10.16.03.28.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Oct 2024 03:28:20 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v4 4/8] chardev/char: rename frontend mux calls Date: Wed, 16 Oct 2024 12:26:01 +0200 Message-Id: <20241016102605.459395-5-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241016102605.459395-1-r.peniaev@gmail.com> References: <20241016102605.459395-1-r.peniaev@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::52f; envelope-from=r.peniaev@gmail.com; helo=mail-ed1-x52f.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This patch renames calls in the frontend mux implementation to reflect its frontend nature. Patch does the following: s/mux_chr/mux_fe_chr/g No functional changes are made. Signed-off-by: Roman Penyaev Cc: "Marc-André Lureau" Cc: qemu-devel@nongnu.org --- chardev/char-fe.c | 6 ++-- chardev/char-mux-fe.c | 68 +++++++++++++++++++------------------- chardev/chardev-internal.h | 8 ++--- 3 files changed, 41 insertions(+), 41 deletions(-) diff --git a/chardev/char-fe.c b/chardev/char-fe.c index 7b1ae16c62a4..a2b5bff39fd9 100644 --- a/chardev/char-fe.c +++ b/chardev/char-fe.c @@ -197,7 +197,7 @@ bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp) if (CHARDEV_IS_MUX_FE(s)) { MuxFeChardev *d = MUX_FE_CHARDEV(s); - if (!mux_chr_attach_frontend(d, b, &tag, errp)) { + if (!mux_fe_chr_attach_frontend(d, b, &tag, errp)) { return false; } } else if (s->be) { @@ -225,7 +225,7 @@ void qemu_chr_fe_deinit(CharBackend *b, bool del) } if (CHARDEV_IS_MUX_FE(b->chr)) { MuxFeChardev *d = MUX_FE_CHARDEV(b->chr); - mux_chr_detach_frontend(d, b->tag); + mux_fe_chr_detach_frontend(d, b->tag); } if (del) { Object *obj = OBJECT(b->chr); @@ -306,7 +306,7 @@ void qemu_chr_fe_take_focus(CharBackend *b) } if (CHARDEV_IS_MUX_FE(b->chr)) { - mux_set_focus(b->chr, b->tag); + mux_fe_chr_set_focus(b->chr, b->tag); } } diff --git a/chardev/char-mux-fe.c b/chardev/char-mux-fe.c index 6a195390a3c9..dcfce099ea9a 100644 --- a/chardev/char-mux-fe.c +++ b/chardev/char-mux-fe.c @@ -35,7 +35,7 @@ /* MUX driver for serial I/O splitting */ /* Called with chr_write_lock held. */ -static int mux_chr_write(Chardev *chr, const uint8_t *buf, int len) +static int mux_fe_chr_write(Chardev *chr, const uint8_t *buf, int len) { MuxFeChardev *d = MUX_FE_CHARDEV(chr); int ret; @@ -118,8 +118,8 @@ static void mux_print_help(Chardev *chr) } } -static void mux_chr_send_event(MuxFeChardev *d, unsigned int mux_nr, - QEMUChrEvent event) +static void mux_fe_chr_send_event(MuxFeChardev *d, unsigned int mux_nr, + QEMUChrEvent event) { CharBackend *be = d->backends[mux_nr]; @@ -128,12 +128,12 @@ static void mux_chr_send_event(MuxFeChardev *d, unsigned int mux_nr, } } -static void mux_chr_be_event(Chardev *chr, QEMUChrEvent event) +static void mux_fe_chr_be_event(Chardev *chr, QEMUChrEvent event) { MuxFeChardev *d = MUX_FE_CHARDEV(chr); if (d->focus != -1) { - mux_chr_send_event(d, d->focus, event); + mux_fe_chr_send_event(d, d->focus, event); } } @@ -172,7 +172,7 @@ static int mux_proc_byte(Chardev *chr, MuxFeChardev *d, int ch) if (bit >= MAX_MUX) { bit = find_next_bit(&d->mux_bitset, MAX_MUX, 0); } - mux_set_focus(chr, bit); + mux_fe_chr_set_focus(chr, bit); break; } case 't': d->timestamps = !d->timestamps; @@ -189,7 +189,7 @@ static int mux_proc_byte(Chardev *chr, MuxFeChardev *d, int ch) return 0; } -static void mux_chr_accept_input(Chardev *chr) +static void mux_fe_chr_accept_input(Chardev *chr) { MuxFeChardev *d = MUX_FE_CHARDEV(chr); int m = d->focus; @@ -202,7 +202,7 @@ static void mux_chr_accept_input(Chardev *chr) } } -static int mux_chr_can_read(void *opaque) +static int mux_fe_chr_can_read(void *opaque) { MuxFeChardev *d = MUX_FE_CHARDEV(opaque); int m = d->focus; @@ -219,7 +219,7 @@ static int mux_chr_can_read(void *opaque) return 0; } -static void mux_chr_read(void *opaque, const uint8_t *buf, int size) +static void mux_fe_chr_read(void *opaque, const uint8_t *buf, int size) { Chardev *chr = CHARDEV(opaque); MuxFeChardev *d = MUX_FE_CHARDEV(opaque); @@ -227,7 +227,7 @@ static void mux_chr_read(void *opaque, const uint8_t *buf, int size) CharBackend *be = d->backends[m]; int i; - mux_chr_accept_input(opaque); + mux_fe_chr_accept_input(opaque); for (i = 0; i < size; i++) if (mux_proc_byte(chr, d, buf[i])) { @@ -248,16 +248,16 @@ void mux_fe_chr_send_all_event(MuxFeChardev *d, QEMUChrEvent event) /* Send the event to all registered listeners */ bit = -1; while ((bit = find_next_bit(&d->mux_bitset, MAX_MUX, bit + 1)) < MAX_MUX) { - mux_chr_send_event(d, bit, event); + mux_fe_chr_send_event(d, bit, event); } } -static void mux_chr_event(void *opaque, QEMUChrEvent event) +static void mux_fe_chr_event(void *opaque, QEMUChrEvent event) { mux_chr_send_all_event(CHARDEV(opaque), event); } -static GSource *mux_chr_add_watch(Chardev *s, GIOCondition cond) +static GSource *mux_fe_chr_add_watch(Chardev *s, GIOCondition cond) { MuxFeChardev *d = MUX_FE_CHARDEV(s); Chardev *chr = qemu_chr_fe_get_driver(&d->chr); @@ -270,7 +270,7 @@ static GSource *mux_chr_add_watch(Chardev *s, GIOCondition cond) return cc->chr_add_watch(chr, cond); } -static void char_mux_finalize(Object *obj) +static void char_mux_fe_finalize(Object *obj) { MuxFeChardev *d = MUX_FE_CHARDEV(obj); int bit; @@ -285,22 +285,22 @@ static void char_mux_finalize(Object *obj) qemu_chr_fe_deinit(&d->chr, false); } -static void mux_chr_update_read_handlers(Chardev *chr) +static void mux_fe_chr_update_read_handlers(Chardev *chr) { MuxFeChardev *d = MUX_FE_CHARDEV(chr); /* Fix up the real driver with mux routines */ qemu_chr_fe_set_handlers_full(&d->chr, - mux_chr_can_read, - mux_chr_read, - mux_chr_event, + mux_fe_chr_can_read, + mux_fe_chr_read, + mux_fe_chr_event, NULL, chr, chr->gcontext, true, false); } -bool mux_chr_attach_frontend(MuxFeChardev *d, CharBackend *b, - unsigned int *tag, Error **errp) +bool mux_fe_chr_attach_frontend(MuxFeChardev *d, CharBackend *b, + unsigned int *tag, Error **errp) { unsigned int bit; @@ -320,7 +320,7 @@ bool mux_chr_attach_frontend(MuxFeChardev *d, CharBackend *b, return true; } -bool mux_chr_detach_frontend(MuxFeChardev *d, unsigned int tag) +bool mux_fe_chr_detach_frontend(MuxFeChardev *d, unsigned int tag) { unsigned int bit; @@ -335,19 +335,19 @@ bool mux_chr_detach_frontend(MuxFeChardev *d, unsigned int tag) return true; } -void mux_set_focus(Chardev *chr, unsigned int focus) +void mux_fe_chr_set_focus(Chardev *chr, unsigned int focus) { MuxFeChardev *d = MUX_FE_CHARDEV(chr); assert(find_next_bit(&d->mux_bitset, MAX_MUX, focus) == focus); if (d->focus != -1) { - mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT); + mux_fe_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT); } d->focus = focus; chr->be = d->backends[focus]; - mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN); + mux_fe_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN); } static void qemu_chr_open_mux(Chardev *chr, @@ -389,30 +389,30 @@ static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend, mux->chardev = g_strdup(chardev); } -static void char_mux_class_init(ObjectClass *oc, void *data) +static void char_mux_fe_class_init(ObjectClass *oc, void *data) { ChardevClass *cc = CHARDEV_CLASS(oc); cc->parse = qemu_chr_parse_mux; cc->open = qemu_chr_open_mux; - cc->chr_write = mux_chr_write; - cc->chr_accept_input = mux_chr_accept_input; - cc->chr_add_watch = mux_chr_add_watch; - cc->chr_be_event = mux_chr_be_event; - cc->chr_update_read_handler = mux_chr_update_read_handlers; + cc->chr_write = mux_fe_chr_write; + cc->chr_accept_input = mux_fe_chr_accept_input; + cc->chr_add_watch = mux_fe_chr_add_watch; + cc->chr_be_event = mux_fe_chr_be_event; + cc->chr_update_read_handler = mux_fe_chr_update_read_handlers; } -static const TypeInfo char_mux_type_info = { +static const TypeInfo char_mux_fe_type_info = { .name = TYPE_CHARDEV_MUX_FE, .parent = TYPE_CHARDEV, - .class_init = char_mux_class_init, + .class_init = char_mux_fe_class_init, .instance_size = sizeof(MuxFeChardev), - .instance_finalize = char_mux_finalize, + .instance_finalize = char_mux_fe_finalize, }; static void register_types(void) { - type_register_static(&char_mux_type_info); + type_register_static(&char_mux_fe_type_info); } type_init(register_types); diff --git a/chardev/chardev-internal.h b/chardev/chardev-internal.h index c874850a41ad..94c8d07ac235 100644 --- a/chardev/chardev-internal.h +++ b/chardev/chardev-internal.h @@ -59,14 +59,14 @@ DECLARE_INSTANCE_CHECKER(MuxFeChardev, MUX_FE_CHARDEV, #define CHARDEV_IS_MUX_FE(chr) \ object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_MUX_FE) -bool mux_chr_attach_frontend(MuxFeChardev *d, CharBackend *b, - unsigned int *tag, Error **errp); -bool mux_chr_detach_frontend(MuxFeChardev *d, unsigned int tag); -void mux_set_focus(Chardev *chr, unsigned int focus); void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event); /* Mux type dependent calls */ +void mux_fe_chr_set_focus(Chardev *d, unsigned int focus); void mux_fe_chr_send_all_event(MuxFeChardev *d, QEMUChrEvent event); +bool mux_fe_chr_attach_frontend(MuxFeChardev *d, CharBackend *b, + unsigned int *tag, Error **errp); +bool mux_fe_chr_detach_frontend(MuxFeChardev *d, unsigned int tag); Object *get_chardevs_root(void); From patchwork Wed Oct 16 10:26:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13838175 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 0BD4BD1AD43 for ; Wed, 16 Oct 2024 10:29:02 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t11GY-0003jc-9w; Wed, 16 Oct 2024 06:28:30 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1t11GV-0003iZ-7k for qemu-devel@nongnu.org; Wed, 16 Oct 2024 06:28:27 -0400 Received: from mail-ed1-x530.google.com ([2a00:1450:4864:20::530]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1t11GT-00049f-QG for qemu-devel@nongnu.org; Wed, 16 Oct 2024 06:28:26 -0400 Received: by mail-ed1-x530.google.com with SMTP id 4fb4d7f45d1cf-5c94c4ad9d8so7269124a12.2 for ; Wed, 16 Oct 2024 03:28:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1729074504; x=1729679304; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=TcLknQffuaT4ojoTGdmSGCeAGfXDZnwetn6Ee4o+pCY=; b=gT/Nsc17ih6Evz5nQrcI7fZhg/YjhSjBSgLRc0P2u3Fu/tpXnaplahuUH7FVTq8vHw wl9yi+SgxketjT84drDdS8EYAcWP7zNX3ymwoLdwApclggpXOjIzJAB2DjzJ3FPj2TI8 ZMj52AoI01itp3/uGnvhJ0CabZCiSDEwTOjr+4y9py/JwfLlSPMwSmA/2nplGtLl5Xdc u2bOCDWBAV1+Xk86DYLgT8ZVhO/fLnTpUn41begiMc6QABwy3NwBhTFQWbibfQ+IwXkJ VhiKwUzT76k2Q3Ky+/lIJkCInd1GOXeGn6nvPvYSmpeSYIkMybEYLKFwRelw3aNMnURN TJAQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729074504; x=1729679304; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=TcLknQffuaT4ojoTGdmSGCeAGfXDZnwetn6Ee4o+pCY=; b=jcdRH37Y6gxB2UDe+pTooVblsbO/vsK5bHyLOLfWXswna3XdOZClx0Mi0RU4JB7DsU Cw3mSIyLVH4U0uZQ3k+dUbAzBxpNTkqzzZDShQjMvELsvS+HXxUGPhpCT+sgFsoEHV5j Qu6Tx/q2bIhOXXBt42+DkBgD4Zcts1DV5U7ZJfU33epg/e82slXVCajreq0lCWJ7L/qu U8/lu9T+r0R5YZfO0WUiifRn8iIDdeDkiVogVH+2kNwaL3CH1b1G56zSAvI4fl5b1t5m QJGjhzKg3XeMNoM2My0kLsvakIo+k1tIczh3EdhpjG5lXJomd5netGvZ8u8JKoWeXiwf 8LTw== X-Forwarded-Encrypted: i=1; AJvYcCUBY6J+XMaZ/Xy4lciLpdlPxogRR1nAyW4SxkmLQoQNUlFDxbaQCQDOTml3TfVB4hh2RH5T5QbUVC7L@nongnu.org X-Gm-Message-State: AOJu0YzSqZvRdmMLXWaZliLBE7UgilNThoehTbn/MaYZwatnU57xB2Dc HSuWdAqrEs/oFchxSg6l7FGrz7Sa/SsW5PLZ9Cosfj+1idisoQbrpfeE0Q== X-Google-Smtp-Source: AGHT+IGeqNkFEzAJmjUgv9SBOdaNXbwaZ1PYb6q2FNk2/RygJ8/fE4wmbyxIlSWBWqioudYEUIiyLQ== X-Received: by 2002:a05:6402:1e8e:b0:5c9:7024:234f with SMTP id 4fb4d7f45d1cf-5c970242a14mr8582767a12.6.1729074504076; Wed, 16 Oct 2024 03:28:24 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:eb7f:8fd0:f96c:766b]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5c98d4f85dcsm1566680a12.22.2024.10.16.03.28.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Oct 2024 03:28:23 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v4 5/8] chardev/char: introduce `mux-be-id=ID` option Date: Wed, 16 Oct 2024 12:26:02 +0200 Message-Id: <20241016102605.459395-6-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241016102605.459395-1-r.peniaev@gmail.com> References: <20241016102605.459395-1-r.peniaev@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::530; envelope-from=r.peniaev@gmail.com; helo=mail-ed1-x530.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Patch introduces `mux-be-id=ID` option for all chardev devices. This is necessary to attach chardev to `mux-be` for backend multiplexing. Actual implementation wimplementation will follow. Signed-off-by: Roman Penyaev Cc: "Marc-André Lureau" Cc: qemu-devel@nongnu.org --- chardev/char.c | 3 +++ qapi/char.json | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/chardev/char.c b/chardev/char.c index d8dbdb6f84f1..cffe60860589 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -933,6 +933,9 @@ QemuOptsList qemu_chardev_opts = { },{ .name = "mux", .type = QEMU_OPT_BOOL, + },{ + .name = "mux-be-id", + .type = QEMU_OPT_STRING, },{ .name = "signal", .type = QEMU_OPT_BOOL, diff --git a/qapi/char.json b/qapi/char.json index e04535435034..fb0dedb24383 100644 --- a/qapi/char.json +++ b/qapi/char.json @@ -199,11 +199,15 @@ # @logappend: true to append instead of truncate (default to false to # truncate) # +# @mux-be-id: id of the mux-be device for backend multiplexing +# (since: 9.2) +# # Since: 2.6 ## { 'struct': 'ChardevCommon', 'data': { '*logfile': 'str', - '*logappend': 'bool' } } + '*logappend': 'bool', + '*mux-be-id': 'str' } } ## # @ChardevFile: From patchwork Wed Oct 16 10:26:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13838174 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 183F8D1AD42 for ; Wed, 16 Oct 2024 10:28:56 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t11Ga-0003k2-8z; Wed, 16 Oct 2024 06:28:32 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1t11GY-0003jk-PW for qemu-devel@nongnu.org; Wed, 16 Oct 2024 06:28:30 -0400 Received: from mail-ed1-x534.google.com ([2a00:1450:4864:20::534]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1t11GW-0004A1-1M for qemu-devel@nongnu.org; Wed, 16 Oct 2024 06:28:30 -0400 Received: by mail-ed1-x534.google.com with SMTP id 4fb4d7f45d1cf-5c948c41edeso6558512a12.1 for ; Wed, 16 Oct 2024 03:28:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1729074506; x=1729679306; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=X9zT3MZrOGL/t29kFbnD0fAH14pe4eE+Lql08cruuD8=; b=VahrHyGVOe+RAPAGODiorSyCDr/3QroiMT7Rt2kj/A9mmBb9sxlMC04P3Qt/CmsjPo Vht7DhdTmk9ZfqQvqUwUAS5Yp2K8Jn0Nme+X4ZRW2IVeGJm3Z5WfBOAhDDidIm541oE7 itqZeUP1Yo+No/Zzt3wee6/o39302C/su5sGL63/1NB/hOKvyjhchD1VS3OcMNj3Vz/R 1iB7yTj7mSOQffRaO6elIsxNmZanv56pajOgHegGpSMgexfkker3VDmkljJW/ua+i5+1 0ycE2FXLMgkn135wz9oUutiWznW8LnpKbOzrwGFpXIoOUUJxYy4ziTeslZK+DMyEr6Kx hdXg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729074506; x=1729679306; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=X9zT3MZrOGL/t29kFbnD0fAH14pe4eE+Lql08cruuD8=; b=et2xuXXMwGlRIqTiFtsz1wEYJox8DlPUPlEQJhNuv1FcLl9mPDl298ZzPa1wOMRMzv Ku8+BCvXALWLOPHpGxkEyd7Iv5+JKH7ugyWC6fCjB7yAU9q7Z58XNys8DUPWsg5D89xM zdnWnLmSy3pmX6TeXrnQe+C01thfgWZWa6RFmZwSdZEyartOePZtkTFf8B+3p1xXA01q bi31GuTxp3rVf6vfAHN9mN7Fp1YtDOUfOY5QHR2ume3/iylhJaVDIgm4IPWXdSltBNOM 5YIItwGaHR2Zof8jHbmTsgYKqCL4Poa4zsHvG2On3D/bqsu7qJXgjjrUmm4rZvxzYkBn EOrA== X-Forwarded-Encrypted: i=1; AJvYcCUzWKulsGloXqrjsrMlpJ5vBfrt5+zvO/1UFBQq8Pzv2hvv7J51uQwtZrYH0fZtt2c2kbRqkcOItoR4@nongnu.org X-Gm-Message-State: AOJu0Yxv0jHvPM+w5OfJulU/FzIxjypm47vlKnd9XBiwqFKYg8QKLRzZ sv8gDazrWEmDMiCOCQgbJn7z8RffNv1sZ6niybuQ0NIsQNa5axEHKheETQ== X-Google-Smtp-Source: AGHT+IHg8OdJZD4dP72XHOIWgWia+M/NmjJT1BsBtw9roL2EKPlqdEILD37erD8rkn3mD6tVQdJsPw== X-Received: by 2002:a05:6402:3510:b0:5c9:5584:ddb8 with SMTP id 4fb4d7f45d1cf-5c95584de65mr12265460a12.12.1729074506033; Wed, 16 Oct 2024 03:28:26 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:eb7f:8fd0:f96c:766b]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5c98d4f85dcsm1566680a12.22.2024.10.16.03.28.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Oct 2024 03:28:24 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v4 6/8] chardev/char-mux: implement backend chardev multiplexing Date: Wed, 16 Oct 2024 12:26:03 +0200 Message-Id: <20241016102605.459395-7-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241016102605.459395-1-r.peniaev@gmail.com> References: <20241016102605.459395-1-r.peniaev@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::534; envelope-from=r.peniaev@gmail.com; helo=mail-ed1-x534.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This patch implements multiplexing capability of several backend devices, which opens up an opportunity to use a single frontend device on the guest, which can be manipulated from several backend devices. The idea of the change is trivial: keep list of backend devices (up to 4), init them on demand and forward data buffer back and forth. Patch implements another multiplexer type `mux-be`. The following is QEMU command line example: -chardev mux-be,id=mux0 \ -chardev socket,path=/tmp/sock,server=on,wait=off,id=sock0,mux-be-id=mux0 \ -chardev vc,id=vc0,mux-be-id=mux0 \ -device virtconsole,chardev=mux0 \ -vnc 0.0.0.0:0 Which creates 2 backend devices: text virtual console (`vc0`) and a socket (`sock0`) connected to the single virtio hvc console with the backend multiplexer (`mux0`) help. `vc0` renders text to an image, which can be shared over the VNC protocol. `sock0` is a socket backend which provides biderectional communication to the virtio hvc console. Signed-off-by: Roman Penyaev Cc: "Marc-André Lureau" Cc: qemu-devel@nongnu.org --- chardev/char-fe.c | 9 ++ chardev/char-mux-be.c | 290 +++++++++++++++++++++++++++++++++++++ chardev/char.c | 56 +++++-- chardev/chardev-internal.h | 34 ++++- chardev/meson.build | 1 + include/chardev/char.h | 1 + qapi/char.json | 25 ++++ 7 files changed, 403 insertions(+), 13 deletions(-) create mode 100644 chardev/char-mux-be.c diff --git a/chardev/char-fe.c b/chardev/char-fe.c index a2b5bff39fd9..2f794674563b 100644 --- a/chardev/char-fe.c +++ b/chardev/char-fe.c @@ -200,6 +200,12 @@ bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp) if (!mux_fe_chr_attach_frontend(d, b, &tag, errp)) { return false; } + } else if (CHARDEV_IS_MUX_BE(s)) { + MuxBeChardev *d = MUX_BE_CHARDEV(s); + + if (!mux_be_chr_attach_frontend(d, b, errp)) { + return false; + } } else if (s->be) { error_setg(errp, "chardev '%s' is already in use", s->label); return false; @@ -226,6 +232,9 @@ void qemu_chr_fe_deinit(CharBackend *b, bool del) if (CHARDEV_IS_MUX_FE(b->chr)) { MuxFeChardev *d = MUX_FE_CHARDEV(b->chr); mux_fe_chr_detach_frontend(d, b->tag); + } else if (CHARDEV_IS_MUX_BE(b->chr)) { + MuxBeChardev *d = MUX_BE_CHARDEV(b->chr); + mux_be_chr_detach_frontend(d); } if (del) { Object *obj = OBJECT(b->chr); diff --git a/chardev/char-mux-be.c b/chardev/char-mux-be.c new file mode 100644 index 000000000000..64a4f2c00034 --- /dev/null +++ b/chardev/char-mux-be.c @@ -0,0 +1,290 @@ +/* + * QEMU Character Backend Multiplexer + * + * Author: Roman Penyaev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/module.h" +#include "qemu/option.h" +#include "qemu/cutils.h" +#include "chardev/char.h" +#include "sysemu/block-backend.h" +#include "qapi/qapi-commands-control.h" +#include "qapi/clone-visitor.h" +#include "qapi/qapi-builtin-visit.h" +#include "chardev-internal.h" + +/* + * MUX-BE driver for multiplexing 1 frontend device with N backend devices + */ + +/* + * Write to all backends. Different backend devices accept data with + * various rate, so it is quite possible that one device returns less, + * then others. In this case we return minimum to the caller, + * expecting caller will repeat operation soon. When repeat happens + * send to the devices which consume data faster must be avoided + * for obvious reasons not to send data, which was already sent. + */ +static int mux_be_chr_write_to_all(MuxBeChardev *d, const uint8_t *buf, int len) +{ + int r, i, ret = len; + unsigned int written; + + for (i = 0; i < d->be_cnt; i++) { + written = d->be_written[i] - d->be_min_written; + if (written) { + /* Written in the previous call so take into account */ + ret = MIN(written, ret); + continue; + } + r = qemu_chr_fe_write(&d->backends[i], buf, len); + if (r < 0 && errno == EAGAIN) { + /* + * Fail immediately if write would block. Expect to be called + * soon on watch wake up. + */ + return r; + } else if (r < 0) { + /* + * Ignore all other errors and pretend the entire buffer is + * written to avoid this chardev being watched. This device + * becomes disabled until the following write succeeds, but + * writing continues to others. + */ + r = len; + } + d->be_written[i] += r; + ret = MIN(r, ret); + } + d->be_min_written += ret; + + return ret; +} + +/* Called with chr_write_lock held. */ +static int mux_be_chr_write(Chardev *chr, const uint8_t *buf, int len) +{ + MuxBeChardev *d = MUX_BE_CHARDEV(chr); + return mux_be_chr_write_to_all(d, buf, len); +} + +static void mux_be_chr_send_event(MuxBeChardev *d, QEMUChrEvent event) +{ + CharBackend *fe = d->frontend; + + if (fe && fe->chr_event) { + fe->chr_event(fe->opaque, event); + } +} + +static void mux_be_chr_be_event(Chardev *chr, QEMUChrEvent event) +{ + MuxBeChardev *d = MUX_BE_CHARDEV(chr); + + mux_be_chr_send_event(d, event); +} + +static int mux_be_chr_can_read(void *opaque) +{ + MuxBeChardev *d = MUX_BE_CHARDEV(opaque); + CharBackend *fe = d->frontend; + + if (fe && fe->chr_can_read) { + return fe->chr_can_read(fe->opaque); + } + + return 0; +} + +static void mux_be_chr_read(void *opaque, const uint8_t *buf, int size) +{ + MuxBeChardev *d = MUX_BE_CHARDEV(opaque); + CharBackend *fe = d->frontend; + + if (fe && fe->chr_read) { + fe->chr_read(fe->opaque, buf, size); + } +} + +void mux_be_chr_send_all_event(MuxBeChardev *d, QEMUChrEvent event) +{ + mux_be_chr_send_event(d, event); +} + +static void mux_be_chr_event(void *opaque, QEMUChrEvent event) +{ + mux_chr_send_all_event(CHARDEV(opaque), event); +} + +static GSource *mux_be_chr_add_watch(Chardev *s, GIOCondition cond) +{ + MuxBeChardev *d = MUX_BE_CHARDEV(s); + Chardev *chr; + ChardevClass *cc; + unsigned int written; + int i; + + for (i = 0; i < d->be_cnt; i++) { + written = d->be_written[i] - d->be_min_written; + if (written) { + /* We skip the device with already written buffer */ + continue; + } + + /* + * The first device that has no data written to it must be + * the device that recently returned EAGAIN and should be + * watched. + */ + + chr = qemu_chr_fe_get_driver(&d->backends[i]); + cc = CHARDEV_GET_CLASS(chr); + + if (!cc->chr_add_watch) { + return NULL; + } + + return cc->chr_add_watch(chr, cond); + } + + return NULL; +} + +bool mux_be_chr_attach_chardev(MuxBeChardev *d, Chardev *chr, Error **errp) +{ + bool ret; + + if (d->be_cnt >= MAX_MUX) { + error_setg(errp, "too many uses of multiplexed chardev '%s'" + " (maximum is " stringify(MAX_MUX) ")", + d->parent.label); + return false; + } + ret = qemu_chr_fe_init(&d->backends[d->be_cnt], chr, errp); + if (ret) { + /* Catch up with what was already written */ + d->be_written[d->be_cnt] = d->be_min_written; + d->be_cnt += 1; + } + + return ret; +} + +static void char_mux_be_finalize(Object *obj) +{ + MuxBeChardev *d = MUX_BE_CHARDEV(obj); + CharBackend *fe = d->frontend; + int i; + + if (fe) { + fe->chr = NULL; + } + for (i = 0; i < d->be_cnt; i++) { + qemu_chr_fe_deinit(&d->backends[i], false); + } +} + +static void mux_be_chr_update_read_handlers(Chardev *chr) +{ + MuxBeChardev *d = MUX_BE_CHARDEV(chr); + int i; + + for (i = 0; i < d->be_cnt; i++) { + /* Fix up the real driver with mux routines */ + qemu_chr_fe_set_handlers_full(&d->backends[i], + mux_be_chr_can_read, + mux_be_chr_read, + mux_be_chr_event, + NULL, + chr, + chr->gcontext, true, false); + } +} + +bool mux_be_chr_attach_frontend(MuxBeChardev *d, CharBackend *b, Error **errp) +{ + if (d->frontend) { + error_setg(errp, + "multiplexed chardev '%s' is already used " + "for multiplexing", d->parent.label); + return false; + } + d->frontend = b; + + return true; +} + +void mux_be_chr_detach_frontend(MuxBeChardev *d) +{ + d->frontend = NULL; +} + +static void qemu_chr_open_mux_be(Chardev *chr, + ChardevBackend *backend, + bool *be_opened, + Error **errp) +{ + /* + * Only default to opened state if we've realized the initial + * set of muxes + */ + *be_opened = mux_is_opened(); +} + +static void qemu_chr_parse_mux_be(QemuOpts *opts, ChardevBackend *backend, + Error **errp) +{ + ChardevMuxBe *mux; + + backend->type = CHARDEV_BACKEND_KIND_MUX_BE; + mux = backend->u.mux_be.data = g_new0(ChardevMuxBe, 1); + qemu_chr_parse_common(opts, qapi_ChardevMuxBe_base(mux)); +} + +static void char_mux_be_class_init(ObjectClass *oc, void *data) +{ + ChardevClass *cc = CHARDEV_CLASS(oc); + + cc->parse = qemu_chr_parse_mux_be; + cc->open = qemu_chr_open_mux_be; + cc->chr_write = mux_be_chr_write; + cc->chr_add_watch = mux_be_chr_add_watch; + cc->chr_be_event = mux_be_chr_be_event; + cc->chr_update_read_handler = mux_be_chr_update_read_handlers; +} + +static const TypeInfo char_mux_be_type_info = { + .name = TYPE_CHARDEV_MUX_BE, + .parent = TYPE_CHARDEV, + .class_init = char_mux_be_class_init, + .instance_size = sizeof(MuxBeChardev), + .instance_finalize = char_mux_be_finalize, +}; + +static void register_types(void) +{ + type_register_static(&char_mux_be_type_info); +} + +type_init(register_types); diff --git a/chardev/char.c b/chardev/char.c index cffe60860589..58fa8ac70a1e 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -341,6 +341,9 @@ static bool qemu_chr_is_busy(Chardev *s) if (CHARDEV_IS_MUX_FE(s)) { MuxFeChardev *d = MUX_FE_CHARDEV(s); return d->mux_bitset != 0; + } else if (CHARDEV_IS_MUX_BE(s)) { + MuxBeChardev *d = MUX_BE_CHARDEV(s); + return d->frontend != NULL; } else { return s->be != NULL; } @@ -648,7 +651,8 @@ static Chardev *__qemu_chr_new_from_opts(QemuOpts *opts, GMainContext *context, ChardevBackend *backend = NULL; const char *name = qemu_opt_get(opts, "backend"); const char *id = qemu_opts_id(opts); - char *bid = NULL; + const char *mux_be_id = NULL; + char *mux_fe_id = NULL; if (name && is_help_option(name)) { GString *str = g_string_new(""); @@ -676,10 +680,16 @@ static Chardev *__qemu_chr_new_from_opts(QemuOpts *opts, GMainContext *context, } if (qemu_opt_get_bool(opts, "mux", 0)) { - bid = g_strdup_printf("%s-base", id); + mux_fe_id = g_strdup_printf("%s-base", id); + } + mux_be_id = qemu_opt_get(opts, "mux-be-id"); + if (mux_be_id && mux_fe_id) { + error_setg(errp, "chardev: mux and mux-be can't be used for the same " + "device"); + goto out; } - chr = qemu_chardev_new(bid ? bid : id, + chr = qemu_chardev_new(mux_fe_id ? mux_fe_id : id, object_class_get_name(OBJECT_CLASS(cc)), backend, context, errp); if (chr == NULL) { @@ -687,25 +697,40 @@ static Chardev *__qemu_chr_new_from_opts(QemuOpts *opts, GMainContext *context, } base = chr; - if (bid) { + if (mux_fe_id) { Chardev *mux; qapi_free_ChardevBackend(backend); backend = g_new0(ChardevBackend, 1); backend->type = CHARDEV_BACKEND_KIND_MUX; backend->u.mux.data = g_new0(ChardevMux, 1); - backend->u.mux.data->chardev = g_strdup(bid); + backend->u.mux.data->chardev = g_strdup(mux_fe_id); mux = qemu_chardev_new(id, TYPE_CHARDEV_MUX_FE, backend, context, errp); if (mux == NULL) { - object_unparent(OBJECT(chr)); - chr = NULL; - goto out; + goto unparent_and_out; } chr = mux; + } else if (mux_be_id) { + Chardev *s; + + s = qemu_chr_find(mux_be_id); + if (!s) { + error_setg(errp, "chardev: mux-be device can't be found by id '%s'", + mux_be_id); + goto unparent_and_out; + } + if (!CHARDEV_IS_MUX_BE(s)) { + error_setg(errp, "chardev: device '%s' is not a multiplexer device" + " of 'mux-be' type", mux_be_id); + goto unparent_and_out; + } + if (!mux_be_chr_attach_chardev(MUX_BE_CHARDEV(s), chr, errp)) { + goto unparent_and_out; + } } out: qapi_free_ChardevBackend(backend); - g_free(bid); + g_free(mux_fe_id); if (replay && base) { /* RR should be set on the base device, not the mux */ @@ -713,6 +738,11 @@ out: } return chr; + +unparent_and_out: + object_unparent(OBJECT(chr)); + chr = NULL; + goto out; } Chardev *qemu_chr_new_from_opts(QemuOpts *opts, GMainContext *context, @@ -1114,7 +1144,7 @@ ChardevReturn *qmp_chardev_change(const char *id, ChardevBackend *backend, return NULL; } - if (CHARDEV_IS_MUX_FE(chr)) { + if (CHARDEV_IS_MUX_FE(chr) || CHARDEV_IS_MUX_BE(chr)) { error_setg(errp, "Mux device hotswap not supported yet"); return NULL; } @@ -1302,7 +1332,7 @@ static int chardev_options_parsed_cb(Object *child, void *opaque) { Chardev *chr = (Chardev *)child; - if (!chr->be_open && CHARDEV_IS_MUX_FE(chr)) { + if (!chr->be_open && (CHARDEV_IS_MUX_FE(chr) || CHARDEV_IS_MUX_BE(chr))) { open_muxes(chr); } @@ -1329,8 +1359,10 @@ void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event) if (CHARDEV_IS_MUX_FE(chr)) { MuxFeChardev *d = MUX_FE_CHARDEV(chr); - mux_fe_chr_send_all_event(d, event); + } else if (CHARDEV_IS_MUX_BE(chr)) { + MuxBeChardev *d = MUX_BE_CHARDEV(chr); + mux_be_chr_send_all_event(d, event); } } diff --git a/chardev/chardev-internal.h b/chardev/chardev-internal.h index 94c8d07ac235..8ea1258f8ff4 100644 --- a/chardev/chardev-internal.h +++ b/chardev/chardev-internal.h @@ -35,7 +35,9 @@ struct MuxFeChardev { Chardev parent; + /* Linked frontends */ CharBackend *backends[MAX_MUX]; + /* Linked backend */ CharBackend chr; unsigned long mux_bitset; int focus; @@ -54,10 +56,36 @@ struct MuxFeChardev { }; typedef struct MuxFeChardev MuxFeChardev; +struct MuxBeChardev { + Chardev parent; + /* Linked frontend */ + CharBackend *frontend; + /* Linked backends */ + CharBackend backends[MAX_MUX]; + /* + * Number of backends attached to this mux. Once attached, a + * backend can't be detached, so the counter is only increasing. + * To safely remove a backend, mux has to be removed first. + */ + unsigned int be_cnt; + /* + * Counters of written bytes from a single frontend device + * to multiple backend devices. + */ + unsigned int be_written[MAX_MUX]; + unsigned int be_min_written; +}; +typedef struct MuxBeChardev MuxBeChardev; + DECLARE_INSTANCE_CHECKER(MuxFeChardev, MUX_FE_CHARDEV, TYPE_CHARDEV_MUX_FE) -#define CHARDEV_IS_MUX_FE(chr) \ +DECLARE_INSTANCE_CHECKER(MuxBeChardev, MUX_BE_CHARDEV, + TYPE_CHARDEV_MUX_BE) + +#define CHARDEV_IS_MUX_FE(chr) \ object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_MUX_FE) +#define CHARDEV_IS_MUX_BE(chr) \ + object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_MUX_BE) void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event); @@ -67,6 +95,10 @@ void mux_fe_chr_send_all_event(MuxFeChardev *d, QEMUChrEvent event); bool mux_fe_chr_attach_frontend(MuxFeChardev *d, CharBackend *b, unsigned int *tag, Error **errp); bool mux_fe_chr_detach_frontend(MuxFeChardev *d, unsigned int tag); +void mux_be_chr_send_all_event(MuxBeChardev *d, QEMUChrEvent event); +bool mux_be_chr_attach_chardev(MuxBeChardev *d, Chardev *chr, Error **errp); +bool mux_be_chr_attach_frontend(MuxBeChardev *d, CharBackend *b, Error **errp); +void mux_be_chr_detach_frontend(MuxBeChardev *d); Object *get_chardevs_root(void); diff --git a/chardev/meson.build b/chardev/meson.build index 778444a00ca6..3a9f5565372b 100644 --- a/chardev/meson.build +++ b/chardev/meson.build @@ -3,6 +3,7 @@ chardev_ss.add(files( 'char-file.c', 'char-io.c', 'char-mux-fe.c', + 'char-mux-be.c', 'char-null.c', 'char-pipe.c', 'char-ringbuf.c', diff --git a/include/chardev/char.h b/include/chardev/char.h index 0bec974f9d73..c58c11c4eeaf 100644 --- a/include/chardev/char.h +++ b/include/chardev/char.h @@ -232,6 +232,7 @@ OBJECT_DECLARE_TYPE(Chardev, ChardevClass, CHARDEV) #define TYPE_CHARDEV_NULL "chardev-null" #define TYPE_CHARDEV_MUX_FE "chardev-mux" +#define TYPE_CHARDEV_MUX_BE "chardev-mux-be" #define TYPE_CHARDEV_RINGBUF "chardev-ringbuf" #define TYPE_CHARDEV_PTY "chardev-pty" #define TYPE_CHARDEV_CONSOLE "chardev-console" diff --git a/qapi/char.json b/qapi/char.json index fb0dedb24383..cdec8f9cf4e2 100644 --- a/qapi/char.json +++ b/qapi/char.json @@ -336,6 +336,17 @@ 'data': { 'chardev': 'str' }, 'base': 'ChardevCommon' } +## +# @ChardevMuxBe: +# +# Configuration info for mux-be chardevs. +# +# Since: 9.2 +## +{ 'struct': 'ChardevMuxBe', + 'data': { }, + 'base': 'ChardevCommon' } + ## # @ChardevStdio: # @@ -483,6 +494,8 @@ # # @mux: (since 1.5) # +# @mux-be: (since 9.2) +# # @msmouse: emulated Microsoft serial mouse (since 1.5) # # @wctablet: emulated Wacom Penpartner serial tablet (since 2.9) @@ -525,6 +538,7 @@ 'pty', 'null', 'mux', + 'mux-be', 'msmouse', 'wctablet', { 'name': 'braille', 'if': 'CONFIG_BRLAPI' }, @@ -599,6 +613,16 @@ { 'struct': 'ChardevMuxWrapper', 'data': { 'data': 'ChardevMux' } } +## +# @ChardevMuxBeWrapper: +# +# @data: Configuration info for mux-be chardevs +# +# Since: 9.2 +## +{ 'struct': 'ChardevMuxBeWrapper', + 'data': { 'data': 'ChardevMuxBe' } } + ## # @ChardevStdioWrapper: # @@ -707,6 +731,7 @@ 'pty': 'ChardevPtyWrapper', 'null': 'ChardevCommonWrapper', 'mux': 'ChardevMuxWrapper', + 'mux-be': 'ChardevMuxBeWrapper', 'msmouse': 'ChardevCommonWrapper', 'wctablet': 'ChardevCommonWrapper', 'braille': { 'type': 'ChardevCommonWrapper', From patchwork Wed Oct 16 10:26:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13838180 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 8ED63D1AD43 for ; Wed, 16 Oct 2024 10:29:51 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t11Gg-0003kx-21; Wed, 16 Oct 2024 06:28:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1t11GY-0003jl-QN for qemu-devel@nongnu.org; Wed, 16 Oct 2024 06:28:30 -0400 Received: from mail-ed1-x52a.google.com ([2a00:1450:4864:20::52a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1t11GW-0004A8-4y for qemu-devel@nongnu.org; Wed, 16 Oct 2024 06:28:29 -0400 Received: by mail-ed1-x52a.google.com with SMTP id 4fb4d7f45d1cf-5c962c3e97dso4679393a12.0 for ; Wed, 16 Oct 2024 03:28:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1729074507; x=1729679307; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=NtGdGZ/zn8WcWNHkcuhdBpfqRucUKp/hW6ytn0g9Z6I=; b=Bl5LvzlXu7muOxE7wqSa0dLKiexjDAGoqcSI4c0vpvuitT6TANy2typkA04UZb/KdP gZ1b5WinyWYjjY7PGO8U8+19l9J9A01lNBNmwtrhN2iOBb/MIWkJMmC/Xb6NWxYmjhcX v9RrKinOeQEVgSEceWuR1BLZ63MVY2ne8JG6YOA5hV4trMx+//PNjvoZv2+pjaRa2yQ6 AbSwvCCnbyhKrfUr/a4Ec40flGJKfdZriVyaw/hvAh/fp5NMCIQUMxt0cP3OIaCtrTS8 6sUVUQCVWjqxkeHob2pEqebgdvT+SapIwRy/LmoM8eiEqwe9HozwGcHtdZgHhsqXwbsC veAQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729074507; x=1729679307; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=NtGdGZ/zn8WcWNHkcuhdBpfqRucUKp/hW6ytn0g9Z6I=; b=AvMu+ajFs4MXrqN/Kw1hvwgc0aO+lh/lkIupTAWPTi1gwPBNnyUrQTSaBmJXOBB/su uSySqQlibnOMg723ZzhTJwjijIAaWMuot79c6pvjJzxSfbojPKbdqq3dXxfNDCS0/8Us 3aVmyffMndN9SU91IoQF8noTgWz36sGHphWVYzDkyx+HYCISagqYMhTMuvJm2cRBuarr lnKiytpmnNH+ibVClKv6fssl8U9xpI6XIw2fmROSS533ad8PgYDHZhs5ri6RGoGZh8jh SagzoXI7vk/pVaa9edeUpHXv4txqsx56K6DYWGCsnmYsO1+N4XUHg2ofeszqXDwAtwsH aFNQ== X-Forwarded-Encrypted: i=1; AJvYcCWhQhFRqjattUhnomP8WKs2gUghE0/Ddgs9+iCzL2IjniTBMN42NThtwlZ0Mxu7llM6gvVy7nLHrUfa@nongnu.org X-Gm-Message-State: AOJu0YwZy0OMIxlDBefq9GUrXBBgTj7MrpIDvGGfHFy9mAnVp2GTtXSc cHwifh6vPu2o85pI9IYSmknLST4BCciklmDiMa7AuEygOnq/SZPM X-Google-Smtp-Source: AGHT+IExrIANhl29jKyslrSdYdC8026kESn+4GOFQdmZKGtqlKE11ShnDqBmwlrcsOf45q9P95ONIw== X-Received: by 2002:a05:6402:2748:b0:5c9:4a9b:31f9 with SMTP id 4fb4d7f45d1cf-5c94a9b5292mr14227939a12.35.1729074506532; Wed, 16 Oct 2024 03:28:26 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:eb7f:8fd0:f96c:766b]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5c98d4f85dcsm1566680a12.22.2024.10.16.03.28.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Oct 2024 03:28:26 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v4 7/8] tests/unit/test-char: add unit test for the `mux-be` multiplexer Date: Wed, 16 Oct 2024 12:26:04 +0200 Message-Id: <20241016102605.459395-8-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241016102605.459395-1-r.peniaev@gmail.com> References: <20241016102605.459395-1-r.peniaev@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::52a; envelope-from=r.peniaev@gmail.com; helo=mail-ed1-x52a.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org The test is trivial: several backends, 1 `mux-be`, 1 frontend do the buffer write and read. Pipe is used for EAGAIN verification. Signed-off-by: Roman Penyaev Cc: "Marc-André Lureau" Cc: qemu-devel@nongnu.org --- tests/unit/test-char.c | 306 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 304 insertions(+), 2 deletions(-) diff --git a/tests/unit/test-char.c b/tests/unit/test-char.c index a1c6bb874c8e..3eb0692b199f 100644 --- a/tests/unit/test-char.c +++ b/tests/unit/test-char.c @@ -178,7 +178,7 @@ static void char_ringbuf_test(void) qemu_opts_del(opts); } -static void char_mux_test(void) +static void char_mux_fe_test(void) { QemuOpts *opts; Chardev *chr, *base; @@ -359,6 +359,307 @@ static void char_mux_test(void) qmp_chardev_remove("mux-label", &error_abort); } +static void char_mux_be_test(void) +{ + QemuOpts *opts; + Chardev *mux_be, *chr1, *chr2, *base; + char *data; + FeHandler h = { 0, false, 0, false, }; + Error *error = NULL; + CharBackend chr_be; + int ret, i; + +#define RB_SIZE 128 + + /* Create mux-be */ + opts = qemu_opts_create(qemu_find_opts("chardev"), "mux0", + 1, &error_abort); + qemu_opt_set(opts, "backend", "mux-be", &error_abort); + mux_be = qemu_chr_new_from_opts(opts, NULL, &error_abort); + g_assert_nonnull(mux_be); + qemu_opts_del(opts); + + /* Check maximum allowed backends */ + for (i = 0; true; i++) { + char name[8]; + + snprintf(name, sizeof(name), "chr%d", i); + opts = qemu_opts_create(qemu_find_opts("chardev"), name, + 1, &error_abort); + qemu_opt_set(opts, "backend", "ringbuf", &error_abort); + qemu_opt_set(opts, "size", stringify(RB_SIZE), &error_abort); + qemu_opt_set(opts, "mux-be-id", "mux0", &error_abort); + base = qemu_chr_new_from_opts(opts, NULL, &error); + if (error) { + const char *err_fmt = + "too many uses of multiplexed chardev 'mux0' (maximum is %u)"; + unsigned n; + + ret = sscanf(error_get_pretty(error), err_fmt, &n); + error_free(error); + error = NULL; + g_assert_cmpint(ret, ==, 1); + g_assert_cmpint(i, ==, n); + break; + } + g_assert_nonnull(base); + qemu_opts_del(opts); + } + /* Finalize mux0 */ + qmp_chardev_remove("mux0", &error_abort); + + /* Finalize all backends */ + while (i--) { + char name[8]; + snprintf(name, sizeof(name), "chr%d", i); + qmp_chardev_remove(name, &error_abort); + } + + /* Create mux-be */ + opts = qemu_opts_create(qemu_find_opts("chardev"), "mux0", + 1, &error_abort); + qemu_opt_set(opts, "backend", "mux-be", &error_abort); + mux_be = qemu_chr_new_from_opts(opts, NULL, &error_abort); + g_assert_nonnull(mux_be); + qemu_opts_del(opts); + + /* Create chardev which fails */ + opts = qemu_opts_create(qemu_find_opts("chardev"), "chr1", + 1, &error_abort); + qemu_opt_set(opts, "backend", "ringbuf", &error_abort); + qemu_opt_set(opts, "size", stringify(RB_SIZE), &error_abort); + qemu_opt_set(opts, "mux-be-id", "mux0", &error_abort); + qemu_opt_set(opts, "mux", "on", &error_abort); + chr1 = qemu_chr_new_from_opts(opts, NULL, &error); + g_assert_cmpstr(error_get_pretty(error), ==, "chardev: mux and mux-be " + "can't be used for the same device"); + error_free(error); + error = NULL; + qemu_opts_del(opts); + + /* Create first chardev */ + opts = qemu_opts_create(qemu_find_opts("chardev"), "chr1", + 1, &error_abort); + qemu_opt_set(opts, "backend", "ringbuf", &error_abort); + qemu_opt_set(opts, "size", stringify(RB_SIZE), &error_abort); + qemu_opt_set(opts, "mux-be-id", "mux0", &error_abort); + chr1 = qemu_chr_new_from_opts(opts, NULL, &error_abort); + g_assert_nonnull(chr1); + qemu_opts_del(opts); + + /* Create second chardev */ + opts = qemu_opts_create(qemu_find_opts("chardev"), "chr2", + 1, &error_abort); + qemu_opt_set(opts, "backend", "ringbuf", &error_abort); + qemu_opt_set(opts, "size", stringify(RB_SIZE), &error_abort); + qemu_opt_set(opts, "mux-be-id", "mux0", &error_abort); + chr2 = qemu_chr_new_from_opts(opts, NULL, &error_abort); + g_assert_nonnull(chr2); + qemu_opts_del(opts); + + /* Attach mux-be to a frontend */ + qemu_chr_fe_init(&chr_be, mux_be, &error_abort); + qemu_chr_fe_set_handlers(&chr_be, + fe_can_read, + fe_read, + fe_event, + NULL, + &h, + NULL, true); + + /* Fails second time */ + qemu_chr_fe_init(&chr_be, mux_be, &error); + g_assert_cmpstr(error_get_pretty(error), ==, "multiplexed chardev 'mux0' " + "is already used for multiplexing"); + error_free(error); + error = NULL; + + /* Write to backend, chr1 */ + base = qemu_chr_find("chr1"); + g_assert_cmpint(qemu_chr_be_can_write(base), !=, 0); + + qemu_chr_be_write(base, (void *)"hello", 6); + g_assert_cmpint(h.read_count, ==, 6); + g_assert_cmpstr(h.read_buf, ==, "hello"); + h.read_count = 0; + + /* Write to backend, chr2 */ + base = qemu_chr_find("chr2"); + g_assert_cmpint(qemu_chr_be_can_write(base), !=, 0); + + qemu_chr_be_write(base, (void *)"olleh", 6); + g_assert_cmpint(h.read_count, ==, 6); + g_assert_cmpstr(h.read_buf, ==, "olleh"); + h.read_count = 0; + + /* Write to frontend, chr_be */ + ret = qemu_chr_fe_write(&chr_be, (void *)"heyhey", 6); + g_assert_cmpint(ret, ==, 6); + + data = qmp_ringbuf_read("chr1", RB_SIZE, false, 0, &error_abort); + g_assert_cmpint(strlen(data), ==, 6); + g_assert_cmpstr(data, ==, "heyhey"); + g_free(data); + + data = qmp_ringbuf_read("chr2", RB_SIZE, false, 0, &error_abort); + g_assert_cmpint(strlen(data), ==, 6); + g_assert_cmpstr(data, ==, "heyhey"); + g_free(data); + + +#ifndef _WIN32 + /* + * Create third chardev to simulate EAGAIN and watcher. + * Mainly copied from char_pipe_test(). + */ + { + gchar *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL); + gchar *in, *out, *pipe = g_build_filename(tmp_path, "pipe", NULL); + Chardev *chr3; + int fd, len; + char buf[128]; + + in = g_strdup_printf("%s.in", pipe); + if (mkfifo(in, 0600) < 0) { + abort(); + } + out = g_strdup_printf("%s.out", pipe); + if (mkfifo(out, 0600) < 0) { + abort(); + } + + opts = qemu_opts_create(qemu_find_opts("chardev"), "chr3", + 1, &error_abort); + qemu_opt_set(opts, "backend", "pipe", &error_abort); + qemu_opt_set(opts, "path", pipe, &error_abort); + qemu_opt_set(opts, "mux-be-id", "mux0", &error_abort); + chr3 = qemu_chr_new_from_opts(opts, NULL, &error_abort); + g_assert_nonnull(chr3); + + /* Write to frontend, chr_be */ + ret = qemu_chr_fe_write(&chr_be, (void *)"thisis", 6); + g_assert_cmpint(ret, ==, 6); + + data = qmp_ringbuf_read("chr1", RB_SIZE, false, 0, &error_abort); + g_assert_cmpint(strlen(data), ==, 6); + g_assert_cmpstr(data, ==, "thisis"); + g_free(data); + + data = qmp_ringbuf_read("chr2", RB_SIZE, false, 0, &error_abort); + g_assert_cmpint(strlen(data), ==, 6); + g_assert_cmpstr(data, ==, "thisis"); + g_free(data); + + fd = open(out, O_RDWR); + ret = read(fd, buf, sizeof(buf)); + g_assert_cmpint(ret, ==, 6); + buf[ret] = 0; + g_assert_cmpstr(buf, ==, "thisis"); + close(fd); + + /* Add watch. 0 indicates no watches if nothing to wait for */ + ret = qemu_chr_fe_add_watch(&chr_be, G_IO_OUT | G_IO_HUP, + NULL, NULL); + g_assert_cmpint(ret, ==, 0); + + /* + * Write to frontend, chr_be, until EAGAIN. Make sure length is + * power of two to fit nicely the whole pipe buffer. + */ + len = 0; + while ((ret = qemu_chr_fe_write(&chr_be, (void *)"thisisit", 8)) + != -1) { + len += ret; + } + g_assert_cmpint(errno, ==, EAGAIN); + + /* Further all writes should cause EAGAIN */ + ret = qemu_chr_fe_write(&chr_be, (void *)"b", 1); + g_assert_cmpint(ret, ==, -1); + g_assert_cmpint(errno, ==, EAGAIN); + + /* + * Add watch. Non 0 indicates we have a blocked chardev, which + * can wakes us up when write is possible. + */ + ret = qemu_chr_fe_add_watch(&chr_be, G_IO_OUT | G_IO_HUP, + NULL, NULL); + g_assert_cmpint(ret, !=, 0); + g_source_remove(ret); + + /* Drain pipe and ring buffers */ + fd = open(out, O_RDWR); + while ((ret = read(fd, buf, MIN(sizeof(buf), len))) != -1 && len > 0) { + len -= ret; + } + close(fd); + + data = qmp_ringbuf_read("chr1", RB_SIZE, false, 0, &error_abort); + g_assert_cmpint(strlen(data), ==, 128); + g_free(data); + + data = qmp_ringbuf_read("chr2", RB_SIZE, false, 0, &error_abort); + g_assert_cmpint(strlen(data), ==, 128); + g_free(data); + + /* + * Now we are good to go, first repeat "lost" sequence, which + * was already consumed and drained by the ring buffers, but + * pipe have not recieved that yet. + */ + ret = qemu_chr_fe_write(&chr_be, (void *)"thisisit", 8); + g_assert_cmpint(ret, ==, 8); + + ret = qemu_chr_fe_write(&chr_be, (void *)"streamisrestored", 16); + g_assert_cmpint(ret, ==, 16); + + data = qmp_ringbuf_read("chr1", RB_SIZE, false, 0, &error_abort); + g_assert_cmpint(strlen(data), ==, 16); + /* Only last 16 bytes, see big comment above */ + g_assert_cmpstr(data, ==, "streamisrestored"); + g_free(data); + + data = qmp_ringbuf_read("chr2", RB_SIZE, false, 0, &error_abort); + g_assert_cmpint(strlen(data), ==, 16); + /* Only last 16 bytes, see big comment above */ + g_assert_cmpstr(data, ==, "streamisrestored"); + g_free(data); + + fd = open(out, O_RDWR); + ret = read(fd, buf, sizeof(buf)); + g_assert_cmpint(ret, ==, 24); + buf[ret] = 0; + /* Both 8 and 16 bytes */ + g_assert_cmpstr(buf, ==, "thisisitstreamisrestored"); + close(fd); + } +#endif + + /* Can't be removed, depends on mux0 */ + qmp_chardev_remove("chr1", &error); + g_assert_cmpstr(error_get_pretty(error), ==, "Chardev 'chr1' is busy"); + error_free(error); + error = NULL; + + /* Can't be removed, depends on frontend chr_be */ + qmp_chardev_remove("mux0", &error); + g_assert_cmpstr(error_get_pretty(error), ==, "Chardev 'mux0' is busy"); + error_free(error); + error = NULL; + + /* Finalize frontend */ + qemu_chr_fe_deinit(&chr_be, false); + + /* Finalize mux0 */ + qmp_chardev_remove("mux0", &error_abort); + + /* Finalize backend chardevs */ + qmp_chardev_remove("chr1", &error_abort); + qmp_chardev_remove("chr2", &error_abort); +#ifndef _WIN32 + qmp_chardev_remove("chr3", &error_abort); +#endif +} static void websock_server_read(void *opaque, const uint8_t *buf, int size) { @@ -1506,7 +1807,8 @@ int main(int argc, char **argv) g_test_add_func("/char/null", char_null_test); g_test_add_func("/char/invalid", char_invalid_test); g_test_add_func("/char/ringbuf", char_ringbuf_test); - g_test_add_func("/char/mux", char_mux_test); + g_test_add_func("/char/mux", char_mux_fe_test); + g_test_add_func("/char/mux-be", char_mux_be_test); #ifdef _WIN32 g_test_add_func("/char/console/subprocess", char_console_test_subprocess); g_test_add_func("/char/console", char_console_test); From patchwork Wed Oct 16 10:26:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13838181 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id F3789D1AD46 for ; Wed, 16 Oct 2024 10:29:53 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t11Gh-0003la-Av; Wed, 16 Oct 2024 06:28:39 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1t11Gc-0003k9-4i for qemu-devel@nongnu.org; Wed, 16 Oct 2024 06:28:34 -0400 Received: from mail-ed1-x533.google.com ([2a00:1450:4864:20::533]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1t11GY-0004AP-Ib for qemu-devel@nongnu.org; Wed, 16 Oct 2024 06:28:33 -0400 Received: by mail-ed1-x533.google.com with SMTP id 4fb4d7f45d1cf-5c94c4ad9d8so7269213a12.2 for ; Wed, 16 Oct 2024 03:28:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1729074507; x=1729679307; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=1du4d0NmPYqLOtlMCdpgrqgdr5HPrFmwCgaSazfzxPk=; b=PnSS/DfaRLmK3P5eKCelT4EAR/SsOoK83qf8xKepdl1blAmXIGkuvPMmcDGFqfQ4nq miofiwgLKpSHMCFZoXnUKxQQsp5NzoXo5KMGBVC2SA+QOL2WXKuagZ8BtQd7NMqZ91yf fbStiMgZzPlnCXT2jTC7+Y7/llbQHUzQq2c2ZFUXXGIwRGNRBlaUzTrivoSsaeG0GmJv CMymK2V8u1EIOVJTS5Wmo/gXSYkxFo4FNR7RgXSBb6AOd7meUx6pIeX06bs3laQDIZ7+ kXhSueQQOLeovHqzwGhV+kbOKpAFesr6fiJczmUQ7feQDiVLTrxYI95szIt7ovRIh3Ns HI+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729074507; x=1729679307; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=1du4d0NmPYqLOtlMCdpgrqgdr5HPrFmwCgaSazfzxPk=; b=c2qcJRSlUXo2mNhXLnMiMzNJ4dLjYN/yYVFWd1ahgKlWeVFKIdfcx5KFNBC2fK9u0W Kp4ohRngeRr2VtM7nXBWs0sr5nBSfH8RnPLGFQ/QMTcGWqjeL9rXQRMB0e6ELA/NL2zw TiLh3oiHopBKJ2KHCwGiTS5vlr+eDjgm0VsjnwfE9+u39KuP8gwAS+wkGlc89nq+X28k MEL+4qaWw1WgNAN3yifGTl6VE+zh6B1IHHPQpx0BxzlGy6DFzIpwjiL8QonFLJWrFovu mRL23pGwuHhFVsYuodoJ5hHX2DLkGU+PaUmPFfDPaqS9a5bXRylNfOTdiATsFD48/y1i srrw== X-Forwarded-Encrypted: i=1; AJvYcCWsQaDWX3UkDvInPdd/tvnR2hdePu3NERS75EIQ2yoyrQ02g0Nw0wH+P/TuxXAeE5kuPdMsd14cMhhX@nongnu.org X-Gm-Message-State: AOJu0YxPiu7IAAFuJDBI7RhhSTkuxSGjo28+UkqKYP5Cp9nnK0cijjQW BnFjjf1VoMv/dHbjAsVYwSX35da1v3g5pGUPWvTZ/44bT82RC52v X-Google-Smtp-Source: AGHT+IHGSF66ekJ56SaZBd0NJDAfGTMgHJl/bC8O8ht2s+Gn1S82RNxYq3Fx1z2Y0eY2xrH/0NqGRw== X-Received: by 2002:a05:6402:3491:b0:5c9:5c40:6d9a with SMTP id 4fb4d7f45d1cf-5c95c4070f8mr9287248a12.34.1729074507301; Wed, 16 Oct 2024 03:28:27 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:eb7f:8fd0:f96c:766b]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5c98d4f85dcsm1566680a12.22.2024.10.16.03.28.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Oct 2024 03:28:26 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v4 8/8] qemu-options.hx: describe multiplexing of several backend devices Date: Wed, 16 Oct 2024 12:26:05 +0200 Message-Id: <20241016102605.459395-9-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241016102605.459395-1-r.peniaev@gmail.com> References: <20241016102605.459395-1-r.peniaev@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::533; envelope-from=r.peniaev@gmail.com; helo=mail-ed1-x533.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This adds a few lines describing `mux-be` multiplexer configuration for multiplexing several backend devices with a single frontend device. Signed-off-by: Roman Penyaev Cc: "Marc-André Lureau" Cc: qemu-devel@nongnu.org --- qemu-options.hx | 78 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 58 insertions(+), 20 deletions(-) diff --git a/qemu-options.hx b/qemu-options.hx index daae49414740..dd5dfe8596f0 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -3677,37 +3677,37 @@ DEFHEADING(Character device options:) DEF("chardev", HAS_ARG, QEMU_OPTION_chardev, "-chardev help\n" - "-chardev null,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" + "-chardev null,id=id[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" "-chardev socket,id=id[,host=host],port=port[,to=to][,ipv4=on|off][,ipv6=on|off][,nodelay=on|off]\n" - " [,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds][,mux=on|off]\n" + " [,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds][,mux=on|off][,mux-be-id=id]\n" " [,logfile=PATH][,logappend=on|off][,tls-creds=ID][,tls-authz=ID] (tcp)\n" "-chardev socket,id=id,path=path[,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds]\n" - " [,mux=on|off][,logfile=PATH][,logappend=on|off][,abstract=on|off][,tight=on|off] (unix)\n" + " [,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off][,abstract=on|off][,tight=on|off] (unix)\n" "-chardev udp,id=id[,host=host],port=port[,localaddr=localaddr]\n" - " [,localport=localport][,ipv4=on|off][,ipv6=on|off][,mux=on|off]\n" + " [,localport=localport][,ipv4=on|off][,ipv6=on|off][,mux=on|off][,mux-be-id=id]\n" " [,logfile=PATH][,logappend=on|off]\n" - "-chardev msmouse,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" + "-chardev msmouse,id=id[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" "-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]\n" - " [,mux=on|off][,logfile=PATH][,logappend=on|off]\n" + " [,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" "-chardev ringbuf,id=id[,size=size][,logfile=PATH][,logappend=on|off]\n" - "-chardev file,id=id,path=path[,input-path=input-file][,mux=on|off][,logfile=PATH][,logappend=on|off]\n" - "-chardev pipe,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" + "-chardev file,id=id,path=path[,input-path=input-file][,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" + "-chardev pipe,id=id,path=path[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" #ifdef _WIN32 - "-chardev console,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" - "-chardev serial,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" + "-chardev console,id=id[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" + "-chardev serial,id=id,path=path[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" #else - "-chardev pty,id=id[,path=path][,mux=on|off][,logfile=PATH][,logappend=on|off]\n" - "-chardev stdio,id=id[,mux=on|off][,signal=on|off][,logfile=PATH][,logappend=on|off]\n" + "-chardev pty,id=id[,path=path][,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" + "-chardev stdio,id=id[,mux=on|off][,mux-be-id=id][,signal=on|off][,logfile=PATH][,logappend=on|off]\n" #endif #ifdef CONFIG_BRLAPI - "-chardev braille,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" + "-chardev braille,id=id[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" #endif #if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) - "-chardev serial,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" + "-chardev serial,id=id,path=path[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" #endif #if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__) - "-chardev parallel,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" + "-chardev parallel,id=id,path=path[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" #endif #if defined(CONFIG_SPICE) "-chardev spicevmc,id=id,name=name[,debug=debug][,logfile=PATH][,logappend=on|off]\n" @@ -3719,8 +3719,8 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev, SRST The general form of a character device option is: -``-chardev backend,id=id[,mux=on|off][,options]`` - Backend is one of: ``null``, ``socket``, ``udp``, ``msmouse``, +``-chardev backend,id=id[,mux=on|off][,mux-be-id=id][,options]`` + Backend is one of: ``null``, ``socket``, ``udp``, ``msmouse``, ``mux-be``, ``vc``, ``ringbuf``, ``file``, ``pipe``, ``console``, ``serial``, ``pty``, ``stdio``, ``braille``, ``parallel``, ``spicevmc``, ``spiceport``. The specific backend will determine the @@ -3777,9 +3777,10 @@ The general form of a character device option is: the QEMU monitor, and ``-nographic`` also multiplexes the console and the monitor to stdio. - There is currently no support for multiplexing in the other - direction (where a single QEMU front end takes input and output from - multiple chardevs). + If you need to multiplex in the opposite direction (where one QEMU + interface receives input and output from multiple chardev devices), + each character device needs ``mux-be-id=id`` option. Please refer + to the paragraph below regarding chardev ``mux-be`` configuration. Every backend supports the ``logfile`` option, which supplies the path to a file to record all data transmitted via the backend. The @@ -3879,6 +3880,43 @@ The available backends are: Forward QEMU's emulated msmouse events to the guest. ``msmouse`` does not take any options. +``-chardev mux-be,id=id`` + Explicitly create chardev backend multiplexer with possibility to + multiplex in the opposite direction, where one QEMU interface + (frontend device) receives input and output from multiple chardev + backend devices. + + For example the following is a use case of 2 backend devices: text + virtual console ``vc0`` and a socket ``sock0`` connected + to a single virtio hvc console frontend device with multiplexer + ``mux0`` help. Virtual console renders text to an image, which + can be shared over the VNC protocol, in turn socket backend provides + biderectional communication to the virtio hvc console over socket. + The example configuration can be the following: + + :: + + -chardev mux-be,id=mux0 \ + -chardev socket,path=/tmp/sock,server=on,wait=off,id=sock0,mux-be-id=mux0 \ + -chardev vc,id=vc0,mux-be-id=mux0 \ + -device virtconsole,chardev=mux0 \ + -vnc 0.0.0.0:0 + + Once QEMU starts VNC client and any TTY emulator can be used to + control a single hvc console: + + :: + + # VNC client + vncviewer :0 + + # TTY emulator + socat unix-connect:/tmp/sock pty,link=/tmp/pty & \ + tio /tmp/pty + + Multiplexing of several backend devices with serveral frontend devices + is not supported. + ``-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]`` Connect to a QEMU text console. ``vc`` may optionally be given a specific size.