Blame 0013-spice-qemu-char.c-add-throttling.patch

Justin M. Forbes 252f3a
>From 06ad256d2939aea4086428dcb5e5e7d5f86eb335 Mon Sep 17 00:00:00 2001
Justin M. Forbes 252f3a
From: Alon Levy <alevy@redhat.com>
Justin M. Forbes 252f3a
Date: Tue, 22 Mar 2011 12:27:59 +0200
Justin M. Forbes 252f3a
Subject: [PATCH 13/17] spice-qemu-char.c: add throttling
Justin M. Forbes 252f3a
Justin M. Forbes 252f3a
BZ: 672191
Justin M. Forbes 252f3a
Justin M. Forbes 252f3a
upstream: not submitted (explained below)
Justin M. Forbes 252f3a
Justin M. Forbes 252f3a
Adds throttling support to spicevmc chardev. Uses a timer to avoid recursing:
Justin M. Forbes 252f3a
1. spice-server: reds.c:            read_from_vdi_port
Justin M. Forbes 252f3a
2. qemu:         spice-qemu-char.c: vmc_read
Justin M. Forbes 252f3a
3.                                  chr_write_unblocked
Justin M. Forbes 252f3a
                                (calls virtio_serial_throttle_port(port, false))
Justin M. Forbes 252f3a
4. qemu:         virtio ...
Justin M. Forbes 252f3a
5. qemu:         spice-qemu-char.c: spice_chr_write
Justin M. Forbes 252f3a
6. qemu:         spice-qemu-char.c: wakeup (calls into spice-server)
Justin M. Forbes 252f3a
7. spice-server: ...
Justin M. Forbes 252f3a
8. qemu:         spice-qemu-char.c: vmc_read
Justin M. Forbes 252f3a
Justin M. Forbes 252f3a
Instead, in vmc_read if we were throttled and we are just about to return
Justin M. Forbes 252f3a
all the bytes we will set a timer to be triggered immediately to call
Justin M. Forbes 252f3a
chr_write_unblocked. Then we return after 2 above, and 3 is called from the
Justin M. Forbes 252f3a
timer callback. This also means we can later remove some ugly recursion protection
Justin M. Forbes 252f3a
from spice-server.
Justin M. Forbes 252f3a
Justin M. Forbes 252f3a
The other tricky point in this patch is not returning the leftover chunk twice.
Justin M. Forbes 252f3a
When we throttle, by definition we have data that spice server didn't consume.
Justin M. Forbes 252f3a
It is being kept by virtio-serial, and by us. The next vmc_read callback needs
Justin M. Forbes 252f3a
to not return it, but just do unthrottling. Then virtio will give us the remaining
Justin M. Forbes 252f3a
chunk as usual in spice_chr_write, and we will pass it to spice server in the
Justin M. Forbes 252f3a
next vmc_read.
Justin M. Forbes 252f3a
Justin M. Forbes 252f3a
This patch relies on Amit's series to expose throttling to chardev's, which
Justin M. Forbes 252f3a
was not accepted upstream, and will not be accepted upstream until the mainloop
Justin M. Forbes 252f3a
is reworked to use glib.
Justin M. Forbes 252f3a
---
Justin M. Forbes 252f3a
 spice-qemu-char.c |   39 +++++++++++++++++++++++++++++++++++----
Justin M. Forbes 252f3a
 1 files changed, 35 insertions(+), 4 deletions(-)
Justin M. Forbes 252f3a
Justin M. Forbes 252f3a
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
Justin M. Forbes 252f3a
index 517f337..91467d5 100644
Justin M. Forbes 252f3a
--- a/spice-qemu-char.c
Justin M. Forbes 252f3a
+++ b/spice-qemu-char.c
Justin M. Forbes 252f3a
@@ -1,4 +1,6 @@
Justin M. Forbes 252f3a
 #include "config-host.h"
Justin M. Forbes 252f3a
+#include "qemu-common.h"
Justin M. Forbes 252f3a
+#include "qemu-timer.h"
Justin M. Forbes 252f3a
 #include "trace.h"
Justin M. Forbes 252f3a
 #include "ui/qemu-spice.h"
Justin M. Forbes 252f3a
 #include <spice.h>
Justin M. Forbes 252f3a
@@ -25,6 +27,7 @@ typedef struct SpiceCharDriver {
Justin M. Forbes 252f3a
     uint8_t               *datapos;
Justin M. Forbes 252f3a
     ssize_t               bufsize, datalen;
Justin M. Forbes 252f3a
     uint32_t              debug;
Justin M. Forbes 252f3a
+    QEMUTimer             *unblock_timer;
Justin M. Forbes 252f3a
 } SpiceCharDriver;
Justin M. Forbes 252f3a
 
Justin M. Forbes 252f3a
 static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
Justin M. Forbes 252f3a
@@ -51,6 +54,17 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
Justin M. Forbes 252f3a
     return out;
Justin M. Forbes 252f3a
 }
Justin M. Forbes 252f3a
 
Justin M. Forbes 252f3a
+static void spice_chr_unblock(void *opaque)
Justin M. Forbes 252f3a
+{
Justin M. Forbes 252f3a
+    SpiceCharDriver *scd = opaque;
Justin M. Forbes 252f3a
+
Justin M. Forbes 252f3a
+    if (scd->chr->chr_write_unblocked == NULL) {
Justin M. Forbes 252f3a
+        dprintf(scd, 1, "%s: backend doesn't support unthrottling.\n", __func__);
Justin M. Forbes 252f3a
+        return;
Justin M. Forbes 252f3a
+    }
Justin M. Forbes 252f3a
+    scd->chr->chr_write_unblocked(scd->chr->handler_opaque);
Justin M. Forbes 252f3a
+}
Justin M. Forbes 252f3a
+
Justin M. Forbes 252f3a
 static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
Justin M. Forbes 252f3a
 {
Justin M. Forbes 252f3a
     SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
Justin M. Forbes 252f3a
@@ -62,9 +76,16 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
Justin M. Forbes 252f3a
         scd->datapos += bytes;
Justin M. Forbes 252f3a
         scd->datalen -= bytes;
Justin M. Forbes 252f3a
         assert(scd->datalen >= 0);
Justin M. Forbes 252f3a
-        if (scd->datalen == 0) {
Justin M. Forbes 252f3a
-            scd->datapos = 0;
Justin M. Forbes 252f3a
-        }
Justin M. Forbes 252f3a
+    }
Justin M. Forbes 252f3a
+    if (scd->datalen == 0 && scd->chr->write_blocked) {
Justin M. Forbes 252f3a
+        dprintf(scd, 1, "%s: unthrottling (%d)\n", __func__, bytes);
Justin M. Forbes 252f3a
+        scd->chr->write_blocked = false;
Justin M. Forbes 252f3a
+        /*
Justin M. Forbes 252f3a
+         * set a timer instead of calling scd->chr->chr_write_unblocked directly,
Justin M. Forbes 252f3a
+         * because that will call back into spice_chr_write (see
Justin M. Forbes 252f3a
+         * virtio-console.c:chr_write_unblocked), which is unwanted.
Justin M. Forbes 252f3a
+         */
Justin M. Forbes 252f3a
+        qemu_mod_timer(scd->unblock_timer, 0);
Justin M. Forbes 252f3a
     }
Justin M. Forbes 252f3a
     trace_spice_vmc_read(bytes, len);
Justin M. Forbes 252f3a
     return bytes;
Justin M. Forbes 252f3a
@@ -107,6 +128,7 @@ static void vmc_unregister_interface(SpiceCharDriver *scd)
Justin M. Forbes 252f3a
 static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
Justin M. Forbes 252f3a
 {
Justin M. Forbes 252f3a
     SpiceCharDriver *s = chr->opaque;
Justin M. Forbes 252f3a
+    int read_bytes;
Justin M. Forbes 252f3a
 
Justin M. Forbes 252f3a
     dprintf(s, 2, "%s: %d\n", __func__, len);
Justin M. Forbes 252f3a
     vmc_register_interface(s);
Justin M. Forbes 252f3a
@@ -119,7 +141,15 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
Justin M. Forbes 252f3a
     s->datapos = s->buffer;
Justin M. Forbes 252f3a
     s->datalen = len;
Justin M. Forbes 252f3a
     spice_server_char_device_wakeup(&s->sin);
Justin M. Forbes 252f3a
-    return len;
Justin M. Forbes 252f3a
+    read_bytes = len - s->datalen;
Justin M. Forbes 252f3a
+    if (read_bytes != len) {
Justin M. Forbes 252f3a
+        dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__,
Justin M. Forbes 252f3a
+                read_bytes, len, s->bufsize);
Justin M. Forbes 252f3a
+        s->chr->write_blocked = true;
Justin M. Forbes 252f3a
+        /* We'll get passed in the unconsumed data with the next call */
Justin M. Forbes 252f3a
+        s->datalen = 0;
Justin M. Forbes 252f3a
+    }
Justin M. Forbes 252f3a
+    return read_bytes;
Justin M. Forbes 252f3a
 }
Justin M. Forbes 252f3a
 
Justin M. Forbes 252f3a
 static void spice_chr_close(struct CharDriverState *chr)
Justin M. Forbes 252f3a
@@ -183,6 +213,7 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
Justin M. Forbes 252f3a
     chr->opaque = s;
Justin M. Forbes 252f3a
     chr->chr_write = spice_chr_write;
Justin M. Forbes 252f3a
     chr->chr_close = spice_chr_close;
Justin M. Forbes 252f3a
+    s->unblock_timer = qemu_new_timer(vm_clock, spice_chr_unblock, s);
Justin M. Forbes 252f3a
 
Justin M. Forbes 252f3a
     qemu_chr_generic_open(chr);
Justin M. Forbes 252f3a
 
Justin M. Forbes 252f3a
-- 
Justin M. Forbes 252f3a
1.7.3.2
Justin M. Forbes 252f3a