From patchwork Wed Mar 13 18:56:23 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joel Schopp X-Patchwork-Id: 227333 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 8933C2C007C for ; Thu, 14 Mar 2013 06:00:08 +1100 (EST) Received: from localhost ([::1]:53931 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UFquE-0006Qb-Mn for incoming@patchwork.ozlabs.org; Wed, 13 Mar 2013 15:00:06 -0400 Received: from eggs.gnu.org ([208.118.235.92]:49898) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UFqsU-0003x4-00 for qemu-devel@nongnu.org; Wed, 13 Mar 2013 14:58:24 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UFqsK-0003df-AJ for qemu-devel@nongnu.org; Wed, 13 Mar 2013 14:58:17 -0400 Received: from e39.co.us.ibm.com ([32.97.110.160]:53353) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UFqsK-0003d3-3T for qemu-devel@nongnu.org; Wed, 13 Mar 2013 14:58:08 -0400 Received: from /spool/local by e39.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 13 Mar 2013 12:57:13 -0600 Received: from d01dlp02.pok.ibm.com (9.56.250.167) by e39.co.us.ibm.com (192.168.1.139) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 13 Mar 2013 12:57:11 -0600 Received: from d01relay07.pok.ibm.com (d01relay07.pok.ibm.com [9.56.227.147]) by d01dlp02.pok.ibm.com (Postfix) with ESMTP id 6F8726E804C for ; Wed, 13 Mar 2013 14:57:02 -0400 (EDT) Received: from d03av06.boulder.ibm.com (d03av06.boulder.ibm.com [9.17.195.245]) by d01relay07.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id r2DIurwW60686420 for ; Wed, 13 Mar 2013 14:56:53 -0400 Received: from d03av06.boulder.ibm.com (loopback [127.0.0.1]) by d03av06.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id r2DIxFkl005704 for ; Wed, 13 Mar 2013 12:59:15 -0600 Received: from jschopp-w520 ([9.80.103.106]) by d03av06.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with SMTP id r2DIxD1E005511; Wed, 13 Mar 2013 12:59:13 -0600 Received: by jschopp-w520 (Postfix, from userid 1000) id B9936500A66; Wed, 13 Mar 2013 13:56:33 -0500 (CDT) From: Joel Schopp To: qemu-devel@nongnu.org Date: Wed, 13 Mar 2013 13:56:23 -0500 Message-Id: <1363200988-17865-5-git-send-email-jschopp@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1363200988-17865-1-git-send-email-jschopp@linux.vnet.ibm.com> References: <1363200988-17865-1-git-send-email-jschopp@linux.vnet.ibm.com> X-TM-AS-MML: No X-Content-Scanned: Fidelis XPS MAILER x-cbid: 13031318-3620-0000-0000-0000019D3FE5 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4.x-2.6.x [generic] X-Received-From: 32.97.110.160 Cc: Joel Schopp , Stefan Berger Subject: [Qemu-devel] [PATCH 4/9] qemu_qsb.diff X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This patch adds support functions for operating on in memory sized file buffers. Signed-off-by: Stefan Berger Signed-off-by: Joel Schopp --- include/migration/qemu-file.h | 12 +++ include/qemu-common.h | 15 ++++ util/qemu-file.c | 184 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 211 insertions(+) diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h index 07d8362..2bc77b1 100644 --- a/include/migration/qemu-file.h +++ b/include/migration/qemu-file.h @@ -24,6 +24,8 @@ #ifndef QEMU_FILE_H #define QEMU_FILE_H 1 +#include + /* This function writes a chunk of data to a file at the given position. * The pos argument can be ignored if the file is only being used for * streaming. The handler should try to write all of the data it can. @@ -58,6 +60,14 @@ typedef struct QEMUFileOps { QEMUFileGetFD *get_fd; } QEMUFileOps; +struct QEMUSizedBuffer { + unsigned char *buffer; + uint64_t size; + uint64_t used; +}; + +typedef struct QEMUSizedBuffer QEMUSizedBuffer; + QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops); QEMUFile *qemu_fopen(const char *filename, const char *mode); QEMUFile *qemu_fdopen(int fd, const char *mode); @@ -71,6 +81,8 @@ void qemu_put_byte(QEMUFile *f, int v); int qemu_read_bytes(QEMUFile *f, uint8_t *buf, int size); int qemu_peek_bytes(QEMUFile *f, uint8_t *buf, int size, size_t offset); int qemu_write_bytes(QEMUFile *f, const uint8_t *buf, int size); +QEMUFile *qemu_bufopen(const char *mode, QEMUSizedBuffer *input); +const QEMUSizedBuffer *qemu_buf_get(QEMUFile *f); static inline void qemu_put_ubyte(QEMUFile *f, unsigned int v) { diff --git a/include/qemu-common.h b/include/qemu-common.h index 5e13708..de1cdc0 100644 --- a/include/qemu-common.h +++ b/include/qemu-common.h @@ -442,4 +442,19 @@ int64_t pow2floor(int64_t value); int uleb128_encode_small(uint8_t *out, uint32_t n); int uleb128_decode_small(const uint8_t *in, uint32_t *n); +/* QEMU Sized Buffer */ +#include "include/migration/qemu-file.h" +QEMUSizedBuffer *qsb_create(const uint8_t *buffer, uint64_t len); +QEMUSizedBuffer *qsb_clone(const QEMUSizedBuffer *); +void qsb_free(QEMUSizedBuffer *); +uint64_t qsb_set_length(QEMUSizedBuffer *qsb, uint64_t length); +uint64_t qsb_get_length(const QEMUSizedBuffer *qsb); +const unsigned char *qsb_get_buffer(const QEMUSizedBuffer *, int64_t pos); +int qsb_write_at(QEMUSizedBuffer *qsb, const uint8_t *buf, + int64_t pos, int size); +int qsb_append_qsb(QEMUSizedBuffer *dest, const QEMUSizedBuffer *src); +int qsb_append(QEMUSizedBuffer *dest, const uint8_t *buffer, uint64_t len); + + + #endif diff --git a/util/qemu-file.c b/util/qemu-file.c index e698713..4442dcc 100644 --- a/util/qemu-file.c +++ b/util/qemu-file.c @@ -710,3 +710,187 @@ int qemu_write_bytes(QEMUFile *f, const uint8_t *buf, int size) return size; } + + +QEMUSizedBuffer *qsb_create(const uint8_t *buffer, uint64_t len) +{ + QEMUSizedBuffer *qsb; + uint64_t alloc_len; + + alloc_len = (len > 1024) ? len : 1024; + + qsb = g_new0(QEMUSizedBuffer, 1); + if (!qsb) { + return NULL; + } + + qsb->buffer = g_malloc(alloc_len); + if (!qsb->buffer) { + g_free(qsb); + return NULL; + } + qsb->size = alloc_len; + + if (buffer) { + memcpy(qsb->buffer, buffer, len); + qsb->used = len; + } + + return qsb; +} + +void qsb_free(QEMUSizedBuffer *qsb) +{ + if (!qsb) { + return; + } + g_free(qsb->buffer); + g_free(qsb); +} + +uint64_t qsb_get_length(const QEMUSizedBuffer *qsb) +{ + return qsb->used; +} + +uint64_t qsb_set_length(QEMUSizedBuffer *qsb, uint64_t new_len) +{ + if (new_len <= qsb->size) { + qsb->used = new_len; + } else { + qsb->used = qsb->size; + } + return qsb->used; +} + +const unsigned char *qsb_get_buffer(const QEMUSizedBuffer *qsb, int64_t pos) +{ + if (pos < qsb->used) { + return &qsb->buffer[pos]; + } + return NULL; +} + +int qsb_write_at(QEMUSizedBuffer *qsb, const uint8_t *buf, + int64_t pos, int size) +{ + if (pos + size > qsb->size) { + qsb->buffer = g_realloc(qsb->buffer, pos + size + 1024); + if (qsb->buffer == NULL) { + return -ENOMEM; + } + qsb->size = pos + size; + } + memcpy(&qsb->buffer[pos], buf, size); + if (pos + size > qsb->used) { + qsb->used = pos + size; + } + + return size; +} + +int qsb_append_qsb(QEMUSizedBuffer *dest, const QEMUSizedBuffer *src) +{ + return qsb_write_at(dest, qsb_get_buffer(src, 0), + qsb_get_length(dest), qsb_get_length(src)); +} + +int qsb_append(QEMUSizedBuffer *dest, const uint8_t *buf, uint64_t len) +{ + return qsb_write_at(dest, buf, + qsb_get_length(dest), len); +} + +QEMUSizedBuffer *qsb_clone(const QEMUSizedBuffer *in) +{ + return qsb_create(qsb_get_buffer(in, 0), + qsb_get_length(in)); +} + +typedef struct QEMUBuffer { + QEMUSizedBuffer *qsb; + QEMUFile *file; +} QEMUBuffer; + +static int buf_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) +{ + QEMUBuffer *s = opaque; + ssize_t len = qsb_get_length(s->qsb) - pos; + + if (len <= 0) { + return 0; + } + + if (len > size) { + len = size; + } + memcpy(buf, qsb_get_buffer(s->qsb, pos), len); + + return len; +} + +static int buf_put_buffer(void *opaque, const uint8_t *buf, + int64_t pos, int size) +{ + QEMUBuffer *s = opaque; + + return qsb_write_at(s->qsb, buf, pos, size); +} + +static int buf_close(void *opaque) +{ + QEMUBuffer *s = opaque; + + qsb_free(s->qsb); + + g_free(s); + + return 0; +} + +const QEMUSizedBuffer *qemu_buf_get(QEMUFile *f) +{ + QEMUBuffer *p; + + qemu_fflush(f); + + p = (QEMUBuffer *)f->opaque; + + return p->qsb; +} + +static const QEMUFileOps buf_read_ops = { + .get_buffer = buf_get_buffer, + .close = buf_close +}; + +static const QEMUFileOps buf_write_ops = { + .put_buffer = buf_put_buffer, + .close = buf_close +}; + +QEMUFile *qemu_bufopen(const char *mode, QEMUSizedBuffer *input) +{ + QEMUBuffer *s; + + if (mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || mode[1] != 0) { + fprintf(stderr, "qemu_bufopen: Argument validity check failed\n"); + return NULL; + } + + s = g_malloc0(sizeof(QEMUBuffer)); + if (mode[0] == 'r') { + s->qsb = input; + } + + if (s->qsb == NULL) { + s->qsb = qsb_create(NULL, 0); + } + + if (mode[0] == 'r') { + s->file = qemu_fopen_ops(s, &buf_read_ops); + } else { + s->file = qemu_fopen_ops(s, &buf_write_ops); + } + return s->file; +}