On Mon, Oct 13, 2025 at 5:40 PM Vladimir Sementsov-Ogievskiy <[email protected]> wrote: > > We'll need a possibility to postpone connect step to later point in > time to implement backend-transfer migration feature for vhost-user-blk > in further commits. Let's start with new char interface for backends. > > .init() takes QAPI parameters and should parse them, called early > > .connect() should actually establish a connection, and postponed to > the point of attaching to frontend. Called at later point, either > at time of attaching frontend, either from qemu_chr_wait_connected(). > > Signed-off-by: Vladimir Sementsov-Ogievskiy <[email protected]>
Reviewed-by: Marc-André Lureau <[email protected]> > --- > chardev/char-fe.c | 4 ++++ > chardev/char.c | 40 +++++++++++++++++++++++++++++++++++++--- > include/chardev/char.h | 22 +++++++++++++++++++++- > 3 files changed, 62 insertions(+), 4 deletions(-) > > diff --git a/chardev/char-fe.c b/chardev/char-fe.c > index 158a5f4f55..973fed5bea 100644 > --- a/chardev/char-fe.c > +++ b/chardev/char-fe.c > @@ -193,6 +193,10 @@ bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error > **errp) > { > unsigned int tag = 0; > > + if (!qemu_chr_connect(s, errp)) { > + return false; > + } > + > if (s) { > if (CHARDEV_IS_MUX(s)) { > MuxChardev *d = MUX_CHARDEV(s); > diff --git a/chardev/char.c b/chardev/char.c > index 6498d53daa..01ffe37acf 100644 > --- a/chardev/char.c > +++ b/chardev/char.c > @@ -33,6 +33,7 @@ > #include "qapi/error.h" > #include "qapi/qapi-commands-char.h" > #include "qapi/qmp/qerror.h" > +#include "qom/object.h" > #include "system/replay.h" > #include "qemu/help_option.h" > #include "qemu/module.h" > @@ -338,10 +339,29 @@ static bool qemu_chr_is_busy(Chardev *s) > } > } > > +bool qemu_chr_connect(Chardev *chr, Error **errp) > +{ > + ChardevClass *cc = CHARDEV_GET_CLASS(chr); > + > + if (chr->connect_postponed) { > + assert(cc->connect); > + chr->connect_postponed = false; > + if (!cc->connect(chr, errp)) { > + return false; > + } > + } > + > + return true; > +} > + > int qemu_chr_wait_connected(Chardev *chr, Error **errp) > { > ChardevClass *cc = CHARDEV_GET_CLASS(chr); > > + if (!qemu_chr_connect(chr, errp)) { > + return -1; > + } > + > if (cc->chr_wait_connected) { > return cc->chr_wait_connected(chr, errp); > } > @@ -1029,7 +1049,7 @@ static Chardev *chardev_new(const char *id, const char > *typename, > { > Object *obj; > Chardev *chr = NULL; > - Error *local_err = NULL; > + ChardevClass *cc; > > assert(g_str_has_prefix(typename, "chardev-")); > assert(id); > @@ -1044,8 +1064,22 @@ static Chardev *chardev_new(const char *id, const char > *typename, > goto fail; > } > > - if (!qemu_char_open(chr, backend, typename + 8, &local_err)) { > - goto fail; > + cc = CHARDEV_GET_CLASS(chr); > + > + if (cc->init) { > + assert(!cc->open); > + assert(cc->connect); > + > + if (!cc->init(chr, backend, errp)) { > + goto fail; > + } > + assert(chr->filename); > + > + chr->connect_postponed = true; > + } else { > + if (!qemu_char_open(chr, backend, typename + 8, errp)) { > + goto fail; > + } > } > > return chr; > diff --git a/include/chardev/char.h b/include/chardev/char.h > index 429852f8d9..ebadaf3482 100644 > --- a/include/chardev/char.h > +++ b/include/chardev/char.h > @@ -63,6 +63,7 @@ struct Chardev { > CharBackend *be; > char *label; > char *filename; > + bool connect_postponed; > int logfd; > int be_open; > /* used to coordinate the chardev-change special-case: */ > @@ -225,6 +226,7 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const > char *filename, > bool permit_mux_mon); > int qemu_chr_write(Chardev *s, const uint8_t *buf, int len, bool write_all); > #define qemu_chr_write_all(s, buf, len) qemu_chr_write(s, buf, len, true) > +bool qemu_chr_connect(Chardev *chr, Error **errp); > int qemu_chr_wait_connected(Chardev *chr, Error **errp); > > #define TYPE_CHARDEV "chardev" > @@ -259,10 +261,28 @@ struct ChardevClass { > /* parse command line options and populate QAPI @backend */ > void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp); > > - /* called after construction, open/starts the backend */ > + /* > + * Called after construction, create and open/starts the backend, > + * mutual exclusive with .init. .connect must not be defined when > + * .open is defined. > + */ > void (*open)(Chardev *chr, ChardevBackend *backend, > bool *be_opened, Error **errp); > > + /* > + * Called after construction, create the backend, mutual exclusive > + * with .open, and must be accompanied by .connect. > + * Must set chr-filename. > + */ > + bool (*init)(Chardev *chr, ChardevBackend *backend, > + Error **errp); > + > + /* > + * Called after .init(), open/starts the backend, mutual exclusive > + * with .open. Must send CHR_EVENT_OPENED. > + */ > + bool (*connect)(Chardev *chr, Error **errp); > + > /* write buf to the backend */ > int (*chr_write)(Chardev *s, const uint8_t *buf, int len); > > -- > 2.48.1 > > -- Marc-André Lureau
