From b9c7f698ec784ebb55a813b93f5fa9ae59284ce0 Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Mon, 3 May 2010 12:56:02 -0300 Subject: [PATCH 08/15] spice-vmc: add spice_vmc_ring_t; fix write function RH-Author: Alon Levy Message-id: <1272891368-32706-8-git-send-email-alevy@redhat.com> Patchwork-id: 8964 O-Subject: [RHEL-6 PATCH 07/13] spice-vmc: add spice_vmc_ring_t; fix write function Bugzilla: 576488 RH-Acked-by: Arnon Gilboa RH-Acked-by: Amit Shah RH-Acked-by: Juan Quintela From: alon.levy A simple ring buffer to hold data from guest until spice-server reads it. BZ: 576488 --- hw/spice-vmc.c | 108 ++++++++++++++++++++++++++++++++++--------------------- 1 files changed, 67 insertions(+), 41 deletions(-) Signed-off-by: Eduardo Habkost --- hw/spice-vmc.c | 108 ++++++++++++++++++++++++++++++++++--------------------- 1 files changed, 67 insertions(+), 41 deletions(-) diff --git a/hw/spice-vmc.c b/hw/spice-vmc.c index d563459..cf9ef72 100644 --- a/hw/spice-vmc.c +++ b/hw/spice-vmc.c @@ -42,6 +42,16 @@ #define SPICE_VM_CHANNEL_GUEST_DEVICE_NAME "org.redhat.spice.0" #define SPICE_VM_CHANNEL_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 port; bool running; @@ -50,15 +60,58 @@ typedef struct SpiceVMChannel { VDIPortPlug *plug; /* buffer the memory written by the guest until spice-server reads */ - struct { - uint8 d[1024*16]; /* 16 KiB */ - unsigned write_pos; - int bytes; /* in [0, sizeof(d)] */ - int read_pos; - } guest_out_ring; + spice_vmc_ring_t guest_out_ring; } 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 */ @@ -85,7 +138,7 @@ static void spice_vmc_interface_unplug( /* XXX - throw away anything the client has not read */ if (svc->guest_out_ring.bytes != 0) { - printf("warning: %s: %d unwritten bytes discarded.\n", + printf("warning: %s: %lu unwritten bytes discarded.\n", __func__, svc->guest_out_ring.bytes); } svc->guest_out_ring.read_pos = svc->guest_out_ring.write_pos; @@ -115,25 +168,10 @@ 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); - int actual_read = MIN(len, svc->guest_out_ring.bytes); - if (actual_read > 0) { - if (actual_read + svc->guest_out_ring.read_pos > sizeof(svc->guest_out_ring.d)) { - // two parts - int first_part = sizeof(svc->guest_out_ring.d) - svc->guest_out_ring.read_pos; - memcpy(buf, svc->guest_out_ring.d + svc->guest_out_ring.read_pos, - first_part); - memcpy(buf + first_part, svc->guest_out_ring.d, actual_read - first_part); - svc->guest_out_ring.read_pos = actual_read - first_part; - } else { - // one part - memcpy(buf, svc->guest_out_ring.d + svc->guest_out_ring.read_pos, - actual_read); - svc->guest_out_ring.read_pos += actual_read; - } - svc->guest_out_ring.bytes -= actual_read; - } + actual_read = spice_ring_read(&(svc->guest_out_ring), buf, len); return actual_read; } @@ -211,26 +249,14 @@ static void spice_vmc_have_data( VirtIOSerialPort *port, const uint8_t *buf, size_t len) { SpiceVMChannel *svc = DO_UPCAST(SpiceVMChannel, port, port); + int bytes_written; - if (svc->guest_out_ring.bytes == sizeof(svc->guest_out_ring.d)) { - printf("WARNING: %s: throwing away %lu bytes due to ring being full\n", - __func__, len); + 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; } - int bytes_read = MIN(sizeof(svc->guest_out_ring.d) - svc->guest_out_ring.bytes, len); - if (svc->guest_out_ring.write_pos + bytes_read > sizeof(svc->guest_out_ring.d)) { - /* two parts */ - size_t first_part = sizeof(svc->guest_out_ring.d) - svc->guest_out_ring.write_pos; - memcpy(svc->guest_out_ring.d + svc->guest_out_ring.write_pos, buf, first_part); - memcpy(svc->guest_out_ring.d, buf + first_part, bytes_read - first_part); - svc->guest_out_ring.write_pos = bytes_read - first_part; - } else { - /* one part */ - memcpy(svc->guest_out_ring.d + svc->guest_out_ring.write_pos, buf, bytes_read); - svc->guest_out_ring.write_pos += bytes_read; - } - svc->guest_out_ring.bytes += bytes_read; - // wakeup spice if (svc->plug) { svc->plug->wakeup(svc->plug); } -- 1.7.0.3