From 9fd3a478a3823258516f06201fa681e07dce1781 Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Mon, 21 Mar 2011 22:02:47 +0100 Subject: [PATCH] char: Equip the unix/tcp backend to handle nonblocking writes# Now that the infrastructure is in place to return -EAGAIN to callers, individual char drivers can set their update_fd_handlers() function to set or remove an fd's write handler. This handler checks if the driver became writable. A generic callback routine is used for unblocking writes and letting users of chardevs know that a driver became writable again. Signed-off-by: Amit Shah Signed-off-by: Cole Robinson --- qemu-char.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/qemu-char.c b/qemu-char.c index 3d6e2f8..18e980d 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -105,6 +105,19 @@ static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs = QTAILQ_HEAD_INITIALIZER(chardevs); +/* + * Generic routine that gets called when chardev becomes writable. + * Lets chardev user know it's OK to send more data. + */ +static void char_write_unblocked(void *opaque) +{ + CharDriverState *chr = opaque; + + chr->write_blocked = false; + chr->chr_disable_write_fd_handler(chr); + chr->chr_write_unblocked(chr->handler_opaque); +} + void qemu_chr_be_event(CharDriverState *s, int event) { /* Keep track if the char device is open */ @@ -126,6 +139,9 @@ static void qemu_chr_fire_open_event(void *opaque) { CharDriverState *s = opaque; qemu_chr_be_event(s, CHR_EVENT_OPENED); + if (s->write_blocked) { + char_write_unblocked(s); + } qemu_free_timer(s->open_timer); s->open_timer = NULL; } @@ -2245,6 +2261,17 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) ret = send_all(chr, s->fd, buf, len); if (ret == -1 && errno == EPIPE) { tcp_closed(chr); + + if (chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) { + /* + * Since we haven't written out anything, let's say + * we're throttled. This will prevent any output from + * the guest getting lost if host-side chardev goes + * down. Unthrottle when we re-connect. + */ + chr->write_blocked = true; + return 0; + } } return ret; } else {