From b1f45e402af97406d4dd2fb998f419d342b88384 Mon Sep 17 00:00:00 2001
From: Amit Shah <amit.shah@redhat.com>
Date: Fri, 4 Feb 2011 08:20:49 -0200
Subject: [RHEL6 qemu-kvm PATCH 18/27] char: Throttle when host connection is down

RH-Author: Amit Shah <amit.shah@redhat.com>
Message-id: <b438535323c90f53128ab47e6b7026954169f620.1296806194.git.amit.shah@redhat.com>
Patchwork-id: 17719
O-Subject: [RHEL6.1 qemu PATCH v5 18/19] char: Throttle when host connection is
	down
Bugzilla: 588916
RH-Acked-by: Alon Levy <alevy@redhat.com>
RH-Acked-by: Juan Quintela <quintela@redhat.com>
RH-Acked-by: Jes Sorensen <Jes.Sorensen@redhat.com>

When the host-side connection goes down, throttle the virtio-serial bus
and later unthrottle when a connection gets established.  This helps
prevent any lost IO (guest->host) while the host connection was down.

Bugzilla: 621484

This commit actually helps the bug mentioned above as no writes will now
get lost because of the throttling done here.  With just the patches
sent earlier for that bug, one write will end up getting lost in the
worst case (host d/c, guest write, host connect).

Signed-off-by: Amit Shah <amit.shah@redhat.com>
---
 qemu-char.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 qemu-char.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/qemu-char.c b/qemu-char.c
index dc3e930..bd7dc92 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -132,6 +132,9 @@ static void qemu_chr_generic_open_bh(void *opaque)
 {
     CharDriverState *s = opaque;
     qemu_chr_event(s, CHR_EVENT_OPENED);
+    if (s->write_blocked) {
+        char_write_unblocked(s);
+    }
     qemu_bh_delete(s->bh);
     s->bh = NULL;
 }
@@ -2017,6 +2020,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 {
-- 
1.7.3.2

