From: Anthony Liguori <aliguori@linux.vnet.ibm.com>
To: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
Cc: ericvh@gmail.com, aliguori@us.ibm.com, qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH -V5 02/21] virtio-9p: Add a virtio 9p device to qemu
Date: Wed, 28 Apr 2010 14:52:31 -0500 [thread overview]
Message-ID: <4BD891FF.3060804@linux.vnet.ibm.com> (raw)
In-Reply-To: <1271340671-19558-3-git-send-email-aneesh.kumar@linux.vnet.ibm.com>
On 04/15/2010 09:10 AM, Aneesh Kumar K.V wrote:
> From: Anthony Liguori<aliguori@us.ibm.com>
>
> 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<aliguori@us.ibm.com>
> Signed-off-by: Aneesh Kumar K.V<aneesh.kumar@linux.vnet.ibm.com>
> ---
> 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<aneesh.kumar@linux.vnet.ibm.com>
> + *
> + * 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<stdbool.h>
> +
> +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<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 "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<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 "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<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 "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
next prev parent reply other threads:[~2010-04-28 19:52 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-04-15 14:10 [Qemu-devel] [PATCH -V5 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
2010-04-15 14:10 ` [Qemu-devel] [PATCH -V5 01/21] virtio-9p: Create a commandline option -fsdev Aneesh Kumar K.V
2010-04-28 19:53 ` Anthony Liguori
2010-04-15 14:10 ` [Qemu-devel] [PATCH -V5 02/21] virtio-9p: Add a virtio 9p device to qemu Aneesh Kumar K.V
2010-04-28 19:52 ` Anthony Liguori [this message]
2010-04-15 14:10 ` [Qemu-devel] [PATCH -V5 03/21] virtio-9p: pdu processing support Aneesh Kumar K.V
2010-04-15 14:10 ` [Qemu-devel] [PATCH -V5 04/21] virtio-9p: Add string manipulation support Aneesh Kumar K.V
2010-04-15 14:10 ` [Qemu-devel] [PATCH -V5 05/21] virtio-9p: Add minimal set of FileOperations Aneesh Kumar K.V
2010-04-15 14:10 ` [Qemu-devel] [PATCH -V5 06/21] virtio-9p: Add fid and qid management support Aneesh Kumar K.V
2010-04-15 14:10 ` [Qemu-devel] [PATCH -V5 07/21] virtio-9p: Add stat and mode related helper functions Aneesh Kumar K.V
2010-04-15 14:10 ` [Qemu-devel] [PATCH -V5 08/21] virtio-9p: Add sg " Aneesh Kumar K.V
2010-04-15 14:10 ` [Qemu-devel] [PATCH -V5 09/21] virtio-9p: Add P9_TVERSION support Aneesh Kumar K.V
2010-04-15 14:11 ` [Qemu-devel] [PATCH -V5 10/21] virtio-9p: Add P9_TATTACH support Aneesh Kumar K.V
2010-04-15 14:11 ` [Qemu-devel] [PATCH -V5 11/21] virtio-9p: Add P9_TSTAT support Aneesh Kumar K.V
2010-04-15 14:11 ` [Qemu-devel] [PATCH -V5 12/21] virtio-9p: Add P9_TWALK support Aneesh Kumar K.V
2010-04-15 14:11 ` [Qemu-devel] [PATCH -V5 13/21] virtio-9p: Add P9_TOPEN support Aneesh Kumar K.V
2010-04-15 14:11 ` [Qemu-devel] [PATCH -V5 14/21] virtio-9p: Add P9_TREAD support Aneesh Kumar K.V
2010-04-15 14:11 ` [Qemu-devel] [PATCH -V5 15/21] virtio-9p: Add P9_TCLUNK support Aneesh Kumar K.V
2010-04-15 14:11 ` [Qemu-devel] [PATCH -V5 16/21] virtio-9p: Add P9_TWRITE support Aneesh Kumar K.V
2010-04-15 14:11 ` [Qemu-devel] [PATCH -V5 17/21] virtio-9p: Add P9_TCREATE support Aneesh Kumar K.V
2010-04-15 14:11 ` [Qemu-devel] [PATCH -V5 18/21] virtio-9p: Add P9_TWSTAT support Aneesh Kumar K.V
2010-04-15 14:11 ` [Qemu-devel] [PATCH -V5 19/21] virtio-9p: Add P9_TREMOVE support Aneesh Kumar K.V
2010-04-15 14:11 ` [Qemu-devel] [PATCH -V5 20/21] virtio-9p: Add P9_TFLUSH support Aneesh Kumar K.V
2010-04-15 14:11 ` [Qemu-devel] [PATCH -V5 21/21] virtio-9p: Create a syntactic shortcut for the file-system pass-thru Aneesh Kumar K.V
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=4BD891FF.3060804@linux.vnet.ibm.com \
--to=aliguori@linux.vnet.ibm.com \
--cc=aliguori@us.ibm.com \
--cc=aneesh.kumar@linux.vnet.ibm.com \
--cc=ericvh@gmail.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.