chardev patches

-----BEGIN PGP SIGNATURE-----
 
 iQIcBAABAgAGBQJbtKCeAAoJENro4Ql1lpzlpSAQALQLmMMuzYwUkpC7J5rxvlYv
 bKpdi3urdXxQ2zG+QDErCQEsJdGefmJkcT236qRyWR2Ol5J0x5aOA/vZO3EDRGbH
 uEvuaJt0WamPOT8H2JKGfYyp6dT+VvO7ZIJqeCWGFyMy1LJaJR6eYnEjr2Z0eB/J
 s8MhIPTw5xl4x44Bi9/52nkk3HZlpZF36CvdQA+rGVvz1E/MFbDECgV6xMGMmTPw
 P95pgK73JWB+B+6IZcEDUrL42xH3SBqm/ty9r8kT45NGui1l6CdwjEck4MDnafdc
 bsGTMCJn35B0rPx/vPd9M/ocw4q1Ql2ErvOiMo6Kx6d98Y7O7+jf1NF3uZfT19fc
 Y1/ysv2a7BMHF81iJcR4xYQGs5s1xenxm2pK1A1dxz5Ltwbw/3ns+sDCkQvZww9q
 UAc9y+fywmqJVFhX/pF7DLkpeKa2LPviBiJkEKErrrgXv1bU5TcR18NkDcXl4eR6
 Mi9mjyx868lotlHOwcbcdZGvrY82HFToxTuU8tleNKsdAE9q8zT9Iocg6Q5xAvH2
 2gwW4isY0RvGvhWwabAhOVw1kIsPD2qICzMUZGKtYA6o4whbY4uvxP+EVtKuy8KP
 OIyMd4YcGvS065QvHzwCu8U9U7eJPZP9cbrn+iP93gBGBHiL+w9hhU10sEiTUYw+
 JqwsmDWVhUx9RIdftiZn
 =xdVN
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/elmarco/tags/chardev-pull-request' into staging

chardev patches

# gpg: Signature made Wed 03 Oct 2018 11:57:34 BST
# gpg:                using RSA key DAE8E10975969CE5
# gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>"
# gpg:                 aka "Marc-André Lureau <marcandre.lureau@gmail.com>"
# Primary key fingerprint: 87A9 BD93 3F87 C606 D276  F62D DAE8 E109 7596 9CE5

* remotes/elmarco/tags/chardev-pull-request:
  chardev: use a child source for qio input source
  chardev: mark the calls that allow an implicit mux monitor
  char.h: fix gtk-doc comment style
  chardev: unref if underlying chardev has no parent
  chardev: remove qemu_chr_fe_read_all() counter
  chardev: avoid crash if no associated address

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2018-10-03 14:07:49 +01:00
commit b8e5671a8c
10 changed files with 149 additions and 147 deletions

View File

@ -56,7 +56,7 @@ int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len)
int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len)
{
Chardev *s = be->chr;
int offset = 0, counter = 10;
int offset = 0;
int res;
if (!s || !CHARDEV_GET_CLASS(s)->chr_sync_read) {
@ -88,10 +88,6 @@ int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len)
}
offset += res;
if (!counter--) {
break;
}
}
if (qemu_chr_replay(s) && replay_mode == REPLAY_MODE_RECORD) {
@ -239,7 +235,12 @@ void qemu_chr_fe_deinit(CharBackend *b, bool del)
d->backends[b->tag] = NULL;
}
if (del) {
object_unparent(OBJECT(b->chr));
Object *obj = OBJECT(b->chr);
if (obj->parent) {
object_unparent(obj);
} else {
object_unref(obj);
}
}
b->chr = NULL;
}

View File

@ -33,7 +33,6 @@ typedef struct IOWatchPoll {
IOCanReadHandler *fd_can_read;
GSourceFunc fd_read;
void *opaque;
GMainContext *context;
} IOWatchPoll;
static IOWatchPoll *io_watch_poll_from_source(GSource *source)
@ -55,47 +54,24 @@ static gboolean io_watch_poll_prepare(GSource *source,
iwp->src = qio_channel_create_watch(
iwp->ioc, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL);
g_source_set_callback(iwp->src, iwp->fd_read, iwp->opaque, NULL);
g_source_attach(iwp->src, iwp->context);
} else {
g_source_destroy(iwp->src);
g_source_add_child_source(source, iwp->src);
g_source_unref(iwp->src);
} else {
g_source_remove_child_source(source, iwp->src);
iwp->src = NULL;
}
return FALSE;
}
static gboolean io_watch_poll_check(GSource *source)
{
return FALSE;
}
static gboolean io_watch_poll_dispatch(GSource *source, GSourceFunc callback,
gpointer user_data)
{
abort();
}
static void io_watch_poll_finalize(GSource *source)
{
/* Due to a glib bug, removing the last reference to a source
* inside a finalize callback causes recursive locking (and a
* deadlock). This is not a problem inside other callbacks,
* including dispatch callbacks, so we call io_remove_watch_poll
* to remove this source. At this point, iwp->src must
* be NULL, or we would leak it.
*
* This would be solved much more elegantly by child sources,
* but we support older glib versions that do not have them.
*/
IOWatchPoll *iwp = io_watch_poll_from_source(source);
assert(iwp->src == NULL);
return G_SOURCE_CONTINUE;
}
static GSourceFuncs io_watch_poll_funcs = {
.prepare = io_watch_poll_prepare,
.check = io_watch_poll_check,
.dispatch = io_watch_poll_dispatch,
.finalize = io_watch_poll_finalize,
};
GSource *io_add_watch_poll(Chardev *chr,
@ -115,7 +91,6 @@ GSource *io_add_watch_poll(Chardev *chr,
iwp->ioc = ioc;
iwp->fd_read = (GSourceFunc) fd_read;
iwp->src = NULL;
iwp->context = context;
name = g_strdup_printf("chardev-iowatch-%s", chr->label);
g_source_set_name((GSource *)iwp, name);
@ -126,23 +101,10 @@ GSource *io_add_watch_poll(Chardev *chr,
return (GSource *)iwp;
}
static void io_remove_watch_poll(GSource *source)
{
IOWatchPoll *iwp;
iwp = io_watch_poll_from_source(source);
if (iwp->src) {
g_source_destroy(iwp->src);
g_source_unref(iwp->src);
iwp->src = NULL;
}
g_source_destroy(&iwp->parent);
}
void remove_fd_in_watch(Chardev *chr)
{
if (chr->gsource) {
io_remove_watch_poll(chr->gsource);
g_source_destroy(chr->gsource);
chr->gsource = NULL;
}
}

View File

@ -423,8 +423,12 @@ static void update_disconnected_filename(SocketChardev *s)
Chardev *chr = CHARDEV(s);
g_free(chr->filename);
chr->filename = SocketAddress_to_str("disconnected:", s->addr,
s->is_listen, s->is_telnet);
if (s->addr) {
chr->filename = SocketAddress_to_str("disconnected:", s->addr,
s->is_listen, s->is_telnet);
} else {
chr->filename = g_strdup("disconnected:socket");
}
}
/* NB may be called even if tcp_chr_connect has not been

View File

@ -329,7 +329,8 @@ int qemu_chr_wait_connected(Chardev *chr, Error **errp)
return 0;
}
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename,
bool permit_mux_mon)
{
char host[65], port[33], width[8], height[8];
int pos;
@ -344,6 +345,10 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
}
if (strstart(filename, "mon:", &p)) {
if (!permit_mux_mon) {
error_report("mon: isn't supported in this context");
return NULL;
}
filename = p;
qemu_opt_set(opts, "mux", "on", &error_abort);
if (strcmp(filename, "stdio") == 0) {
@ -683,7 +688,8 @@ out:
return chr;
}
Chardev *qemu_chr_new_noreplay(const char *label, const char *filename)
Chardev *qemu_chr_new_noreplay(const char *label, const char *filename,
bool permit_mux_mon)
{
const char *p;
Chardev *chr;
@ -694,25 +700,32 @@ Chardev *qemu_chr_new_noreplay(const char *label, const char *filename)
return qemu_chr_find(p);
}
opts = qemu_chr_parse_compat(label, filename);
opts = qemu_chr_parse_compat(label, filename, permit_mux_mon);
if (!opts)
return NULL;
chr = qemu_chr_new_from_opts(opts, &err);
if (err) {
if (!chr) {
error_report_err(err);
goto out;
}
if (chr && qemu_opt_get_bool(opts, "mux", 0)) {
if (qemu_opt_get_bool(opts, "mux", 0)) {
assert(permit_mux_mon);
monitor_init(chr, MONITOR_USE_READLINE);
}
out:
qemu_opts_del(opts);
return chr;
}
Chardev *qemu_chr_new(const char *label, const char *filename)
static Chardev *qemu_chr_new_permit_mux_mon(const char *label,
const char *filename,
bool permit_mux_mon)
{
Chardev *chr;
chr = qemu_chr_new_noreplay(label, filename);
chr = qemu_chr_new_noreplay(label, filename, permit_mux_mon);
if (chr) {
if (replay_mode != REPLAY_MODE_NONE) {
qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_REPLAY);
@ -726,6 +739,16 @@ Chardev *qemu_chr_new(const char *label, const char *filename)
return chr;
}
Chardev *qemu_chr_new(const char *label, const char *filename)
{
return qemu_chr_new_permit_mux_mon(label, filename, false);
}
Chardev *qemu_chr_new_mux_mon(const char *label, const char *filename)
{
return qemu_chr_new_permit_mux_mon(label, filename, true);
}
static int qmp_query_chardev_foreach(Object *obj, void *data)
{
Chardev *chr = CHARDEV(obj);

View File

@ -2038,7 +2038,11 @@ int gdbserver_start(const char *device)
sigaction(SIGINT, &act, NULL);
}
#endif
chr = qemu_chr_new_noreplay("gdb", device);
/*
* FIXME: it's a bit weird to allow using a mux chardev here
* and implicitly setup a monitor. We may want to break this.
*/
chr = qemu_chr_new_noreplay("gdb", device, true);
if (!chr)
return -1;
}

View File

@ -207,7 +207,11 @@ static int con_init(struct XenDevice *xendev)
} else {
snprintf(label, sizeof(label), "xencons%d", con->xendev.dev);
qemu_chr_fe_init(&con->chr,
qemu_chr_new(label, output), &error_abort);
/*
* FIXME: sure we want to support implicit
* muxed monitors here?
*/
qemu_chr_new_mux_mon(label, output), &error_abort);
}
xenstore_store_pv_console_info(con->xendev.dev,

View File

@ -20,7 +20,7 @@ struct CharBackend {
};
/**
* @qemu_chr_fe_init:
* qemu_chr_fe_init:
*
* Initializes a front end for the given CharBackend and
* Chardev. Call qemu_chr_fe_deinit() to remove the association and
@ -31,7 +31,7 @@ struct CharBackend {
bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp);
/**
* @qemu_chr_fe_deinit:
* qemu_chr_fe_deinit:
* @b: a CharBackend
* @del: if true, delete the chardev backend
*
@ -42,9 +42,9 @@ bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp);
void qemu_chr_fe_deinit(CharBackend *b, bool del);
/**
* @qemu_chr_fe_get_driver:
* qemu_chr_fe_get_driver:
*
* Returns the driver associated with a CharBackend or NULL if no
* Returns: the driver associated with a CharBackend or NULL if no
* associated Chardev.
* Note: avoid this function as the driver should never be accessed directly,
* especially by the frontends that support chardevice hotswap.
@ -53,21 +53,21 @@ void qemu_chr_fe_deinit(CharBackend *b, bool del);
Chardev *qemu_chr_fe_get_driver(CharBackend *be);
/**
* @qemu_chr_fe_backend_connected:
* qemu_chr_fe_backend_connected:
*
* Returns true if there is a chardevice associated with @be.
* Returns: true if there is a chardevice associated with @be.
*/
bool qemu_chr_fe_backend_connected(CharBackend *be);
/**
* @qemu_chr_fe_backend_open:
* qemu_chr_fe_backend_open:
*
* Returns true if chardevice associated with @be is open.
* Returns: true if chardevice associated with @be is open.
*/
bool qemu_chr_fe_backend_open(CharBackend *be);
/**
* @qemu_chr_fe_set_handlers:
* qemu_chr_fe_set_handlers:
* @b: a CharBackend
* @fd_can_read: callback to get the amount of data the frontend may
* receive
@ -95,7 +95,7 @@ void qemu_chr_fe_set_handlers(CharBackend *b,
bool set_open);
/**
* @qemu_chr_fe_take_focus:
* qemu_chr_fe_take_focus:
*
* Take the focus (if the front end is muxed).
*
@ -104,14 +104,14 @@ void qemu_chr_fe_set_handlers(CharBackend *b,
void qemu_chr_fe_take_focus(CharBackend *b);
/**
* @qemu_chr_fe_accept_input:
* qemu_chr_fe_accept_input:
*
* Notify that the frontend is ready to receive data
*/
void qemu_chr_fe_accept_input(CharBackend *be);
/**
* @qemu_chr_fe_disconnect:
* qemu_chr_fe_disconnect:
*
* Close a fd accepted by character backend.
* Without associated Chardev, do nothing.
@ -119,7 +119,7 @@ void qemu_chr_fe_accept_input(CharBackend *be);
void qemu_chr_fe_disconnect(CharBackend *be);
/**
* @qemu_chr_fe_wait_connected:
* qemu_chr_fe_wait_connected:
*
* Wait for characted backend to be connected, return < 0 on error or
* if no associated Chardev.
@ -127,19 +127,18 @@ void qemu_chr_fe_disconnect(CharBackend *be);
int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp);
/**
* @qemu_chr_fe_set_echo:
* qemu_chr_fe_set_echo:
* @echo: true to enable echo, false to disable echo
*
* Ask the backend to override its normal echo setting. This only really
* applies to the stdio backend and is used by the QMP server such that you
* can see what you type if you try to type QMP commands.
* Without associated Chardev, do nothing.
*
* @echo true to enable echo, false to disable echo
*/
void qemu_chr_fe_set_echo(CharBackend *be, bool echo);
/**
* @qemu_chr_fe_set_open:
* qemu_chr_fe_set_open:
*
* Set character frontend open status. This is an indication that the
* front end is ready (or not) to begin doing I/O.
@ -148,83 +147,77 @@ void qemu_chr_fe_set_echo(CharBackend *be, bool echo);
void qemu_chr_fe_set_open(CharBackend *be, int fe_open);
/**
* @qemu_chr_fe_printf:
* qemu_chr_fe_printf:
* @fmt: see #printf
*
* Write to a character backend using a printf style interface. This
* function is thread-safe. It does nothing without associated
* Chardev.
*
* @fmt see #printf
*/
void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...)
GCC_FMT_ATTR(2, 3);
/**
* @qemu_chr_fe_add_watch:
* qemu_chr_fe_add_watch:
* @cond: the condition to poll for
* @func: the function to call when the condition happens
* @user_data: the opaque pointer to pass to @func
*
* If the backend is connected, create and add a #GSource that fires
* when the given condition (typically G_IO_OUT|G_IO_HUP or G_IO_HUP)
* is active; return the #GSource's tag. If it is disconnected,
* or without associated Chardev, return 0.
*
* @cond the condition to poll for
* @func the function to call when the condition happens
* @user_data the opaque pointer to pass to @func
*
* Returns: the source tag
*/
guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond,
GIOFunc func, void *user_data);
/**
* @qemu_chr_fe_write:
* qemu_chr_fe_write:
* @buf: the data
* @len: the number of bytes to send
*
* Write data to a character backend from the front end. This function
* will send data from the front end to the back end. This function
* is thread-safe.
*
* @buf the data
* @len the number of bytes to send
*
* Returns: the number of bytes consumed (0 if no associated Chardev)
*/
int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len);
/**
* @qemu_chr_fe_write_all:
* qemu_chr_fe_write_all:
* @buf: the data
* @len: the number of bytes to send
*
* Write data to a character backend from the front end. This function will
* send data from the front end to the back end. Unlike @qemu_chr_fe_write,
* this function will block if the back end cannot consume all of the data
* attempted to be written. This function is thread-safe.
*
* @buf the data
* @len the number of bytes to send
*
* Returns: the number of bytes consumed (0 if no associated Chardev)
*/
int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len);
/**
* @qemu_chr_fe_read_all:
* qemu_chr_fe_read_all:
* @buf: the data buffer
* @len: the number of bytes to read
*
* Read data to a buffer from the back end.
*
* @buf the data buffer
* @len the number of bytes to read
*
* Returns: the number of bytes read (0 if no associated Chardev)
*/
int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len);
/**
* @qemu_chr_fe_ioctl:
* qemu_chr_fe_ioctl:
* @cmd: see CHR_IOCTL_*
* @arg: the data associated with @cmd
*
* Issue a device specific ioctl to a backend. This function is thread-safe.
*
* @cmd see CHR_IOCTL_*
* @arg the data associated with @cmd
*
* Returns: if @cmd is not supported by the backend or there is no
* associated Chardev, -ENOTSUP, otherwise the return
* value depends on the semantics of @cmd
@ -232,7 +225,7 @@ int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len);
int qemu_chr_fe_ioctl(CharBackend *be, int cmd, void *arg);
/**
* @qemu_chr_fe_get_msgfd:
* qemu_chr_fe_get_msgfd:
*
* For backends capable of fd passing, return the latest file descriptor passed
* by a client.
@ -245,7 +238,7 @@ int qemu_chr_fe_ioctl(CharBackend *be, int cmd, void *arg);
int qemu_chr_fe_get_msgfd(CharBackend *be);
/**
* @qemu_chr_fe_get_msgfds:
* qemu_chr_fe_get_msgfds:
*
* For backends capable of fd passing, return the number of file received
* descriptors and fills the fds array up to num elements
@ -258,7 +251,7 @@ int qemu_chr_fe_get_msgfd(CharBackend *be);
int qemu_chr_fe_get_msgfds(CharBackend *be, int *fds, int num);
/**
* @qemu_chr_fe_set_msgfds:
* qemu_chr_fe_set_msgfds:
*
* For backends capable of fd passing, set an array of fds to be passed with
* the next send operation.

View File

@ -68,12 +68,11 @@ struct Chardev {
};
/**
* @qemu_chr_new_from_opts:
* qemu_chr_new_from_opts:
* @opts: see qemu-config.c for a list of valid options
*
* Create a new character backend from a QemuOpts list.
*
* @opts see qemu-config.c for a list of valid options
*
* Returns: on success: a new character backend
* otherwise: NULL; @errp specifies the error
* or left untouched in case of help option
@ -82,17 +81,16 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
Error **errp);
/**
* @qemu_chr_parse_common:
* qemu_chr_parse_common:
* @opts: the options that still need parsing
* @backend: a new backend
*
* Parse the common options available to all character backends.
*
* @opts the options that still need parsing
* @backend a new backend
*/
void qemu_chr_parse_common(QemuOpts *opts, ChardevCommon *backend);
/**
* @qemu_chr_parse_opts:
* qemu_chr_parse_opts:
*
* Parse the options to the ChardevBackend struct.
*
@ -102,49 +100,61 @@ ChardevBackend *qemu_chr_parse_opts(QemuOpts *opts,
Error **errp);
/**
* @qemu_chr_new:
* qemu_chr_new:
* @label: the name of the backend
* @filename: the URI
*
* Create a new character backend from a URI.
*
* @label the name of the backend
* @filename the URI
* Do not implicitly initialize a monitor if the chardev is muxed.
*
* Returns: a new character backend
*/
Chardev *qemu_chr_new(const char *label, const char *filename);
/**
* @qemu_chr_change:
* qemu_chr_new_mux_mon:
* @label: the name of the backend
* @filename: the URI
*
* Create a new character backend from a URI.
* Implicitly initialize a monitor if the chardev is muxed.
*
* Returns: a new character backend
*/
Chardev *qemu_chr_new_mux_mon(const char *label, const char *filename);
/**
* qemu_chr_change:
* @opts: the new backend options
*
* Change an existing character backend
*
* @opts the new backend options
*/
void qemu_chr_change(QemuOpts *opts, Error **errp);
/**
* @qemu_chr_cleanup:
* qemu_chr_cleanup:
*
* Delete all chardevs (when leaving qemu)
*/
void qemu_chr_cleanup(void);
/**
* @qemu_chr_new_noreplay:
* qemu_chr_new_noreplay:
* @label: the name of the backend
* @filename: the URI
* @permit_mux_mon: if chardev is muxed, initialize a monitor
*
* Create a new character backend from a URI.
* Character device communications are not written
* into the replay log.
*
* @label the name of the backend
* @filename the URI
*
* Returns: a new character backend
*/
Chardev *qemu_chr_new_noreplay(const char *label, const char *filename);
Chardev *qemu_chr_new_noreplay(const char *label, const char *filename,
bool permit_mux_mon);
/**
* @qemu_chr_be_can_write:
* qemu_chr_be_can_write:
*
* Determine how much data the front end can currently accept. This function
* returns the number of bytes the front end can accept. If it returns 0, the
@ -156,43 +166,39 @@ Chardev *qemu_chr_new_noreplay(const char *label, const char *filename);
int qemu_chr_be_can_write(Chardev *s);
/**
* @qemu_chr_be_write:
* qemu_chr_be_write:
* @buf: a buffer to receive data from the front end
* @len: the number of bytes to receive from the front end
*
* Write data from the back end to the front end. Before issuing this call,
* the caller should call @qemu_chr_be_can_write to determine how much data
* the front end can currently accept.
*
* @buf a buffer to receive data from the front end
* @len the number of bytes to receive from the front end
*/
void qemu_chr_be_write(Chardev *s, uint8_t *buf, int len);
/**
* @qemu_chr_be_write_impl:
* qemu_chr_be_write_impl:
* @buf: a buffer to receive data from the front end
* @len: the number of bytes to receive from the front end
*
* Implementation of back end writing. Used by replay module.
*
* @buf a buffer to receive data from the front end
* @len the number of bytes to receive from the front end
*/
void qemu_chr_be_write_impl(Chardev *s, uint8_t *buf, int len);
/**
* @qemu_chr_be_update_read_handlers:
* qemu_chr_be_update_read_handlers:
* @context: the gcontext that will be used to attach the watch sources
*
* Invoked when frontend read handlers are setup
*
* @context the gcontext that will be used to attach the watch sources
*/
void qemu_chr_be_update_read_handlers(Chardev *s,
GMainContext *context);
/**
* @qemu_chr_be_event:
* qemu_chr_be_event:
* @event: the event to send
*
* Send an event from the back end to the front end.
*
* @event the event to send
*/
void qemu_chr_be_event(Chardev *s, int event);
@ -203,7 +209,8 @@ bool qemu_chr_has_feature(Chardev *chr,
ChardevFeature feature);
void qemu_chr_set_feature(Chardev *chr,
ChardevFeature feature);
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
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)
int qemu_chr_wait_connected(Chardev *chr, Error **errp);

View File

@ -764,7 +764,11 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp)
}
} else {
Error *err = NULL;
Chardev *chr = qemu_chr_new(buf, p);
/*
* FIXME: sure we want to support implicit
* muxed monitors here?
*/
Chardev *chr = qemu_chr_new_mux_mon(buf, p);
if (!chr) {
error_setg(errp, "Could not open guest forwarding device '%s'",

10
vl.c
View File

@ -2310,7 +2310,7 @@ static void monitor_parse(const char *optarg, const char *mode, bool pretty)
} else {
snprintf(label, sizeof(label), "compat_monitor%d",
monitor_device_index);
opts = qemu_chr_parse_compat(label, optarg);
opts = qemu_chr_parse_compat(label, optarg, true);
if (!opts) {
error_report("parse error: %s", optarg);
exit(1);
@ -2382,7 +2382,7 @@ static int serial_parse(const char *devname)
snprintf(label, sizeof(label), "serial%d", index);
serial_hds = g_renew(Chardev *, serial_hds, index + 1);
serial_hds[index] = qemu_chr_new(label, devname);
serial_hds[index] = qemu_chr_new_mux_mon(label, devname);
if (!serial_hds[index]) {
error_report("could not connect serial device"
" to character backend '%s'", devname);
@ -2418,7 +2418,7 @@ static int parallel_parse(const char *devname)
exit(1);
}
snprintf(label, sizeof(label), "parallel%d", index);
parallel_hds[index] = qemu_chr_new(label, devname);
parallel_hds[index] = qemu_chr_new_mux_mon(label, devname);
if (!parallel_hds[index]) {
error_report("could not connect parallel device"
" to character backend '%s'", devname);
@ -2449,7 +2449,7 @@ static int virtcon_parse(const char *devname)
qemu_opt_set(dev_opts, "driver", "virtconsole", &error_abort);
snprintf(label, sizeof(label), "virtcon%d", index);
virtcon_hds[index] = qemu_chr_new(label, devname);
virtcon_hds[index] = qemu_chr_new_mux_mon(label, devname);
if (!virtcon_hds[index]) {
error_report("could not connect virtio console"
" to character backend '%s'", devname);
@ -2465,7 +2465,7 @@ static int debugcon_parse(const char *devname)
{
QemuOpts *opts;
if (!qemu_chr_new("debugcon", devname)) {
if (!qemu_chr_new_mux_mon("debugcon", devname)) {
exit(1);
}
opts = qemu_opts_create(qemu_find_opts("device"), "debugcon", 1, NULL);