From patchwork Thu Oct 17 14:43:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13840140 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 A52BED374A4 for ; Thu, 17 Oct 2024 14:46:12 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t1Rkz-0003Ux-RV; Thu, 17 Oct 2024 10:45:41 -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 1t1Rkx-0003Tf-6g for qemu-devel@nongnu.org; Thu, 17 Oct 2024 10:45:39 -0400 Received: from mail-ed1-x535.google.com ([2a00:1450:4864:20::535]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1t1Rku-0005cl-UE for qemu-devel@nongnu.org; Thu, 17 Oct 2024 10:45:38 -0400 Received: by mail-ed1-x535.google.com with SMTP id 4fb4d7f45d1cf-5c984352742so1188671a12.1 for ; Thu, 17 Oct 2024 07:45:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1729176335; x=1729781135; 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=Mhs5OiuF77kuGUaFZJ2f5B51MrnBBXQFIunBcNmnGYq9CwzWz4gsdu7UOIjgKF2TP2 M4KmAYtwb11JyMkShkwWve9AW1T3c1+kjUcgZWWCuPnofqVLmD5/bFTKCpI3jvVHBXva GGnpwGK0SJOJ2wRAoARd2/DYbj9B8njYiLqZksyW//OzJSaOkuQ2XBgnX0S5rp658Hm+ rM8QL2hTYhBKTTG6IekajQmg5QZLbd5lFLz45VcHubTZvb3z77NBIFJj6fxcKyrsl560 d420KlfBNWnP6MXDH6EK+0VZ9yyM7UZmmzGL+CktO1INbTGciJsk5KG9CKbiMGO4gUzH Yn5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729176335; x=1729781135; 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=MJoNN+lSkZceLKhMzy4Ta5weddQpNJbXz2xpZ6xt3fIVTbsvLQcSdb5JTSGkGLbq8o RdOOeGyWYCiZpcidz/+kR+HMWf0+Y37yNMn66sGSzEum2Y70xogvk372ICgEdGhnVSlE jPi6hAIn/vOVT1MIgnRN+UXaVUW0UJ9A1GIbw1Y69ITyO9r5xeYqUXF1+sB8FyOEy/US J36jZlUFNFWlXiyNTer+eDUG8jUyt+RQ7cm/ARRGaoIVxSRkg9kH+xjgWfg5wI5xLtzm YBbIwOBSGO+U7G2j8h9fGABMDSULc/SLkmi+Lc8O61Jlt3WMh4b7WzY0ra3kqFKdRqF2 GIFA== X-Forwarded-Encrypted: i=1; AJvYcCVVa7Oy+N+v+gw7e47EKe0160M70wlBHdzTjhEWsqeKiOO5MBPR5R7VpMjZYY0vnj/qRHoZqowWcqGH@nongnu.org X-Gm-Message-State: AOJu0YxNs4qEMmFSDwicppsyAJKwfjkd6deIonrhn4sokMvDxPSwSbnt 56cIb1ct9oYRmpLPA486D5DEnCcKSFQre8Nq+QZ785kz9cbiPQbnWX0EqIhY X-Google-Smtp-Source: AGHT+IHc/D7yCSD5mjcpw/BQnXjpbZiPvSHDTwlKvfuM2NBZra64dLb6/ik3Ts6+Pt+yjzPaRYalyg== X-Received: by 2002:a05:6402:4308:b0:5c4:14fe:971e with SMTP id 4fb4d7f45d1cf-5c9951ce829mr5155428a12.23.1729176334822; Thu, 17 Oct 2024 07:45:34 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:9c4:b066:486:f408]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5c98d507a14sm2867581a12.49.2024.10.17.07.45.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Oct 2024 07:45:34 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v5 1/8] chardev/char: rename `MuxChardev` struct to `MuxFeChardev` Date: Thu, 17 Oct 2024 16:43:09 +0200 Message-Id: <20241017144316.517709-2-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241017144316.517709-1-r.peniaev@gmail.com> References: <20241017144316.517709-1-r.peniaev@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::535; envelope-from=r.peniaev@gmail.com; helo=mail-ed1-x535.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 Thu Oct 17 14:43:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13840146 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 8CCB4D374A2 for ; Thu, 17 Oct 2024 14:47:17 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t1Rl0-0003Uz-CM; Thu, 17 Oct 2024 10:45:42 -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 1t1Rky-0003UI-EE for qemu-devel@nongnu.org; Thu, 17 Oct 2024 10:45:40 -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 1t1Rkw-0005dB-Rl for qemu-devel@nongnu.org; Thu, 17 Oct 2024 10:45:40 -0400 Received: by mail-ed1-x530.google.com with SMTP id 4fb4d7f45d1cf-5c9552d02e6so1306851a12.2 for ; Thu, 17 Oct 2024 07:45:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1729176337; x=1729781137; 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=curorWq933SuKtgCvjv6I0zkuJwAjHFQpwu/PH1GYprjyf1syEGbNnMmtKDGe4kp9G J1GVv6EoU3HJCCFzTx7y9rqIN6szXAb0XhXdKw6kdS9IQVOPC4awmdNec8cQ6DrumY1c fSw+P7YhaYGV5UuKydjsOK93rTTdC2gQA2FxzHeVcqpTa5aNrqpz3EBEjH2lLvVDAtNF SJWOQN8Y2sYP66FqAMH8VoBBwysD68VbLJGTRsRobZUurUZoXBB2M+UMvUZpDZnJA7GP IINMf5gTqPzpVih2SlHZSXhlL12ctNDVpq0LSA0dl0PmGxUVH/OFiKQSUFJcUnV0g+Cq ZfGg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729176337; x=1729781137; 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=lh+6S/S7o3URD0K87zDqYdnZjdVC8wArvOtylGaZcNcxlxGJubd6E9fztoWx5dYnOm xQO2Xx/P6nGS3x/yHMI8eaD4on4xACVOhDQe97NJ4C4yeyt5f3keyLutrwu7Kj4v0ze+ wXN4EFW47jz2hMokaAuHIvRZmDfAb85ekd/JzH5o/fPaIr6X1htkdbk/oFrrZ8kTNGCN 935bYcrEBgz0AiuUOFilZ0RkR9FBXuLi5FlqfKArZZxhoMBkmYKiqp3SRA94rR6kSxvz azUNmeHghs1wRQCQ9snPm/2SssCuG3438ZpqfwELGB0cbMf+/Lz8ZznPydVndROWTQ+s c9gA== X-Forwarded-Encrypted: i=1; AJvYcCVNKFfejyVCCWKyOpqTXffTlAD5CAr5vx4SBEfNfmdlRaGMStfoYSG3tlwDr8hWRYQ8Fb3RUXgqmT7g@nongnu.org X-Gm-Message-State: AOJu0YxSc0VU2tjrB4lVoG+lgJT3Dp2HQ36v8u61PT9Ritbsm+J3OVSA 9zurndfrNwxwcR9yZx/cYXQx3YJlG8PuJtIz6Ns9gq5D5hpdvJVC X-Google-Smtp-Source: AGHT+IF2YCixYqLfzI4/DGl98h6fPQzush1VKvg4kaTKTnP6VmKNDYdJis+Xyt7V+o1jBkWqmoNOLg== X-Received: by 2002:a05:6402:2710:b0:5c9:6f56:b042 with SMTP id 4fb4d7f45d1cf-5c9950946d4mr5724322a12.4.1729176336915; Thu, 17 Oct 2024 07:45:36 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:9c4:b066:486:f408]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5c98d507a14sm2867581a12.49.2024.10.17.07.45.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Oct 2024 07:45:35 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v5 2/8] chardev/char: rename `char-mux.c` to `char-mux-fe.c` Date: Thu, 17 Oct 2024 16:43:10 +0200 Message-Id: <20241017144316.517709-3-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241017144316.517709-1-r.peniaev@gmail.com> References: <20241017144316.517709-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 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 Thu Oct 17 14:43:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13840147 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 3EDF4D374A3 for ; Thu, 17 Oct 2024 14:47:21 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t1Rl1-0003VI-4O; Thu, 17 Oct 2024 10:45:43 -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 1t1Rkz-0003Up-Gy for qemu-devel@nongnu.org; Thu, 17 Oct 2024 10:45:41 -0400 Received: from mail-ej1-x632.google.com ([2a00:1450:4864:20::632]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1t1Rkx-0005dL-MO for qemu-devel@nongnu.org; Thu, 17 Oct 2024 10:45:41 -0400 Received: by mail-ej1-x632.google.com with SMTP id a640c23a62f3a-a99fa009adcso52723066b.0 for ; Thu, 17 Oct 2024 07:45:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1729176338; x=1729781138; 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=C62QrGLsgS8ADy16BLAY0bbWXgmVTy7Ts04Ix1Oos2n3Z4lvHjNTyzOBGKHgsMG5ZS eg3h/8Nlewl0r/JbM4VVoqAByEvUydfWC2IboYXRJYn1scjHTFyBiwkl/L4cOrk0/N9s 9YfgpLmpRT/6edknmwCvAV1RsSl2A1kDSszaQt0WEaEMqYb3kFChmMw9PxrYnu4gxoCv cGVkKdQCExjmV5XK1RtQqsuHvYkDAkUoVARVyGQXPV6ieWqavrXHSLJOnIJqXAZXPjO9 0MDPdma/PRwPj5M9SKMOd+qhR1hD+02osBTTFcwgD1v0ivqFF+7mI2rNRKuUjmxZz8E3 ZP1A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729176338; x=1729781138; 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=BCcXA3hrqT3fiEKfhXpzRf8Y4dJlrFpHJW6zmLHJQwZOKC7Gldo6ThD/yhlohQF/My 1xAMhlErEHZ5cRqz5L7UBnusiq+6h1kJQWEZEQ3QNDM/6xsh7cQXNG3UjVTy4V8Cg+w6 5S16hkS+angiAeKOmaO+efNq7rjpRLhOjZrEM8Sj7i9F6Pjoorpp3V8MTg0bgdqVpNO6 um9bUC8AkEUG/qJ58oXcDKUAsbCY+idi6vQPZMB0AClR/Zby7O/DiKlFdi5cM5QcqlRx s00gsjvzoDPDwhhBWzitrhsgrC98ngED9tzkbB747XDRJQxPoc9iCJa1WJWnqabEUjU7 ioSA== X-Forwarded-Encrypted: i=1; AJvYcCU1vi2gVLG8R0xLFdFwliW8G0h9nrgJxHAouVS0f61+9V44dGNYmPanbDph241VXTuRapDgVMOkindf@nongnu.org X-Gm-Message-State: AOJu0Yxd7W8Ahf2gx1s6XdoIWjFwroGfJQbOxvLKakm9awhWUwYb9xXL k4bltqa+RrHAeIApmHUXotzNclXYMUnqJprV1JHj/5CV4RLum1tyzEzrurqR X-Google-Smtp-Source: AGHT+IG2EWOVrjhx9LINNklSjxtydl4/ODgdQhzRgzLGUoPwjY13UcTIHgMZBc9aHoreub4io60j7g== X-Received: by 2002:a05:6402:5515:b0:5c9:1beb:b971 with SMTP id 4fb4d7f45d1cf-5c95ac50710mr27530672a12.24.1729176337735; Thu, 17 Oct 2024 07:45:37 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:9c4:b066:486:f408]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5c98d507a14sm2867581a12.49.2024.10.17.07.45.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Oct 2024 07:45:37 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v5 3/8] chardev/char: move away mux suspend/resume calls Date: Thu, 17 Oct 2024 16:43:11 +0200 Message-Id: <20241017144316.517709-4-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241017144316.517709-1-r.peniaev@gmail.com> References: <20241017144316.517709-1-r.peniaev@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::632; envelope-from=r.peniaev@gmail.com; helo=mail-ej1-x632.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 Thu Oct 17 14:43:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13840141 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 3CD41D374A3 for ; Thu, 17 Oct 2024 14:46:13 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t1Rl3-0003WW-8Z; Thu, 17 Oct 2024 10:45:45 -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 1t1Rl1-0003Vh-O5 for qemu-devel@nongnu.org; Thu, 17 Oct 2024 10:45:43 -0400 Received: from mail-lj1-x234.google.com ([2a00:1450:4864:20::234]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1t1Rkz-0005di-Og for qemu-devel@nongnu.org; Thu, 17 Oct 2024 10:45:43 -0400 Received: by mail-lj1-x234.google.com with SMTP id 38308e7fff4ca-2fb4fa17044so11876571fa.3 for ; Thu, 17 Oct 2024 07:45:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1729176340; x=1729781140; 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=X53C9YlUX0EiCW9eo9z20g6pWopwj3vY80M8JYJWB+rS71WBp7eqenhoeB9bQuvib1 ZLcyDAx+kZTot4ULbfTYmvuQsOSFFUOPb4X2g/qkxVDBa68UQ2Lq2r8Ym8q8/tYc4UU6 cLAqizJ5XKAjKDCFCAd/Y3P1ESAFcyOVSlgjRLFFKF4ypW3IKjsFi3X8b35Y8s4qbYkz 7v5LNp3IgrTNoMKcGO4MG0FCKPWy1cA3qrOL5LQmOjMWCJ2bxYNsgXnxMfV2WraZilv8 gO2q+OEghvPxzDTKz7CE2WrEZ2GXfG9Bnbc/e1WoXhkI9gMxp2wfCEKk2KqpuPm01jRn FSVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729176340; x=1729781140; 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=sbrU2uvb1ngU0uc+XVQVMlRJEWehrlEOPZAGEt7VEocqMdtIz36BDAlQDazV+CZzyQ 9RIhvGlMPKQZistgVsXbu38cJUBZqoxV01ZS0QUe+fAP8A6d14hyfnurn+e5JzesxWdN jSRsPx9XOuNacM4AZBY0f+o17CRwL2uf250a4DnSikI/UCCDVwILb996JpvUn4QEcran WZMUb5bfe1XX1S5PfqZcYS2sj+A6kSGy5QgHZjySAiuJa4Wtqw8IdAOOsZqot+efnEEb lJYp1yKJfYjl9w2LplXEx/3wDg1+ua5ZHiNcYltOvP++4hUjpWaQezOxJyHbrWY+u6FJ P05w== X-Forwarded-Encrypted: i=1; AJvYcCW7CTf62QITflKu8zHcjqhCWrPl19CxjHpB4qlXbCbYwA07RmuSewVt2xhffl111Vn5x1zPZS72eUVv@nongnu.org X-Gm-Message-State: AOJu0YyTzhtzJTwq/DqtBv8priu7XvNW7SGZGn6On7mIiwVXFQ6s1yPf JlCfYdxMHbh9F12bf/z7gWphYW0OPZhuFVbSlmLmz3uUjrRoo0ngn2ycdqpD X-Google-Smtp-Source: AGHT+IF2MF2uELI/PYTtWbP9qVbmDRb1YFKiCxdfTGd0GSrHygdQJr2XnuNlOgbNMsFvESW/16d9qg== X-Received: by 2002:a2e:a550:0:b0:2f7:53b8:ca57 with SMTP id 38308e7fff4ca-2fb3f1d3c4cmr92025871fa.19.1729176339601; Thu, 17 Oct 2024 07:45:39 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:9c4:b066:486:f408]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5c98d507a14sm2867581a12.49.2024.10.17.07.45.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Oct 2024 07:45:38 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v5 4/8] chardev/char: rename frontend mux calls Date: Thu, 17 Oct 2024 16:43:12 +0200 Message-Id: <20241017144316.517709-5-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241017144316.517709-1-r.peniaev@gmail.com> References: <20241017144316.517709-1-r.peniaev@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::234; envelope-from=r.peniaev@gmail.com; helo=mail-lj1-x234.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 Thu Oct 17 14:43:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13840139 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 8750DD374A2 for ; Thu, 17 Oct 2024 14:46:12 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t1Rl6-0003Xd-MQ; Thu, 17 Oct 2024 10:45:48 -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 1t1Rl2-0003WP-V1 for qemu-devel@nongnu.org; Thu, 17 Oct 2024 10:45:45 -0400 Received: from mail-ed1-x531.google.com ([2a00:1450:4864:20::531]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1t1Rkz-0005dy-Tb for qemu-devel@nongnu.org; Thu, 17 Oct 2024 10:45:44 -0400 Received: by mail-ed1-x531.google.com with SMTP id 4fb4d7f45d1cf-5c9388a00cfso1203957a12.3 for ; Thu, 17 Oct 2024 07:45:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1729176340; x=1729781140; 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=Rn/d9xVEyTZikeUBgk2zKWDml8U6e/x1G+niwIFwvFYRqeHeoB0QEHgYeTvRLAbUAY ykgs433a26KhzIg4AOx9D97LsfXbmidf5VZKoFSM2ruVDyn1nTIh3goXvU2RZAi6dU47 hRM+L8KcFwwk+6dbr3YQtSq490pKY0L8dmt1I/DzJ53G/lRMsly4jIKfPkiZFpOiBoEC bnlU7rRguJ0Wvev4bOJpVyDwJliLuGKCmIrGwA7jEv7Z+aeDL7OCkZqjFnlKK42G29gN sJhEssWR8h1W45sddHZICfLDV0s81zHBuAI+a9d1kCHLx4whVb5R2Ley1nPgVd38A6zh PwIg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729176340; x=1729781140; 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=WwM+5Y/eXi2VVu9HA1aCjbkZPB2IYJetjaZsPQN3JIKI6WkUQ8MACDEQfHEUeDZHfr QIlt1mD6yRkjd4w3auSa+sOyD8161ga556m61mKcHfpoPaHgPf8CkR2DDpPg4x+e/yyP IMkvAAZqUXJnZtSEeBk3E2qoMVcDxdad48w9uUyC/XhQJpV3/GVNIQ2WQr3NyH2RofMY I+JJ3h8af+KSQR2yY4YfliydfjNF2A2sL4tcgGsMZVHn/erMzngSh5vxkZSHxngPfeoj nbZKb7GQMLgjWkhOKwhTkKrrsGTGFFFto+N3nb/ZTlWw9pXjxIi6bymzd54RI7At+4Xi DbTw== X-Forwarded-Encrypted: i=1; AJvYcCWPBJy3M8nf7rgddUeqvsDO/Y4/2pKhtynHjddbmAwUFEdMaMxPzKR37J7DxDSFUTjSejZWTqCj57dF@nongnu.org X-Gm-Message-State: AOJu0Yx9A5T7bKh33vtrEcIMzCwofnFntUpB5t+xcZ5V3cqi4KWqaSAl NH9LlNr5NYWjNphW1TU+5qonQI9n3nctxiz9aplIVMrxdpj5rW240BY1w6YR X-Google-Smtp-Source: AGHT+IFGSayl88pRs72BuiytCGOTv9sFpDs8PbGAUOpFxe/1e5WwWz42kCQHovDYXSVI08z5JDqRnA== X-Received: by 2002:a05:6402:34c9:b0:5c5:c5c0:74ec with SMTP id 4fb4d7f45d1cf-5c9950e7399mr6168530a12.24.1729176340314; Thu, 17 Oct 2024 07:45:40 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:9c4:b066:486:f408]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5c98d507a14sm2867581a12.49.2024.10.17.07.45.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Oct 2024 07:45:39 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v5 5/8] chardev/char: introduce `mux-be-id=ID` option Date: Thu, 17 Oct 2024 16:43:13 +0200 Message-Id: <20241017144316.517709-6-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241017144316.517709-1-r.peniaev@gmail.com> References: <20241017144316.517709-1-r.peniaev@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::531; envelope-from=r.peniaev@gmail.com; helo=mail-ed1-x531.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 Thu Oct 17 14:43:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13840145 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 ACA30D374A3 for ; Thu, 17 Oct 2024 14:46:57 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t1Rl7-0003Y7-7A; Thu, 17 Oct 2024 10:45:49 -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 1t1Rl4-0003X3-Qs for qemu-devel@nongnu.org; Thu, 17 Oct 2024 10:45:46 -0400 Received: from mail-ed1-x536.google.com ([2a00:1450:4864:20::536]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1t1Rl1-0005es-Vs for qemu-devel@nongnu.org; Thu, 17 Oct 2024 10:45:46 -0400 Received: by mail-ed1-x536.google.com with SMTP id 4fb4d7f45d1cf-5c97c7852e8so1513923a12.1 for ; Thu, 17 Oct 2024 07:45:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1729176342; x=1729781142; 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=y8uFRJduKBOIoIdWhyfSl/CyT6kPP6VnOfjMEjyVSjY=; b=ewWJ5VGB9hn6TyQ30hrg6bIE/vKq09pCW8w51UShpwrZrsEp5hS/YuIRSp15Ki2i1M GTllW4X1t1cVkoxlLSt0zvECyQc2OnNVjdlNlxBzjwZaAOjTQ/jVG29L0puOKZact5I5 YPr0secoPT6DWZkKQAeFSDaxETTsDXMpi2xrOFmKGgQ8Q7p8VSJnkdMLRwqgGaI9uqwi a0/q2ytqgGxJ3lblDq1ri8yvjPzMDabKho7FBhI4+KvhmVYL/qiiL05zPSAhLmaz5C8o WZcQEN5ec3Zbd2iTF3cria0rBRn6OvCUKP0+PMsgZBZfC/HTs6oyAMUNIkoFCSIYlfsS OA4g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729176342; x=1729781142; 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=y8uFRJduKBOIoIdWhyfSl/CyT6kPP6VnOfjMEjyVSjY=; b=ht00TTQR7k6xikks1fwruxJK+j8/EUMWl5EKuxWSN7EeHcUDq+2Ts6AX83JqweAcLF I1lfkWhuHWn3Y7tGYawUTo0uksTg+3jyFW9DtUzDZPBK6+7BsCNnl8myIMcxM6Vnh4/8 Is3bD7sobWu6zvfykoP+jWGxSrZIfelQzBGCq2SuAYIV0CoN4fSxaESekidCs/1N6rGo KDKMcqj7Jya9Z+9NHDm+BVqVu4zHmsi2S5hbNL7CQqxu68Qn8ewJ7M84uz+TrXwNBBeQ qXVPVt6bBSuvc+BsUbeqyP6ENWlUtbQjbDQ15luYB6vbc5UN72htIdOYflLWThU+5zRB 2u1Q== X-Forwarded-Encrypted: i=1; AJvYcCU+zlfyD8jEMhz+xvMIICN3CimEHzAtisUu+aDyANGlrrkghrYH0kW4suaS76JysTDg72v6+L/SyaUA@nongnu.org X-Gm-Message-State: AOJu0YxQ3mLeBneb+7JpEvydva06Y5tJYFyJQqThgbquz9Wmnqk4x3JR dk3RsZlcK9Lc7Kqk5vxugfVBKvT4vQssf4n/PYtFfncNo7MX7JbM X-Google-Smtp-Source: AGHT+IHCHyVjlbWv9f3e8uQnJJy0IaAq5mKIPCjBbokRthtCIrFzYfPfYKDfdEh+7vyU23K0c+2rBw== X-Received: by 2002:a05:6402:34d4:b0:5c8:8381:c1bf with SMTP id 4fb4d7f45d1cf-5c95ac098e1mr11534626a12.3.1729176342199; Thu, 17 Oct 2024 07:45:42 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:9c4:b066:486:f408]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5c98d507a14sm2867581a12.49.2024.10.17.07.45.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Oct 2024 07:45:40 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v5 6/8] chardev/char-mux: implement backend chardev multiplexing Date: Thu, 17 Oct 2024 16:43:14 +0200 Message-Id: <20241017144316.517709-7-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241017144316.517709-1-r.peniaev@gmail.com> References: <20241017144316.517709-1-r.peniaev@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::536; envelope-from=r.peniaev@gmail.com; helo=mail-ed1-x536.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 | 62 ++++++-- chardev/chardev-internal.h | 34 ++++- chardev/meson.build | 1 + include/chardev/char.h | 1 + qapi/char.json | 25 ++++ 7 files changed, 409 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..551ae402cba7 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,25 @@ 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; + } else if (mux_be_id) { + const ObjectClass *oc = &cc->parent_class; + + if (oc == object_class_by_name(TYPE_CHARDEV_MUX_FE) || + oc == object_class_by_name(TYPE_CHARDEV_MUX_BE)) { + /* Stacking is not supported due to possible dependency loops */ + error_setg(errp, "chardev: multiplexers can't be stacked"); + 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 +703,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 +744,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 +1150,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 +1338,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 +1365,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 Thu Oct 17 14:43:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13840142 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 991AAD374A2 for ; Thu, 17 Oct 2024 14:46:28 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t1Rl8-0003Zk-Bf; Thu, 17 Oct 2024 10:45:50 -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 1t1Rl5-0003XQ-UU for qemu-devel@nongnu.org; Thu, 17 Oct 2024 10:45:47 -0400 Received: from mail-lj1-x22b.google.com ([2a00:1450:4864:20::22b]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1t1Rl2-0005fB-OA for qemu-devel@nongnu.org; Thu, 17 Oct 2024 10:45:47 -0400 Received: by mail-lj1-x22b.google.com with SMTP id 38308e7fff4ca-2fb518014b9so9839151fa.3 for ; Thu, 17 Oct 2024 07:45:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1729176343; x=1729781143; 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=OuAtGnIZeBLL9MISZlOD/G0pLbwC3CAC1YLQSZfl9F0=; b=XGnw0b/dtJEBmYQCmMHDpCGR2nhLMPJlzRWQ8c5Lg6v35AbnnqxdeSBNP9AKjuf76f We71ySOH6xkO9y4qmUvIxsw4nkVOwTtfoYUIsb0exegGf3Q9WF4Va3wSI8R9dN+Pg7K1 E+lOwEtISQwpvhzzn/ZLSC/LdOKWFTkeJnrTbQdeMGK60G/WWo85j+LVgWxFhQ1H0e0F B4B5rnc5vH5hvebBWjdjHXaaqmLrvnNKLgAdAM6JwAjgfnmH/QQpbtJ0WNP56SP5MWvt GX6ZDftN8lShDNqRx2F0SZSYhZItK1UiCWtew/XgufW0MqOCBm4NB/D9yIOSUuxQrBd9 93KQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729176343; x=1729781143; 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=OuAtGnIZeBLL9MISZlOD/G0pLbwC3CAC1YLQSZfl9F0=; b=iZ/uD+5YwhByB7SYdroFz08LnCDWJrszDTHo3geoGvXjbet5V9W0c+ajRVVh+gez7g A+ufMU5OxDgGbxThvXUIMqpaxgZ3TBpkVsd3haqekG49Cn2pFaTb38AeTlCPLS/cZXKn AuB/2fTNGONqNXzT1/EZMog93u9f22IY9KJtkP/b/BLrqEy+HjAYa9pL+e3sbRQWh7Jh 9yq5kOxOP/q6G8js/3IoFh5NUP7pcH2l8XZ0+C6JAoHnrl/5LhrPNkVXT2FzrhUrhbpv Og5HB5GLX0NebfkjQDIAwFiqku9IMb8HLpb5iboPZtrnspO0ZkJ09Ati4gb0B9er2hd1 WVOg== X-Forwarded-Encrypted: i=1; AJvYcCViQrZ+K7LWsJGU/FXj2FOiiMok9yWKO81vG6NaF7yQE/SiaIwPgNcoGDsfdg/1CbGGi2pHZxBrttbk@nongnu.org X-Gm-Message-State: AOJu0YwTax1UkgT0FXv3y61gXSsQAE63QTURknH8TLpG4GF/O/wjhkAU e2GUoHDXVj1ztHlFzpuwdtG8gLVYuGmDPtgwq2uMIoBEPp6ZFY/B X-Google-Smtp-Source: AGHT+IEOwDjU+zn5pLKv89ew8WYvkh3H0ofRVToa0jUlRmou0BDJaApFcCtFgtV94kCOMlBFA4Z4ew== X-Received: by 2002:a2e:be9d:0:b0:2fb:48f6:27e4 with SMTP id 38308e7fff4ca-2fb61b3e646mr53709811fa.3.1729176342843; Thu, 17 Oct 2024 07:45:42 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:9c4:b066:486:f408]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5c98d507a14sm2867581a12.49.2024.10.17.07.45.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Oct 2024 07:45:42 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v5 7/8] tests/unit/test-char: add unit test for the `mux-be` multiplexer Date: Thu, 17 Oct 2024 16:43:15 +0200 Message-Id: <20241017144316.517709-8-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241017144316.517709-1-r.peniaev@gmail.com> References: <20241017144316.517709-1-r.peniaev@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::22b; envelope-from=r.peniaev@gmail.com; helo=mail-lj1-x22b.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 | 323 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 321 insertions(+), 2 deletions(-) diff --git a/tests/unit/test-char.c b/tests/unit/test-char.c index a1c6bb874c8e..25bb5b70347e 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,324 @@ 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 with invalid mux-be-id */ + opts = qemu_opts_create(qemu_find_opts("chardev"), "mux0", + 1, &error_abort); + qemu_opt_set(opts, "backend", "mux-be", &error_abort); + qemu_opt_set(opts, "mux-be-id", "something", &error_abort); + mux_be = qemu_chr_new_from_opts(opts, NULL, &error); + g_assert_cmpstr(error_get_pretty(error), ==, "chardev: multiplexers " + "can't be stacked"); + error_free(error); + error = NULL; + qemu_opts_del(opts); + + /* 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); + + g_free(in); + g_free(out); + g_free(tmp_path); + g_free(pipe); + } +#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 +1824,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 Thu Oct 17 14:43:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13840143 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 88253D374A4 for ; Thu, 17 Oct 2024 14:46:47 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t1Rl7-0003YK-Un; Thu, 17 Oct 2024 10:45:49 -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 1t1Rl6-0003XZ-4o for qemu-devel@nongnu.org; Thu, 17 Oct 2024 10:45:48 -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 1t1Rl4-0005fe-16 for qemu-devel@nongnu.org; Thu, 17 Oct 2024 10:45:47 -0400 Received: by mail-ed1-x533.google.com with SMTP id 4fb4d7f45d1cf-5c9625cfe4dso1383810a12.0 for ; Thu, 17 Oct 2024 07:45:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1729176344; x=1729781144; 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=BPum5WuUR1pl6Nf8anLI5uEzQpe4u1JtVxTalO9kwT8=; b=WTkDgsTzGOOE5aXRHxsZvbBLJdiILT4AX4O2caw8iXWhJzuPguwgLEkxr8GR8xQT7/ XifHGfIlETmmzGK24sR7cDOR6wbILd8r6oNJw6jMrEmidLCbnNh7H6ytfWNbUA3ZitKQ X164H+ZrjK7M7wX05dVtLtbnB+l5B1kpOfeLELXcSxEeDsfGKMPWdbQA6Ehzz1sswpug Aid9NdVo6bfqd9ONRE6m8KrkNbI7xkEvWN7DTaOnxr/isSJqQJHDfHW3HdRReVj/lFVF +4H5VRLpIX7koVzaxdO0qrrhxVePfwNGBZIBiut3rJd3KpILE37qx4KlEgLMVRWHSeJ7 P7Ig== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729176344; x=1729781144; 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=BPum5WuUR1pl6Nf8anLI5uEzQpe4u1JtVxTalO9kwT8=; b=JtIYk5/mEKOl9Wsh0hZapvTIMPnyEnm5b5FHm0H9/7STqD1nNZG6q31MriyfRgux7e LggUVqiW25Bvjg1pwtt14zo4wtWVZ98VaXHno5YALEuFjVxWjFgybAqmtn0QxAdjIT2a SIdgLlv0UES79xuuMWDEL2TaT+axPWvXrH5v8DSNT4OFrdUEKfJqVQHl4LYacM9zhfAe P+52yV7daG2CLAiI4vUD39RcB/KCE7lKDBdeUjlDTC2+BwcFVQ8q0lmKTWlGpj1tjz1x dFIMxS8qcoGCYzEIaM369clZgTh18a1BLlzp0h/pFF/CcHMaEkc0xUQhWKjy+S3B1upR eutA== X-Forwarded-Encrypted: i=1; AJvYcCV3Dd1Xg6RVutDluVYVqxsLu3VdKodAqcvU9vVDIvo03ScjaaQ7tZc6JjjkIluXehaJSSQd5g9MHPRg@nongnu.org X-Gm-Message-State: AOJu0YxXwF+rQxB62LrRZFvjE7PyszvkwieUhtHInuQF7mhsQzZGrq4D USPAxwwj3lnrd034IL28Amy0TEt6GKjzAfremQHwol0yzc1BNufV X-Google-Smtp-Source: AGHT+IFB7wPcnERiA5LRenZDfsxhw2O3PPrNeBoEPL1806/I5t6mCc+tmrXj3qhmVbSaVrHOPDgSVQ== X-Received: by 2002:a05:6402:1e93:b0:5c9:845f:25fd with SMTP id 4fb4d7f45d1cf-5c9845f2752mr10802859a12.23.1729176344220; Thu, 17 Oct 2024 07:45:44 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:9c4:b066:486:f408]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5c98d507a14sm2867581a12.49.2024.10.17.07.45.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Oct 2024 07:45:43 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v5 8/8] qemu-options.hx: describe multiplexing of several backend devices Date: Thu, 17 Oct 2024 16:43:16 +0200 Message-Id: <20241017144316.517709-9-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241017144316.517709-1-r.peniaev@gmail.com> References: <20241017144316.517709-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 | 80 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 20 deletions(-) diff --git a/qemu-options.hx b/qemu-options.hx index daae49414740..d620dc39b489 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,11 @@ 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 the ``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 +3881,44 @@ 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 the possibility + to multiplex in the opposite direction, where one QEMU interface + (frontend device) receives input and output from multiple chardev + backend devices. (Since 9.2) + + For example, the following is a use case of 2 backend devices: + 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 + bidirectional communication to the virtio hvc console over the + socket. The example configuration can be as follows: + + :: + + -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 several frontend + devices is not supported. Stacking of multiplexers is not + supported as well. + ``-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.