From patchwork Thu Oct 27 17:06:29 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Roth X-Patchwork-Id: 122184 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id EFAE3B6F91 for ; Fri, 28 Oct 2011 04:08:18 +1100 (EST) Received: from localhost ([::1]:35500 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RJTQt-0002p3-3m for incoming@patchwork.ozlabs.org; Thu, 27 Oct 2011 13:07:59 -0400 Received: from eggs.gnu.org ([140.186.70.92]:42582) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RJTQb-0002QQ-Sh for qemu-devel@nongnu.org; Thu, 27 Oct 2011 13:07:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RJTQX-0000ke-Ax for qemu-devel@nongnu.org; Thu, 27 Oct 2011 13:07:41 -0400 Received: from mout.perfora.net ([74.208.4.194]:56709) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RJTQX-0000ka-6k for qemu-devel@nongnu.org; Thu, 27 Oct 2011 13:07:37 -0400 Received: from illuin.austin.ibm.com ([32.97.110.59]) by mrelay.perfora.net (node=mrus0) with ESMTP (Nemesis) id 0LdH3Z-1Qb6432sr3-00iEkP; Thu, 27 Oct 2011 13:07:27 -0400 From: Michael Roth To: qemu-devel@nongnu.org Date: Thu, 27 Oct 2011 12:06:29 -0500 Message-Id: <1319735193-4718-7-git-send-email-mdroth@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1319735193-4718-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1319735193-4718-1-git-send-email-mdroth@linux.vnet.ibm.com> X-Provags-ID: V02:K0:/YZvxCwjOknSCFdaeAIe74irV87XkCbKKSAdNm7TIcb dJZz0v56nxQ7KWNE5ZiVB0NBKCy9F1T+6yBRV4yE+X0fPQHfBE PdH6vh9Df+debu6yfkxBjF9b0Fs/o1DOA9wq5tHRwrGd8+FZkC VqStxCDKnbWymd+Yh005BIspjKnOCfVlAgtZWZOPKFqCWxkq+3 DhAv6rLi0YZPm6zv9uEtUMebXCXWkrRkE/1Oe0jhoAMAZu29lH X5JJD7B1OuuwxDiFhzyQdETcd6QCSGFeaTuYA6nZDb8idZ7O2B lnf9T19DYVyNW2blzgFeS0Du456uspoNe1hldYUpMRrYQVMyht NeTduODo2GotBOs6Y/zmGB7VD8D8j291X88UVKlm8xqgxOV4x4 vAFro+oZTz1n/JwKhoxuKjp4X9JgwfQLHU= X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 74.208.4.194 Cc: aliguori@us.ibm.com, mdroth@linux.vnet.ibm.com, quintela@redhat.com Subject: [Qemu-devel] [PATCH v2 06/10] qemu-file: add QEMUFile<->visitor lookup routines 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 interface is to allow switching between Visitor-based and direct QEMUFile usage to serialize/de-serialize fields. Once we're passed the transitionary stages and all requisite interfaces are converted to accepting Visitor objects, we can drop this dual approach and begin utilizing non-QEMUFile-based Visitors. Signed-off-by: Michael Roth --- hw/hw.h | 7 ++++ qemu-file.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 110 insertions(+), 1 deletions(-) diff --git a/hw/hw.h b/hw/hw.h index a793974..5c0eb65 100644 --- a/hw/hw.h +++ b/hw/hw.h @@ -10,6 +10,13 @@ #include "ioport.h" #include "irq.h" +#include "qemu-queue.h" +#include "qapi/qapi-visit-core.h" +#include "qapi/qemu-file-output-visitor.h" +#include "qapi/qemu-file-input-visitor.h" + +Visitor *qemu_file_get_visitor(QEMUFile *f); +QEMUFile *qemu_file_from_visitor(Visitor *v); /* VM Load/Save */ diff --git a/qemu-file.c b/qemu-file.c index a4aee9a..cdfe8a3 100644 --- a/qemu-file.c +++ b/qemu-file.c @@ -25,6 +25,8 @@ #include "qemu-common.h" #include "qemu_socket.h" #include "hw/hw.h" +#include "qapi/qemu-file-output-visitor.h" +#include "qapi/qemu-file-input-visitor.h" #define IO_BUF_SIZE 32768 @@ -59,6 +61,94 @@ typedef struct QEMUFileSocket QEMUFile *file; } QEMUFileSocket; +/* TODO: temporary mechanism to support existing function signatures by + * creating a 1-to-1 mapping between QEMUFile's and the actual Visitor type. + * In the case of QemuFileOutputVisitor/QemuFileInputVisitor, the QEMUFile + * arg corresponds to the handle used by the visitor for reads/writes. For + * other visitors, the QEMUFile will serve purely as a key. + * + * Once all interfaces are converted to using Visitor directly, we will + * remove this lookup logic and pass the Visitor to the registered save/load + * functions directly. + */ + +/* Clean up a *Visitor object associated with the QEMUFile */ +typedef int (QEMUFileVisitorCleanupFunc)(void *opaque); + +typedef struct VisitorNode { + void *opaque; + Visitor *visitor; + QEMUFile *file; + QEMUFileVisitorCleanupFunc *cleanup; + QTAILQ_ENTRY(VisitorNode) entry; +} VisitorNode; + +static QTAILQ_HEAD(, VisitorNode) qemu_file_visitors = + QTAILQ_HEAD_INITIALIZER(qemu_file_visitors); + +Visitor *qemu_file_get_visitor(QEMUFile *f) +{ + VisitorNode *vnode; + QTAILQ_FOREACH(vnode, &qemu_file_visitors, entry) { + if (vnode->file == f) { + return vnode->visitor; + } + } + /* all QEMUFile instances should have an associated visitor */ + assert(false); +} + +QEMUFile *qemu_file_from_visitor(Visitor *v) +{ + VisitorNode *vnode; + QTAILQ_FOREACH(vnode, &qemu_file_visitors, entry) { + if (vnode->visitor == v) { + return vnode->file; + } + } + return NULL; +} + +static void qemu_file_put_visitor(QEMUFile *f, Visitor *v, void *opaque, + QEMUFileVisitorCleanupFunc *cleanup) +{ + VisitorNode *vnode = g_malloc0(sizeof(*vnode)); + vnode->file = f; + vnode->visitor = v; + vnode->opaque = opaque; + vnode->cleanup = cleanup; + QTAILQ_INSERT_TAIL(&qemu_file_visitors, vnode, entry); +} + +static void qemu_file_remove_visitor(QEMUFile *f) +{ + VisitorNode *vnode; + QTAILQ_FOREACH(vnode, &qemu_file_visitors, entry) { + if (vnode->file == f) { + QTAILQ_REMOVE(&qemu_file_visitors, vnode, entry); + if (vnode->cleanup) { + vnode->cleanup(vnode->opaque); + } + g_free(vnode); + } + } +} + +static int qemu_file_cleanup_output_visitor(void *opaque) +{ + QemuFileOutputVisitor *v = opaque; + qemu_file_output_visitor_cleanup(v); + return 0; +} + +static int qemu_file_cleanup_input_visitor(void *opaque) +{ + QemuFileInputVisitor *v = opaque; + qemu_file_input_visitor_cleanup(v); + return 0; +} + + static int socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) { QEMUFileSocket *s = opaque; @@ -177,8 +267,9 @@ QEMUFile *qemu_fdopen(int fd, const char *mode) s = g_malloc0(sizeof(QEMUFileStdio)); s->stdio_file = fdopen(fd, mode); - if (!s->stdio_file) + if (!s->stdio_file) { goto fail; + } if (mode[0] == 'r') { s->file = qemu_fopen_ops(s, NULL, stdio_get_buffer, stdio_fclose, @@ -270,6 +361,16 @@ QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer, f->get_rate_limit = get_rate_limit; f->is_write = 0; + if (put_buffer) { + QemuFileOutputVisitor *ov = qemu_file_output_visitor_new(f); + qemu_file_put_visitor(f, qemu_file_output_get_visitor(ov), ov, + qemu_file_cleanup_output_visitor); + } else { + QemuFileInputVisitor *iv = qemu_file_input_visitor_new(f); + qemu_file_put_visitor(f, qemu_file_input_get_visitor(iv), iv, + qemu_file_cleanup_input_visitor); + } + return f; } @@ -336,6 +437,7 @@ int qemu_fclose(QEMUFile *f) { int ret = 0; qemu_fflush(f); + qemu_file_remove_visitor(f); if (f->close) { ret = f->close(f->opaque); }