[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 26/41] buffered_file: factor out buffer managemen
From: |
Isaku Yamahata |
Subject: |
[Qemu-devel] [PATCH v2 26/41] buffered_file: factor out buffer management logic |
Date: |
Mon, 4 Jun 2012 18:57:28 +0900 |
This patch factors out buffer management logic.
Signed-off-by: Isaku Yamahata <address@hidden>
---
buffered_file.c | 141 +++++++++++++++++++++++++++++++++---------------------
buffered_file.h | 8 +++
2 files changed, 94 insertions(+), 55 deletions(-)
diff --git a/buffered_file.c b/buffered_file.c
index a38caec..22dd4c9 100644
--- a/buffered_file.c
+++ b/buffered_file.c
@@ -20,24 +20,6 @@
#include "buffered_file.h"
//#define DEBUG_BUFFERED_FILE
-
-typedef struct QEMUFileBuffered
-{
- BufferedPutFunc *put_buffer;
- BufferedPutReadyFunc *put_ready;
- BufferedWaitForUnfreezeFunc *wait_for_unfreeze;
- BufferedCloseFunc *close;
- void *opaque;
- QEMUFile *file;
- int freeze_output;
- size_t bytes_xfer;
- size_t xfer_limit;
- uint8_t *buffer;
- size_t buffer_size;
- size_t buffer_capacity;
- QEMUTimer *timer;
-} QEMUFileBuffered;
-
#ifdef DEBUG_BUFFERED_FILE
#define DPRINTF(fmt, ...) \
do { printf("buffered-file: " fmt, ## __VA_ARGS__); } while (0)
@@ -46,57 +28,71 @@ typedef struct QEMUFileBuffered
do { } while (0)
#endif
-static void buffered_append(QEMUFileBuffered *s,
- const uint8_t *buf, size_t size)
-{
- if (size > (s->buffer_capacity - s->buffer_size)) {
- void *tmp;
-
- DPRINTF("increasing buffer capacity from %zu by %zu\n",
- s->buffer_capacity, size + 1024);
- s->buffer_capacity += size + 1024;
+/***************************************************************************
+ * buffer management
+ */
- tmp = g_realloc(s->buffer, s->buffer_capacity);
- if (tmp == NULL) {
- fprintf(stderr, "qemu file buffer expansion failed\n");
- exit(1);
- }
+static void buffer_destroy(QEMUBuffer *s)
+{
+ g_free(s->buffer);
+}
- s->buffer = tmp;
+static void buffer_consume(QEMUBuffer *s, size_t offset)
+{
+ if (offset > 0) {
+ assert(s->buffer_size >= offset);
+ memmove(s->buffer, s->buffer + offset, s->buffer_size - offset);
+ s->buffer_size -= offset;
}
+}
+static void buffer_append(QEMUBuffer *s, const uint8_t *buf, size_t size)
+{
+#define BUF_SIZE_INC (32 * 1024) /* = IO_BUF_SIZE */
+ int inc = size - (s->buffer_capacity - s->buffer_size);
+ if (inc > 0) {
+ s->buffer_capacity += DIV_ROUND_UP(inc, BUF_SIZE_INC) * BUF_SIZE_INC;
+ s->buffer = g_realloc(s->buffer, s->buffer_capacity);
+ }
memcpy(s->buffer + s->buffer_size, buf, size);
s->buffer_size += size;
}
-static void buffered_flush(QEMUFileBuffered *s)
+typedef ssize_t (BufferPutBuf)(void *opaque, const void *data, size_t size);
+
+static void buffer_flush(QEMUBuffer *buf, QEMUFile *file,
+ void *opaque, BufferPutBuf *put_buf)
{
size_t offset = 0;
int error;
- error = qemu_file_get_error(s->file);
+ error = qemu_file_get_error(file);
if (error != 0) {
DPRINTF("flush when error, bailing: %s\n", strerror(-error));
return;
}
- DPRINTF("flushing %zu byte(s) of data\n", s->buffer_size);
+ DPRINTF("flushing %zu byte(s) of data\n", buf->buffer_size);
- while (offset < s->buffer_size) {
+ while (offset < buf->buffer_size) {
ssize_t ret;
- ret = s->put_buffer(s->opaque, s->buffer + offset,
- s->buffer_size - offset);
- if (ret == -EAGAIN) {
+ ret = put_buf(opaque, buf->buffer + offset, buf->buffer_size - offset);
+ if (ret == -EINTR) {
+ continue;
+ } else if (ret == -EAGAIN) {
DPRINTF("backend not ready, freezing\n");
- s->freeze_output = 1;
+ buf->freeze_output = true;
break;
}
- if (ret <= 0) {
+ if (ret < 0) {
DPRINTF("error flushing data, %zd\n", ret);
- qemu_file_set_error(s->file, ret);
+ qemu_file_set_error(file, ret);
+ break;
+ } else if (ret == 0) {
+ DPRINTF("ret == 0\n");
break;
} else {
DPRINTF("flushed %zd byte(s)\n", ret);
@@ -104,9 +100,44 @@ static void buffered_flush(QEMUFileBuffered *s)
}
}
- DPRINTF("flushed %zu of %zu byte(s)\n", offset, s->buffer_size);
- memmove(s->buffer, s->buffer + offset, s->buffer_size - offset);
- s->buffer_size -= offset;
+ DPRINTF("flushed %zu of %zu byte(s)\n", offset, buf->buffer_size);
+ buffer_consume(buf, offset);
+}
+
+
+/***************************************************************************
+ * Buffered File
+ */
+
+typedef struct QEMUFileBuffered
+{
+ BufferedPutFunc *put_buffer;
+ BufferedPutReadyFunc *put_ready;
+ BufferedWaitForUnfreezeFunc *wait_for_unfreeze;
+ BufferedCloseFunc *close;
+ void *opaque;
+ QEMUFile *file;
+ size_t bytes_xfer;
+ size_t xfer_limit;
+ QEMUTimer *timer;
+ QEMUBuffer buf;
+} QEMUFileBuffered;
+
+static ssize_t buffered_flush_putbuf(void *opaque,
+ const void *data, size_t size)
+{
+ QEMUFileBuffered *s = opaque;
+ ssize_t ret = s->put_buffer(s->opaque, data, size);
+ if (ret == 0) {
+ DPRINTF("error flushing data, %zd\n", ret);
+ qemu_file_set_error(s->file, ret);
+ }
+ return ret;
+}
+
+static void buffered_flush(QEMUFileBuffered *s)
+{
+ buffer_flush(&s->buf, s->file, s, buffered_flush_putbuf);
}
static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos,
int size)
@@ -124,11 +155,11 @@ static int buffered_put_buffer(void *opaque, const
uint8_t *buf, int64_t pos, in
}
DPRINTF("unfreezing output\n");
- s->freeze_output = 0;
+ s->buf.freeze_output = false;
buffered_flush(s);
- while (!s->freeze_output && offset < size) {
+ while (!s->buf.freeze_output && offset < size) {
if (s->bytes_xfer > s->xfer_limit) {
DPRINTF("transfer limit exceeded when putting\n");
break;
@@ -137,7 +168,7 @@ static int buffered_put_buffer(void *opaque, const uint8_t
*buf, int64_t pos, in
ret = s->put_buffer(s->opaque, buf + offset, size - offset);
if (ret == -EAGAIN) {
DPRINTF("backend not ready, freezing\n");
- s->freeze_output = 1;
+ s->buf.freeze_output = true;
break;
}
@@ -155,7 +186,7 @@ static int buffered_put_buffer(void *opaque, const uint8_t
*buf, int64_t pos, in
if (offset >= 0) {
DPRINTF("buffering %d bytes\n", size - offset);
- buffered_append(s, buf + offset, size - offset);
+ buffer_append(&s->buf, buf + offset, size - offset);
offset = size;
}
@@ -172,9 +203,9 @@ static int buffered_put_buffer(void *opaque, const uint8_t
*buf, int64_t pos, in
static void buffered_drain(QEMUFileBuffered *s)
{
- while (!qemu_file_get_error(s->file) && s->buffer_size) {
+ while (!qemu_file_get_error(s->file) && s->buf.buffer_size) {
buffered_flush(s);
- if (s->freeze_output)
+ if (s->buf.freeze_output)
s->wait_for_unfreeze(s->opaque);
}
}
@@ -192,7 +223,7 @@ static int buffered_close(void *opaque)
qemu_del_timer(s->timer);
qemu_free_timer(s->timer);
- g_free(s->buffer);
+ buffer_destroy(&s->buf);
g_free(s);
return ret;
@@ -213,7 +244,7 @@ static int buffered_rate_limit(void *opaque)
if (ret) {
return ret;
}
- if (s->freeze_output)
+ if (s->buf.freeze_output)
return 1;
if (s->bytes_xfer > s->xfer_limit)
@@ -256,7 +287,7 @@ static void buffered_rate_tick(void *opaque)
qemu_mod_timer(s->timer, qemu_get_clock_ms(rt_clock) + 100);
- if (s->freeze_output)
+ if (s->buf.freeze_output)
return;
s->bytes_xfer = 0;
diff --git a/buffered_file.h b/buffered_file.h
index cd8e1e8..d3ef546 100644
--- a/buffered_file.h
+++ b/buffered_file.h
@@ -16,6 +16,14 @@
#include "hw/hw.h"
+struct QEMUBuffer {
+ uint8_t *buffer;
+ size_t buffer_size;
+ size_t buffer_capacity;
+ bool freeze_output;
+};
+typedef struct QEMUBuffer QEMUBuffer;
+
typedef ssize_t (BufferedPutFunc)(void *opaque, const void *data, size_t size);
typedef void (BufferedPutReadyFunc)(void *opaque);
typedef void (BufferedWaitForUnfreezeFunc)(void *opaque);
--
1.7.1.1
- [Qemu-devel] [PATCH v2 29/41] umem.h: import Linux umem.h, (continued)
- [Qemu-devel] [PATCH v2 29/41] umem.h: import Linux umem.h, Isaku Yamahata, 2012/06/04
- [Qemu-devel] [PATCH v2 19/41] savevm/QEMUFile: drop qemu_stdio_fd, Isaku Yamahata, 2012/06/04
- [Qemu-devel] [PATCH v2 32/41] savevm: add new section that is used by postcopy, Isaku Yamahata, 2012/06/04
- [Qemu-devel] [PATCH v2 15/41] savevm: export qemu_peek_buffer, qemu_peek_byte, qemu_file_skip, Isaku Yamahata, 2012/06/04
- [Qemu-devel] [PATCH v2 25/41] migration: factor out parameters into MigrationParams, Isaku Yamahata, 2012/06/04
- [Qemu-devel] [PATCH v2 30/41] update-linux-headers.sh: teach umem.h to update-linux-headers.sh, Isaku Yamahata, 2012/06/04
- [Qemu-devel] [PATCH v2 38/41] postcopy/outgoing: add forward, backward option to specify the size of prefault, Isaku Yamahata, 2012/06/04
- [Qemu-devel] [PATCH v2 10/41] arch_init: simplify a bit by ram_find_block(), Isaku Yamahata, 2012/06/04
- [Qemu-devel] [PATCH v2 34/41] postcopy outgoing: add -p and -n option to migrate command, Isaku Yamahata, 2012/06/04
- [Qemu-devel] [PATCH v2 39/41] postcopy/outgoing: implement prefault, Isaku Yamahata, 2012/06/04
- [Qemu-devel] [PATCH v2 26/41] buffered_file: factor out buffer management logic,
Isaku Yamahata <=
- [Qemu-devel] [PATCH v2 14/41] exec.c: export last_ram_offset(), Isaku Yamahata, 2012/06/04
- [Qemu-devel] [PATCH v2 08/41] arch_init/ram_load: refactor ram_load, Isaku Yamahata, 2012/06/04
- [Qemu-devel] [PATCH v2 28/41] buffered_file: add qemu_file to read/write to buffer in memory, Isaku Yamahata, 2012/06/04
- [Qemu-devel] [PATCH v2 33/41] postcopy: introduce -postcopy and -postcopy-flags option, Isaku Yamahata, 2012/06/04
- [Qemu-devel] [PATCH v2 12/41] arch_init: factor out setting last_block, last_offset, Isaku Yamahata, 2012/06/04
- [Qemu-devel] [PATCH v2 36/41] postcopy: implement incoming part of postcopy live migration, Isaku Yamahata, 2012/06/04