qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH -V5 02/21] virtio-9p: Add a virtio 9p device to


From: Anthony Liguori
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
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.5) Gecko/20091209 Fedora/3.0-4.fc12 Lightning/1.0pre Thunderbird/3.0

On 04/15/2010 09:10 AM, Aneesh Kumar K.V wrote:
From: Anthony Liguori<address@hidden>

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

address@hidden: Little-Endian to host format conversion]
address@hidden: Multiple-mounts support]

Signed-off-by: Anthony Liguori<address@hidden>
Signed-off-by: Aneesh Kumar K.V<address@hidden>
---
  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<address@hidden>
+ *
+ * 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<address@hidden>
+ *
+ * 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<address@hidden>
+ *
+ * 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<address@hidden>
+ *
+ * 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]