All of lore.kernel.org
 help / color / mirror / Atom feed
From: Anthony Liguori <aliguori@us.ibm.com>
To: qemu-devel@nongnu.org
Cc: Anthony Liguori <aliguori@us.ibm.com>,
	"Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
Subject: [Qemu-devel] [PATCH 01/17] vitio-9p: Add a virtio 9p device to qemu
Date: Wed,  3 Mar 2010 13:00:58 -0600	[thread overview]
Message-ID: <1267642874-15001-3-git-send-email-aliguori@us.ibm.com> (raw)
In-Reply-To: <1267642874-15001-1-git-send-email-aliguori@us.ibm.com>

This patch doesn't implement the 9p protocol handling
code. It add a simple device which dump the protocl data

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 Makefile.target      |    1 +
 hw/virtio-9p-debug.c |  442 ++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/virtio-9p.c       |  275 +++++++++++++++++++++++++++++++
 hw/virtio-9p.h       |   70 ++++++++
 hw/virtio-pci.c      |   25 +++
 hw/virtio.h          |    1 +
 6 files changed, 814 insertions(+), 0 deletions(-)
 create mode 100644 hw/virtio-9p-debug.c
 create mode 100644 hw/virtio-9p.c
 create mode 100644 hw/virtio-9p.h

diff --git a/Makefile.target b/Makefile.target
index 4c4d397..8f240ea 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -173,6 +173,7 @@ obj-y = vl.o async.o monitor.o pci.o pci_host.o pcie_host.o machine.o gdbstub.o
 # virtio has to be here due to weird dependency between PCI and virtio-net.
 # need to fix this properly
 obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-pci.o virtio-serial-bus.o
+obj-y += virtio-9p.o virtio-9p-debug.o
 obj-y += rwhandler.o
 obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
diff --git a/hw/virtio-9p-debug.c b/hw/virtio-9p-debug.c
new file mode 100644
index 0000000..060337f
--- /dev/null
+++ b/hw/virtio-9p-debug.c
@@ -0,0 +1,442 @@
+/*
+ * Virtio 9p PDU debug
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+#include "virtio.h"
+#include "pc.h"
+#include "virtio-9p.h"
+
+#include <assert.h>
+#include <sys/uio.h>
+
+#define BUG_ON(cond) assert(!(cond))
+
+extern int dotu;
+static FILE *llogfile;
+
+static struct iovec *get_sg(V9fsPDU *pdu, int rx)
+{
+    if (rx)
+	return pdu->elem.in_sg;
+    return pdu->elem.out_sg;
+}
+
+static void pprint_int8(V9fsPDU *pdu, int rx, size_t *offsetp,
+						const char *name)
+{
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    int8_t value;
+
+    BUG_ON((offset + sizeof(value)) > sg[0].iov_len);
+
+    memcpy(&value, sg[0].iov_base + offset, sizeof(value));
+    offset += sizeof(value);
+
+    fprintf(llogfile, "%s=0x%x", name, value);
+
+    *offsetp = offset;
+}
+
+static void pprint_int16(V9fsPDU *pdu, int rx, size_t *offsetp,
+						const char *name)
+{
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    int16_t value;
+
+    BUG_ON((offset + sizeof(value)) > sg[0].iov_len);
+
+    memcpy(&value, sg[0].iov_base + offset, sizeof(value));
+    offset += sizeof(value);
+
+    fprintf(llogfile, "%s=0x%x", name, value);
+
+    *offsetp = offset;
+}
+
+static void pprint_int32(V9fsPDU *pdu, int rx, size_t *offsetp,
+						const char *name)
+{
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    int32_t value;
+
+    BUG_ON((offset + sizeof(value)) > sg[0].iov_len);
+
+    memcpy(&value, sg[0].iov_base + offset, sizeof(value));
+    offset += sizeof(value);
+
+    fprintf(llogfile, "%s=0x%x", name, value);
+
+    *offsetp = offset;
+}
+
+static void pprint_int64(V9fsPDU *pdu, int rx, size_t *offsetp,
+						const char *name)
+{
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    int64_t value;
+
+    BUG_ON((offset + sizeof(value)) > sg[0].iov_len);
+
+    memcpy(&value, sg[0].iov_base + offset, sizeof(value));
+    offset += sizeof(value);
+
+    fprintf(llogfile, "%s=0x%" PRIx64, name, value);
+
+    *offsetp = offset;
+}
+
+static void pprint_str(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
+{
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    int16_t size;
+    size_t result;
+
+    BUG_ON((offset + 2) > sg[0].iov_len);
+    memcpy(&size, sg[0].iov_base + offset, 2);
+    offset += 2;
+
+    BUG_ON((offset + size) > sg[0].iov_len);
+    fprintf(llogfile, "%s=", name);
+    result = fwrite(sg[0].iov_base + offset, 1, size, llogfile);
+    BUG_ON(result != size);
+    offset += size;
+
+    *offsetp = offset;
+}
+
+static void pprint_qid(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
+{
+    fprintf(llogfile, "%s={", name);
+    pprint_int8(pdu, rx, offsetp, "type");
+    pprint_int32(pdu, rx, offsetp, ", version");
+    pprint_int64(pdu, rx, offsetp, ", path");
+    fprintf(llogfile, "}");
+}
+
+static void pprint_stat(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
+{
+    fprintf(llogfile, "%s={", name);
+    pprint_int16(pdu, rx, offsetp, "size");
+    pprint_int16(pdu, rx, offsetp, ", type");
+    pprint_int32(pdu, rx, offsetp, ", dev");
+    pprint_qid(pdu, rx, offsetp, ", qid");
+    pprint_int32(pdu, rx, offsetp, ", mode");
+    pprint_int32(pdu, rx, offsetp, ", atime");
+    pprint_int32(pdu, rx, offsetp, ", mtime");
+    pprint_int64(pdu, rx, offsetp, ", length");
+    pprint_str(pdu, rx, offsetp, ", name");
+    pprint_str(pdu, rx, offsetp, ", uid");
+    pprint_str(pdu, rx, offsetp, ", gid");
+    pprint_str(pdu, rx, offsetp, ", muid");
+    if (dotu) {
+	pprint_str(pdu, rx, offsetp, ", extension");
+	pprint_int32(pdu, rx, offsetp, ", uid");
+	pprint_int32(pdu, rx, offsetp, ", gid");
+	pprint_int32(pdu, rx, offsetp, ", muid");
+    }
+    fprintf(llogfile, "}");
+}
+
+static void pprint_strs(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
+{
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    int16_t count, i;
+
+    fprintf(llogfile, "%s={", name);
+
+    BUG_ON((offset + 2) > sg[0].iov_len);
+    memcpy(&count, sg[0].iov_base + offset, 2);
+    offset += 2;
+
+    for (i = 0; i < count; i++) {
+	char str[512];
+	if (i)
+	    fprintf(llogfile, ", ");
+	snprintf(str, sizeof(str), "[%d]", i);
+	pprint_str(pdu, rx, &offset, str);
+    }
+
+    fprintf(llogfile, "}");
+
+    *offsetp = offset;
+}
+
+static void pprint_qids(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
+{
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    int16_t count, i;
+
+    fprintf(llogfile, "%s={", name);
+
+    BUG_ON((offset + 2) > sg[0].iov_len);
+    memcpy(&count, sg[0].iov_base + offset, 2);
+    offset += 2;
+
+    for (i = 0; i < count; i++) {
+	char str[512];
+	if (i)
+	    fprintf(llogfile, ", ");
+	snprintf(str, sizeof(str), "[%d]", i);
+	pprint_qid(pdu, rx, &offset, str);
+    }
+
+    fprintf(llogfile, "}");
+
+    *offsetp = offset;
+}
+
+static void pprint_sg(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
+{
+    struct iovec *sg = get_sg(pdu, rx);
+    unsigned int count;
+    int i;
+
+    if (rx)
+	count = pdu->elem.in_num;
+    else
+	count = pdu->elem.out_num;
+
+    fprintf(llogfile, "%s={", name);
+    for (i = 0; i < count; i++) {
+	if (i)
+	    fprintf(llogfile, ", ");
+	fprintf(llogfile, "(%p, 0x%zx)", sg[i].iov_base, sg[i].iov_len);
+    }
+    fprintf(llogfile, "}");
+}
+
+/* FIXME: read from a directory fid returns serialized stat_t's */
+#ifdef DEBUG_DATA
+static void pprint_data(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
+{
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    unsigned int count;
+    int32_t size;
+    int total, i, j;
+    ssize_t len;
+
+    if (rx)
+	count = pdu->elem.in_num;
+    else
+	count = pdu->elem.out_num;
+
+    BUG_ON((offset + sizeof(size)) > sg[0].iov_len);
+
+    memcpy(&size, sg[0].iov_base + offset, sizeof(size));
+    offset += sizeof(size);
+
+    fprintf(llogfile, "size: %x\n", size);
+
+    sg[0].iov_base += 11; /* skip header */
+    sg[0].iov_len -= 11;
+
+    total = 0;
+    for (i = 0; i < count; i++) {
+	    total += sg[i].iov_len;
+	    if (total >= size) {
+		    /* trim sg list so writev does the right thing */
+		    sg[i].iov_len -= (total - size);
+		    i++;
+		    break;
+	    }
+    }
+
+    fprintf(llogfile, "%s={\"", name);
+    fflush(llogfile);
+    for (j = 0; j < i; j++) {
+	    if (j) {
+		    fprintf(llogfile, "\", \"");
+		    fflush(llogfile);
+	    }
+
+	    do {
+		    len = writev(fileno(llogfile), &sg[j], 1);
+	    } while (len == -1 && errno == EINTR);
+	    fprintf(llogfile, "len == %ld: %m\n", len);
+	    BUG_ON(len != sg[j].iov_len);
+    }
+    fprintf(llogfile, "\"}");
+
+    sg[0].iov_base -= 11;
+    sg[0].iov_len += 11;
+
+}
+#endif
+
+void pprint_pdu(V9fsPDU *pdu);
+
+void pprint_pdu(V9fsPDU *pdu)
+{
+    size_t offset = 7;
+
+    if (llogfile == NULL)
+	llogfile = fopen("/tmp/pdu.log", "w");
+
+    switch (pdu->id) {
+    case P9_TVERSION: {
+	fprintf(llogfile, "TVERSION: (");
+	pprint_int32(pdu, 0, &offset, "msize");
+	pprint_str(pdu, 0, &offset, ", version");
+	break;
+    }
+    case P9_RVERSION:
+	fprintf(llogfile, "RVERSION: (");
+	pprint_int32(pdu, 1, &offset, "msize");
+	pprint_str(pdu, 1, &offset, ", version");
+	break;
+    case P9_TAUTH:
+	fprintf(llogfile, "TAUTH: (");
+	pprint_int32(pdu, 0, &offset, "afid");
+	pprint_str(pdu, 0, &offset, ", uname");
+	pprint_str(pdu, 0, &offset, ", aname");
+	if (dotu)
+	    pprint_int32(pdu, 0, &offset, ", n_uname");
+	break;
+    case P9_RAUTH:
+	fprintf(llogfile, "RAUTH: (");
+	pprint_qid(pdu, 1, &offset, "qid");
+	break;
+    case P9_TATTACH:
+	fprintf(llogfile, "TATTACH: (");
+	pprint_int32(pdu, 0, &offset, "fid");
+	pprint_int32(pdu, 0, &offset, ", afid");
+	pprint_str(pdu, 0, &offset, ", uname");
+	pprint_str(pdu, 0, &offset, ", aname");
+	if (dotu)
+	    pprint_int32(pdu, 0, &offset, ", n_uname");
+	break;
+    case P9_RATTACH:
+	fprintf(llogfile, "RATTACH: (");
+	pprint_qid(pdu, 1, &offset, "qid");
+	break;
+    case P9_TERROR:
+	fprintf(llogfile, "TERROR: (");
+	break;
+    case P9_RERROR:
+	fprintf(llogfile, "RERROR: (");
+	pprint_str(pdu, 1, &offset, "ename");
+	if (dotu)
+	    pprint_int32(pdu, 1, &offset, ", ecode");
+	break;
+    case P9_TFLUSH:
+	fprintf(llogfile, "TFLUSH: (");
+	pprint_int16(pdu, 0, &offset, "oldtag");
+	break;
+    case P9_RFLUSH:
+	fprintf(llogfile, "RFLUSH: (");
+	break;
+    case P9_TWALK:
+	fprintf(llogfile, "TWALK: (");
+	pprint_int32(pdu, 0, &offset, "fid");
+	pprint_int32(pdu, 0, &offset, ", newfid");
+	pprint_strs(pdu, 0, &offset, ", wnames");
+	break;
+    case P9_RWALK:
+	fprintf(llogfile, "RWALK: (");
+	pprint_qids(pdu, 1, &offset, "wqids");
+	break;
+    case P9_TOPEN:
+	fprintf(llogfile, "TOPEN: (");
+	pprint_int32(pdu, 0, &offset, "fid");
+	pprint_int8(pdu, 0, &offset, ", mode");
+	break;
+    case P9_ROPEN:
+	fprintf(llogfile, "ROPEN: (");
+	pprint_qid(pdu, 1, &offset, "qid");
+	pprint_int32(pdu, 1, &offset, ", iounit");
+	break;
+    case P9_TCREATE:
+	fprintf(llogfile, "TCREATE: (");
+	pprint_int32(pdu, 0, &offset, "fid");
+	pprint_str(pdu, 0, &offset, ", name");
+	pprint_int32(pdu, 0, &offset, ", perm");
+	pprint_int8(pdu, 0, &offset, ", mode");
+	if (dotu)
+	    pprint_str(pdu, 0, &offset, ", extension");
+	break;
+    case P9_RCREATE:
+	fprintf(llogfile, "RCREATE: (");
+	pprint_qid(pdu, 1, &offset, "qid");
+	pprint_int32(pdu, 1, &offset, ", iounit");
+	break;
+    case P9_TREAD:
+	fprintf(llogfile, "TREAD: (");
+	pprint_int32(pdu, 0, &offset, "fid");
+	pprint_int64(pdu, 0, &offset, ", offset");
+	pprint_int32(pdu, 0, &offset, ", count");
+	pprint_sg(pdu, 0, &offset, ", sg");
+	break;
+    case P9_RREAD:
+	fprintf(llogfile, "RREAD: (");
+	pprint_int32(pdu, 1, &offset, "count");
+	pprint_sg(pdu, 1, &offset, ", sg");
+	offset = 7;
+#ifdef DEBUG_DATA
+	pprint_data(pdu, 1, &offset, ", data");
+#endif
+	break;
+    case P9_TWRITE:
+	fprintf(llogfile, "TWRITE: (");
+	pprint_int32(pdu, 0, &offset, "fid");
+	pprint_int64(pdu, 0, &offset, ", offset");
+	pprint_int32(pdu, 0, &offset, ", count");
+	break;
+    case P9_RWRITE:
+	fprintf(llogfile, "RWRITE: (");
+	pprint_int32(pdu, 1, &offset, "count");
+	break;
+    case P9_TCLUNK:
+	fprintf(llogfile, "TCLUNK: (");
+	pprint_int32(pdu, 0, &offset, "fid");
+	break;
+    case P9_RCLUNK:
+	fprintf(llogfile, "RCLUNK: (");
+	break;
+    case P9_TREMOVE:
+	fprintf(llogfile, "TREMOVE: (");
+	pprint_int32(pdu, 0, &offset, "fid");
+	break;
+    case P9_RREMOVE:
+	fprintf(llogfile, "RREMOVE: (");
+	break;
+    case P9_TSTAT:
+	fprintf(llogfile, "TSTAT: (");
+	pprint_int32(pdu, 0, &offset, "fid");
+	break;
+    case P9_RSTAT:
+	fprintf(llogfile, "RSTAT: (");
+	offset += 2; /* ignored */
+	pprint_stat(pdu, 1, &offset, "stat");
+	break;
+    case P9_TWSTAT:
+	fprintf(llogfile, "TWSTAT: (");
+	pprint_int32(pdu, 0, &offset, "fid");
+	offset += 2; /* ignored */
+	pprint_stat(pdu, 0, &offset, ", stat");
+	break;
+    case P9_RWSTAT:
+	fprintf(llogfile, "RWSTAT: (");
+	break;
+    default:
+	fprintf(llogfile, "unknown(%d): (", pdu->id);
+	break;
+    }
+
+    fprintf(llogfile, ")\n");
+}
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
new file mode 100644
index 0000000..93402c5
--- /dev/null
+++ b/hw/virtio-9p.c
@@ -0,0 +1,275 @@
+/*
+ * Virtio 9p backend
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "virtio.h"
+#include "pc.h"
+#include "qemu_socket.h"
+#include "virtio-9p.h"
+
+#include <assert.h>
+
+/* from Linux's linux/virtio_9p.h */
+
+/* The ID for virtio console */
+#define VIRTIO_ID_9P	9
+/* Maximum number of virtio channels per partition (1 for now) */
+#define MAX_9P_CHAN	1
+
+#define MAX_REQ		128
+
+#define BUG_ON(cond) assert(!(cond))
+
+typedef struct V9fsFidState V9fsFidState;
+
+typedef struct V9fsString
+{
+    int16_t size;
+    char *data;
+} V9fsString;
+
+typedef struct V9fsQID
+{
+    int8_t type;
+    int32_t version;
+    int64_t path;
+} V9fsQID;
+
+typedef struct V9fsStat
+{
+    int16_t size;
+    int16_t type;
+    int32_t dev;
+    V9fsQID qid;
+    int32_t mode;
+    int32_t atime;
+    int32_t mtime;
+    int64_t length;
+    V9fsString name;
+    V9fsString uid;
+    V9fsString gid;
+    V9fsString muid;
+    /* 9p2000.u */
+    V9fsString extension;
+    int32_t n_uid;
+    int32_t n_gid;
+    int32_t n_muid;
+} V9fsStat;
+
+struct V9fsFidState
+{
+    int32_t fid;
+    V9fsString path;
+    int fd;
+    DIR *dir;
+    uid_t uid;
+    V9fsFidState *next;
+};
+
+typedef struct V9fsState
+{
+    VirtIODevice vdev;
+    VirtQueue *vq;
+    V9fsPDU pdus[MAX_REQ];
+    V9fsPDU *free_pdu;
+    V9fsFidState *fid_list;
+    char *root;
+    uid_t uid;
+} V9fsState;
+
+int dotu = 1;
+int debug_9p_pdu = 1;
+
+extern void pprint_pdu(V9fsPDU *pdu);
+
+static V9fsPDU *alloc_pdu(V9fsState *s)
+{
+    V9fsPDU *pdu = NULL;
+
+    if (s->free_pdu) {
+	pdu = s->free_pdu;
+	s->free_pdu = pdu->next;
+    }
+
+    return pdu;
+}
+
+static void free_pdu(V9fsState *s, V9fsPDU *pdu)
+{
+    if (pdu) {
+	pdu->next = s->free_pdu;
+	s->free_pdu = pdu;
+    }
+}
+
+static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu)
+	pprint_pdu(pdu);
+}
+
+static void v9fs_attach(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu)
+	pprint_pdu(pdu);
+}
+
+static void v9fs_stat(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu)
+	pprint_pdu(pdu);
+}
+
+static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu)
+	pprint_pdu(pdu);
+}
+
+static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu)
+	pprint_pdu(pdu);
+}
+
+static void v9fs_open(V9fsState *s, V9fsPDU *pdu)
+{    if (debug_9p_pdu)
+	pprint_pdu(pdu);
+}
+
+static void v9fs_read(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu)
+	pprint_pdu(pdu);
+}
+
+static void v9fs_write(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu)
+	pprint_pdu(pdu);
+}
+
+static void v9fs_create(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu)
+	pprint_pdu(pdu);
+}
+
+static void v9fs_flush(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu)
+	pprint_pdu(pdu);
+}
+
+static void v9fs_remove(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu)
+	pprint_pdu(pdu);
+}
+
+static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu)
+	pprint_pdu(pdu);
+}
+
+typedef void (pdu_handler_t)(V9fsState *s, V9fsPDU *pdu);
+
+static pdu_handler_t *pdu_handlers[] = {
+    [P9_TVERSION] = v9fs_version,
+    [P9_TATTACH] = v9fs_attach,
+    [P9_TSTAT] = v9fs_stat,
+    [P9_TWALK] = v9fs_walk,
+    [P9_TCLUNK] = v9fs_clunk,
+    [P9_TOPEN] = v9fs_open,
+    [P9_TREAD] = v9fs_read,
+#if 0
+    [P9_TAUTH] = v9fs_auth,
+#endif
+    [P9_TFLUSH] = v9fs_flush,
+    [P9_TCREATE] = v9fs_create,
+    [P9_TWRITE] = v9fs_write,
+    [P9_TWSTAT] = v9fs_wstat,
+    [P9_TREMOVE] = v9fs_remove,
+};
+
+static void submit_pdu(V9fsState *s, V9fsPDU *pdu)
+{
+    pdu_handler_t *handler;
+
+    if (debug_9p_pdu)
+	pprint_pdu(pdu);
+
+    BUG_ON(pdu->id >= ARRAY_SIZE(pdu_handlers));
+
+    handler = pdu_handlers[pdu->id];
+    BUG_ON(handler == NULL);
+
+    handler(s, pdu);
+}
+
+static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
+{
+    V9fsState *s = (V9fsState *)vdev;
+    V9fsPDU *pdu;
+    ssize_t len;
+
+    while ((pdu = alloc_pdu(s)) &&
+	   (len = virtqueue_pop(vq, &pdu->elem)) != 0) {
+	uint8_t *ptr;
+
+	BUG_ON(pdu->elem.out_num == 0 || pdu->elem.in_num == 0);
+	BUG_ON(pdu->elem.out_sg[0].iov_len < 7);
+
+	ptr = pdu->elem.out_sg[0].iov_base;
+
+	memcpy(&pdu->size, ptr, 4);
+	pdu->id = ptr[4];
+	memcpy(&pdu->tag, ptr + 5, 2);
+
+	submit_pdu(s, pdu);
+    }
+
+    free_pdu(s, pdu);
+}
+
+static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features)
+{
+    return features;
+}
+
+VirtIODevice *virtio_9p_init(DeviceState *dev, const char *path)
+{
+    V9fsState *s;
+    int i;
+
+    s = (V9fsState *)virtio_common_init("virtio-9p",
+				     VIRTIO_ID_9P,
+				     0, sizeof(V9fsState));
+
+    /* initialize pdu allocator */
+    s->free_pdu = &s->pdus[0];
+    for (i = 0; i < (MAX_REQ - 1); i++)
+	s->pdus[i].next = &s->pdus[i + 1];
+    s->pdus[i].next = NULL;
+
+    s->vq = virtio_add_queue(&s->vdev, MAX_REQ, handle_9p_output);
+    BUG_ON(s->vq == NULL);
+
+    s->root = strdup("/");
+    BUG_ON(s->root == NULL);
+    s->uid = -1;
+
+    s->vdev.get_features = virtio_9p_get_features;
+
+    return &s->vdev;
+}
diff --git a/hw/virtio-9p.h b/hw/virtio-9p.h
new file mode 100644
index 0000000..3945f81
--- /dev/null
+++ b/hw/virtio-9p.h
@@ -0,0 +1,70 @@
+#ifndef _QEMU_VIRTIO_9P_H
+#define _QEMU_VIRTIO_9P_H
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/time.h>
+#include <utime.h>
+
+enum {
+	P9_TVERSION = 100,
+	P9_RVERSION,
+	P9_TAUTH = 102,
+	P9_RAUTH,
+	P9_TATTACH = 104,
+	P9_RATTACH,
+	P9_TERROR = 106,
+	P9_RERROR,
+	P9_TFLUSH = 108,
+	P9_RFLUSH,
+	P9_TWALK = 110,
+	P9_RWALK,
+	P9_TOPEN = 112,
+	P9_ROPEN,
+	P9_TCREATE = 114,
+	P9_RCREATE,
+	P9_TREAD = 116,
+	P9_RREAD,
+	P9_TWRITE = 118,
+	P9_RWRITE,
+	P9_TCLUNK = 120,
+	P9_RCLUNK,
+	P9_TREMOVE = 122,
+	P9_RREMOVE,
+	P9_TSTAT = 124,
+	P9_RSTAT,
+	P9_TWSTAT = 126,
+	P9_RWSTAT,
+};
+
+
+/* qid.types */
+enum {
+	P9_QTDIR = 0x80,
+	P9_QTAPPEND = 0x40,
+	P9_QTEXCL = 0x20,
+	P9_QTMOUNT = 0x10,
+	P9_QTAUTH = 0x08,
+	P9_QTTMP = 0x04,
+	P9_QTSYMLINK = 0x02,
+	P9_QTLINK = 0x01,
+	P9_QTFILE = 0x00,
+};
+
+#define P9_NOTAG	(u16)(~0)
+#define P9_NOFID	(u32)(~0)
+#define P9_MAXWELEM	16
+
+typedef struct V9fsPDU V9fsPDU;
+
+struct V9fsPDU
+{
+    uint32_t size;
+    uint16_t tag;
+    uint8_t id;
+    VirtQueueElement elem;
+    V9fsPDU *next;
+};
+
+
+#endif
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index bcd40f7..f837376 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -96,6 +96,7 @@ typedef struct {
     BlockConf block;
     NICConf nic;
     uint32_t host_features;
+    char *share_path;
     /* Max. number of ports we can have for a the virtio-serial device */
     uint32_t max_virtserial_ports;
 } VirtIOPCIProxy;
@@ -551,6 +552,21 @@ static int virtio_balloon_init_pci(PCIDevice *pci_dev)
     return 0;
 }
 
+static int virtio_9p_init_pci(PCIDevice *pci_dev)
+{
+    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+    VirtIODevice *vdev;
+
+    vdev = virtio_9p_init(&pci_dev->qdev, proxy->share_path);
+    virtio_init_pci(proxy, vdev,
+		    PCI_VENDOR_ID_REDHAT_QUMRANET,
+		    0x1009,
+		    0x2,
+		    0x00);
+
+    return 0;
+}
+
 static PCIDeviceInfo virtio_info[] = {
     {
         .qdev.name = "virtio-blk-pci",
@@ -604,6 +620,15 @@ static PCIDeviceInfo virtio_info[] = {
         },
         .qdev.reset = virtio_pci_reset,
     },{
+        .qdev.name = "virtio-9p-pci",
+        .qdev.size = sizeof(VirtIOPCIProxy),
+        .init      = virtio_9p_init_pci,
+        .qdev.props = (Property[]) {
+            DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+            DEFINE_PROP_STRING("share_path", VirtIOPCIProxy, share_path),
+            DEFINE_PROP_END_OF_LIST(),
+        },
+    },{
         /* end of list */
     }
 };
diff --git a/hw/virtio.h b/hw/virtio.h
index 3baa2a3..4032a96 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -174,6 +174,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf);
 VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf);
 VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports);
 VirtIODevice *virtio_balloon_init(DeviceState *dev);
+VirtIODevice *virtio_9p_init(DeviceState *dev, const char *path);
 
 void virtio_net_exit(VirtIODevice *vdev);
 
-- 
1.6.5.2

  parent reply	other threads:[~2010-03-03 19:01 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-03-03 19:00 [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough Anthony Liguori
2010-03-03 19:00 ` Anthony Liguori
2010-03-03 19:00 ` Anthony Liguori [this message]
2010-03-03 19:00 ` [Qemu-devel] [PATCH 02/17] vrtio-9p: Implement P9_TVERSION for 9P Anthony Liguori
2010-03-04  9:23   ` [Qemu-devel] " Michael S. Tsirkin
2010-03-04 14:30     ` Aneesh Kumar K. V
2010-03-03 19:01 ` [Qemu-devel] [PATCH 03/17] virtio-9p: Implement P9_TATTACH Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 04/17] virtio-9p: Implement P9_TSTAT Anthony Liguori
2010-03-03 20:35   ` malc
2010-03-04 14:15     ` Aneesh Kumar K. V
2010-03-09  2:08       ` jvrao
2010-03-09 12:30         ` Paul Brook
2010-03-09 14:35           ` Aneesh Kumar K. V
2010-03-09 15:59           ` jvrao
2010-03-11 16:37             ` Paul Brook
2010-03-03 19:01 ` [Qemu-devel] [PATCH 05/17] virtio-9p: Implement P9_TWALK Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 06/17] virtio-9p: Implement P9_TOPEN Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 07/17] virtio-9p: Implement P9_TREAD Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 08/17] virtio-9p: Implement P9_TCLUNK Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 09/17] virtio-9p: Implement P9_TWRITE Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 10/17] virtio-9p: Implement P9_TCREATE Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 11/17] virtio-9p: Implement P9_TWSTAT Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 12/17] virtio-9p: Implement P9_TREMOVE Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 13/17] virtio-9p: Implement P9_TFLUSH Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 14/17] virtio-9p: Add multiple mount point support Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 15/17] virtio-9p: Use little endian format on virtio Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 16/17] virtio-9p: Add support for hardlink Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 17/17] Implement sync support in 9p server Anthony Liguori

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1267642874-15001-3-git-send-email-aliguori@us.ibm.com \
    --to=aliguori@us.ibm.com \
    --cc=aneesh.kumar@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.