From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1O7DJN-0001Yx-NR for qemu-devel@nongnu.org; Wed, 28 Apr 2010 15:52:45 -0400 Received: from [140.186.70.92] (port=56272 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O7DJL-0001VZ-4f for qemu-devel@nongnu.org; Wed, 28 Apr 2010 15:52:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1O7DJG-0002oA-Fs for qemu-devel@nongnu.org; Wed, 28 Apr 2010 15:52:43 -0400 Received: from e2.ny.us.ibm.com ([32.97.182.142]:43870) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1O7DJF-0002nh-Ba for qemu-devel@nongnu.org; Wed, 28 Apr 2010 15:52:38 -0400 Received: from d01relay05.pok.ibm.com (d01relay05.pok.ibm.com [9.56.227.237]) by e2.ny.us.ibm.com (8.14.3/8.13.1) with ESMTP id o3SJewRT027689 for ; Wed, 28 Apr 2010 15:40:58 -0400 Received: from d03av05.boulder.ibm.com (d03av05.boulder.ibm.com [9.17.195.85]) by d01relay05.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id o3SJqXfI174854 for ; Wed, 28 Apr 2010 15:52:33 -0400 Received: from d03av05.boulder.ibm.com (loopback [127.0.0.1]) by d03av05.boulder.ibm.com (8.14.3/8.13.1/NCO v10.0 AVout) with ESMTP id o3SJqWi2016011 for ; Wed, 28 Apr 2010 13:52:32 -0600 Message-ID: <4BD891FF.3060804@linux.vnet.ibm.com> Date: Wed, 28 Apr 2010 14:52:31 -0500 From: Anthony Liguori MIME-Version: 1.0 Subject: Re: [Qemu-devel] [PATCH -V5 02/21] virtio-9p: Add a virtio 9p device to qemu References: <1271340671-19558-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com> <1271340671-19558-3-git-send-email-aneesh.kumar@linux.vnet.ibm.com> In-Reply-To: <1271340671-19558-3-git-send-email-aneesh.kumar@linux.vnet.ibm.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: "Aneesh Kumar K.V" Cc: ericvh@gmail.com, aliguori@us.ibm.com, qemu-devel@nongnu.org On 04/15/2010 09:10 AM, Aneesh Kumar K.V wrote: > From: Anthony Liguori > > This patch doesn't implement the 9p protocol handling > code. It adds a simple device which dump the protocol data. > > [jvrao@linux.vnet.ibm.com: Little-Endian to host format conversion] > [aneesh.kumar@linux.vnet.ibm.com: Multiple-mounts support] > > Signed-off-by: Anthony Liguori > Signed-off-by: Aneesh Kumar K.V > --- > Makefile.target | 1 + > fsdev/qemu-fsdev.c | 2 +- > fsdev/qemu-fsdev.h | 1 + > hw/9p.h | 26 +++ > hw/virtio-9p-debug.c | 484 ++++++++++++++++++++++++++++++++++++++++++++++++++ > hw/virtio-9p-local.c | 17 ++ > hw/virtio-9p.c | 329 ++++++++++++++++++++++++++++++++++ > hw/virtio-9p.h | 166 +++++++++++++++++ > hw/virtio-pci.c | 32 ++++ > hw/virtio.h | 7 + > 10 files changed, 1064 insertions(+), 1 deletions(-) > create mode 100644 hw/9p.h > create mode 100644 hw/virtio-9p-debug.c > create mode 100644 hw/virtio-9p-local.c > create mode 100644 hw/virtio-9p.c > create mode 100644 hw/virtio-9p.h > > diff --git a/Makefile.target b/Makefile.target > index 95c9d23..5550047 100644 > --- a/Makefile.target > +++ b/Makefile.target > @@ -169,6 +169,7 @@ obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o > obj-y += event_notifier.o > obj-y += vhost_net.o > obj-$(CONFIG_VHOST_NET) += vhost.o > +obj-$(CONFIG_LINUX_VIRTFS) += virtio-9p.o virtio-9p-debug.o virtio-9p-local.o > obj-y += rwhandler.o > obj-$(CONFIG_KVM) += kvm.o kvm-all.o > LIBS+=-lz > diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c > index 48bbfd9..813e1f7 100644 > --- a/fsdev/qemu-fsdev.c > +++ b/fsdev/qemu-fsdev.c > @@ -21,7 +21,7 @@ static QTAILQ_HEAD(FsTypeEntry_head, FsTypeListEntry) fstype_entries = > QTAILQ_HEAD_INITIALIZER(fstype_entries); > > static FsTypeTable FsTypes[] = { > - { .name = "local", .ops = NULL}, > + { .name = "local", .ops =&local_ops}, > }; > > int qemu_fsdev_add(QemuOpts *opts) > diff --git a/fsdev/qemu-fsdev.h b/fsdev/qemu-fsdev.h > index 7fa4f60..b50fbe0 100644 > --- a/fsdev/qemu-fsdev.h > +++ b/fsdev/qemu-fsdev.h > @@ -50,4 +50,5 @@ typedef struct FsTypeListEntry { > > extern int qemu_fsdev_add(QemuOpts *opts); > extern FsTypeEntry *get_fsdev_fsentry(char *id); > +extern FileOperations local_ops; > #endif > diff --git a/hw/9p.h b/hw/9p.h > new file mode 100644 > index 0000000..5fdd770 > --- /dev/null > +++ b/hw/9p.h > @@ -0,0 +1,26 @@ > +/* > + * Virtio 9p > + * > + * Copyright IBM, Corp. 2010 > + * > + * Authors: > + * Aneesh Kumar K.V > + * > + * This work is licensed under the terms of the GNU GPL, version 2. See > + * the COPYING file in the top-level directory. > + * > + */ > + > +#ifndef QEMU_9P_H > +#define QEMU_9P_H > + > +#include > + > +typedef struct V9fsConf > +{ > + /* tag name for the device */ > + char *tag; > + char *fsdev_id; > +} V9fsConf; > + > +#endif > diff --git a/hw/virtio-9p-debug.c b/hw/virtio-9p-debug.c > new file mode 100644 > index 0000000..2fb2673 > --- /dev/null > +++ b/hw/virtio-9p-debug.c > @@ -0,0 +1,484 @@ > +/* > + * Virtio 9p PDU debug > + * > + * Copyright IBM, Corp. 2010 > + * > + * Authors: > + * Anthony Liguori > + * > + * 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 "virtio-9p-debug.h" > + > +#define BUG_ON(cond) assert(!(cond)) > + > +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 int get_sg_count(V9fsPDU *pdu, int rx) > +{ > + if (rx) { > + return pdu->elem.in_num; > + } > + return pdu->elem.out_num; > + > +} > + > +static void pprint_int8(V9fsPDU *pdu, int rx, size_t *offsetp, > + const char *name) > +{ > + size_t copied; > + int count = get_sg_count(pdu, rx); > + size_t offset = *offsetp; > + struct iovec *sg = get_sg(pdu, rx); > + int8_t value; > + > + copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value)); > + > + BUG_ON(copied != 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) > +{ > + size_t copied; > + int count = get_sg_count(pdu, rx); > + struct iovec *sg = get_sg(pdu, rx); > + size_t offset = *offsetp; > + int16_t value; > + > + > + copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value)); > + > + BUG_ON(copied != 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) > +{ > + size_t copied; > + int count = get_sg_count(pdu, rx); > + struct iovec *sg = get_sg(pdu, rx); > + size_t offset = *offsetp; > + int32_t value; > + > + > + copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value)); > + > + BUG_ON(copied != 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) > +{ > + size_t copied; > + int count = get_sg_count(pdu, rx); > + struct iovec *sg = get_sg(pdu, rx); > + size_t offset = *offsetp; > + int64_t value; > + > + > + copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value)); > + > + BUG_ON(copied != 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) > +{ > + int sg_count = get_sg_count(pdu, rx); > + struct iovec *sg = get_sg(pdu, rx); > + size_t offset = *offsetp; > + uint16_t tmp_size, size; > + size_t result; > + size_t copied = 0; > + int i = 0; > + > + /* get the size */ > + copied = do_pdu_unpack(&tmp_size, sg, sg_count, offset, sizeof(tmp_size)); > + BUG_ON(copied != sizeof(tmp_size)); > + size = le16_to_cpupu(&tmp_size); > + offset += copied; > + > + fprintf(llogfile, "%s=", name); > + for (i = 0; size&& i< sg_count; i++) { > + size_t len; > + if (offset>= sg[i].iov_len) { > + /* skip this sg */ > + offset -= sg[i].iov_len; > + continue; > + } else { > + len = MIN(sg[i].iov_len - offset, size); > + result = fwrite(sg[i].iov_base + offset, 1, len, llogfile); > + BUG_ON(result != len); > + size -= len; > + copied += len; > + if (size) { > + offset = 0; > + continue; > + } > + } > + } > + *offsetp += copied; > +} > + > +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) > +{ > + int sg_count = get_sg_count(pdu, rx); > + struct iovec *sg = get_sg(pdu, rx); > + size_t offset = *offsetp; > + uint16_t tmp_count, count, i; > + size_t copied = 0; > + > + fprintf(llogfile, "%s={", name); > + > + /* Get the count */ > + copied = do_pdu_unpack(&tmp_count, sg, sg_count, offset, sizeof(tmp_count)); > + BUG_ON(copied != sizeof(tmp_count)); > + count = le16_to_cpupu(&tmp_count); > + offset += copied; > + > + 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) > +{ > + int sg_count = get_sg_count(pdu, rx); > + struct iovec *sg = get_sg(pdu, rx); > + size_t offset = *offsetp; > + uint16_t tmp_count, count, i; > + size_t copied = 0; > + > + fprintf(llogfile, "%s={", name); > + > + copied = do_pdu_unpack(&tmp_count, sg, sg_count, offset, sizeof(tmp_count)); > + BUG_ON(copied != sizeof(tmp_count)); > + count = le16_to_cpupu(&tmp_count); > + offset += copied; > + > + 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) > +{ > + 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-local.c b/hw/virtio-9p-local.c > new file mode 100644 > index 0000000..379af60 > --- /dev/null > +++ b/hw/virtio-9p-local.c > @@ -0,0 +1,17 @@ > +/* > + * Virtio 9p Posix callback > + * > + * Copyright IBM, Corp. 2010 > + * > + * Authors: > + * Anthony Liguori > + * > + * 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 "virtio-9p.h" > + > +FileOperations local_ops = { > +}; > diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c > new file mode 100644 > index 0000000..0685c2d > --- /dev/null > +++ b/hw/virtio-9p.c > @@ -0,0 +1,329 @@ > +/* > + * Virtio 9p backend > + * > + * Copyright IBM, Corp. 2010 > + * > + * Authors: > + * Anthony Liguori > + * > + * 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 "fsdev/qemu-fsdev.h" > +#include "virtio-9p-debug.h" > + > +int dotu = 1; > +int debug_9p_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; > + } > +} > + > +size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count, > + size_t offset, size_t size, int pack) > +{ > + int i = 0; > + size_t copied = 0; > + > + for (i = 0; size&& i< sg_count; i++) { > + size_t len; > + if (offset>= sg[i].iov_len) { > + /* skip this sg */ > + offset -= sg[i].iov_len; > + continue; > + } else { > + len = MIN(sg[i].iov_len - offset, size); > + if (pack) { > + memcpy(sg[i].iov_base + offset, addr, len); > + } else { > + memcpy(addr, sg[i].iov_base + offset, len); > + } > + size -= len; > + copied += len; > + addr += len; > + if (size) { > + offset = 0; > + continue; > + } > + } > + } > + > + return copied; > +} > + > +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) > +{ > + features |= 1<< VIRTIO_9P_MOUNT_TAG; > + return features; > +} > + > +static V9fsState *to_virtio_9p(VirtIODevice *vdev) > +{ > + return (V9fsState *)vdev; > +} > + > +static void virtio_9p_set_config(VirtIODevice *vdev, const uint8_t *config) > +{ > + uint16_t tag_len; > + struct virtio_9p_config *cfg; > + V9fsState *s = to_virtio_9p(vdev); > + > + memcpy(&tag_len, config, sizeof(tag_len)); > + cfg = qemu_mallocz(sizeof(struct virtio_9p_config) + tag_len); > + > + memcpy(cfg, config, s->config_size); > + memcpy(&s->tag_len,&cfg->tag_len, sizeof(uint16_t)); > + /* free the old config details */ > + qemu_free(s->tag); > + s->tag = qemu_malloc(tag_len); > + memcpy(s->tag, cfg->tag, cfg->tag_len); > Should the guest really be able to set the config? I think these values should be read-only. > + qemu_free(cfg); > +} > + > +static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config) > +{ > + struct virtio_9p_config *cfg; > + V9fsState *s = to_virtio_9p(vdev); > + > + cfg = qemu_mallocz(sizeof(struct virtio_9p_config) + > + s->tag_len); > + memcpy(&cfg->tag_len,&s->tag_len, sizeof(uint16_t)); > This is incorrect. Endianness conversion is needed to convert from the host's endianness to the guest's endianness. Note the uses of st[lwq]_raw() in virtio-blk.c. > + memcpy(cfg->tag, s->tag, s->tag_len); > + memcpy(config, cfg, s->config_size); > + qemu_free(cfg); > +} > + > +VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf) > + { > + V9fsState *s; > + int i, len; > + struct stat stat; > + FsTypeEntry *fse; > + > + > + s = (V9fsState *)virtio_common_init("virtio-9p", > + VIRTIO_ID_9P, > + sizeof(struct virtio_9p_config)+ > + MAX_TAG_LEN, > + 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; > Shouldn't open code this link list. Regards, Anthony Liguori