diff options
author | Christian Borntraeger <borntraeger@de.ibm.com> | 2011-12-29 13:47:43 +0100 |
---|---|---|
committer | Amit Shah <amit.shah@redhat.com> | 2011-12-30 11:10:10 +0530 |
commit | ed8e5a85a1741147ce06932b478a509ce3407061 (patch) | |
tree | 3d558ff8830d891e8214a7b1103e62ee263bb605 | |
parent | 8d3bc5178fbc06cdd89c064ae8f44e77c503e91e (diff) |
virtio-console: Fix failure on unconnected pty
when I tried qemu with -virtio-console pty the guest hangs and attaching
on /dev/pts/<x> does not return anything if the attachment is too late.
This results in pty_chr_write() returning 0, which causes the port to
get throttled. This results in the guest getting frozen as the
guest->host virtio_console writes don't return until the host releases
the vq element back to the guest.
For the virtio-serial use case we don't want to lose data but for the
console case we better drop data instead of "killing" the guest
console. If we get chardev->frontend notification and a better behaving
virtio-console we can revert this fix.
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Amit Shah <amit.shah@redhat.com>
-rw-r--r-- | hw/virtio-serial-bus.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c index fe0233f6f1..3a9004a9b8 100644 --- a/hw/virtio-serial-bus.c +++ b/hw/virtio-serial-bus.c @@ -163,7 +163,19 @@ static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq, abort(); } if (ret == -EAGAIN || (ret >= 0 && ret < buf_size)) { - virtio_serial_throttle_port(port, true); + /* + * this is a temporary check until chardevs can signal to + * frontends that they are writable again. This prevents + * the console from going into throttled mode (forever) + * if virtio-console is connected to a pty without a + * listener. Otherwise the guest spins forever. + * We can revert this if + * 1: chardevs can notify frondends + * 2: the guest driver does not spin in these cases + */ + if (!info->is_console) { + virtio_serial_throttle_port(port, true); + } port->iov_idx = i; if (ret > 0) { port->iov_offset += ret; |