From 2b5f560065c1cf3f7f86bd18acb6f0fe604affd7 Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Thu, 28 Aug 2014 17:36:30 +0200 Subject: [PATCH 2/2] char: restore read callback on a reattached (hotplug) chardev Message-id: Patchwork-id: 60748 O-Subject: [RHEL6.6 qemu-kvm PATCH v2 2/2] char: restore read callback on a reattached (hotplug) chardev Bugzilla: 1027181 RH-Acked-by: Gerd Hoffmann RH-Acked-by: Paolo Bonzini RH-Acked-by: Laszlo Ersek From: Gal Hammer Fix a bug that was introduced in commit 386a5a1e. A removal of a device set the chr handlers to NULL. However when the device is plugged back, its read callback is not restored so data can't be transferred from the host to the guest (e.g. via the virtio-serial port). https://bugzilla.redhat.com/show_bug.cgi?id=1027181 Signed-off-by: Gal Hammer Signed-off-by: Gerd Hoffmann (cherry picked from commit ac1b84dd1e020648db82a99260891aa982d1142c) Signed-off-by: Amit Shah RHEL6 note: RHEL6 version of patch mentioned above is a9b3aa794a4 Conflicts: qemu-char.c We don't have several commits from upstream; it doesn't matter that we don't have the fe_open and explicit_fe_open bits from upstream, as they are only used if the functionality exists (and spice was the only modified user of fe_open at the time of the orig. commit upstream). The fe_open in the original upstream commit was used to determine whether the front end was being opened (or was already open); as against qemu_chr_add_handlers() being called to close the frontend. Our dummy fe_open in the previous commit fits the role perfectly, and this backport matches upstream quite well with that bit separated out. Signed-off-by: Amit Shah --- qemu-char.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) Signed-off-by: Miroslav Rezanina --- qemu-char.c | 17 +++++++++++++++-- 1 files changed, 15 insertions(+), 2 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 16f2a17..c16d66b 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -234,7 +234,7 @@ void qemu_chr_add_handlers(CharDriverState *s, s->chr_read = fd_read; s->chr_event = fd_event; s->handler_opaque = opaque; - if (s->chr_update_read_handler) + if (fe_open && s->chr_update_read_handler) s->chr_update_read_handler(s); /* We're connecting to an already opened device, so let's make sure we @@ -1141,13 +1141,14 @@ static void pty_chr_state(CharDriverState *chr, int connected) if (!s->connected) { qemu_chr_generic_open(chr); s->connected = 1; + } + if (!chr->fd_in_tag) { chr->fd_in_tag = io_add_watch_poll(s->fd, pty_chr_read_poll, pty_chr_read, chr); } } } - static void pty_chr_close(struct CharDriverState *chr) { PtyCharDriver *s = chr->opaque; @@ -2301,6 +2302,17 @@ static void tcp_chr_connect(void *opaque) qemu_chr_generic_open(chr); } +static void tcp_chr_update_read_handler(CharDriverState *chr) +{ + TCPCharDriver *s = chr->opaque; + + remove_fd_in_watch(chr); + if (s->chan) { + chr->fd_in_tag = io_add_watch_poll(s->chan, tcp_chr_read_poll, + tcp_chr_read, chr); + } +} + #define IACSET(x,a,b,c) x[0] = a; x[1] = b; x[2] = c; static void tcp_chr_telnet_init(int fd) { @@ -2449,6 +2461,7 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay, chr->chr_close = tcp_chr_close; chr->get_msgfd = tcp_get_msgfd; chr->chr_add_watch = tcp_chr_add_watch; + chr->chr_update_read_handler = tcp_chr_update_read_handler; if (is_listen) { s->listen_fd = fd; -- 1.7.1