958e1b
From 9c6b84014b3650e478494d3c19b7461b947b3b14 Mon Sep 17 00:00:00 2001
eb5a2f
From: Gal Hammer <ghammer@redhat.com>
eb5a2f
Date: Sun, 16 Mar 2014 09:57:09 +0100
958e1b
Subject: [PATCH 01/31] char: restore read callback on a reattached (hotplug) chardev
eb5a2f
eb5a2f
RH-Author: Gal Hammer <ghammer@redhat.com>
eb5a2f
Message-id: <1394963829-5384-1-git-send-email-ghammer@redhat.com>
eb5a2f
Patchwork-id: 58105
eb5a2f
O-Subject: [RHEL-7.0 qemu-kvm PATCH] char: restore read callback on a reattached (hotplug) chardev
958e1b
Bugzilla: 1038914
eb5a2f
RH-Acked-by: Gerd Hoffmann <kraxel@redhat.com>
eb5a2f
RH-Acked-by: Amit Shah <amit.shah@redhat.com>
eb5a2f
RH-Acked-by: Amos Kong <akong@redhat.com>
eb5a2f
958e1b
Bugzilla: 1027181
eb5a2f
Brew: https://brewweb.devel.redhat.com/taskinfo?taskID=7207613
eb5a2f
Upstream: commit ac1b84dd1e020648db82a99260891aa982d1142c
eb5a2f
eb5a2f
Fix a bug that was introduced in commit 386a5a1e. A removal of a device
eb5a2f
set the chr handlers to NULL. However when the device is plugged back,
eb5a2f
its read callback is not restored so data can't be transferred from the
eb5a2f
host to the guest (e.g. via the virtio-serial port).
eb5a2f
958e1b
https://bugzilla.redhat.com/show_bug.cgi?id=1027181
958e1b
eb5a2f
Signed-off-by: Gal Hammer <ghammer@redhat.com>
eb5a2f
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
eb5a2f
---
eb5a2f
 qemu-char.c | 17 +++++++++++++++--
eb5a2f
 1 file changed, 15 insertions(+), 2 deletions(-)
eb5a2f
eb5a2f
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
eb5a2f
---
eb5a2f
 qemu-char.c |   17 +++++++++++++++--
eb5a2f
 1 files changed, 15 insertions(+), 2 deletions(-)
eb5a2f
eb5a2f
diff --git a/qemu-char.c b/qemu-char.c
eb5a2f
index 983f686..930f3d4 100644
eb5a2f
--- a/qemu-char.c
eb5a2f
+++ b/qemu-char.c
eb5a2f
@@ -215,7 +215,7 @@ void qemu_chr_add_handlers(CharDriverState *s,
eb5a2f
     s->chr_read = fd_read;
eb5a2f
     s->chr_event = fd_event;
eb5a2f
     s->handler_opaque = opaque;
eb5a2f
-    if (s->chr_update_read_handler)
eb5a2f
+    if (fe_open && s->chr_update_read_handler)
eb5a2f
         s->chr_update_read_handler(s);
eb5a2f
 
eb5a2f
     if (!s->explicit_fe_open) {
eb5a2f
@@ -1140,13 +1140,14 @@ static void pty_chr_state(CharDriverState *chr, int connected)
eb5a2f
         if (!s->connected) {
eb5a2f
             s->connected = 1;
eb5a2f
             qemu_chr_be_generic_open(chr);
eb5a2f
+        }
eb5a2f
+        if (!chr->fd_in_tag) {
eb5a2f
             chr->fd_in_tag = io_add_watch_poll(s->fd, pty_chr_read_poll,
eb5a2f
                                                pty_chr_read, chr);
eb5a2f
         }
eb5a2f
     }
eb5a2f
 }
eb5a2f
 
eb5a2f
-
eb5a2f
 static void pty_chr_close(struct CharDriverState *chr)
eb5a2f
 {
eb5a2f
     PtyCharDriver *s = chr->opaque;
eb5a2f
@@ -2514,6 +2515,17 @@ static void tcp_chr_connect(void *opaque)
eb5a2f
     qemu_chr_be_generic_open(chr);
eb5a2f
 }
eb5a2f
 
eb5a2f
+static void tcp_chr_update_read_handler(CharDriverState *chr)
eb5a2f
+{
eb5a2f
+    TCPCharDriver *s = chr->opaque;
eb5a2f
+
eb5a2f
+    remove_fd_in_watch(chr);
eb5a2f
+    if (s->chan) {
eb5a2f
+        chr->fd_in_tag = io_add_watch_poll(s->chan, tcp_chr_read_poll,
eb5a2f
+                                           tcp_chr_read, chr);
eb5a2f
+    }
eb5a2f
+}
eb5a2f
+
eb5a2f
 #define IACSET(x,a,b,c) x[0] = a; x[1] = b; x[2] = c;
eb5a2f
 static void tcp_chr_telnet_init(int fd)
eb5a2f
 {
eb5a2f
@@ -2669,6 +2681,7 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay,
eb5a2f
     chr->get_msgfd = tcp_get_msgfd;
eb5a2f
     chr->chr_add_client = tcp_chr_add_client;
eb5a2f
     chr->chr_add_watch = tcp_chr_add_watch;
eb5a2f
+    chr->chr_update_read_handler = tcp_chr_update_read_handler;
eb5a2f
     /* be isn't opened until we get a connection */
eb5a2f
     chr->explicit_be_open = true;
eb5a2f
 
eb5a2f
-- 
eb5a2f
1.7.1
eb5a2f