qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Amit Shah <amit.shah@redhat.com>
To: qemu list <qemu-devel@nongnu.org>
Cc: Amit Shah <amit.shah@redhat.com>,
	Juan Quintela <quintela@redhat.com>,
	Gerd Hoffmann <kraxel@redhat.com>,
	Paul Brook <paul@codesourcery.com>
Subject: [Qemu-devel] [PATCH 6/7] virtio-serial: Add support for flow control
Date: Wed, 19 Jan 2011 17:57:18 +0530	[thread overview]
Message-ID: <475cfc6880f2f35f29358160dfa5d08be33d0c6a.1295439749.git.amit.shah@redhat.com> (raw)
In-Reply-To: <cover.1295439749.git.amit.shah@redhat.com>
In-Reply-To: <cover.1295439749.git.amit.shah@redhat.com>

This commit lets apps signal an incomplete write.  When that happens,
stop sending out any more data to the app and wait for it to unthrottle
the port.

Signed-off-by: Amit Shah <amit.shah@redhat.com>
---
 hw/virtio-serial-bus.c |   49 +++++++++++++++++++++++++++++++++++++----------
 hw/virtio-serial.h     |   17 ++++++++++++++++
 2 files changed, 55 insertions(+), 11 deletions(-)

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 6726f72..32938b5 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -126,24 +126,49 @@ static void discard_vq_data(VirtQueue *vq, VirtIODevice *vdev)
 static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
                                  VirtIODevice *vdev)
 {
-    VirtQueueElement elem;
-
     assert(port);
     assert(virtio_queue_ready(vq));
 
-    while (!port->throttled && virtqueue_pop(vq, &elem)) {
+    while (!port->throttled) {
         unsigned int i;
 
-        for (i = 0; i < elem.out_num; i++) {
-            size_t buf_size;
-
-            buf_size = elem.out_sg[i].iov_len;
+        /* Pop an elem only if we haven't left off a previous one mid-way */
+        if (!port->elem.out_num) {
+            if (!virtqueue_pop(vq, &port->elem)) {
+                break;
+            }
+            port->iov_idx = 0;
+            port->iov_offset = 0;
+        }
 
-            port->info->have_data(port,
-                                  elem.out_sg[i].iov_base,
-                                  buf_size);
+        for (i = port->iov_idx; i < port->elem.out_num; i++) {
+            size_t buf_size;
+            ssize_t ret;
+
+            buf_size = port->elem.out_sg[i].iov_len - port->iov_offset;
+            ret = port->info->have_data(port,
+                                        port->elem.out_sg[i].iov_base
+                                          + port->iov_offset,
+                                        buf_size);
+            if (ret < 0 && ret != -EAGAIN) {
+                /* We don't handle any other type of errors here */
+                abort();
+            }
+            if (ret == -EAGAIN || (ret >= 0 && ret < buf_size)) {
+                virtio_serial_throttle_port(port, true);
+                port->iov_idx = i;
+                if (ret > 0) {
+                    port->iov_offset += ret;
+                }
+                break;
+            }
+            port->iov_offset = 0;
         }
-        virtqueue_push(vq, &elem, 0);
+        if (port->throttled) {
+            break;
+        }
+        virtqueue_push(vq, &port->elem, 0);
+        port->elem.out_num = 0;
     }
     virtio_notify(vdev, vq);
 }
@@ -709,6 +734,8 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
         port->guest_connected = true;
     }
 
+    port->elem.out_num = 0;
+
     QTAILQ_INSERT_TAIL(&port->vser->ports, port, next);
     port->ivq = port->vser->ivqs[port->id];
     port->ovq = port->vser->ovqs[port->id];
diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h
index 9cc0fb3..a308196 100644
--- a/hw/virtio-serial.h
+++ b/hw/virtio-serial.h
@@ -102,6 +102,23 @@ struct VirtIOSerialPort {
      */
     uint32_t id;
 
+    /*
+     * This is the elem that we pop from the virtqueue.  A slow
+     * backend that consumes guest data (e.g. the file backend for
+     * qemu chardevs) can cause the guest to block till all the output
+     * is flushed.  This isn't desired, so we keep a note of the last
+     * element popped and continue consuming it once the backend
+     * becomes writable again.
+     */
+    VirtQueueElement elem;
+
+    /*
+     * The index and the offset into the iov buffer that was popped in
+     * elem above.
+     */
+    uint32_t iov_idx;
+    uint64_t iov_offset;
+
     /* Identify if this is a port that binds with hvc in the guest */
     uint8_t is_console;
 
-- 
1.7.3.4

  parent reply	other threads:[~2011-01-19 12:27 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-01-19 12:27 [Qemu-devel] [PATCH 0/7] virtio-serial: Don't copy guest buf to host, flow control Amit Shah
2011-01-19 12:27 ` [Qemu-devel] [PATCH 1/7] virtio-console: Factor out common init between console and generic ports Amit Shah
2011-01-19 12:27 ` [Qemu-devel] [PATCH 2/7] virtio-console: Remove unnecessary braces Amit Shah
2011-01-19 12:27 ` [Qemu-devel] [PATCH 3/7] virtio-serial-bus: separate out discard logic in a separate function Amit Shah
2011-01-19 12:27 ` [Qemu-devel] [PATCH 4/7] virtio-serial: Don't copy over guest buffer to host Amit Shah
2011-01-19 12:27 ` [Qemu-devel] [PATCH 5/7] virtio-serial: Let virtio-serial-bus know if all data was consumed Amit Shah
2011-01-19 12:27 ` Amit Shah [this message]
2011-01-19 12:27 ` [Qemu-devel] [PATCH 7/7] virtio-serial: save/restore new fields in port struct Amit Shah

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=475cfc6880f2f35f29358160dfa5d08be33d0c6a.1295439749.git.amit.shah@redhat.com \
    --to=amit.shah@redhat.com \
    --cc=kraxel@redhat.com \
    --cc=paul@codesourcery.com \
    --cc=qemu-devel@nongnu.org \
    --cc=quintela@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).