For further vhost-user-blk backend-transfer migration realization we want to give it (vhost-user-blk) a possibility (and responsibility) to decide when do connect.
For incoming migration we'll need to postpone connect at least until early stage of migrate-incoming command, when we already know all migration parameters and can decide, are we going to do incoming backend-transfer (and get chardev fd from incoming stream), or we finally need to connect. Signed-off-by: Vladimir Sementsov-Ogievskiy <[email protected]> --- chardev/char-fe.c | 32 ++++++++++++++++++++++++----- hw/core/qdev-properties-system.c | 26 ++++++++++++++++++++--- include/chardev/char-fe.h | 8 ++++++-- include/hw/qdev-properties-system.h | 3 +++ 4 files changed, 59 insertions(+), 10 deletions(-) diff --git a/chardev/char-fe.c b/chardev/char-fe.c index c67b4d640f..1132ec0501 100644 --- a/chardev/char-fe.c +++ b/chardev/char-fe.c @@ -189,15 +189,26 @@ bool qemu_chr_fe_backend_open(CharFrontend *c) return c->chr && c->chr->be_open; } -bool qemu_chr_fe_init(CharFrontend *c, Chardev *s, Error **errp) +bool qemu_chr_fe_init_ex(CharFrontend *c, Chardev *s, bool connect, + Error **errp) { unsigned int tag = 0; - if (!qemu_chr_connect(s, errp)) { - return false; - } - if (s) { + if (connect) { + if (!qemu_chr_connect(s, errp)) { + return false; + } + } else { + /* DEFINE_PROP_CHR_NO_CONNECT */ + if (!s->connect_postponed) { + error_setg(errp, + "Chardev %s does not support postponed connect", + s->label); + return false; + } + } + if (CHARDEV_IS_MUX(s)) { MuxChardev *d = MUX_CHARDEV(s); @@ -210,6 +221,12 @@ bool qemu_chr_fe_init(CharFrontend *c, Chardev *s, Error **errp) } else { s->fe = c; } + } else { + /* + * connect=false comes only from DEFINE_PROP_CHR_NO_CONNECT, + * through do_set_chr, which provides chardev ptr. + */ + assert(connect); } c->fe_is_open = false; @@ -218,6 +235,11 @@ bool qemu_chr_fe_init(CharFrontend *c, Chardev *s, Error **errp) return true; } +bool qemu_chr_fe_init(CharFrontend *c, Chardev *s, Error **errp) +{ + return qemu_chr_fe_init_ex(c, s, true, errp); +} + void qemu_chr_fe_deinit(CharFrontend *c, bool del) { assert(c); diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 13cc91680b..00f4b19238 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -266,8 +266,8 @@ static void get_chr(Object *obj, Visitor *v, const char *name, void *opaque, g_free(p); } -static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque, - Error **errp) +static void do_set_chr(Object *obj, Visitor *v, const char *name, void *opaque, + bool connect, Error **errp) { ERRP_GUARD(); const Property *prop = opaque; @@ -297,13 +297,25 @@ static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque, if (s == NULL) { error_setg(errp, "Property '%s.%s' can't find value '%s'", object_get_typename(obj), name, str); - } else if (!qemu_chr_fe_init(fe, s, errp)) { + } else if (!qemu_chr_fe_init_ex(fe, s, connect, errp)) { error_prepend(errp, "Property '%s.%s' can't take value '%s': ", object_get_typename(obj), name, str); } g_free(str); } +static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque, + Error **errp) +{ + do_set_chr(obj, v, name, opaque, true, errp); +} + +static void set_chr_no_connect(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + do_set_chr(obj, v, name, opaque, false, errp); +} + static void release_chr(Object *obj, const char *name, void *opaque) { const Property *prop = opaque; @@ -320,6 +332,14 @@ const PropertyInfo qdev_prop_chr = { .release = release_chr, }; +const PropertyInfo qdev_prop_chr_no_connect = { + .type = "str", + .description = "ID of a chardev to use as a backend", + .get = get_chr, + .set = set_chr_no_connect, + .release = release_chr, +}; + /* --- mac address --- */ /* diff --git a/include/chardev/char-fe.h b/include/chardev/char-fe.h index 5f8a6df17d..f3df57afa1 100644 --- a/include/chardev/char-fe.h +++ b/include/chardev/char-fe.h @@ -25,14 +25,18 @@ struct CharFrontend { }; /** - * qemu_chr_fe_init: + * qemu_chr_fe_init(_ex): * * Initializes the frontend @c for the given Chardev backend @s. Call * qemu_chr_fe_deinit() to remove the association and release the backend. + * Call qemu_chr_connect(), except for the case when connect=false + * parameter set for _ex() version. * * Returns: false on error. */ -bool qemu_chr_fe_init(CharFrontend *c, Chardev *be, Error **errp); +bool qemu_chr_fe_init(CharFrontend *c, Chardev *s, Error **errp); +bool qemu_chr_fe_init_ex(CharFrontend *c, Chardev *s, bool connect, + Error **errp); /** * qemu_chr_fe_deinit: diff --git a/include/hw/qdev-properties-system.h b/include/hw/qdev-properties-system.h index 5c6cc5eae8..a0b14a2f77 100644 --- a/include/hw/qdev-properties-system.h +++ b/include/hw/qdev-properties-system.h @@ -7,6 +7,7 @@ bool qdev_prop_sanitize_s390x_loadparm(uint8_t *loadparm, const char *str, Error **errp); extern const PropertyInfo qdev_prop_chr; +extern const PropertyInfo qdev_prop_chr_no_connect; extern const PropertyInfo qdev_prop_macaddr; extern const PropertyInfo qdev_prop_reserved_region; extern const PropertyInfo qdev_prop_multifd_compression; @@ -39,6 +40,8 @@ extern const PropertyInfo qdev_prop_virtio_gpu_output_list; #define DEFINE_PROP_CHR(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharFrontend) +#define DEFINE_PROP_CHR_NO_CONNECT(_n, _s, _f) \ + DEFINE_PROP(_n, _s, _f, qdev_prop_chr_no_connect, CharFrontend) #define DEFINE_PROP_NETDEV(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, NICPeers) #define DEFINE_PROP_DRIVE(_n, _s, _f) \ -- 2.48.1
