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]> --- 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
