From 0097be008cbe33598605064e94a713aaf3d7c348 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Thu, 20 May 2010 19:13:09 -0300
Subject: [PATCH 7/8] spice-vmc: remove ringbuffer

RH-Author: Alon Levy <alevy@redhat.com>
Message-id: <1274382790-12832-2-git-send-email-alevy@redhat.com>
Patchwork-id: 9447
O-Subject: [RHEL6 PATCH v4 1/2] spice-vmc: remove ringbuffer
Bugzilla: 589670
RH-Acked-by: Gerd Hoffmann <kraxel@redhat.com>
RH-Acked-by: Juan Quintela <quintela@redhat.com>
RH-Acked-by: Amit Shah <amit.shah@redhat.com>

BZ 589670

Remove spice_vmc_ring_t, do not copy data that arrives in have_data,
just store the location and length in datapos/datalen, and decrement
until interface consumes it all by successive reads. Data is only
valid during the have_data callback. Since all reads are done from
the wakup which is called from have_data, this is valid.

Signed-off-by: Alon Levy <alevy@redhat.com>
---
 hw/spice-vmc.c |  105 ++++++++++++++-----------------------------------------
 1 files changed, 27 insertions(+), 78 deletions(-)

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 hw/spice-vmc.c |  105 ++++++++++++++-----------------------------------------
 1 files changed, 27 insertions(+), 78 deletions(-)

diff --git a/hw/spice-vmc.c b/hw/spice-vmc.c
index 72a292d..b5a27d2 100644
--- a/hw/spice-vmc.c
+++ b/hw/spice-vmc.c
@@ -42,77 +42,19 @@
 #define SPICE_VMC_GUEST_DEVICE_NAME "com.redhat.spice.0"
 #define SPICE_VMC_DEVICE_NAME       "spicevmc"
 
-typedef struct {
-    uint8_t  d[1024*16]; /* 16 KiB */
-    uint64_t write_pos;
-    uint64_t bytes;      /* in [0, sizeof(d)] */
-    uint64_t read_pos;
-} spice_vmc_ring_t;
-
-size_t spice_ring_read(spice_vmc_ring_t* ring, uint8_t* buf, size_t len);
-size_t spice_ring_write(spice_vmc_ring_t* ring, const uint8_t* buf, size_t len);
-
 typedef struct SpiceVMChannel {
-    VirtIOSerialPort vserport;
-    bool running;
-    bool active_interface;
-    uint8_t active_interface_vmstate;
-    VDIPortInterface interface;
-    VDIPortPlug *plug;
-
-    /* buffer the memory written by the guest until spice-server reads */
-    spice_vmc_ring_t guest_out_ring;
+    VirtIOSerialPort    vserport;
+    bool                running;
+    bool                active_interface;
+    uint8_t             active_interface_vmstate;
+    VDIPortInterface    interface;
+    VDIPortPlug         *plug;
+    uint8_t             *datapos;
+    uint32_t            datalen;
+    uint32_t            debug;
 } SpiceVMChannel;
 
 /*
- * ring buffer
- */
-
-size_t spice_ring_read(spice_vmc_ring_t* ring, uint8_t* buf, size_t len)
-{
-    size_t actual_read = MIN(len, ring->bytes);
-    size_t first_part;
-    if (actual_read > 0) {
-        if (actual_read + ring->read_pos > sizeof(ring->d)) {
-            /* two parts */
-            first_part = sizeof(ring->d) - ring->read_pos;
-            memcpy(buf, ring->d + ring->read_pos, first_part);
-            memcpy(buf + first_part, ring->d, actual_read - first_part);
-            ring->read_pos = actual_read - first_part;
-        } else {
-            /* one part */
-            memcpy(buf, ring->d + ring->read_pos, actual_read);
-            ring->read_pos += actual_read;
-        }
-        ring->bytes -= actual_read;
-    }
-    return actual_read;
-}
-
-size_t spice_ring_write(spice_vmc_ring_t* ring, const uint8_t* buf, size_t len)
-{
-    size_t bytes_written = 0;
-    size_t first_part;
-    if (ring->bytes == sizeof(ring->d)) {
-        return 0;
-    }
-    bytes_written = MIN(sizeof(ring->d) - ring->bytes, len);
-    if (ring->write_pos + bytes_written > sizeof(ring->d)) {
-        /* two parts */
-        first_part = sizeof(ring->d) - ring->write_pos;
-        memcpy(ring->d + ring->write_pos, buf, first_part);
-        memcpy(ring->d, buf + first_part, bytes_written - first_part);
-        ring->write_pos = bytes_written - first_part;
-    } else {
-        /* one part */
-        memcpy(ring->d + ring->write_pos, buf, bytes_written);
-        ring->write_pos += bytes_written;
-    }
-    ring->bytes += bytes_written;
-    return bytes_written;
-}
-
-/*
  * VDIPortInterface callbacks
  */
 
@@ -157,11 +99,20 @@ static int spice_vmc_interface_write(
 static int spice_vmc_interface_read(
     VDIPortInterface *port, VDObjectRef plug, uint8_t *buf, int len)
 {
-    int actual_read;
     SpiceVMChannel *svc = container_of(port, SpiceVMChannel, interface);
-
-    actual_read = spice_ring_read(&(svc->guest_out_ring), buf, len);
-    return actual_read;
+    int bytes = MIN(len, svc->datalen);
+
+    if (bytes) {
+        assert(svc->datapos);
+        memcpy(buf, svc->datapos, bytes);
+        svc->datapos += bytes;
+        svc->datalen -= bytes;
+        assert(svc->datalen >= 0);
+        if (svc->datalen == 0) {
+            svc->datapos = NULL;
+        }
+    }
+    return bytes;
 }
 
 static void spice_vmc_register_interface(SpiceVMChannel *svc)
@@ -238,14 +189,12 @@ static void spice_vmc_have_data(
                 VirtIOSerialPort *vserport, const uint8_t *buf, size_t len)
 {
     SpiceVMChannel *svc = DO_UPCAST(SpiceVMChannel, vserport, vserport);
-    int bytes_written;
 
-    bytes_written = spice_ring_write(&(svc->guest_out_ring), buf, len);
-    if (bytes_written != len) {
-        printf("WARNING: %s: threw away %lu bytes due to ring being full\n",
-            __func__, (len - bytes_written));
-        return;
-    }
+    assert(svc->datalen == 0);
+    /* unconst cast is fine: datapos is only accessed through  _read
+     * where it is copied out */
+    svc->datapos = (uint8_t*)buf;
+    svc->datalen = len;
     if (svc->plug) {
         svc->plug->wakeup(svc->plug);
     }
-- 
1.7.0.3

