Hi On Fri, Oct 31, 2025 at 7:59 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, or 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 | 39 +++++++++++++++++++++++++++++++++++++-- > include/chardev/char.h | 30 +++++++++++++++++++++++++++++- > 3 files changed, 70 insertions(+), 3 deletions(-) > > diff --git a/chardev/char-fe.c b/chardev/char-fe.c > index 34b83fc1c4..c67b4d640f 100644 > --- a/chardev/char-fe.c > +++ b/chardev/char-fe.c > @@ -193,6 +193,10 @@ bool qemu_chr_fe_init(CharFrontend *c, Chardev *s, > Error **errp) > { > unsigned int tag = 0; > > + if (!qemu_chr_connect(s, errp)) { > + return false; > + } > this should be after "if (s)" condition. It is moved in a later patch, but better do it now. > + > if (s) { > if (CHARDEV_IS_MUX(s)) { > MuxChardev *d = MUX_CHARDEV(s); > diff --git a/chardev/char.c b/chardev/char.c > index 7a029b0eb9..33eba0cdc0 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); > } > @@ -1030,6 +1050,7 @@ static Chardev *chardev_new(const char *id, const > char *typename, > { > Object *obj; > Chardev *chr = NULL; > + ChardevClass *cc; > > assert(g_str_has_prefix(typename, "chardev-")); > assert(id); > @@ -1044,8 +1065,22 @@ static Chardev *chardev_new(const char *id, const > char *typename, > goto fail; > } > > - if (!qemu_char_open(chr, backend, typename + 8, errp)) { > - 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 b65e9981c1..24c449b07b 100644 > --- a/include/chardev/char.h > +++ b/include/chardev/char.h > @@ -63,6 +63,7 @@ struct Chardev { > CharFrontend *fe; > 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,7 +261,33 @@ 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 the backend, mutually exclusive > + * with @open, and should be followed by @connect(). > + * Must set the Chardev's chr->filename on success. > + */ > + bool (*init)(Chardev *chr, ChardevBackend *backend, > + Error **errp); > + > + /* > + * Called after @init(), starts the backend, mutually exclusive > + * with @open. Should care to send CHR_EVENT_OPENED when connected > + * (this may happen asynchronously after .connect() call alredy > + * returned). > + */ > + bool (*connect)(Chardev *chr, Error **errp); > + > + /* > + * Called after construction, an alternative to @init + @connect > + * and should do the work for both: create and start the backend. > + * Mutually exclusive with @init and @connect. > + * > + * May not set the Chardev's chr->filename (generic code will care), > + * and may not send CHR_EVENT_OPENED when connected (@be_opened > + * should not be touched in this case, to signal the generic code > + * to care about CHR_EVENT_OPENED). If the backend cares about > + * CHR_EVENT_OPENED, it should set @be_opened to false. > + */ > void (*open)(Chardev *chr, ChardevBackend *backend, > bool *be_opened, Error **errp); > > -- > 2.48.1 > >
