aboutsummaryrefslogtreecommitdiff
path: root/qemu-char.c
diff options
context:
space:
mode:
authorDaniel P. Berrange <berrange@redhat.com>2016-01-11 12:44:41 +0000
committerPaolo Bonzini <pbonzini@redhat.com>2016-01-15 18:58:02 +0100
commitd0d7708ba29cbcc343364a46bff981e0ff88366f (patch)
treec8cdee194dc2a941021082b68dfd5cbeff9752db /qemu-char.c
parentf1c17521e79df863a5771d96974fab0d07f02be0 (diff)
qemu-char: add logfile facility to all chardev backends
Typically a UNIX guest OS will log boot messages to a serial port in addition to any graphical console. An admin user may also wish to use the serial port for an interactive console. A virtualization management system may wish to collect system boot messages by logging the serial port, but also wish to allow admins interactive access. Currently providing such a feature forces the mgmt app to either provide 2 separate serial ports, one for logging boot messages and one for interactive console login, or to proxy all output via a separate service that can multiplex the two needs onto one serial port. While both are valid approaches, they each have their own downsides. The former causes confusion and extra setup work for VM admins creating disk images. The latter places an extra burden to re-implement much of the QEMU chardev backends logic in libvirt or even higher level mgmt apps and adds extra hops in the data transfer path. A simpler approach that is satisfactory for many use cases is to allow the QEMU chardev backends to have a "logfile" property associated with them. $QEMU -chardev socket,host=localhost,port=9000,\ server=on,nowait,id-charserial0,\ logfile=/var/log/libvirt/qemu/test-serial0.log -device isa-serial,chardev=charserial0,id=serial0 This patch introduces a 'ChardevCommon' struct which is setup as a base for all the ChardevBackend types. Ideally this would be registered directly as a base against ChardevBackend, rather than each type, but the QAPI generator doesn't allow that since the ChardevBackend is a non-discriminated union. The ChardevCommon struct provides the optional 'logfile' parameter, as well as 'logappend' which controls whether QEMU truncates or appends (default truncate). Signed-off-by: Daniel P. Berrange <berrange@redhat.com> Message-Id: <1452516281-27519-1-git-send-email-berrange@redhat.com> [Call qemu_chr_parse_common if cd->parse is NULL. - Paolo] Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'qemu-char.c')
-rw-r--r--qemu-char.c248
1 files changed, 208 insertions, 40 deletions
diff --git a/qemu-char.c b/qemu-char.c
index d7be1851e5..11caa5648d 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -159,10 +159,33 @@ static int sockaddr_to_str(char *dest, int max_len,
static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs =
QTAILQ_HEAD_INITIALIZER(chardevs);
-CharDriverState *qemu_chr_alloc(void)
+static void qemu_chr_free_common(CharDriverState *chr);
+
+CharDriverState *qemu_chr_alloc(ChardevCommon *backend, Error **errp)
{
CharDriverState *chr = g_malloc0(sizeof(CharDriverState));
qemu_mutex_init(&chr->chr_write_lock);
+
+ if (backend->has_logfile) {
+ int flags = O_WRONLY | O_CREAT;
+ if (backend->has_logappend &&
+ backend->logappend) {
+ flags |= O_APPEND;
+ } else {
+ flags |= O_TRUNC;
+ }
+ chr->logfd = qemu_open(backend->logfile, flags, 0666);
+ if (chr->logfd < 0) {
+ error_setg_errno(errp, errno,
+ "Unable to open logfile %s",
+ backend->logfile);
+ g_free(chr);
+ return NULL;
+ }
+ } else {
+ chr->logfd = -1;
+ }
+
return chr;
}
@@ -188,12 +211,45 @@ void qemu_chr_be_generic_open(CharDriverState *s)
qemu_chr_be_event(s, CHR_EVENT_OPENED);
}
+
+/* Not reporting errors from writing to logfile, as logs are
+ * defined to be "best effort" only */
+static void qemu_chr_fe_write_log(CharDriverState *s,
+ const uint8_t *buf, size_t len)
+{
+ size_t done = 0;
+ ssize_t ret;
+
+ if (s->logfd < 0) {
+ return;
+ }
+
+ while (done < len) {
+ do {
+ ret = write(s->logfd, buf + done, len - done);
+ if (ret == -1 && errno == EAGAIN) {
+ g_usleep(100);
+ }
+ } while (ret == -1 && errno == EAGAIN);
+
+ if (ret <= 0) {
+ return;
+ }
+ done += ret;
+ }
+}
+
int qemu_chr_fe_write(CharDriverState *s, const uint8_t *buf, int len)
{
int ret;
qemu_mutex_lock(&s->chr_write_lock);
ret = s->chr_write(s, buf, len);
+
+ if (ret > 0) {
+ qemu_chr_fe_write_log(s, buf, ret);
+ }
+
qemu_mutex_unlock(&s->chr_write_lock);
return ret;
}
@@ -218,6 +274,10 @@ int qemu_chr_fe_write_all(CharDriverState *s, const uint8_t *buf, int len)
offset += res;
}
+ if (offset > 0) {
+ qemu_chr_fe_write_log(s, buf, offset);
+ }
+
qemu_mutex_unlock(&s->chr_write_lock);
if (res < 0) {
@@ -365,8 +425,12 @@ static CharDriverState *qemu_chr_open_null(const char *id,
Error **errp)
{
CharDriverState *chr;
+ ChardevCommon *common = qapi_ChardevDummy_base(backend->u.null);
- chr = qemu_chr_alloc();
+ chr = qemu_chr_alloc(common, errp);
+ if (!chr) {
+ return NULL;
+ }
chr->chr_write = null_chr_write;
chr->explicit_be_open = true;
return chr;
@@ -665,6 +729,7 @@ static CharDriverState *qemu_chr_open_mux(const char *id,
ChardevMux *mux = backend->u.mux;
CharDriverState *chr, *drv;
MuxDriver *d;
+ ChardevCommon *common = qapi_ChardevMux_base(backend->u.mux);
drv = qemu_chr_find(mux->chardev);
if (drv == NULL) {
@@ -672,7 +737,10 @@ static CharDriverState *qemu_chr_open_mux(const char *id,
return NULL;
}
- chr = qemu_chr_alloc();
+ chr = qemu_chr_alloc(common, errp);
+ if (!chr) {
+ return NULL;
+ }
d = g_new0(MuxDriver, 1);
chr->opaque = d;
@@ -975,12 +1043,16 @@ static void fd_chr_close(struct CharDriverState *chr)
}
/* open a character device to a unix fd */
-static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
+static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out,
+ ChardevCommon *backend, Error **errp)
{
CharDriverState *chr;
FDCharDriver *s;
- chr = qemu_chr_alloc();
+ chr = qemu_chr_alloc(backend, errp);
+ if (!chr) {
+ return NULL;
+ }
s = g_new0(FDCharDriver, 1);
s->fd_in = io_channel_from_fd(fd_in);
s->fd_out = io_channel_from_fd(fd_out);
@@ -1005,6 +1077,7 @@ static CharDriverState *qemu_chr_open_pipe(const char *id,
char filename_in[CHR_MAX_FILENAME_SIZE];
char filename_out[CHR_MAX_FILENAME_SIZE];
const char *filename = opts->device;
+ ChardevCommon *common = qapi_ChardevHostdev_base(backend->u.pipe);
snprintf(filename_in, CHR_MAX_FILENAME_SIZE, "%s.in", filename);
snprintf(filename_out, CHR_MAX_FILENAME_SIZE, "%s.out", filename);
@@ -1021,7 +1094,7 @@ static CharDriverState *qemu_chr_open_pipe(const char *id,
return NULL;
}
}
- return qemu_chr_open_fd(fd_in, fd_out);
+ return qemu_chr_open_fd(fd_in, fd_out, common, errp);
}
/* init terminal so that we can grab keys */
@@ -1081,6 +1154,7 @@ static CharDriverState *qemu_chr_open_stdio(const char *id,
ChardevStdio *opts = backend->u.stdio;
CharDriverState *chr;
struct sigaction act;
+ ChardevCommon *common = qapi_ChardevStdio_base(backend->u.stdio);
if (is_daemonized()) {
error_setg(errp, "cannot use stdio with -daemonize");
@@ -1102,7 +1176,7 @@ static CharDriverState *qemu_chr_open_stdio(const char *id,
act.sa_handler = term_stdio_handler;
sigaction(SIGCONT, &act, NULL);
- chr = qemu_chr_open_fd(0, 1);
+ chr = qemu_chr_open_fd(0, 1, common, errp);
chr->chr_close = qemu_chr_close_stdio;
chr->chr_set_echo = qemu_chr_set_echo_stdio;
if (opts->has_signal) {
@@ -1324,6 +1398,7 @@ static CharDriverState *qemu_chr_open_pty(const char *id,
PtyCharDriver *s;
int master_fd, slave_fd;
char pty_name[PATH_MAX];
+ ChardevCommon *common = qapi_ChardevDummy_base(backend->u.pty);
master_fd = qemu_openpty_raw(&slave_fd, pty_name);
if (master_fd < 0) {
@@ -1334,7 +1409,11 @@ static CharDriverState *qemu_chr_open_pty(const char *id,
close(slave_fd);
qemu_set_nonblock(master_fd);
- chr = qemu_chr_alloc();
+ chr = qemu_chr_alloc(common, errp);
+ if (!chr) {
+ close(master_fd);
+ return NULL;
+ }
chr->filename = g_strdup_printf("pty:%s", pty_name);
ret->pty = g_strdup(pty_name);
@@ -1557,12 +1636,14 @@ static void qemu_chr_close_tty(CharDriverState *chr)
}
}
-static CharDriverState *qemu_chr_open_tty_fd(int fd)
+static CharDriverState *qemu_chr_open_tty_fd(int fd,
+ ChardevCommon *backend,
+ Error **errp)
{
CharDriverState *chr;
tty_serial_init(fd, 115200, 'N', 8, 1);
- chr = qemu_chr_open_fd(fd, fd);
+ chr = qemu_chr_open_fd(fd, fd, backend, errp);
chr->chr_ioctl = tty_serial_ioctl;
chr->chr_close = qemu_chr_close_tty;
return chr;
@@ -1682,7 +1763,9 @@ static void pp_close(CharDriverState *chr)
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
-static CharDriverState *qemu_chr_open_pp_fd(int fd, Error **errp)
+static CharDriverState *qemu_chr_open_pp_fd(int fd,
+ ChardevCommon *backend,
+ Error **errp)
{
CharDriverState *chr;
ParallelCharDriver *drv;
@@ -1697,7 +1780,10 @@ static CharDriverState *qemu_chr_open_pp_fd(int fd, Error **errp)
drv->fd = fd;
drv->mode = IEEE1284_MODE_COMPAT;
- chr = qemu_chr_alloc();
+ chr = qemu_chr_alloc(backend, errp);
+ if (!chr) {
+ return NULL;
+ }
chr->chr_write = null_chr_write;
chr->chr_ioctl = pp_ioctl;
chr->chr_close = pp_close;
@@ -1748,11 +1834,16 @@ static int pp_ioctl(CharDriverState *chr, int cmd, void *arg)
return 0;
}
-static CharDriverState *qemu_chr_open_pp_fd(int fd, Error **errp)
+static CharDriverState *qemu_chr_open_pp_fd(int fd,
+ ChardevBackend *backend,
+ Error **errp)
{
CharDriverState *chr;
- chr = qemu_chr_alloc();
+ chr = qemu_chr_alloc(common, errp);
+ if (!chr) {
+ return NULL;
+ }
chr->opaque = (void *)(intptr_t)fd;
chr->chr_write = null_chr_write;
chr->chr_ioctl = pp_ioctl;
@@ -1978,12 +2069,16 @@ static int win_chr_poll(void *opaque)
}
static CharDriverState *qemu_chr_open_win_path(const char *filename,
+ ChardevCommon *backend,
Error **errp)
{
CharDriverState *chr;
WinCharState *s;
- chr = qemu_chr_alloc();
+ chr = qemu_chr_alloc(backend, errp);
+ if (!chr) {
+ return NULL;
+ }
s = g_new0(WinCharState, 1);
chr->opaque = s;
chr->chr_write = win_chr_write;
@@ -1991,7 +2086,7 @@ static CharDriverState *qemu_chr_open_win_path(const char *filename,
if (win_chr_init(chr, filename, errp) < 0) {
g_free(s);
- g_free(chr);
+ qemu_chr_free_common(chr);
return NULL;
}
return chr;
@@ -2086,8 +2181,12 @@ static CharDriverState *qemu_chr_open_pipe(const char *id,
const char *filename = opts->device;
CharDriverState *chr;
WinCharState *s;
+ ChardevCommon *common = qapi_ChardevHostdev_base(backend->u.pipe);
- chr = qemu_chr_alloc();
+ chr = qemu_chr_alloc(common, errp);
+ if (!chr) {
+ return NULL;
+ }
s = g_new0(WinCharState, 1);
chr->opaque = s;
chr->chr_write = win_chr_write;
@@ -2095,18 +2194,23 @@ static CharDriverState *qemu_chr_open_pipe(const char *id,
if (win_chr_pipe_init(chr, filename, errp) < 0) {
g_free(s);
- g_free(chr);
+ qemu_chr_free_common(chr);
return NULL;
}
return chr;
}
-static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
+static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out,
+ ChardevCommon *backend,
+ Error **errp)
{
CharDriverState *chr;
WinCharState *s;
- chr = qemu_chr_alloc();
+ chr = qemu_chr_alloc(backend, errp);
+ if (!chr) {
+ return NULL;
+ }
s = g_new0(WinCharState, 1);
s->hcom = fd_out;
chr->opaque = s;
@@ -2119,7 +2223,9 @@ static CharDriverState *qemu_chr_open_win_con(const char *id,
ChardevReturn *ret,
Error **errp)
{
- return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE));
+ ChardevCommon *common = qapi_ChardevDummy_base(backend->u.console);
+ return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE),
+ common, errp);
}
static int win_stdio_write(CharDriverState *chr, const uint8_t *buf, int len)
@@ -2267,8 +2373,12 @@ static CharDriverState *qemu_chr_open_stdio(const char *id,
WinStdioCharState *stdio;
DWORD dwMode;
int is_console = 0;
+ ChardevCommon *common = qapi_ChardevStdio_base(backend->u.stdio);
- chr = qemu_chr_alloc();
+ chr = qemu_chr_alloc(common, errp);
+ if (!chr) {
+ return NULL;
+ }
stdio = g_new0(WinStdioCharState, 1);
stdio->hStdIn = GetStdHandle(STD_INPUT_HANDLE);
@@ -2440,12 +2550,17 @@ static void udp_chr_close(CharDriverState *chr)
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
-static CharDriverState *qemu_chr_open_udp_fd(int fd)
+static CharDriverState *qemu_chr_open_udp_fd(int fd,
+ ChardevCommon *backend,
+ Error **errp)
{
CharDriverState *chr = NULL;
NetCharDriver *s = NULL;
- chr = qemu_chr_alloc();
+ chr = qemu_chr_alloc(backend, errp);
+ if (!chr) {
+ return NULL;
+ }
s = g_new0(NetCharDriver, 1);
s->fd = fd;
@@ -2856,7 +2971,7 @@ static int tcp_chr_sync_read(CharDriverState *chr, const uint8_t *buf, int len)
#ifndef _WIN32
CharDriverState *qemu_chr_open_eventfd(int eventfd)
{
- CharDriverState *chr = qemu_chr_open_fd(eventfd, eventfd);
+ CharDriverState *chr = qemu_chr_open_fd(eventfd, eventfd, NULL, NULL);
if (chr) {
chr->avail_connections = 1;
@@ -3138,10 +3253,14 @@ static CharDriverState *qemu_chr_open_ringbuf(const char *id,
Error **errp)
{
ChardevRingbuf *opts = backend->u.ringbuf;
+ ChardevCommon *common = qapi_ChardevRingbuf_base(backend->u.ringbuf);
CharDriverState *chr;
RingBufCharDriver *d;
- chr = qemu_chr_alloc();
+ chr = qemu_chr_alloc(common, errp);
+ if (!chr) {
+ return NULL;
+ }
d = g_malloc(sizeof(*d));
d->size = opts->has_size ? opts->size : 65536;
@@ -3164,7 +3283,7 @@ static CharDriverState *qemu_chr_open_ringbuf(const char *id,
fail:
g_free(d);
- g_free(chr);
+ qemu_chr_free_common(chr);
return NULL;
}
@@ -3408,6 +3527,18 @@ fail:
return NULL;
}
+static void qemu_chr_parse_common(QemuOpts *opts, ChardevCommon *backend)
+{
+ const char *logfile = qemu_opt_get(opts, "logfile");
+
+ backend->has_logfile = logfile != NULL;
+ backend->logfile = logfile ? g_strdup(logfile) : NULL;
+
+ backend->has_logappend = true;
+ backend->logappend = qemu_opt_get_bool(opts, "logappend", false);
+}
+
+
static void qemu_chr_parse_file_out(QemuOpts *opts, ChardevBackend *backend,
Error **errp)
{
@@ -3418,6 +3549,7 @@ static void qemu_chr_parse_file_out(QemuOpts *opts, ChardevBackend *backend,
return;
}
backend->u.file = g_new0(ChardevFile, 1);
+ qemu_chr_parse_common(opts, qapi_ChardevFile_base(backend->u.file));
backend->u.file->out = g_strdup(path);
backend->u.file->has_append = true;
@@ -3428,6 +3560,7 @@ static void qemu_chr_parse_stdio(QemuOpts *opts, ChardevBackend *backend,
Error **errp)
{
backend->u.stdio = g_new0(ChardevStdio, 1);
+ qemu_chr_parse_common(opts, qapi_ChardevStdio_base(backend->u.stdio));
backend->u.stdio->has_signal = true;
backend->u.stdio->signal = qemu_opt_get_bool(opts, "signal", true);
}
@@ -3443,6 +3576,7 @@ static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,
return;
}
backend->u.serial = g_new0(ChardevHostdev, 1);
+ qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(backend->u.serial));
backend->u.serial->device = g_strdup(device);
}
#endif
@@ -3458,6 +3592,7 @@ static void qemu_chr_parse_parallel(QemuOpts *opts, ChardevBackend *backend,
return;
}
backend->u.parallel = g_new0(ChardevHostdev, 1);
+ qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(backend->u.parallel));
backend->u.parallel->device = g_strdup(device);
}
#endif
@@ -3472,6 +3607,7 @@ static void qemu_chr_parse_pipe(QemuOpts *opts, ChardevBackend *backend,
return;
}
backend->u.pipe = g_new0(ChardevHostdev, 1);
+ qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(backend->u.pipe));
backend->u.pipe->device = g_strdup(device);
}
@@ -3481,6 +3617,7 @@ static void qemu_chr_parse_ringbuf(QemuOpts *opts, ChardevBackend *backend,
int val;
backend->u.ringbuf = g_new0(ChardevRingbuf, 1);
+ qemu_chr_parse_common(opts, qapi_ChardevRingbuf_base(backend->u.ringbuf));
val = qemu_opt_get_size(opts, "size", 0);
if (val != 0) {
@@ -3499,6 +3636,7 @@ static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend,
return;
}
backend->u.mux = g_new0(ChardevMux, 1);
+ qemu_chr_parse_common(opts, qapi_ChardevMux_base(backend->u.mux));
backend->u.mux->chardev = g_strdup(chardev);
}
@@ -3527,6 +3665,7 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
}
backend->u.socket = g_new0(ChardevSocket, 1);
+ qemu_chr_parse_common(opts, qapi_ChardevSocket_base(backend->u.socket));
backend->u.socket->has_nodelay = true;
backend->u.socket->nodelay = do_nodelay;
@@ -3588,6 +3727,7 @@ static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,
}
backend->u.udp = g_new0(ChardevUdp, 1);
+ qemu_chr_parse_common(opts, qapi_ChardevUdp_base(backend->u.udp));
addr = g_new0(SocketAddress, 1);
addr->type = SOCKET_ADDRESS_KIND_INET;
@@ -3687,7 +3827,12 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
error_propagate(errp, local_err);
goto qapi_out;
}
+ } else {
+ ChardevCommon *cc = g_new0(ChardevCommon, 1);
+ qemu_chr_parse_common(opts, cc);
+ backend->u.data = cc;
}
+
ret = qmp_chardev_add(bid ? bid : id, backend, errp);
if (!ret) {
goto qapi_out;
@@ -3819,17 +3964,25 @@ void qemu_chr_fe_release(CharDriverState *s)
s->avail_connections++;
}
-void qemu_chr_free(CharDriverState *chr)
+static void qemu_chr_free_common(CharDriverState *chr)
{
- if (chr->chr_close) {
- chr->chr_close(chr);
- }
g_free(chr->filename);
g_free(chr->label);
qemu_opts_del(chr->opts);
+ if (chr->logfd != -1) {
+ close(chr->logfd);
+ }
g_free(chr);
}
+void qemu_chr_free(CharDriverState *chr)
+{
+ if (chr->chr_close) {
+ chr->chr_close(chr);
+ }
+ qemu_chr_free_common(chr);
+}
+
void qemu_chr_delete(CharDriverState *chr)
{
QTAILQ_REMOVE(&chardevs, chr, next);
@@ -3982,6 +4135,12 @@ QemuOptsList qemu_chardev_opts = {
},{
.name = "append",
.type = QEMU_OPT_BOOL,
+ },{
+ .name = "logfile",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "logappend",
+ .type = QEMU_OPT_BOOL,
},
{ /* end of list */ }
},
@@ -3995,6 +4154,7 @@ static CharDriverState *qmp_chardev_open_file(const char *id,
Error **errp)
{
ChardevFile *file = backend->u.file;
+ ChardevCommon *common = qapi_ChardevFile_base(backend->u.file);
HANDLE out;
if (file->has_in) {
@@ -4008,7 +4168,7 @@ static CharDriverState *qmp_chardev_open_file(const char *id,
error_setg(errp, "open %s failed", file->out);
return NULL;
}
- return qemu_chr_open_win_file(out);
+ return qemu_chr_open_win_file(out, common, errp);
}
static CharDriverState *qmp_chardev_open_serial(const char *id,
@@ -4017,7 +4177,8 @@ static CharDriverState *qmp_chardev_open_serial(const char *id,
Error **errp)
{
ChardevHostdev *serial = backend->u.serial;
- return qemu_chr_open_win_path(serial->device, errp);
+ ChardevCommon *common = qapi_ChardevHostdev_base(backend->u.serial);
+ return qemu_chr_open_win_path(serial->device, common, errp);
}
#else /* WIN32 */
@@ -4040,6 +4201,7 @@ static CharDriverState *qmp_chardev_open_file(const char *id,
Error **errp)
{
ChardevFile *file = backend->u.file;
+ ChardevCommon *common = qapi_ChardevFile_base(backend->u.file);
int flags, in = -1, out;
flags = O_WRONLY | O_CREAT | O_BINARY;
@@ -4063,7 +4225,7 @@ static CharDriverState *qmp_chardev_open_file(const char *id,
}
}
- return qemu_chr_open_fd(in, out);
+ return qemu_chr_open_fd(in, out, common, errp);
}
#ifdef HAVE_CHARDEV_SERIAL
@@ -4073,6 +4235,7 @@ static CharDriverState *qmp_chardev_open_serial(const char *id,
Error **errp)
{
ChardevHostdev *serial = backend->u.serial;
+ ChardevCommon *common = qapi_ChardevHostdev_base(backend->u.serial);
int fd;
fd = qmp_chardev_open_file_source(serial->device, O_RDWR, errp);
@@ -4080,7 +4243,7 @@ static CharDriverState *qmp_chardev_open_serial(const char *id,
return NULL;
}
qemu_set_nonblock(fd);
- return qemu_chr_open_tty_fd(fd);
+ return qemu_chr_open_tty_fd(fd, common, errp);
}
#endif
@@ -4091,13 +4254,14 @@ static CharDriverState *qmp_chardev_open_parallel(const char *id,
Error **errp)
{
ChardevHostdev *parallel = backend->u.parallel;
+ ChardevCommon *common = qapi_ChardevHostdev_base(backend->u.parallel);
int fd;
fd = qmp_chardev_open_file_source(parallel->device, O_RDWR, errp);
if (fd < 0) {
return NULL;
}
- return qemu_chr_open_pp_fd(fd, errp);
+ return qemu_chr_open_pp_fd(fd, common, errp);
}
#endif
@@ -4142,8 +4306,12 @@ static CharDriverState *qmp_chardev_open_socket(const char *id,
bool is_telnet = sock->has_telnet ? sock->telnet : false;
bool is_waitconnect = sock->has_wait ? sock->wait : false;
int64_t reconnect = sock->has_reconnect ? sock->reconnect : 0;
+ ChardevCommon *common = qapi_ChardevSocket_base(backend->u.socket);
- chr = qemu_chr_alloc();
+ chr = qemu_chr_alloc(common, errp);
+ if (!chr) {
+ return NULL;
+ }
s = g_new0(TCPCharDriver, 1);
s->fd = -1;
@@ -4182,8 +4350,7 @@ static CharDriverState *qmp_chardev_open_socket(const char *id,
socket_try_connect(chr);
} else if (!qemu_chr_open_socket_fd(chr, errp)) {
g_free(s);
- g_free(chr->filename);
- g_free(chr);
+ qemu_chr_free_common(chr);
return NULL;
}
@@ -4203,13 +4370,14 @@ static CharDriverState *qmp_chardev_open_udp(const char *id,
Error **errp)
{
ChardevUdp *udp = backend->u.udp;
+ ChardevCommon *common = qapi_ChardevUdp_base(backend->u.udp);
int fd;
fd = socket_dgram(udp->remote, udp->local, errp);
if (fd < 0) {
return NULL;
}
- return qemu_chr_open_udp_fd(fd);
+ return qemu_chr_open_udp_fd(fd, common, errp);
}
ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,