Features/ChardevFlowControl

From QEMU
Revision as of 06:20, 12 February 2013 by Amit (talk | contribs) (Add summary, status, testing instructions, known bugs.)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Summary

The chardev layer in QEMU did not have any mechanism for flow-control. This meant that a fast guest could pump data to the host (via virtio-serial, for example), and if the host-side reader was slow to consume data, or didn't consume data at all, the guest would freeze. This is resolved by converting the char layer to use the GLib IO loop.


Status

Patches are still under review and discussion, but intended to be merged for the 1.5 release. The main code exists in Anthony's 'char-flow' branches (latest is v2): https://github.com/aliguori/qemu/commits/char-flow.2. Amit's virtio-serial tree has some fixes on top of Anthony's patches: https://git.kernel.org/?p=virt/qemu/amit/virtio-serial.git

Testing

To reproduce a guest freeze on releases without the patches for this feature, invoke QEMU and perform the tests as noted in the two cases below. The examples use the unix backend, but other backends, like udp, tcp, pty exhibit similar behaviour, and should be tested as well.

Start QEMU with chardev in server mode

./x86_64-softmmu/qemu-system-x86_64 -m 512 \
 /guests/f14-nolvm.qcow2 -snapshot -enable-kvm   \
 -chardev socket,path=/tmp/foo,server,nowait,id=foo \
 -device virtio-serial -device virtserialport,chardev=foo,id=test0,nr=2 \
 -monitor stdio

On the host, open the chardev but don't read from it, e.g.

$ python
Python 2.7.3 (default, Aug  9 2012, 17:23:57) 
[GCC 4.7.1 20120720 (Red Hat 4.7.1-5)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket
>>> 
>>> sock = socket.socket(socket.AF_UNIX)
>>> sock.connect("/tmp/foo")
>>> 

and in the guest, write to the virtio-serial port, e.g.

# dd if=/dev/zero of=/dev/virtio-ports/test0

Start QEMU with chardev in client mode

./x86_64-softmmu/qemu-system-x86_64 -m 512 /guests/f14-nolvm.qcow2 \
  -snapshot -enable-kvm   -chardev socket,path=/tmp/foo,id=foo \
  -device virtio-serial -device virtserialport,chardev=foo,id=test0,nr=2 \
  -monitor stdio

on the host, start a listening process, like:

$ socat UNIX-LISTEN:/tmp/foo  -

and in the guest,

# echo foo > /dev/virtio-ports/test0

Known bugs

These are the bugs in the implementation known so far:

  • Starting QEMU with chardevs in client mode as noted in the section above results in the error message
     (process:922): GLib-CRITICAL **: g_io_channel_write_chars: assertion `channel != NULL' failed
  1. start qemu, boot guest
  2. connect netcat to the unix socket
  3. echo some chars to /dev/virtio-ports/$name
  4. watch them appear in netcat
  5. stop netcat, restart it
  6. echo some chars again
  7. watch them *not* appear
Gerd's open-write-close test:
for seq in $(seq 1 100); do echo "test $seq" > /dev/virtio-ports/org.kraxel.test; sleep 1; done
Gerd's keep-device-open test:
(for seq in $(seq 1 100); do echo "test $seq"; sleep 1; done) > /dev/virtio-ports/org.kraxel.test
The bug triggers only with open-write-close.