All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough
@ 2010-03-25 16:43 Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 01/32] vitio-9p: Add a virtio 9p device to qemu Aneesh Kumar K.V
                   ` (31 more replies)
  0 siblings, 32 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori

This patch series adds a paravirtual file system passthrough mechanism to QEMU
based on the 9P protocol. With the current implementation, all I/O is 
implemented in the VCPU thread.  We've modified the protocol handlers so that
we can support dispatch I/O in a thread pool. The actual thread pool implementation
will be posted later

This patch set should work with any recent Linux kernel as virtio-9p has been
supported for a few kernel releases now. Export dir is specified using the below
Qemu option.

-fsdev fstype,id=ID,path=path/to/share \
          -device virtio-9p-pci,fsdev=ID,mount_tag=tag \
or
 
-virtfs fstype,path=path/to/share,mount_tag=tag

Only supported fstype currently is "local". mount_tag is used to identify
the mount point in the kernel. This will be available in Linux
kernel via /sys/devices/virtio-pci/virtio1/mount_tag file.

Changes from V2:
1) Added new method for specifying export dir. This new method should be more flexible.
2) rebased to qemu master bedd2912c83b1a87a6bfe3f59a892fd65cda7084

Changes from V1:
1) fsstress test suite runs successfully with the patches. That should indicate 
   patches are stable enough to be merged.
2) Added proper error handling to all posix_* calls.
3) Fixed code to follow Qemu coding style.
4) Other bug fixes most of which are folded back into the original patches
5) rebased to qemu master 0aef4261ac0ec9089ade0e3a92f986cb4ba7317e

-aneesh

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 01/32] vitio-9p: Add a virtio 9p device to qemu
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 21:04   ` Anthony Liguori
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 02/32] vrtio-9p: Implement P9_TVERSION for 9P Aneesh Kumar K.V
                   ` (30 subsequent siblings)
  31 siblings, 1 reply; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V

From: Anthony Liguori <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 eb4d010..178ddce 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -166,6 +166,7 @@ obj-y += qemu-timer.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-serial-bus.o
+obj-y += virtio-9p.o virtio-9p-debug.o
 obj-y += rwhandler.o
 obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 LIBS+=-lz
diff --git a/hw/virtio-9p-debug.c b/hw/virtio-9p-debug.c
new file mode 100644
index 0000000..9230659
--- /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..115c93b
--- /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..2aa67d0
--- /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 6eb19cd..85879fb 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;
@@ -552,6 +553,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",
@@ -606,6 +622,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.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 02/32] vrtio-9p: Implement P9_TVERSION for 9P
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 01/32] vitio-9p: Add a virtio 9p device to qemu Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 03/32] virtio-9p: Implement P9_TATTACH Aneesh Kumar K.V
                   ` (29 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V

From: Anthony Liguori <aliguori@us.ibm.com>

[kiran@linux.vnet.ibm.com: malloc to qemu_malloc coversion]

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p.c |  263 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 261 insertions(+), 2 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 115c93b..53b3d78 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -111,10 +111,269 @@ static void free_pdu(V9fsState *s, V9fsPDU *pdu)
     }
 }
 
+static void v9fs_string_free(V9fsString *str)
+{
+    free(str->data);
+    str->data = NULL;
+    str->size = 0;
+}
+
+static size_t pdu_unpack(void *dst, V9fsPDU *pdu, size_t offset, size_t size)
+{
+    struct iovec *sg = pdu->elem.out_sg;
+    BUG_ON((offset + size) > sg[0].iov_len);
+    memcpy(dst, sg[0].iov_base + offset, size);
+    return size;
+}
+
+/* FIXME i can do this with less variables */
+static size_t pdu_pack(V9fsPDU *pdu, size_t offset, const void *src, size_t size)
+{
+    struct iovec *sg = pdu->elem.in_sg;
+    size_t off = 0;
+    size_t copied = 0;
+    int i = 0;
+
+    for (i = 0; size && i < pdu->elem.in_num; i++) {
+        size_t len;
+
+        if (offset >= off && offset < (off + sg[i].iov_len)) {
+            len = MIN(sg[i].iov_len - (offset - off), size);
+            memcpy(sg[i].iov_base + (offset - off), src, len);
+            size -= len;
+            offset += len;
+            off = offset;
+            copied += len;
+            src += len;
+        } else {
+            off += sg[i].iov_len;
+        }
+    }
+
+    return copied;
+}
+
+static int pdu_copy_sg(V9fsPDU *pdu, size_t offset, int rx, struct iovec *sg)
+{
+    size_t pos = 0;
+    int i, j;
+    struct iovec *src_sg;
+    unsigned int num;
+
+    if (rx) {
+        src_sg = pdu->elem.in_sg;
+        num = pdu->elem.in_num;
+    } else {
+        src_sg = pdu->elem.out_sg;
+        num = pdu->elem.out_num;
+    }
+
+    j = 0;
+    for (i = 0; i < num; i++) {
+        if (offset <= pos) {
+            sg[j].iov_base = src_sg[i].iov_base;
+            sg[j].iov_len = src_sg[i].iov_len;
+            j++;
+        } else if (offset < (src_sg[i].iov_len + pos)) {
+            sg[j].iov_base = src_sg[i].iov_base;
+            sg[j].iov_len = src_sg[i].iov_len;
+            sg[j].iov_base += (offset - pos);
+            sg[j].iov_len -= (offset - pos);
+            j++;
+        }
+        pos += src_sg[i].iov_len;
+    }
+
+    return j;
+}
+
+static size_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
+{
+    size_t old_offset = offset;
+    va_list ap;
+    int i;
+
+    va_start(ap, fmt);
+    for (i = 0; fmt[i]; i++) {
+	switch (fmt[i]) {
+	case 'b': {
+	    int8_t *valp = va_arg(ap, int8_t *);
+	    offset += pdu_unpack(valp, pdu, offset, sizeof(*valp));
+	    break;
+	}
+	case 'w': {
+	    int16_t *valp = va_arg(ap, int16_t *);
+	    offset += pdu_unpack(valp, pdu, offset, sizeof(*valp));
+	    break;
+	}
+	case 'd': {
+	    int32_t *valp = va_arg(ap, int32_t *);
+	    offset += pdu_unpack(valp, pdu, offset, sizeof(*valp));
+	    break;
+	}
+	case 'q': {
+	    int64_t *valp = va_arg(ap, int64_t *);
+	    offset += pdu_unpack(valp, pdu, offset, sizeof(*valp));
+	    break;
+	}
+	case 'v': {
+	    struct iovec *iov = va_arg(ap, struct iovec *);
+	    int *iovcnt = va_arg(ap, int *);
+	    *iovcnt = pdu_copy_sg(pdu, offset, 0, iov);
+	    break;
+	}
+	case 's': {
+	    V9fsString *str = va_arg(ap, V9fsString *);
+	    offset += pdu_unmarshal(pdu, offset, "w", &str->size);
+	    /* FIXME: sanity check str->size */
+	    str->data = qemu_malloc(str->size + 1);
+	    offset += pdu_unpack(str->data, pdu, offset, str->size);
+	    str->data[str->size] = 0;
+	    break;
+	}
+	case 'Q': {
+	    V9fsQID *qidp = va_arg(ap, V9fsQID *);
+	    offset += pdu_unmarshal(pdu, offset, "bdq",
+				    &qidp->type, &qidp->version, &qidp->path);
+	    break;
+	}
+	case 'S': {
+	    V9fsStat *statp = va_arg(ap, V9fsStat *);
+	    offset += pdu_unmarshal(pdu, offset, "wwdQdddqsssssddd",
+				    &statp->size, &statp->type, &statp->dev,
+				    &statp->qid, &statp->mode, &statp->atime,
+				    &statp->mtime, &statp->length,
+				    &statp->name, &statp->uid, &statp->gid,
+				    &statp->muid, &statp->extension,
+				    &statp->n_uid, &statp->n_gid,
+				    &statp->n_muid);
+	    break;
+	}
+	default:
+	    break;
+	}
+    }
+
+    va_end(ap);
+
+    return offset - old_offset;
+}
+
+static size_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
+{
+    size_t old_offset = offset;
+    va_list ap;
+    int i;
+
+    va_start(ap, fmt);
+    for (i = 0; fmt[i]; i++) {
+	switch (fmt[i]) {
+	case 'b': {
+	    int8_t val = va_arg(ap, int);
+	    offset += pdu_pack(pdu, offset, &val, sizeof(val));
+	    break;
+	}
+	case 'w': {
+	    int16_t val = va_arg(ap, int);
+	    offset += pdu_pack(pdu, offset, &val, sizeof(val));
+	    break;
+	}
+	case 'd': {
+	    int32_t val = va_arg(ap, int);
+	    offset += pdu_pack(pdu, offset, &val, sizeof(val));
+	    break;
+	}
+	case 'q': {
+	    int64_t val = va_arg(ap, int64_t);
+	    offset += pdu_pack(pdu, offset, &val, sizeof(val));
+	    break;
+	}
+	case 'v': {
+	    struct iovec *iov = va_arg(ap, struct iovec *);
+	    int *iovcnt = va_arg(ap, int *);
+	    *iovcnt = pdu_copy_sg(pdu, offset, 1, iov);
+	    break;
+	}
+	case 's': {
+	    V9fsString *str = va_arg(ap, V9fsString *);
+	    offset += pdu_marshal(pdu, offset, "w", str->size);
+	    offset += pdu_pack(pdu, offset, str->data, str->size);
+	    break;
+	}
+	case 'Q': {
+	    V9fsQID *qidp = va_arg(ap, V9fsQID *);
+	    offset += pdu_marshal(pdu, offset, "bdq",
+				  qidp->type, qidp->version, qidp->path);
+	    break;
+	}
+	case 'S': {
+	    V9fsStat *statp = va_arg(ap, V9fsStat *);
+	    offset += pdu_marshal(pdu, offset, "wwdQdddqsssssddd",
+				  statp->size, statp->type, statp->dev,
+				  &statp->qid, statp->mode, statp->atime,
+				  statp->mtime, statp->length, &statp->name,
+				  &statp->uid, &statp->gid, &statp->muid,
+				  &statp->extension, statp->n_uid,
+				  statp->n_gid, statp->n_muid);
+	    break;
+	}
+	default:
+	    break;
+	}
+    }
+    va_end(ap);
+
+    return offset - old_offset;
+}
+
+static void complete_pdu(V9fsState *s, V9fsPDU *pdu, ssize_t len)
+{
+    int8_t id = pdu->id + 1; /* Response */
+
+    if (len < 0) {
+        V9fsString str;
+        int err = -len;
+
+        str.data = strerror(err);
+        str.size = strlen(str.data);
+
+        len = 7;
+        len += pdu_marshal(pdu, len, "s", &str);
+        if (dotu)
+            len += pdu_marshal(pdu, len, "d", err);
+
+        id = P9_RERROR;
+    }
+
+    /* fill out the header */
+    pdu_marshal(pdu, 0, "dbw", (int32_t)len, id, pdu->tag);
+
+    /* keep these in sync */
+    pdu->size = len;
+    pdu->id = id;
+
+    /* push onto queue and notify */
+    virtqueue_push(s->vq, &pdu->elem, len);
+
+    /* FIXME: we should batch these completions */
+    virtio_notify(&s->vdev, s->vq);
+
+    free_pdu(s, pdu);
+}
+
 static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu)
-        pprint_pdu(pdu);
+    int32_t msize;
+    V9fsString version;
+    size_t offset = 7;
+
+    pdu_unmarshal(pdu, offset, "ds", &msize, &version);
+    BUG_ON(strcmp(version.data, "9P2000.u") != 0);
+
+    offset += pdu_marshal(pdu, offset, "ds", msize, &version);
+    complete_pdu(s, pdu, offset);
+
+    v9fs_string_free(&version);
 }
 
 static void v9fs_attach(V9fsState *s, V9fsPDU *pdu)
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 03/32] virtio-9p: Implement P9_TATTACH
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 01/32] vitio-9p: Add a virtio 9p device to qemu Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 02/32] vrtio-9p: Implement P9_TVERSION for 9P Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 04/32] virtio-9p: Implement P9_TSTAT Aneesh Kumar K.V
                   ` (28 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V

From: Anthony Liguori <aliguori@us.ibm.com>

[jvrao@linux.vnet.ibm.com: Added qemu_vasprintf]

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 Makefile.target      |    2 +-
 hw/virtio-9p-local.c |   84 +++++++++++++++++++++++++++
 hw/virtio-9p.c       |  155 +++++++++++++++++++++++++++++++++++++++++++++++---
 hw/virtio-9p.h       |   33 +++++++++++
 qemu-common.h        |    1 +
 qemu-malloc.c        |    5 ++
 6 files changed, 270 insertions(+), 10 deletions(-)
 create mode 100644 hw/virtio-9p-local.c

diff --git a/Makefile.target b/Makefile.target
index 178ddce..960bfe2 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -166,7 +166,7 @@ obj-y += qemu-timer.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-serial-bus.o
-obj-y += virtio-9p.o virtio-9p-debug.o
+obj-y += 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/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
new file mode 100644
index 0000000..1d2523b
--- /dev/null
+++ b/hw/virtio-9p-local.c
@@ -0,0 +1,84 @@
+/*
+ * 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 "pc.h"
+#include "qemu_socket.h"
+#include "virtio-9p.h"
+#include <sys/uio.h>
+#include <arpa/inet.h>
+#include <assert.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+static const char *base_path;
+
+static const char *rpath(const char *path)
+{
+    /* FIXME: so wrong... */
+    static char buffer[4096];
+    snprintf(buffer, sizeof(buffer), "%s/%s", base_path, path);
+    return buffer;
+}
+
+static int local_lstat(void *opaque, const char *path, struct stat *stbuf)
+{
+    return lstat(rpath(path), stbuf);
+}
+
+static int local_setuid(void *opaque, uid_t uid)
+{
+    struct passwd *pw;
+    gid_t groups[33];
+    int ngroups;
+    static uid_t cur_uid = -1;
+
+    if (cur_uid == uid)
+        return 0;
+
+    if (setreuid(0, 0))
+        return -1;
+
+    pw = getpwuid(uid);
+    if (pw == NULL)
+        return -1;
+
+    ngroups = 33;
+    if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups) == -1)
+        return -1;
+
+    if (setgroups(ngroups, groups))
+        return -1;
+
+    if (setregid(-1, pw->pw_gid))
+        return -1;
+
+    if (setreuid(-1, uid))
+        return -1;
+
+    cur_uid = uid;
+
+    return 0;
+}
+
+static V9fsPosixFileOperations ops = {
+    .lstat = local_lstat,
+    .setuid = local_setuid,
+};
+
+V9fsPosixFileOperations *virtio_9p_init_local(const char *path)
+{
+    base_path = path;
+    return &ops;
+}
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 53b3d78..fdff589 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -82,6 +82,7 @@ typedef struct V9fsState
     V9fsPDU pdus[MAX_REQ];
     V9fsPDU *free_pdu;
     V9fsFidState *fid_list;
+    V9fsPosixFileOperations *ops;
     char *root;
     uid_t uid;
 } V9fsState;
@@ -91,6 +92,123 @@ int debug_9p_pdu = 1;
 
 extern void pprint_pdu(V9fsPDU *pdu);
 
+static int posix_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf)
+{
+    return s->ops->lstat(s->ops->opaque, path->data, stbuf);
+}
+
+static int posix_setuid(V9fsState *s, uid_t uid)
+{
+    return s->ops->setuid(s->ops->opaque, uid);
+}
+
+static void v9fs_string_free(V9fsString *str)
+{
+    qemu_free(str->data);
+    str->data = NULL;
+    str->size = 0;
+}
+
+static void v9fs_string_sprintf(V9fsString *str, const char *fmt, ...)
+{
+    va_list ap;
+    int err;
+
+    v9fs_string_free(str);
+
+    va_start(ap, fmt);
+    err = qemu_vasprintf(&str->data, fmt, ap);
+    BUG_ON(err == -1);
+    va_end(ap);
+
+    str->size = err;
+}
+
+static V9fsFidState *lookup_fid(V9fsState *s, int32_t fid)
+{
+    V9fsFidState *f;
+
+    for (f = s->fid_list; f; f = f->next) {
+        if (f->fid == fid) {
+            posix_setuid(s, f->uid);
+            return f;
+        }
+    }
+
+    return NULL;
+}
+
+static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid)
+{
+    V9fsFidState *f;
+
+    f = lookup_fid(s, fid);
+    if (f)
+        return NULL;
+
+    f = qemu_mallocz(sizeof(V9fsFidState));
+    BUG_ON(f == NULL);
+
+    f->fid = fid;
+    f->fd = -1;
+    f->dir = NULL;
+
+    f->next = s->fid_list;
+    s->fid_list = f;
+
+    return f;
+}
+
+#define P9_QID_TYPE_DIR		0x80
+#define P9_QID_TYPE_SYMLINK	0x02
+
+#define P9_STAT_MODE_DIR	0x80000000
+#define P9_STAT_MODE_APPEND	0x40000000
+#define P9_STAT_MODE_EXCL	0x20000000
+#define P9_STAT_MODE_MOUNT	0x10000000
+#define P9_STAT_MODE_AUTH	0x08000000
+#define P9_STAT_MODE_TMP	0x04000000
+#define P9_STAT_MODE_SYMLINK	0x02000000
+#define P9_STAT_MODE_LINK	0x01000000
+#define P9_STAT_MODE_DEVICE	0x00800000
+#define P9_STAT_MODE_NAMED_PIPE	0x00200000
+#define P9_STAT_MODE_SOCKET	0x00100000
+#define P9_STAT_MODE_SETUID	0x00080000
+#define P9_STAT_MODE_SETGID	0x00040000
+#define P9_STAT_MODE_SETVTX	0x00010000
+
+#define P9_STAT_MODE_SPECIAL	(P9_STAT_MODE_NAMED_PIPE | \
+                                P9_STAT_MODE_SYMLINK | \
+                                P9_STAT_MODE_LINK | \
+                                P9_STAT_MODE_DEVICE)
+
+
+/* This is the algorithm from ufs in spfs */
+static void stat_to_qid(const struct stat *stbuf, V9fsQID *qidp)
+{
+    size_t size;
+
+    size = MIN(sizeof(stbuf->st_ino), sizeof(qidp->path));
+    memcpy(&qidp->path, &stbuf->st_ino, size);
+    qidp->version = stbuf->st_mtime ^ (stbuf->st_size << 8);
+    qidp->type = 0;
+    if (S_ISDIR(stbuf->st_mode))
+        qidp->type |= P9_QID_TYPE_DIR;
+    if (S_ISLNK(stbuf->st_mode))
+        qidp->type |= P9_QID_TYPE_SYMLINK;
+}
+
+static void fid_to_qid(V9fsState *s, V9fsFidState *fidp, V9fsQID *qidp)
+{
+    struct stat stbuf;
+    int err;
+
+    err = posix_lstat(s, &fidp->path, &stbuf);
+    BUG_ON(err == -1);
+
+    stat_to_qid(&stbuf, qidp);
+}
+
 static V9fsPDU *alloc_pdu(V9fsState *s)
 {
     V9fsPDU *pdu = NULL;
@@ -111,13 +229,6 @@ static void free_pdu(V9fsState *s, V9fsPDU *pdu)
     }
 }
 
-static void v9fs_string_free(V9fsString *str)
-{
-    free(str->data);
-    str->data = NULL;
-    str->size = 0;
-}
-
 static size_t pdu_unpack(void *dst, V9fsPDU *pdu, size_t offset, size_t size)
 {
     struct iovec *sg = pdu->elem.out_sg;
@@ -378,8 +489,33 @@ static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
 
 static void v9fs_attach(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu)
-        pprint_pdu(pdu);
+    int32_t fid, afid, n_uname;
+    V9fsString uname, aname;
+    V9fsFidState *fidp;
+    V9fsQID qid;
+    size_t offset = 7;
+    ssize_t err;
+
+    pdu_unmarshal(pdu, offset, "ddssd", &fid, &afid, &uname, &aname, &n_uname);
+
+    fidp = alloc_fid(s, fid);
+    if (fidp == NULL) {
+        err = -EINVAL;
+        goto out;
+    }
+
+    fidp->uid = n_uname;
+
+    v9fs_string_sprintf(&fidp->path, "%s", s->root);
+    fid_to_qid(s, fidp, &qid);
+
+    offset += pdu_marshal(pdu, offset, "Q", &qid);
+
+    err = offset;
+out:
+    complete_pdu(s, pdu, err);
+    v9fs_string_free(&uname);
+    v9fs_string_free(&aname);
 }
 
 static void v9fs_stat(V9fsState *s, V9fsPDU *pdu)
@@ -528,6 +664,7 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, const char *path)
     BUG_ON(s->root == NULL);
     s->uid = -1;
 
+    s->ops = virtio_9p_init_local(path);
     s->vdev.get_features = virtio_9p_get_features;
 
     return &s->vdev;
diff --git a/hw/virtio-9p.h b/hw/virtio-9p.h
index 2aa67d0..8e15bf0 100644
--- a/hw/virtio-9p.h
+++ b/hw/virtio-9p.h
@@ -66,5 +66,38 @@ struct V9fsPDU
     V9fsPDU *next;
 };
 
+typedef struct V9fsPosixFileOpertions
+{
+    int (*lstat)(void *, const char *, struct stat *);
+    ssize_t (*readlink)(void *, const char *, char *, size_t);
+    int (*chmod)(void *, const char *, mode_t);
+    int (*chown)(void *, const char *, uid_t, gid_t);
+    int (*mknod)(void *, const char *, mode_t, dev_t);
+    int (*mksock)(void *, const char *);
+    int (*utime)(void *, const char *, const struct utimbuf *);
+    int (*remove)(void *, const char *);
+    int (*symlink)(void *, const char *, const char *);
+    int (*link)(void *, const char *, const char *);
+    int (*setuid)(void *, uid_t);
+    int (*close)(void *, int);
+    int (*closedir)(void *, DIR *);
+    DIR *(*opendir)(void *, const char *);
+    int (*open)(void *, const char *, int);
+    int (*open2)(void *, const char *, int, mode_t);
+    void (*rewinddir)(void *, DIR *);
+    off_t (*telldir)(void *, DIR *);
+    struct dirent *(*readdir)(void *, DIR *);
+    void (*seekdir)(void *, DIR *, off_t);
+    ssize_t (*readv)(void *, int, const struct iovec *, int);
+    ssize_t (*writev)(void *, int, const struct iovec *, int);
+    off_t (*lseek)(void *, int, off_t, int);
+    int (*mkdir)(void *, const char *, mode_t);
+    int (*fstat)(void *, int, struct stat *);
+    int (*rename)(void *, const char *, const char *);
+    int (*truncate)(void *, const char *, off_t);
+    void *opaque;
+} V9fsPosixFileOperations;
+
+V9fsPosixFileOperations *virtio_9p_init_local(const char *path);
 
 #endif
diff --git a/qemu-common.h b/qemu-common.h
index 087c034..6e925ab 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -160,6 +160,7 @@ void *qemu_mallocz(size_t size);
 void qemu_free(void *ptr);
 char *qemu_strdup(const char *str);
 char *qemu_strndup(const char *str, size_t size);
+int qemu_vasprintf(char **strp, const char *fmt, va_list ap);
 
 void *get_mmap_addr(unsigned long size);
 
diff --git a/qemu-malloc.c b/qemu-malloc.c
index 6cdc5de..d6de067 100644
--- a/qemu-malloc.c
+++ b/qemu-malloc.c
@@ -98,3 +98,8 @@ char *qemu_strndup(const char *str, size_t size)
 
     return memcpy(new, str, size);
 }
+
+int qemu_vasprintf(char **strp, const char *fmt, va_list ap)
+{
+    return vasprintf(strp, fmt, ap);
+}
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 04/32] virtio-9p: Implement P9_TSTAT
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (2 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 03/32] virtio-9p: Implement P9_TATTACH Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 05/32] virtio-9p: Implement P9_TWALK Aneesh Kumar K.V
                   ` (27 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V, Gautham R Shenoy

From: Anthony Liguori <aliguori@us.ibm.com>

This get the mount to work on the guest

[kiran@linux.vnet.ibm.com: malloc to qemu_malloc conversion]

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p-local.c |    7 ++
 hw/virtio-9p.c       |  169 +++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 174 insertions(+), 2 deletions(-)

diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 1d2523b..aefb5a8 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -72,9 +72,16 @@ static int local_setuid(void *opaque, uid_t uid)
     return 0;
 }
 
+static ssize_t local_readlink(void *opaque, const char *path,
+                                char *buf, size_t bufsz)
+{
+    return readlink(rpath(path), buf, bufsz);
+}
+
 static V9fsPosixFileOperations ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
+    .readlink = local_readlink,
 };
 
 V9fsPosixFileOperations *virtio_9p_init_local(const char *path)
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index fdff589..de5f6b0 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -102,6 +102,21 @@ static int posix_setuid(V9fsState *s, uid_t uid)
     return s->ops->setuid(s->ops->opaque, uid);
 }
 
+static ssize_t posix_readlink(V9fsState *s, V9fsString *path, V9fsString *buf)
+{
+    ssize_t len;
+
+    buf->data = qemu_malloc(1024);
+
+    len = s->ops->readlink(s->ops->opaque, path->data, buf->data, 1024 - 1);
+    if (len > -1) {
+        buf->size = len;
+        buf->data[len] = 0;
+    }
+
+    return len;
+}
+
 static void v9fs_string_free(V9fsString *str)
 {
     qemu_free(str->data);
@@ -109,6 +124,11 @@ static void v9fs_string_free(V9fsString *str)
     str->size = 0;
 }
 
+static void v9fs_string_null(V9fsString *str)
+{
+    v9fs_string_free(str);
+}
+
 static void v9fs_string_sprintf(V9fsString *str, const char *fmt, ...)
 {
     va_list ap;
@@ -124,6 +144,11 @@ static void v9fs_string_sprintf(V9fsString *str, const char *fmt, ...)
     str->size = err;
 }
 
+static size_t v9fs_string_size(V9fsString *str)
+{
+    return str->size;
+}
+
 static V9fsFidState *lookup_fid(V9fsState *s, int32_t fid)
 {
     V9fsFidState *f;
@@ -437,6 +462,15 @@ static size_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
     return offset - old_offset;
 }
 
+static void v9fs_stat_free(V9fsStat *stat)
+{
+    v9fs_string_free(&stat->name);
+    v9fs_string_free(&stat->uid);
+    v9fs_string_free(&stat->gid);
+    v9fs_string_free(&stat->muid);
+    v9fs_string_free(&stat->extension);
+}
+
 static void complete_pdu(V9fsState *s, V9fsPDU *pdu, ssize_t len)
 {
     int8_t id = pdu->id + 1; /* Response */
@@ -472,6 +506,88 @@ static void complete_pdu(V9fsState *s, V9fsPDU *pdu, ssize_t len)
     free_pdu(s, pdu);
 }
 
+static uint32_t stat_to_v9mode(const struct stat *stbuf)
+{
+    uint32_t mode;
+
+    mode = stbuf->st_mode & 0777;
+    if (S_ISDIR(stbuf->st_mode))
+        mode |= P9_STAT_MODE_DIR;
+
+    if (dotu) {
+        if (S_ISLNK(stbuf->st_mode))
+            mode |= P9_STAT_MODE_SYMLINK;
+        if (S_ISSOCK(stbuf->st_mode))
+            mode |= P9_STAT_MODE_SOCKET;
+        if (S_ISFIFO(stbuf->st_mode))
+            mode |= P9_STAT_MODE_NAMED_PIPE;
+        if (S_ISBLK(stbuf->st_mode) || S_ISCHR(stbuf->st_mode))
+            mode |= P9_STAT_MODE_DEVICE;
+        if (stbuf->st_mode & S_ISUID)
+            mode |= P9_STAT_MODE_SETUID;
+        if (stbuf->st_mode & S_ISGID)
+            mode |= P9_STAT_MODE_SETGID;
+        if (stbuf->st_mode & S_ISVTX)
+            mode |= P9_STAT_MODE_SETVTX;
+    }
+
+    return mode;
+}
+
+static void stat_to_v9stat(V9fsState *s, V9fsString *name,
+                            const struct stat *stbuf,
+                            V9fsStat *v9stat)
+{
+    int err;
+    const char *str;
+
+    memset(v9stat, 0, sizeof(*v9stat));
+
+    stat_to_qid(stbuf, &v9stat->qid);
+    v9stat->mode = stat_to_v9mode(stbuf);
+    v9stat->atime = stbuf->st_atime;
+    v9stat->mtime = stbuf->st_mtime;
+    v9stat->length = stbuf->st_size;
+
+    v9fs_string_null(&v9stat->uid);
+    v9fs_string_null(&v9stat->gid);
+    v9fs_string_null(&v9stat->muid);
+
+    if (dotu) {
+        v9stat->n_uid = stbuf->st_uid;
+        v9stat->n_gid = stbuf->st_gid;
+        v9stat->n_muid = 0;
+
+        v9fs_string_null(&v9stat->extension);
+
+        if (v9stat->mode & P9_STAT_MODE_SYMLINK) {
+            err = posix_readlink(s, name, &v9stat->extension);
+            BUG_ON(err == -1);
+            v9stat->extension.data[err] = 0;
+            v9stat->extension.size = err;
+        } else if (v9stat->mode & P9_STAT_MODE_DEVICE) {
+            v9fs_string_sprintf(&v9stat->extension, "%c %u %u",
+                    S_ISCHR(stbuf->st_mode) ? 'c' : 'b',
+                    major(stbuf->st_rdev), minor(stbuf->st_rdev));
+        }
+    }
+
+    str = strrchr(name->data, '/');
+    if (str)
+        str += 1;
+    else
+        str = name->data;
+
+    v9fs_string_sprintf(&v9stat->name, "%s", str);
+
+    v9stat->size = 61 +
+        v9fs_string_size(&v9stat->name) +
+        v9fs_string_size(&v9stat->uid) +
+        v9fs_string_size(&v9stat->gid) +
+        v9fs_string_size(&v9stat->muid) +
+        v9fs_string_size(&v9stat->extension);
+}
+
 static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
 {
     int32_t msize;
@@ -518,10 +634,59 @@ out:
     v9fs_string_free(&aname);
 }
 
+typedef struct V9fsStatState {
+    V9fsPDU *pdu;
+    size_t offset;
+    int32_t fid;
+    V9fsStat v9stat;
+    V9fsFidState *fidp;
+    struct stat stbuf;
+} V9fsStatState;
+
+static void v9fs_stat_post_lstat(V9fsState *s, V9fsStatState *vs, int err)
+{
+    if (err == -1) {
+        err = -errno;
+        goto out;
+    }
+
+    stat_to_v9stat(s, &vs->fidp->path, &vs->stbuf, &vs->v9stat);
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "wS", 0, &vs->v9stat);
+    err = vs->offset;
+
+out:
+    complete_pdu(s, vs->pdu, err);
+    v9fs_stat_free(&vs->v9stat);
+    qemu_free(vs);
+}
+
 static void v9fs_stat(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu)
-        pprint_pdu(pdu);
+    V9fsStatState *vs;
+    ssize_t err = 0;
+
+    vs = qemu_malloc(sizeof(*vs));
+    vs->pdu = pdu;
+    vs->offset = 7;
+
+    memset(&vs->v9stat, 0, sizeof(vs->v9stat));
+
+    pdu_unmarshal(vs->pdu, vs->offset, "d", &vs->fid);
+
+    vs->fidp = lookup_fid(s, vs->fid);
+    if (vs->fidp == NULL) {
+	    err = -ENOENT;
+        goto out;
+    }
+
+    err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
+    v9fs_stat_post_lstat(s, vs, err);
+    return;
+
+out:
+    complete_pdu(s, vs->pdu, err);
+    v9fs_stat_free(&vs->v9stat);
+    qemu_free(vs);
 }
 
 static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 05/32] virtio-9p: Implement P9_TWALK
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (3 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 04/32] virtio-9p: Implement P9_TSTAT Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 06/32] virtio-9p: Implement P9_TOPEN Aneesh Kumar K.V
                   ` (26 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V, Gautham R Shenoy

From: Anthony Liguori <aliguori@us.ibm.com>

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p-local.c |   12 +++
 hw/virtio-9p.c       |  219 +++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 229 insertions(+), 2 deletions(-)

diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index aefb5a8..409f5b0 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -78,10 +78,22 @@ static ssize_t local_readlink(void *opaque, const char *path,
     return readlink(rpath(path), buf, bufsz);
 }
 
+static int local_close(void *opaque, int fd)
+{
+    return close(fd);
+}
+
+static int local_closedir(void *opaque, DIR *dir)
+{
+    return closedir(dir);
+}
+
 static V9fsPosixFileOperations ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
     .readlink = local_readlink,
+    .close = local_close,
+    .closedir = local_closedir,
 };
 
 V9fsPosixFileOperations *virtio_9p_init_local(const char *path)
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index de5f6b0..784d399 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -117,6 +117,22 @@ static ssize_t posix_readlink(V9fsState *s, V9fsString *path, V9fsString *buf)
     return len;
 }
 
+static int posix_close(V9fsState *s, int fd)
+{
+    return s->ops->close(s->ops->opaque, fd);
+}
+
+static int posix_closedir(V9fsState *s, DIR *dir)
+{
+    return s->ops->closedir(s->ops->opaque, dir);
+}
+
+static void v9fs_string_init(V9fsString *str)
+{
+    str->data = NULL;
+    str->size = 0;
+}
+
 static void v9fs_string_free(V9fsString *str)
 {
     qemu_free(str->data);
@@ -144,6 +160,12 @@ static void v9fs_string_sprintf(V9fsString *str, const char *fmt, ...)
     str->size = err;
 }
 
+static void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs)
+{
+    v9fs_string_free(lhs);
+    v9fs_string_sprintf(lhs, "%s", rhs->data);
+}
+
 static size_t v9fs_string_size(V9fsString *str)
 {
     return str->size;
@@ -184,6 +206,31 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid)
     return f;
 }
 
+static int free_fid(V9fsState *s, int32_t fid)
+{
+    V9fsFidState **fidpp, *fidp;
+
+    for (fidpp = &s->fid_list; *fidpp; fidpp = &(*fidpp)->next) {
+        if ((*fidpp)->fid == fid)
+            break;
+    }
+
+    if (*fidpp == NULL)
+        return -ENOENT;
+
+    fidp = *fidpp;
+    *fidpp = fidp->next;
+
+    if (fidp->fd != -1)
+        posix_close(s, fidp->fd);
+    if (fidp->dir)
+        posix_closedir(s, fidp->dir);
+    v9fs_string_free(&fidp->path);
+    qemu_free(fidp);
+
+    return 0;
+}
+
 #define P9_QID_TYPE_DIR		0x80
 #define P9_QID_TYPE_SYMLINK	0x02
 
@@ -689,10 +736,178 @@ out:
     qemu_free(vs);
 }
 
+typedef struct V9fsWalkState {
+    V9fsPDU *pdu;
+    size_t offset;
+    int32_t fid;
+    int32_t newfid;
+    int16_t nwnames;
+    int name_idx;
+    V9fsQID *qids;
+    V9fsFidState *fidp;
+    V9fsFidState *newfidp;
+    V9fsString path;
+    V9fsString *wnames;
+    struct stat stbuf;
+} V9fsWalkState;
+
+static void v9fs_walk_complete(V9fsState *s, V9fsWalkState *vs, int err)
+{
+    complete_pdu(s, vs->pdu, err);
+
+    if(vs->nwnames) {
+        for (vs->name_idx = 0; vs->name_idx < vs->nwnames; vs->name_idx++)
+            v9fs_string_free(&vs->wnames[vs->name_idx]);
+
+        qemu_free(vs->wnames);
+        qemu_free(vs->qids);
+    }
+}
+
+static void v9fs_walk_marshal(V9fsWalkState *vs)
+{
+    int i;
+    vs->offset = 7;
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "w", vs->nwnames);
+
+    for (i = 0; i < vs->nwnames; i++)
+        vs->offset += pdu_marshal(vs->pdu, vs->offset, "Q", &vs->qids[i]);
+}
+
+static void v9fs_walk_post_newfid_lstat(V9fsState *s, V9fsWalkState *vs,
+                                                                int err)
+{
+    if (err == -1) {
+        free_fid(s, vs->newfid);
+        v9fs_string_free(&vs->path);
+        err = -ENOENT;
+        goto out;
+    }
+
+    stat_to_qid(&vs->stbuf, &vs->qids[vs->name_idx]);
+
+    vs->name_idx++;
+    if (vs->name_idx < vs->nwnames) {
+        v9fs_string_sprintf(&vs->path, "%s/%s", vs->newfidp->path.data,
+                                            vs->wnames[vs->name_idx].data);
+        v9fs_string_copy(&vs->newfidp->path, &vs->path);
+
+        err = posix_lstat(s, &vs->newfidp->path, &vs->stbuf);
+        v9fs_walk_post_newfid_lstat(s, vs, err);
+        return;
+    }
+
+    v9fs_string_free(&vs->path);
+    v9fs_walk_marshal(vs);
+    err = vs->offset;
+out:
+    v9fs_walk_complete(s, vs, err);
+}
+
+static void v9fs_walk_post_oldfid_lstat(V9fsState *s, V9fsWalkState *vs,
+        int err)
+{
+    if (err == -1) {
+        v9fs_string_free(&vs->path);
+        err = -ENOENT;
+        goto out;
+    }
+
+    stat_to_qid(&vs->stbuf, &vs->qids[vs->name_idx]);
+    vs->name_idx++;
+    if (vs->name_idx < vs->nwnames) {
+
+        v9fs_string_sprintf(&vs->path, "%s/%s",
+                vs->fidp->path.data, vs->wnames[vs->name_idx].data);
+        v9fs_string_copy(&vs->fidp->path, &vs->path);
+
+        err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
+        v9fs_walk_post_oldfid_lstat(s, vs, err);
+        return;
+    }
+
+    v9fs_string_free(&vs->path);
+    v9fs_walk_marshal(vs);
+    err = vs->offset;
+out:
+    v9fs_walk_complete(s, vs, err);
+}
+
 static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu)
-        pprint_pdu(pdu);
+    V9fsWalkState *vs;
+    int err = 0;
+    int i;
+
+    vs = qemu_malloc(sizeof(*vs));
+    vs->pdu =pdu;
+    vs->wnames = NULL;
+    vs->qids = NULL;
+    vs->offset = 7;
+
+    vs->offset += pdu_unmarshal(vs->pdu, vs->offset, "ddw", &vs->fid,
+                                            &vs->newfid, &vs->nwnames);
+
+    if(vs->nwnames) {
+        vs->wnames = qemu_mallocz(sizeof(vs->wnames[0]) * vs->nwnames);
+        BUG_ON(vs->wnames == NULL);
+
+        vs->qids = qemu_mallocz(sizeof(vs->qids[0]) * vs->nwnames);
+        BUG_ON(vs->qids == NULL);
+
+        for (i = 0; i < vs->nwnames; i++) {
+            vs->offset += pdu_unmarshal(vs->pdu, vs->offset, "s",
+                                            &vs->wnames[i]);
+        }
+    }
+
+    vs->fidp = lookup_fid(s, vs->fid);
+    if (vs->fidp == NULL) {
+        err = -ENOENT;
+        goto out;
+    }
+
+    /* FIXME: is this really valid? */
+    if (vs->fid == vs->newfid) {
+        v9fs_string_init(&vs->path);
+        vs->name_idx = 0;
+
+        if (vs->name_idx < vs->nwnames) {
+            v9fs_string_sprintf(&vs->path, "%s/%s",
+                vs->fidp->path.data, vs->wnames[vs->name_idx].data);
+            v9fs_string_copy(&vs->fidp->path, &vs->path);
+
+            err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
+            v9fs_walk_post_oldfid_lstat(s, vs, err);
+            return;
+        }
+    } else {
+        vs->newfidp = alloc_fid(s, vs->newfid);
+        if (vs->newfidp == NULL) {
+            err = -EINVAL;
+            goto out;
+        }
+
+        vs->newfidp->uid = vs->fidp->uid;
+        v9fs_string_init(&vs->path);
+        vs->name_idx = 0;
+        v9fs_string_copy(&vs->newfidp->path, &vs->fidp->path);
+
+        if (vs->name_idx < vs->nwnames) {
+            v9fs_string_sprintf(&vs->path, "%s/%s", vs->newfidp->path.data,
+                                vs->wnames[vs->name_idx].data);
+            v9fs_string_copy(&vs->newfidp->path, &vs->path);
+
+            err = posix_lstat(s, &vs->newfidp->path, &vs->stbuf);
+            v9fs_walk_post_newfid_lstat(s, vs, err);
+            return;
+        }
+    }
+
+    v9fs_walk_marshal(vs);
+    err = vs->offset;
+out:
+    v9fs_walk_complete(s, vs, err);
 }
 
 static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 06/32] virtio-9p: Implement P9_TOPEN
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (4 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 05/32] virtio-9p: Implement P9_TWALK Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 07/32] virtio-9p: Implement P9_TREAD Aneesh Kumar K.V
                   ` (25 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V, Gautham R Shenoy

From: Anthony Liguori <aliguori@us.ibm.com>

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p-local.c |   12 ++++
 hw/virtio-9p.c       |  145 +++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 151 insertions(+), 6 deletions(-)

diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 409f5b0..d8cb70d 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -88,12 +88,24 @@ static int local_closedir(void *opaque, DIR *dir)
     return closedir(dir);
 }
 
+static int local_open(void *opaque, const char *path, int flags)
+{
+    return open(rpath(path), flags);
+}
+
+static DIR *local_opendir(void *opaque, const char *path)
+{
+    return opendir(rpath(path));
+}
+
 static V9fsPosixFileOperations ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
     .readlink = local_readlink,
     .close = local_close,
     .closedir = local_closedir,
+    .open = local_open,
+    .opendir = local_opendir,
 };
 
 V9fsPosixFileOperations *virtio_9p_init_local(const char *path)
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 784d399..f1df0b9 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -127,6 +127,16 @@ static int posix_closedir(V9fsState *s, DIR *dir)
     return s->ops->closedir(s->ops->opaque, dir);
 }
 
+static int posix_open(V9fsState *s, V9fsString *path, int flags)
+{
+    return s->ops->open(s->ops->opaque, path->data, flags);
+}
+
+static DIR *posix_opendir(V9fsState *s, V9fsString *path)
+{
+    return s->ops->opendir(s->ops->opaque, path->data);
+}
+
 static void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -910,15 +920,138 @@ out:
     v9fs_walk_complete(s, vs, err);
 }
 
-static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
+typedef struct V9fsOpenState {
+    V9fsPDU *pdu;
+    size_t offset;
+    int32_t fid;
+    int8_t mode;
+    V9fsFidState *fidp;
+    V9fsQID qid;
+    struct stat stbuf;
+
+} V9fsOpenState;
+
+enum {
+    Oread		= 0x00,
+    Owrite		= 0x01,
+    Ordwr		= 0x02,
+    Oexec		= 0x03,
+    Oexcl		= 0x04,
+    Otrunc		= 0x10,
+    Orexec		= 0x20,
+    Orclose		= 0x40,
+    Oappend		= 0x80,
+};
+
+static int omode_to_uflags(int8_t mode)
 {
-    if (debug_9p_pdu)
-        pprint_pdu(pdu);
+    int ret = 0;
+
+    switch (mode & 3) {
+        case Oread:
+            ret = O_RDONLY;
+            break;
+        case Ordwr:
+            ret = O_RDWR;
+            break;
+        case Owrite:
+            ret = O_WRONLY;
+            break;
+        case Oexec:
+            ret = O_RDONLY;
+            break;
+    }
+
+    if (mode & Otrunc)
+        ret |= O_TRUNC;
+
+    if (mode & Oappend)
+        ret |= O_APPEND;
+
+    if (mode & Oexcl)
+        ret |= O_EXCL;
+
+    return ret;
+}
+
+static void v9fs_open_post_opendir(V9fsState *s, V9fsOpenState *vs, int err)
+{
+    if (vs->fidp->dir == NULL) {
+        err = -errno;
+        goto out;
+    }
+
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, 0);
+    err = vs->offset;
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+
 }
 
-    static void v9fs_open(V9fsState *s, V9fsPDU *pdu)
-{    if (debug_9p_pdu)
-    pprint_pdu(pdu);
+static void v9fs_open_post_open(V9fsState *s, V9fsOpenState *vs, int err)
+{
+    if (vs->fidp->fd == -1) {
+        err = -errno;
+        goto out;
+    }
+
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, 0);
+    err = vs->offset;
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_open_post_lstat(V9fsState *s, V9fsOpenState *vs, int err)
+{
+    BUG_ON(err == -1);
+
+    stat_to_qid(&vs->stbuf, &vs->qid);
+
+    if (S_ISDIR(vs->stbuf.st_mode)) {
+        vs->fidp->dir = posix_opendir(s, &vs->fidp->path);
+        v9fs_open_post_opendir(s, vs, err);
+    } else {
+        vs->fidp->fd = posix_open(s, &vs->fidp->path,
+                                    omode_to_uflags(vs->mode));
+        v9fs_open_post_open(s, vs, err);
+    }
+
+}
+
+static void v9fs_open(V9fsState *s, V9fsPDU *pdu)
+{
+
+    V9fsOpenState *vs;
+    ssize_t err = 0;
+
+
+    vs = qemu_malloc(sizeof(*vs));
+    vs->pdu = pdu;
+    vs->offset = 7;
+
+    pdu_unmarshal(vs->pdu, vs->offset, "db", &vs->fid, &vs->mode);
+
+    vs->fidp = lookup_fid(s, vs->fid);
+    if (vs->fidp == NULL) {
+        err = -ENOENT;
+        goto out;
+    }
+
+    err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
+
+    v9fs_open_post_lstat(s, vs, err);
+    return;
+out:
+    complete_pdu(s, pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu)
+	pprint_pdu(pdu);
 }
 
 static void v9fs_read(V9fsState *s, V9fsPDU *pdu)
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 07/32] virtio-9p: Implement P9_TREAD
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (5 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 06/32] virtio-9p: Implement P9_TOPEN Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 08/32] virtio-9p: Implement P9_TCLUNK Aneesh Kumar K.V
                   ` (24 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Venkateswararao Jujjuri, Aneesh Kumar K.V

From: Anthony Liguori <aliguori@us.ibm.com>

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p-local.c |   37 ++++++++
 hw/virtio-9p.c       |  253 +++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 287 insertions(+), 3 deletions(-)

diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index d8cb70d..d77ecc2 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -98,6 +98,37 @@ static DIR *local_opendir(void *opaque, const char *path)
     return opendir(rpath(path));
 }
 
+static void local_rewinddir(void *opaque, DIR *dir)
+{
+    return rewinddir(dir);
+}
+
+static off_t local_telldir(void *opaque, DIR *dir)
+{
+    return telldir(dir);
+}
+
+static struct dirent *local_readdir(void *opaque, DIR *dir)
+{
+    return readdir(dir);
+}
+
+static void local_seekdir(void *opaque, DIR *dir, off_t off)
+{
+    return seekdir(dir, off);
+}
+
+static ssize_t local_readv(void *opaque, int fd, const struct iovec *iov,
+			   int iovcnt)
+{
+    return readv(fd, iov, iovcnt);
+}
+
+static off_t local_lseek(void *opaque, int fd, off_t offset, int whence)
+{
+    return lseek(fd, offset, whence);
+}
+
 static V9fsPosixFileOperations ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
@@ -106,6 +137,12 @@ static V9fsPosixFileOperations ops = {
     .closedir = local_closedir,
     .open = local_open,
     .opendir = local_opendir,
+    .rewinddir = local_rewinddir,
+    .telldir = local_telldir,
+    .readdir = local_readdir,
+    .seekdir = local_seekdir,
+    .readv = local_readv,
+    .lseek = local_lseek,
 };
 
 V9fsPosixFileOperations *virtio_9p_init_local(const char *path)
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index f1df0b9..9bc0a57 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -137,6 +137,37 @@ static DIR *posix_opendir(V9fsState *s, V9fsString *path)
     return s->ops->opendir(s->ops->opaque, path->data);
 }
 
+static void posix_rewinddir(V9fsState *s, DIR *dir)
+{
+    return s->ops->rewinddir(s->ops->opaque, dir);
+}
+
+static off_t posix_telldir(V9fsState *s, DIR *dir)
+{
+    return s->ops->telldir(s->ops->opaque, dir);
+}
+
+static struct dirent *posix_readdir(V9fsState *s, DIR *dir)
+{
+    return s->ops->readdir(s->ops->opaque, dir);
+}
+
+static void posix_seekdir(V9fsState *s, DIR *dir, off_t off)
+{
+    return s->ops->seekdir(s->ops->opaque, dir, off);
+}
+
+static int posix_readv(V9fsState *s, int fd, const struct iovec *iov,
+		       int iovcnt)
+{
+    return s->ops->readv(s->ops->opaque, fd, iov, iovcnt);
+}
+
+static off_t posix_lseek(V9fsState *s, int fd, off_t offset, int whence)
+{
+    return s->ops->lseek(s->ops->opaque, fd, offset, whence);
+}
+
 static void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -1048,14 +1079,230 @@ out:
     qemu_free(vs);
 }
 
-static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
+static struct iovec *adjust_sg(struct iovec *sg, int len, int *iovcnt)
 {
-    if (debug_9p_pdu)
-	pprint_pdu(pdu);
+    while (len && *iovcnt) {
+        if (len < sg->iov_len) {
+            sg->iov_len -= len;
+            sg->iov_base += len;
+            len = 0;
+        } else {
+            len -= sg->iov_len;
+            sg++;
+            *iovcnt -= 1;
+        }
+    }
+
+    return sg;
+}
+
+static struct iovec *cap_sg(struct iovec *sg, int cap, int *cnt)
+{
+    int i;
+    int total = 0;
+
+    for (i = 0; i < *cnt; i++) {
+        if ((total + sg[i].iov_len) > cap) {
+            sg[i].iov_len -= ((total + sg[i].iov_len) - cap);
+            i++;
+            break;
+        }
+        total += sg[i].iov_len;
+    }
+
+    *cnt = i;
+
+    return sg;
+}
+
+static void print_sg(struct iovec *sg, int cnt)
+{
+    int i;
+
+    printf("sg[%d]: {", cnt);
+    for (i = 0; i < cnt; i++) {
+        if (i)
+            printf(", ");
+        printf("(%p, %zd)", sg[i].iov_base, sg[i].iov_len);
+    }
+    printf("}\n");
+}
+
+typedef struct V9fsReadState {
+    V9fsPDU *pdu;
+    size_t offset;
+    int32_t fid;
+    int32_t count;
+    int32_t total;
+    int64_t off;
+    V9fsFidState *fidp;
+    struct iovec iov[128]; /* FIXME: bad, bad, bad */
+    struct iovec *sg;
+    off_t dir_pos;
+    struct dirent *dent;
+    struct stat stbuf;
+    V9fsString name;
+    V9fsStat v9stat;
+    int32_t len;
+    int32_t cnt;
+    int32_t max_count;
+} V9fsReadState;
+
+static void v9fs_read_post_readdir(V9fsState *, V9fsReadState *, ssize_t );
+
+static void v9fs_read_post_seekdir(V9fsState *s, V9fsReadState *vs, ssize_t err)
+{
+    v9fs_stat_free(&vs->v9stat);
+    v9fs_string_free(&vs->name);
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->count);
+    vs->offset += vs->count;
+    err = vs->offset;
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+    return;
+}
+
+static void v9fs_read_post_dir_lstat(V9fsState *s, V9fsReadState *vs,
+                                    ssize_t err)
+{
+    BUG_ON(err == -1);
+    stat_to_v9stat(s, &vs->name, &vs->stbuf, &vs->v9stat);
+
+    vs->len = pdu_marshal(vs->pdu, vs->offset + 4 + vs->count, "S",
+                            &vs->v9stat);
+    if ((vs->len != (vs->v9stat.size + 2)) ||
+            ((vs->count + vs->len) > vs->max_count)) {
+        posix_seekdir(s, vs->fidp->dir, vs->dir_pos);
+        v9fs_read_post_seekdir(s, vs, err);
+        return;
+    }
+    vs->count += vs->len;
+    v9fs_stat_free(&vs->v9stat);
+    v9fs_string_free(&vs->name);
+    vs->dir_pos = vs->dent->d_off;
+    vs->dent = posix_readdir(s, vs->fidp->dir);
+    v9fs_read_post_readdir(s, vs, err);
+    return;
+}
+
+static void v9fs_read_post_readdir(V9fsState *s, V9fsReadState *vs, ssize_t err)
+{
+    if (vs->dent) {
+        memset(&vs->v9stat, 0, sizeof(vs->v9stat));
+        v9fs_string_init(&vs->name);
+        v9fs_string_sprintf(&vs->name, "%s/%s", vs->fidp->path.data,
+                            vs->dent->d_name);
+        err = posix_lstat(s, &vs->name, &vs->stbuf);
+        v9fs_read_post_dir_lstat(s, vs, err);
+        return;
+    }
+
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->count);
+    vs->offset += vs->count;
+    err = vs->offset;
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+    return;
+}
+
+static void v9fs_read_post_telldir(V9fsState *s, V9fsReadState *vs, ssize_t err)
+{
+    vs->dent = posix_readdir(s, vs->fidp->dir);
+    v9fs_read_post_readdir(s, vs, err);
+    return;
+}
+
+static void v9fs_read_post_rewinddir(V9fsState *s, V9fsReadState *vs,
+                                       ssize_t err)
+{
+    vs->dir_pos = posix_telldir(s, vs->fidp->dir);
+    v9fs_read_post_telldir(s, vs, err);
+    return;
+}
+
+static void v9fs_read_post_readv(V9fsState *s, V9fsReadState *vs, ssize_t err)
+{
+    BUG_ON(vs->len < 0);
+    vs->total += vs->len;
+    vs->sg = adjust_sg(vs->sg, vs->len, &vs->cnt);
+    if (vs->total < vs->count && vs->len > 0) {
+        do {
+            if (0) {
+                print_sg(vs->sg, vs->cnt);
+            }
+            vs->len = posix_readv(s, vs->fidp->fd, vs->sg, vs->cnt);
+        } while (vs->len == -1 && errno == EINTR);
+        v9fs_read_post_readv(s, vs, err);
+        return;
+    }
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->total);
+    vs->offset += vs->count;
+    err = vs->offset;
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_read_post_lseek(V9fsState *s, V9fsReadState *vs, ssize_t err)
+{
+    BUG_ON(err == -1);
+    vs->sg = cap_sg(vs->sg, vs->count, &vs->cnt);
+
+    if (vs->total < vs->count) {
+        do {
+            if (0) {
+                print_sg(vs->sg, vs->cnt);
+            }
+            vs->len = posix_readv(s, vs->fidp->fd, vs->sg, vs->cnt);
+        } while (vs->len == -1 && errno == EINTR);
+        v9fs_read_post_readv(s, vs, err);
+        return;
+    }
 }
 
 static void v9fs_read(V9fsState *s, V9fsPDU *pdu)
 {
+    V9fsReadState *vs;
+    ssize_t err = 0;
+
+    vs = qemu_malloc(sizeof(*vs));
+    vs->pdu = pdu;
+    vs->offset = 7;
+    vs->total = 0;
+    vs->len = 0;
+    vs->count = 0;
+
+    pdu_unmarshal(vs->pdu, vs->offset, "dqd", &vs->fid, &vs->off, &vs->count);
+
+    vs->fidp = lookup_fid(s, vs->fid);
+    if (vs->fidp == NULL) {
+        err = -EINVAL;
+        goto out;
+    }
+
+    if (vs->fidp->dir) {
+        vs->max_count = vs->count;
+        vs->count = 0;
+        if (vs->off == 0) {
+            posix_rewinddir(s, vs->fidp->dir);
+        }
+        v9fs_read_post_rewinddir(s, vs, err);
+        return;
+    } else if (vs->fidp->fd != -1) {
+        vs->sg = vs->iov;
+        pdu_marshal(vs->pdu, vs->offset + 4, "v", vs->sg, &vs->cnt);
+        err = posix_lseek(s, vs->fidp->fd, vs->off, SEEK_SET);
+        v9fs_read_post_lseek(s, vs, err);
+        return;
+    } else {
+        err = -EINVAL;
+    }
+out:
+    complete_pdu(s, pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
+{
     if (debug_9p_pdu)
         pprint_pdu(pdu);
 }
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 08/32] virtio-9p: Implement P9_TCLUNK
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (6 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 07/32] virtio-9p: Implement P9_TREAD Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE Aneesh Kumar K.V
                   ` (23 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V

From: Anthony Liguori <aliguori@us.ibm.com>

This patch gets ls -al to work

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p.c |   16 ++++++++++++++--
 1 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 9bc0a57..3ac6255 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -1303,8 +1303,20 @@ out:
 
 static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu)
-        pprint_pdu(pdu);
+    int32_t fid;
+    size_t offset = 7;
+    int err;
+
+    pdu_unmarshal(pdu, offset, "d", &fid);
+
+    err = free_fid(s, fid);
+    if (err < 0)
+        goto out;
+
+    offset = 7;
+    err = offset;
+out:
+    complete_pdu(s, pdu, err);
 }
 
 static void v9fs_write(V9fsState *s, V9fsPDU *pdu)
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (7 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 08/32] virtio-9p: Implement P9_TCLUNK Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-29  6:36   ` [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU jvrao
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 10/32] virtio-9p: Implement P9_TCREATE Aneesh Kumar K.V
                   ` (22 subsequent siblings)
  31 siblings, 1 reply; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Venkateswararao Jujjuri, Aneesh Kumar K.V

From: Anthony Liguori <aliguori@us.ibm.com>

This gets write to file to work

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p-local.c |    7 ++++
 hw/virtio-9p.c       |   97 ++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 102 insertions(+), 2 deletions(-)

diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index d77ecc2..c5d1db3 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -129,6 +129,12 @@ static off_t local_lseek(void *opaque, int fd, off_t offset, int whence)
     return lseek(fd, offset, whence);
 }
 
+static ssize_t local_writev(void *opaque, int fd, const struct iovec *iov,
+			    int iovcnt)
+{
+    return writev(fd, iov, iovcnt);
+}
+
 static V9fsPosixFileOperations ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
@@ -143,6 +149,7 @@ static V9fsPosixFileOperations ops = {
     .seekdir = local_seekdir,
     .readv = local_readv,
     .lseek = local_lseek,
+    .writev = local_writev,
 };
 
 V9fsPosixFileOperations *virtio_9p_init_local(const char *path)
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 3ac6255..bc26d66 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -168,6 +168,12 @@ static off_t posix_lseek(V9fsState *s, int fd, off_t offset, int whence)
     return s->ops->lseek(s->ops->opaque, fd, offset, whence);
 }
 
+static int posix_writev(V9fsState *s, int fd, const struct iovec *iov,
+                       int iovcnt)
+{
+    return s->ops->writev(s->ops->opaque, fd, iov, iovcnt);
+}
+
 static void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -1319,10 +1325,97 @@ out:
     complete_pdu(s, pdu, err);
 }
 
+typedef struct V9fsWriteState {
+    V9fsPDU *pdu;
+    size_t offset;
+    int32_t fid;
+    int32_t len;
+    int32_t count;
+    int32_t total;
+    int64_t off;
+    V9fsFidState *fidp;
+    struct iovec iov[128]; /* FIXME: bad, bad, bad */
+    struct iovec *sg;
+    int cnt;
+} V9fsWriteState;
+
+static void v9fs_write_post_writev(V9fsState *s, V9fsWriteState *vs,
+                                   ssize_t err)
+{
+    BUG_ON(vs->len < 0);
+    vs->total += vs->len;
+    vs->sg = adjust_sg(vs->sg, vs->len, &vs->cnt);
+    if (vs->total < vs->count && vs->len > 0) {
+        do {
+            if (0)
+                print_sg(vs->sg, vs->cnt);
+            vs->len =  posix_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
+        } while (vs->len == -1 && errno == EINTR);
+        v9fs_write_post_writev(s, vs, err);
+    }
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->total);
+
+    err = vs->offset;
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_write_post_lseek(V9fsState *s, V9fsWriteState *vs, ssize_t err)
+{
+    BUG_ON(err == -1);
+
+    vs->sg = cap_sg(vs->sg, vs->count, &vs->cnt);
+
+    if (vs->total < vs->count) {
+        do {
+            if (0)
+                print_sg(vs->sg, vs->cnt);
+            vs->len = posix_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
+        } while (vs->len == -1 && errno == EINTR);
+
+        v9fs_write_post_writev(s, vs, err);
+        return;
+    }
+
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
 static void v9fs_write(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu)
-        pprint_pdu(pdu);
+    V9fsWriteState *vs;
+    ssize_t err;
+
+    vs = qemu_malloc(sizeof(*vs));
+
+    vs->pdu = pdu;
+    vs->offset = 7;
+    vs->sg = vs->iov;
+    vs->total = 0;
+    vs->len = 0;
+
+    pdu_unmarshal(vs->pdu, vs->offset, "dqdv", &vs->fid, &vs->off, &vs->count,
+                    vs->sg, &vs->cnt);
+
+    vs->fidp = lookup_fid(s, vs->fid);
+    if (vs->fidp == NULL) {
+        err = -EINVAL;
+        goto out;
+    }
+
+    if (vs->fidp->fd == -1) {
+        err = -EINVAL;
+        goto out;
+    }
+
+    err = posix_lseek(s, vs->fidp->fd, vs->off, SEEK_SET);
+
+    v9fs_write_post_lseek(s, vs, err);
+    return;
+
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
 }
 
 static void v9fs_create(V9fsState *s, V9fsPDU *pdu)
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 10/32] virtio-9p: Implement P9_TCREATE
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (8 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 11/32] virtio-9p: Implement P9_TWSTAT Aneesh Kumar K.V
                   ` (21 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V, Gautham R Shenoy

From: Anthony Liguori <aliguori@us.ibm.com>

[jvrao@linux.vnet.ibm.com: strdup to qemu_strdup conversion]

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p-local.c |   80 +++++++++++++++
 hw/virtio-9p.c       |  266 +++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 344 insertions(+), 2 deletions(-)

diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index c5d1db3..cdae5c0 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -135,6 +135,78 @@ static ssize_t local_writev(void *opaque, int fd, const struct iovec *iov,
     return writev(fd, iov, iovcnt);
 }
 
+static int local_chmod(void *opaque, const char *path, mode_t mode)
+{
+    return chmod(rpath(path), mode);
+}
+
+static int local_mknod(void *opaque, const char *path, mode_t mode, dev_t dev)
+{
+    return mknod(rpath(path), mode, dev);
+}
+
+static int local_mksock(void *opaque, const char *path)
+{
+    struct sockaddr_un addr;
+    int s;
+
+    addr.sun_family = AF_UNIX;
+    snprintf(addr.sun_path, 108, "%s", rpath(path));
+
+    s = socket(PF_UNIX, SOCK_STREAM, 0);
+    if (s == -1)
+	return -1;
+
+    if (bind(s, (struct sockaddr *)&addr, sizeof(addr))) {
+	close(s);
+	return -1;
+    }
+
+    close(s);
+    return 0;
+}
+
+static int local_mkdir(void *opaque, const char *path, mode_t mode)
+{
+    return mkdir(rpath(path), mode);
+}
+
+static int local_fstat(void *opaque, int fd, struct stat *stbuf)
+{
+    return fstat(fd, stbuf);
+}
+
+static int local_open2(void *opaque, const char *path, int flags, mode_t mode)
+{
+    return open(rpath(path), flags, mode);
+}
+
+static int local_symlink(void *opaque, const char *oldpath,
+			 const char *newpath)
+{
+    return symlink(oldpath, rpath(newpath));
+}
+
+static int local_link(void *opaque, const char *oldpath, const char *newpath)
+{
+    char *tmp = qemu_strdup(rpath(oldpath));
+    int err, serrno = 0;
+
+    if (tmp == NULL)
+	return -ENOMEM;
+
+    err = link(tmp, rpath(newpath));
+    if (err == -1)
+	serrno = errno;
+
+    qemu_free(tmp);
+
+    if (err == -1)
+	errno = serrno;
+
+    return err;
+}
+
 static V9fsPosixFileOperations ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
@@ -150,6 +222,14 @@ static V9fsPosixFileOperations ops = {
     .readv = local_readv,
     .lseek = local_lseek,
     .writev = local_writev,
+    .chmod = local_chmod,
+    .mknod = local_mknod,
+    .mksock = local_mksock,
+    .mkdir = local_mkdir,
+    .fstat = local_fstat,
+    .open2 = local_open2,
+    .symlink = local_symlink,
+    .link = local_link,
 };
 
 V9fsPosixFileOperations *virtio_9p_init_local(const char *path)
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index bc26d66..067cc85 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -174,6 +174,47 @@ static int posix_writev(V9fsState *s, int fd, const struct iovec *iov,
     return s->ops->writev(s->ops->opaque, fd, iov, iovcnt);
 }
 
+static int posix_chmod(V9fsState *s, V9fsString *path, mode_t mode)
+{
+    return s->ops->chmod(s->ops->opaque, path->data, mode);
+}
+
+static int posix_mknod(V9fsState *s, V9fsString *path, mode_t mode, dev_t dev)
+{
+    return s->ops->mknod(s->ops->opaque, path->data, mode, dev);
+}
+
+static int posix_mksock(V9fsState *s, V9fsString *path)
+{
+    return s->ops->mksock(s->ops->opaque, path->data);
+}
+
+static int posix_mkdir(V9fsState *s, V9fsString *path, mode_t mode)
+{
+    return s->ops->mkdir(s->ops->opaque, path->data, mode);
+}
+
+static int posix_fstat(V9fsState *s, int fd, struct stat *stbuf)
+{
+    return s->ops->fstat(s->ops->opaque, fd, stbuf);
+}
+
+static int posix_open2(V9fsState *s, V9fsString *path, int flags, mode_t mode)
+{
+    return s->ops->open2(s->ops->opaque, path->data, flags, mode);
+}
+
+static int posix_symlink(V9fsState *s, V9fsString *oldpath,
+			 V9fsString *newpath)
+{
+    return s->ops->symlink(s->ops->opaque, oldpath->data, newpath->data);
+}
+
+static int posix_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
+{
+    return s->ops->link(s->ops->opaque, oldpath->data, newpath->data);
+}
+
 static void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -1418,10 +1459,231 @@ out:
     qemu_free(vs);
 }
 
+typedef struct V9fsCreateState {
+    V9fsPDU *pdu;
+    size_t offset;
+    int32_t fid;
+    V9fsFidState *fidp;
+    V9fsQID qid;
+    int32_t perm;
+    int8_t mode;
+    struct stat stbuf;
+    V9fsString name;
+    V9fsString extension;
+    V9fsString fullname;
+} V9fsCreateState;
+
+static void v9fs_post_create(V9fsState *s, V9fsCreateState *vs, int err)
+{
+    if (err == 0) {
+        v9fs_string_copy(&vs->fidp->path, &vs->fullname);
+        stat_to_qid(&vs->stbuf, &vs->qid);
+
+        vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, 0);
+
+        err = vs->offset;
+    }
+
+    complete_pdu(s, vs->pdu, err);
+    v9fs_string_free(&vs->name);
+    v9fs_string_free(&vs->extension);
+    v9fs_string_free(&vs->fullname);
+    qemu_free(vs);
+}
+
+static void v9fs_create_post_perms(V9fsState *s, V9fsCreateState *vs, int err)
+{
+    if (err) {
+        err = -errno;
+    }
+    v9fs_post_create(s, vs, err);
+}
+
+static void v9fs_create_post_opendir(V9fsState *s, V9fsCreateState *vs,
+                                                                    int err)
+{
+    if (!vs->fidp->dir) {
+        err = -errno;
+    }
+    v9fs_post_create(s, vs, err);
+}
+
+static void v9fs_create_post_dir_lstat(V9fsState *s, V9fsCreateState *vs,
+                                                                    int err)
+{
+    if (err) {
+        err = -errno;
+        goto out;
+    }
+
+    vs->fidp->dir = posix_opendir(s, &vs->fullname);
+    v9fs_create_post_opendir(s, vs, err);
+    return;
+
+out:
+    v9fs_post_create(s, vs, err);
+}
+
+static void v9fs_create_post_mkdir(V9fsState *s, V9fsCreateState *vs, int err)
+{
+    if (err) {
+        err = -errno;
+        goto out;
+    }
+
+    err = posix_lstat(s, &vs->fullname, &vs->stbuf);
+    v9fs_create_post_dir_lstat(s, vs, err);
+    return;
+
+out:
+    v9fs_post_create(s, vs, err);
+}
+
+static void v9fs_create_post_mksock(V9fsState *s, V9fsCreateState *vs,
+                                                                int err)
+{
+    if (err) {
+        err = -errno;
+        goto out;
+    }
+
+    err = posix_chmod(s, &vs->fullname, vs->perm & 0777);
+    v9fs_create_post_perms(s, vs, err);
+    return;
+
+out:
+    v9fs_post_create(s, vs, err);
+}
+
+static void v9fs_create_post_fstat(V9fsState *s, V9fsCreateState *vs, int err)
+{
+    if (err) {
+        vs->fidp->fd = -1;
+        err = -errno;
+    }
+
+    v9fs_post_create(s, vs, err);
+    return;
+}
+
+static void v9fs_create_post_open2(V9fsState *s, V9fsCreateState *vs, int err)
+{
+    if (vs->fidp->fd == -1) {
+        err = -errno;
+        goto out;
+    }
+
+    err = posix_fstat(s, vs->fidp->fd, &vs->stbuf);
+    v9fs_create_post_fstat(s, vs, err);
+
+    return;
+
+out:
+    v9fs_post_create(s, vs, err);
+
+}
+
+static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err)
+{
+
+    if ( err == 0 || errno != ENOENT) {
+        err = -EEXIST;
+        goto out;
+    }
+
+    if (vs->perm & P9_STAT_MODE_DIR) {
+        err = posix_mkdir(s, &vs->fullname, vs->perm & 0777);
+        v9fs_create_post_mkdir(s, vs, err);
+    } else if (vs->perm & P9_STAT_MODE_SYMLINK) {
+        err = posix_symlink(s, &vs->extension, &vs->fullname);
+        v9fs_create_post_perms(s, vs, err);
+    } else if (vs->perm & P9_STAT_MODE_LINK) {
+        int32_t nfid = atoi(vs->extension.data);
+        V9fsFidState *nfidp = lookup_fid(s, nfid);
+
+        if (nfidp == NULL) {
+            err = -errno;
+            v9fs_post_create(s, vs, err);
+        }
+
+        err = posix_link(s, &nfidp->path, &vs->fullname);
+        v9fs_create_post_perms(s, vs, err);
+    } else if (vs->perm & P9_STAT_MODE_DEVICE) {
+        char ctype;
+        uint32_t major, minor;
+        mode_t nmode = 0;
+
+        if (sscanf(vs->extension.data, "%c %u %u", &ctype, &major, &minor) != 3) {
+            err = -errno;
+            v9fs_post_create(s, vs, err);
+        }
+
+        switch (ctype) {
+        case 'c':
+            nmode = S_IFCHR;
+            break;
+        case 'b':
+            nmode = S_IFBLK;
+            break;
+        default:
+            err = -EIO;
+            v9fs_post_create(s, vs, err);
+        }
+
+        nmode |= vs->perm & 0777;
+        err = posix_mknod(s, &vs->fullname, nmode, makedev(major, minor));
+        v9fs_create_post_perms(s, vs, err);
+    } else if (vs->perm & P9_STAT_MODE_NAMED_PIPE) {
+        err = posix_mknod(s, &vs->fullname, S_IFIFO | (vs->mode & 0777), 0);
+        v9fs_post_create(s, vs, err);
+    } else if (vs->perm & P9_STAT_MODE_SOCKET) {
+        err = posix_mksock(s, &vs->fullname);
+        v9fs_create_post_mksock(s, vs, err);
+    } else {
+        vs->fidp->fd = posix_open2(s, &vs->fullname,
+                                omode_to_uflags(vs->mode) | O_CREAT,
+                                vs->perm & 0777);
+        v9fs_create_post_open2(s, vs, err);
+    }
+
+    return;
+
+out:
+    v9fs_post_create(s, vs, err);
+}
+
 static void v9fs_create(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu)
-        pprint_pdu(pdu);
+    V9fsCreateState *vs;
+    int err = 0;
+
+    vs = qemu_malloc(sizeof(*vs));
+    vs->pdu = pdu;
+    vs->offset = 7;
+
+    v9fs_string_init(&vs->fullname);
+
+    pdu_unmarshal(vs->pdu, vs->offset, "dsdbs", &vs->fid, &vs->name,
+                                &vs->perm, &vs->mode, &vs->extension);
+
+    vs->fidp = lookup_fid(s, vs->fid);
+    if (vs->fidp == NULL) {
+        err = -EINVAL;
+        goto out;
+    }
+
+    v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->fidp->path.data,
+                                                        vs->name.data);
+
+    err = posix_lstat(s, &vs->fullname, &vs->stbuf);
+    v9fs_create_post_lstat(s, vs, err);
+    return;
+
+out:
+    complete_pdu(s, vs->pdu, err);
+    v9fs_string_free(&vs->name);
+    v9fs_string_free(&vs->extension);
+    qemu_free(vs);
 }
 
 static void v9fs_flush(V9fsState *s, V9fsPDU *pdu)
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 11/32] virtio-9p: Implement P9_TWSTAT
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (9 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 10/32] virtio-9p: Implement P9_TCREATE Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 12/32] virtio-9p: Implement P9_TREMOVE Aneesh Kumar K.V
                   ` (20 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V, Gautham R Shenoy

From: Anthony Liguori <aliguori@us.ibm.com>

This gets file and directory creation to work

[jvrao@linux.vnet.ibm.com: strdup to qemu_strdup conversion]

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p-local.c |   42 +++++++++
 hw/virtio-9p.c       |  236 +++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 274 insertions(+), 4 deletions(-)

diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index cdae5c0..829e79a 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -207,6 +207,44 @@ static int local_link(void *opaque, const char *oldpath, const char *newpath)
     return err;
 }
 
+static int local_truncate(void *opaque, const char *path, off_t size)
+{
+    return truncate(rpath(path), size);
+}
+
+static int local_rename(void *opaque, const char *oldpath,
+			const char *newpath)
+{
+    char *tmp;
+    int err;
+
+    tmp = qemu_strdup(rpath(oldpath));
+    if (tmp == NULL)
+	return -1;
+
+    err = rename(tmp, rpath(newpath));
+    if (err == -1) {
+	int serrno = errno;
+	qemu_free(tmp);
+	errno = serrno;
+    } else
+	qemu_free(tmp);
+
+    return err;
+
+}
+
+static int local_chown(void *opaque, const char *path, uid_t uid, gid_t gid)
+{
+    return chown(rpath(path), uid, gid);
+}
+
+static int local_utime(void *opaque, const char *path,
+		       const struct utimbuf *buf)
+{
+    return utime(rpath(path), buf);
+}
+
 static V9fsPosixFileOperations ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
@@ -230,6 +268,10 @@ static V9fsPosixFileOperations ops = {
     .open2 = local_open2,
     .symlink = local_symlink,
     .link = local_link,
+    .truncate = local_truncate,
+    .rename = local_rename,
+    .chown = local_chown,
+    .utime = local_utime,
 };
 
 V9fsPosixFileOperations *virtio_9p_init_local(const char *path)
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 067cc85..c8995a3 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -215,6 +215,28 @@ static int posix_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
     return s->ops->link(s->ops->opaque, oldpath->data, newpath->data);
 }
 
+static int posix_truncate(V9fsState *s, V9fsString *path, off_t size)
+{
+    return s->ops->truncate(s->ops->opaque, path->data, size);
+}
+
+static int posix_rename(V9fsState *s, V9fsString *oldpath,
+			V9fsString *newpath)
+{
+    return s->ops->rename(s->ops->opaque, oldpath->data, newpath->data);
+}
+
+static int posix_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid)
+{
+    return s->ops->chown(s->ops->opaque, path->data, uid, gid);
+}
+
+static int posix_utime(V9fsState *s, V9fsString *path,
+		       const struct utimbuf *buf)
+{
+    return s->ops->utime(s->ops->opaque, path->data, buf);
+}
+
 static void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -398,7 +420,8 @@ static size_t pdu_unpack(void *dst, V9fsPDU *pdu, size_t offset, size_t size)
 }
 
 /* FIXME i can do this with less variables */
-static size_t pdu_pack(V9fsPDU *pdu, size_t offset, const void *src, size_t size)
+static size_t pdu_pack(V9fsPDU *pdu, size_t offset, const void *src,
+							size_t size)
 {
     struct iovec *sg = pdu->elem.in_sg;
     size_t off = 0;
@@ -1613,7 +1636,8 @@ static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err)
         uint32_t major, minor;
         mode_t nmode = 0;
 
-        if (sscanf(vs->extension.data, "%c %u %u", &ctype, &major, &minor) != 3) {
+        if (sscanf(vs->extension.data, "%c %u %u", &ctype, &major,
+							&minor) != 3) {
             err = -errno;
             v9fs_post_create(s, vs, err);
         }
@@ -1698,10 +1722,214 @@ static void v9fs_remove(V9fsState *s, V9fsPDU *pdu)
         pprint_pdu(pdu);
 }
 
+static mode_t v9mode_to_mode(uint32_t mode, V9fsString *extension)
+{
+    mode_t ret;
+
+    ret = mode & 0777;
+    if (mode & P9_STAT_MODE_DIR)
+        ret |= S_IFDIR;
+
+    if (dotu) {
+        if (mode & P9_STAT_MODE_SYMLINK)
+            ret |= S_IFLNK;
+        if (mode & P9_STAT_MODE_SOCKET)
+            ret |= S_IFSOCK;
+        if (mode & P9_STAT_MODE_NAMED_PIPE)
+            ret |= S_IFIFO;
+        if (mode & P9_STAT_MODE_DEVICE) {
+            if (extension && extension->data[0] == 'c')
+                ret |= S_IFCHR;
+            else
+                ret |= S_IFBLK;
+        }
+    }
+
+    if (!(ret&~0777))
+        ret |= S_IFREG;
+
+    if (mode & P9_STAT_MODE_SETUID)
+        ret |= S_ISUID;
+    if (mode & P9_STAT_MODE_SETGID)
+        ret |= S_ISGID;
+    if (mode & P9_STAT_MODE_SETVTX)
+        ret |= S_ISVTX;
+
+    return ret;
+}
+
+typedef struct V9fsWstatState
+{
+    V9fsPDU *pdu;
+    size_t offset;
+    int32_t fid;
+    int16_t unused;
+    V9fsStat v9stat;
+    V9fsFidState *fidp;
+    V9fsString nname;
+} V9fsWstatState;
+
+static void v9fs_wstat_post_truncate(V9fsState *s, V9fsWstatState *vs, int err)
+{
+    if (err < 0) {
+        goto out;
+    }
+
+    err = vs->offset;
+
+out:
+    v9fs_stat_free(&vs->v9stat);
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_wstat_post_rename(V9fsState *s, V9fsWstatState *vs, int err)
+{
+    if (err < 0) {
+        goto out;
+    }
+
+    if (vs->v9stat.name.size != 0) {
+        v9fs_string_free(&vs->nname);
+    }
+
+    if (vs->v9stat.length != -1) {
+        if (posix_truncate(s, &vs->fidp->path, vs->v9stat.length) < 0) {
+            err = -errno;
+        }
+    }
+    v9fs_wstat_post_truncate(s, vs, err);
+    return;
+
+out:
+    v9fs_stat_free(&vs->v9stat);
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_wstat_post_chown(V9fsState *s, V9fsWstatState *vs, int err)
+{
+    if (err < 0) {
+        goto out;
+    }
+
+    if (vs->v9stat.name.size != 0) {
+        char *old_name, *new_name;
+        char *end;
+
+        old_name = vs->fidp->path.data;
+        if ((end = strrchr(old_name, '/')))
+            end++;
+        else
+            end = old_name;
+
+        new_name = qemu_malloc(end - old_name + vs->v9stat.name.size + 1);
+        BUG_ON(new_name == NULL);
+
+        memset(new_name, 0, end - old_name + vs->v9stat.name.size + 1);
+        memcpy(new_name, old_name, end - old_name);
+        memcpy(new_name + (end - old_name), vs->v9stat.name.data,
+                vs->v9stat.name.size);
+        vs->nname.data = new_name;
+        vs->nname.size = strlen(new_name);
+
+        if (strcmp(new_name, vs->fidp->path.data) != 0) {
+            if (posix_rename(s, &vs->fidp->path, &vs->nname)) {
+                err = -errno;
+            }
+        }
+    }
+    v9fs_wstat_post_rename(s, vs, err);
+    return;
+
+out:
+    v9fs_stat_free(&vs->v9stat);
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_wstat_post_utime(V9fsState *s, V9fsWstatState *vs, int err)
+{
+    if (err < 0) {
+        goto out;
+    }
+
+    if (vs->v9stat.n_gid != -1) {
+        if (posix_chown(s, &vs->fidp->path, vs->v9stat.n_uid,
+                    vs->v9stat.n_gid)) {
+            err = -errno;
+        }
+    }
+    v9fs_wstat_post_chown(s, vs, err);
+    return;
+
+out:
+    v9fs_stat_free(&vs->v9stat);
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_wstat_post_chmod(V9fsState *s, V9fsWstatState *vs, int err)
+{
+    if (err < 0) {
+        goto out;
+    }
+
+    if (vs->v9stat.mtime != -1) {
+        struct utimbuf tb;
+        tb.actime = 0;
+        tb.modtime = vs->v9stat.mtime;
+        if (posix_utime(s, &vs->fidp->path, &tb)) {
+            err = -errno;
+        }
+    }
+
+    v9fs_wstat_post_utime(s, vs, err);
+    return;
+
+out:
+    v9fs_stat_free(&vs->v9stat);
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
 static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu)
-        pprint_pdu(pdu);
+    V9fsWstatState *vs;
+    int err = 0;
+
+    vs = qemu_malloc(sizeof(*vs));
+    vs->pdu = pdu;
+    vs->offset = 7;
+
+    pdu_unmarshal(pdu, vs->offset, "dwS", &vs->fid, &vs->unused, &vs->v9stat);
+
+    vs->fidp = lookup_fid(s, vs->fid);
+    if (vs->fidp == NULL) {
+        err = -EINVAL;
+        goto out;
+    }
+
+    if (vs->v9stat.mode != -1) {
+        if (vs->v9stat.mode & P9_STAT_MODE_DIR && vs->fidp->dir == NULL) {
+            err = -EIO;
+            goto out;
+        }
+
+        if (posix_chmod(s, &vs->fidp->path,
+                    v9mode_to_mode(vs->v9stat.mode,
+                        &vs->v9stat.extension))) {
+            err = -errno;
+        }
+    }
+
+    v9fs_wstat_post_chmod(s, vs, err);
+    return;
+
+out:
+    v9fs_stat_free(&vs->v9stat);
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
 }
 
 typedef void (pdu_handler_t)(V9fsState *s, V9fsPDU *pdu);
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 12/32] virtio-9p: Implement P9_TREMOVE
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (10 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 11/32] virtio-9p: Implement P9_TWSTAT Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 13/32] virtio-9p: Implement P9_TFLUSH Aneesh Kumar K.V
                   ` (19 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V, Gautham R Shenoy

From: Anthony Liguori <aliguori@us.ibm.com>

This gets file deletion to work

[mohan@in.ibm.com: Fix truncate to use the relative path]

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p-local.c |    7 ++++++
 hw/virtio-9p.c       |   54 ++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 829e79a..dca6175 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -245,6 +245,12 @@ static int local_utime(void *opaque, const char *path,
     return utime(rpath(path), buf);
 }
 
+static int local_remove(void *opaque, const char *path)
+{
+    return remove(rpath(path));
+}
+
+
 static V9fsPosixFileOperations ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
@@ -272,6 +278,7 @@ static V9fsPosixFileOperations ops = {
     .rename = local_rename,
     .chown = local_chown,
     .utime = local_utime,
+    .remove = local_remove,
 };
 
 V9fsPosixFileOperations *virtio_9p_init_local(const char *path)
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index c8995a3..4478e57 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -237,6 +237,11 @@ static int posix_utime(V9fsState *s, V9fsString *path,
     return s->ops->utime(s->ops->opaque, path->data, buf);
 }
 
+static int posix_remove(V9fsState *s, V9fsString *path)
+{
+    return s->ops->remove(s->ops->opaque, path->data);
+}
+
 static void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -1716,10 +1721,55 @@ static void v9fs_flush(V9fsState *s, V9fsPDU *pdu)
         pprint_pdu(pdu);
 }
 
+typedef struct V9fsRemoveState {
+    V9fsPDU *pdu;
+    size_t offset;
+    int32_t fid;
+    V9fsFidState *fidp;
+} V9fsRemoveState;
+
+static void v9fs_remove_post_remove(V9fsState *s, V9fsRemoveState *vs,
+                                                                int err)
+{
+    if (err) {
+        err = -errno;
+        goto out;
+    }
+
+    err = free_fid(s, vs->fid);
+    if (err < 0)
+        goto out;
+
+    err = vs->offset;
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
 static void v9fs_remove(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu)
-        pprint_pdu(pdu);
+    V9fsRemoveState *vs;
+    int err = 0;
+
+    vs = qemu_malloc(sizeof(*vs));
+    vs->pdu = pdu;
+    vs->offset = 7;
+
+    pdu_unmarshal(vs->pdu, vs->offset, "d", &vs->fid);
+
+    vs->fidp = lookup_fid(s, vs->fid);
+    if (vs->fidp == NULL) {
+        err = -EINVAL;
+        goto out;
+    }
+
+    err = posix_remove(s, &vs->fidp->path);
+    v9fs_remove_post_remove(s, vs, err);
+    return;
+
+out:
+    complete_pdu(s, pdu, err);
+    qemu_free(vs);
 }
 
 static mode_t v9mode_to_mode(uint32_t mode, V9fsString *extension)
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 13/32] virtio-9p: Implement P9_TFLUSH
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (11 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 12/32] virtio-9p: Implement P9_TREMOVE Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 14/32] virtio-9p: Add multiple mount point support Aneesh Kumar K.V
                   ` (18 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V

From: Anthony Liguori <aliguori@us.ibm.com>

Don't do anything special for flush

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 4478e57..1dbb982 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -1717,10 +1717,11 @@ out:
 
 static void v9fs_flush(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu)
-        pprint_pdu(pdu);
+    /* A nop call with no return */
+    complete_pdu(s, pdu, 7);
 }
 
+
 typedef struct V9fsRemoveState {
     V9fsPDU *pdu;
     size_t offset;
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 14/32] virtio-9p: Add multiple mount point support
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (12 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 13/32] virtio-9p: Implement P9_TFLUSH Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 15/32] virtio-9p: Use little endian format on virtio Aneesh Kumar K.V
                   ` (17 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V

This patch add a mount tag name in 9p config space. This tag should
uniquely identify the mount point and should be used in the mount
command as the device name

Qemu command line for specifying 9p share directory now becomes
-device virtio-9p-pci,share_path=/mnt/,mount_tag=v_mnt
-device virtio-9p-pci,share_path=/tmp/,mount_tag=v_tmp

NOTE: We now limit tag name to 32 characters because of
virtio config space limitation.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/9p.h              |   26 ++++++
 hw/virtio-9p-local.c |  101 ++++++++++++-------------
 hw/virtio-9p.c       |  206 ++++++++++++++++++++++++-------------------------
 hw/virtio-9p.h       |  141 ++++++++++++++++++++++++++++-------
 hw/virtio-pci.c      |    8 +-
 hw/virtio.h          |    3 +-
 6 files changed, 296 insertions(+), 189 deletions(-)
 create mode 100644 hw/9p.h

diff --git a/hw/9p.h b/hw/9p.h
new file mode 100644
index 0000000..f0ff45b
--- /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
+{
+    char *share_path;
+    /* tag name for the device */
+    char *tag;
+} V9fsConf;
+
+#endif
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index dca6175..4dd6b22 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -22,22 +22,20 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 
-static const char *base_path;
-
-static const char *rpath(const char *path)
+static const char *rpath(V9fsState *s, const char *path)
 {
     /* FIXME: so wrong... */
     static char buffer[4096];
-    snprintf(buffer, sizeof(buffer), "%s/%s", base_path, path);
+    snprintf(buffer, sizeof(buffer), "%s/%s", s->fs_root, path);
     return buffer;
 }
 
-static int local_lstat(void *opaque, const char *path, struct stat *stbuf)
+static int local_lstat(V9fsState *s, const char *path, struct stat *stbuf)
 {
-    return lstat(rpath(path), stbuf);
+    return lstat(rpath(s, path), stbuf);
 }
 
-static int local_setuid(void *opaque, uid_t uid)
+static int local_setuid(V9fsState *s, uid_t uid)
 {
     struct passwd *pw;
     gid_t groups[33];
@@ -72,86 +70,86 @@ static int local_setuid(void *opaque, uid_t uid)
     return 0;
 }
 
-static ssize_t local_readlink(void *opaque, const char *path,
-                                char *buf, size_t bufsz)
+static ssize_t local_readlink(V9fsState *s, const char *path,
+			      char *buf, size_t bufsz)
 {
-    return readlink(rpath(path), buf, bufsz);
+    return readlink(rpath(s, path), buf, bufsz);
 }
 
-static int local_close(void *opaque, int fd)
+static int local_close(V9fsState *s, int fd)
 {
     return close(fd);
 }
 
-static int local_closedir(void *opaque, DIR *dir)
+static int local_closedir(V9fsState *s, DIR *dir)
 {
     return closedir(dir);
 }
 
-static int local_open(void *opaque, const char *path, int flags)
+static int local_open(V9fsState *s, const char *path, int flags)
 {
-    return open(rpath(path), flags);
+    return open(rpath(s, path), flags);
 }
 
-static DIR *local_opendir(void *opaque, const char *path)
+static DIR *local_opendir(V9fsState *s, const char *path)
 {
-    return opendir(rpath(path));
+    return opendir(rpath(s, path));
 }
 
-static void local_rewinddir(void *opaque, DIR *dir)
+static void local_rewinddir(V9fsState *s, DIR *dir)
 {
     return rewinddir(dir);
 }
 
-static off_t local_telldir(void *opaque, DIR *dir)
+static off_t local_telldir(V9fsState *s, DIR *dir)
 {
     return telldir(dir);
 }
 
-static struct dirent *local_readdir(void *opaque, DIR *dir)
+static struct dirent *local_readdir(V9fsState *s, DIR *dir)
 {
     return readdir(dir);
 }
 
-static void local_seekdir(void *opaque, DIR *dir, off_t off)
+static void local_seekdir(V9fsState *s, DIR *dir, off_t off)
 {
     return seekdir(dir, off);
 }
 
-static ssize_t local_readv(void *opaque, int fd, const struct iovec *iov,
+static ssize_t local_readv(V9fsState *s, int fd, const struct iovec *iov,
 			   int iovcnt)
 {
     return readv(fd, iov, iovcnt);
 }
 
-static off_t local_lseek(void *opaque, int fd, off_t offset, int whence)
+static off_t local_lseek(V9fsState *s, int fd, off_t offset, int whence)
 {
     return lseek(fd, offset, whence);
 }
 
-static ssize_t local_writev(void *opaque, int fd, const struct iovec *iov,
+static ssize_t local_writev(V9fsState *s, int fd, const struct iovec *iov,
 			    int iovcnt)
 {
     return writev(fd, iov, iovcnt);
 }
 
-static int local_chmod(void *opaque, const char *path, mode_t mode)
+static int local_chmod(V9fsState *s, const char *path, mode_t mode)
 {
-    return chmod(rpath(path), mode);
+    return chmod(rpath(s, path), mode);
 }
 
-static int local_mknod(void *opaque, const char *path, mode_t mode, dev_t dev)
+static int local_mknod(V9fsState *s, const char *path, mode_t mode, dev_t dev)
 {
-    return mknod(rpath(path), mode, dev);
+    return mknod(rpath(s, path), mode, dev);
 }
 
-static int local_mksock(void *opaque, const char *path)
+static int local_mksock(V9fsState *s2, const char *path)
 {
     struct sockaddr_un addr;
     int s;
 
     addr.sun_family = AF_UNIX;
-    snprintf(addr.sun_path, 108, "%s", rpath(path));
+    snprintf(addr.sun_path, 108, "%s", rpath(s2, path));
 
     s = socket(PF_UNIX, SOCK_STREAM, 0);
     if (s == -1)
@@ -166,36 +164,36 @@ static int local_mksock(void *opaque, const char *path)
     return 0;
 }
 
-static int local_mkdir(void *opaque, const char *path, mode_t mode)
+static int local_mkdir(V9fsState *s, const char *path, mode_t mode)
 {
-    return mkdir(rpath(path), mode);
+    return mkdir(rpath(s, path), mode);
 }
 
-static int local_fstat(void *opaque, int fd, struct stat *stbuf)
+static int local_fstat(V9fsState *s, int fd, struct stat *stbuf)
 {
     return fstat(fd, stbuf);
 }
 
-static int local_open2(void *opaque, const char *path, int flags, mode_t mode)
+static int local_open2(V9fsState *s, const char *path, int flags, mode_t mode)
 {
-    return open(rpath(path), flags, mode);
+    return open(rpath(s, path), flags, mode);
 }
 
-static int local_symlink(void *opaque, const char *oldpath,
+static int local_symlink(V9fsState *s, const char *oldpath,
 			 const char *newpath)
 {
-    return symlink(oldpath, rpath(newpath));
+    return symlink(oldpath, rpath(s, newpath));
 }
 
-static int local_link(void *opaque, const char *oldpath, const char *newpath)
+static int local_link(V9fsState *s, const char *oldpath, const char *newpath)
 {
-    char *tmp = qemu_strdup(rpath(oldpath));
+    char *tmp = qemu_strdup(rpath(s, oldpath));
     int err, serrno = 0;
 
     if (tmp == NULL)
 	return -ENOMEM;
 
-    err = link(tmp, rpath(newpath));
+    err = link(tmp, rpath(s, newpath));
     if (err == -1)
 	serrno = errno;
 
@@ -207,22 +205,22 @@ static int local_link(void *opaque, const char *oldpath, const char *newpath)
     return err;
 }
 
-static int local_truncate(void *opaque, const char *path, off_t size)
+static int local_truncate(V9fsState *s, const char *path, off_t size)
 {
-    return truncate(rpath(path), size);
+    return truncate(rpath(s, path), size);
 }
 
-static int local_rename(void *opaque, const char *oldpath,
+static int local_rename(V9fsState *s, const char *oldpath,
 			const char *newpath)
 {
     char *tmp;
     int err;
 
-    tmp = qemu_strdup(rpath(oldpath));
+    tmp = qemu_strdup(rpath(s, oldpath));
     if (tmp == NULL)
 	return -1;
 
-    err = rename(tmp, rpath(newpath));
+    err = rename(tmp, rpath(s, newpath));
     if (err == -1) {
 	int serrno = errno;
 	qemu_free(tmp);
@@ -234,20 +232,20 @@ static int local_rename(void *opaque, const char *oldpath,
 
 }
 
-static int local_chown(void *opaque, const char *path, uid_t uid, gid_t gid)
+static int local_chown(V9fsState *s, const char *path, uid_t uid, gid_t gid)
 {
-    return chown(rpath(path), uid, gid);
+    return chown(rpath(s, path), uid, gid);
 }
 
-static int local_utime(void *opaque, const char *path,
+static int local_utime(V9fsState *s, const char *path,
 		       const struct utimbuf *buf)
 {
-    return utime(rpath(path), buf);
+    return utime(rpath(s, path), buf);
 }
 
-static int local_remove(void *opaque, const char *path)
+static int local_remove(V9fsState *s, const char *path)
 {
-    return remove(rpath(path));
+    return remove(rpath(s, path));
 }
 
 
@@ -283,6 +281,5 @@ static V9fsPosixFileOperations ops = {
 
 V9fsPosixFileOperations *virtio_9p_init_local(const char *path)
 {
-    base_path = path;
-    return &ops;
+return &ops;
 }
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 1dbb982..e095916 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -15,78 +15,8 @@
 #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;
-    V9fsPosixFileOperations *ops;
-    char *root;
-    uid_t uid;
-} V9fsState;
-
 int dotu = 1;
 int debug_9p_pdu = 1;
 
@@ -94,12 +24,12 @@ extern void pprint_pdu(V9fsPDU *pdu);
 
 static int posix_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf)
 {
-    return s->ops->lstat(s->ops->opaque, path->data, stbuf);
+    return s->ops->lstat(s, path->data, stbuf);
 }
 
 static int posix_setuid(V9fsState *s, uid_t uid)
 {
-    return s->ops->setuid(s->ops->opaque, uid);
+    return s->ops->setuid(s, uid);
 }
 
 static ssize_t posix_readlink(V9fsState *s, V9fsString *path, V9fsString *buf)
@@ -108,7 +38,7 @@ static ssize_t posix_readlink(V9fsState *s, V9fsString *path, V9fsString *buf)
 
     buf->data = qemu_malloc(1024);
 
-    len = s->ops->readlink(s->ops->opaque, path->data, buf->data, 1024 - 1);
+    len = s->ops->readlink(s, path->data, buf->data, 1024 - 1);
     if (len > -1) {
         buf->size = len;
         buf->data[len] = 0;
@@ -119,127 +49,127 @@ static ssize_t posix_readlink(V9fsState *s, V9fsString *path, V9fsString *buf)
 
 static int posix_close(V9fsState *s, int fd)
 {
-    return s->ops->close(s->ops->opaque, fd);
+    return s->ops->close(s, fd);
 }
 
 static int posix_closedir(V9fsState *s, DIR *dir)
 {
-    return s->ops->closedir(s->ops->opaque, dir);
+    return s->ops->closedir(s, dir);
 }
 
 static int posix_open(V9fsState *s, V9fsString *path, int flags)
 {
-    return s->ops->open(s->ops->opaque, path->data, flags);
+    return s->ops->open(s, path->data, flags);
 }
 
 static DIR *posix_opendir(V9fsState *s, V9fsString *path)
 {
-    return s->ops->opendir(s->ops->opaque, path->data);
+    return s->ops->opendir(s, path->data);
 }
 
 static void posix_rewinddir(V9fsState *s, DIR *dir)
 {
-    return s->ops->rewinddir(s->ops->opaque, dir);
+    return s->ops->rewinddir(s, dir);
 }
 
 static off_t posix_telldir(V9fsState *s, DIR *dir)
 {
-    return s->ops->telldir(s->ops->opaque, dir);
+    return s->ops->telldir(s, dir);
 }
 
 static struct dirent *posix_readdir(V9fsState *s, DIR *dir)
 {
-    return s->ops->readdir(s->ops->opaque, dir);
+    return s->ops->readdir(s, dir);
 }
 
 static void posix_seekdir(V9fsState *s, DIR *dir, off_t off)
 {
-    return s->ops->seekdir(s->ops->opaque, dir, off);
+    return s->ops->seekdir(s, dir, off);
 }
 
 static int posix_readv(V9fsState *s, int fd, const struct iovec *iov,
 		       int iovcnt)
 {
-    return s->ops->readv(s->ops->opaque, fd, iov, iovcnt);
+    return s->ops->readv(s, fd, iov, iovcnt);
 }
 
 static off_t posix_lseek(V9fsState *s, int fd, off_t offset, int whence)
 {
-    return s->ops->lseek(s->ops->opaque, fd, offset, whence);
+    return s->ops->lseek(s, fd, offset, whence);
 }
 
 static int posix_writev(V9fsState *s, int fd, const struct iovec *iov,
                        int iovcnt)
 {
-    return s->ops->writev(s->ops->opaque, fd, iov, iovcnt);
+    return s->ops->writev(s, fd, iov, iovcnt);
 }
 
 static int posix_chmod(V9fsState *s, V9fsString *path, mode_t mode)
 {
-    return s->ops->chmod(s->ops->opaque, path->data, mode);
+    return s->ops->chmod(s, path->data, mode);
 }
 
 static int posix_mknod(V9fsState *s, V9fsString *path, mode_t mode, dev_t dev)
 {
-    return s->ops->mknod(s->ops->opaque, path->data, mode, dev);
+    return s->ops->mknod(s, path->data, mode, dev);
 }
 
 static int posix_mksock(V9fsState *s, V9fsString *path)
 {
-    return s->ops->mksock(s->ops->opaque, path->data);
+    return s->ops->mksock(s, path->data);
 }
 
 static int posix_mkdir(V9fsState *s, V9fsString *path, mode_t mode)
 {
-    return s->ops->mkdir(s->ops->opaque, path->data, mode);
+    return s->ops->mkdir(s, path->data, mode);
 }
 
 static int posix_fstat(V9fsState *s, int fd, struct stat *stbuf)
 {
-    return s->ops->fstat(s->ops->opaque, fd, stbuf);
+    return s->ops->fstat(s, fd, stbuf);
 }
 
 static int posix_open2(V9fsState *s, V9fsString *path, int flags, mode_t mode)
 {
-    return s->ops->open2(s->ops->opaque, path->data, flags, mode);
+    return s->ops->open2(s, path->data, flags, mode);
 }
 
 static int posix_symlink(V9fsState *s, V9fsString *oldpath,
 			 V9fsString *newpath)
 {
-    return s->ops->symlink(s->ops->opaque, oldpath->data, newpath->data);
+    return s->ops->symlink(s, oldpath->data, newpath->data);
 }
 
 static int posix_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
 {
-    return s->ops->link(s->ops->opaque, oldpath->data, newpath->data);
+    return s->ops->link(s, oldpath->data, newpath->data);
 }
 
 static int posix_truncate(V9fsState *s, V9fsString *path, off_t size)
 {
-    return s->ops->truncate(s->ops->opaque, path->data, size);
+    return s->ops->truncate(s, path->data, size);
 }
 
 static int posix_rename(V9fsState *s, V9fsString *oldpath,
 			V9fsString *newpath)
 {
-    return s->ops->rename(s->ops->opaque, oldpath->data, newpath->data);
+    return s->ops->rename(s, oldpath->data, newpath->data);
 }
 
 static int posix_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid)
 {
-    return s->ops->chown(s->ops->opaque, path->data, uid, gid);
+    return s->ops->chown(s, path->data, uid, gid);
 }
 
 static int posix_utime(V9fsState *s, V9fsString *path,
 		       const struct utimbuf *buf)
 {
-    return s->ops->utime(s->ops->opaque, path->data, buf);
+    return s->ops->utime(s, path->data, buf);
 }
 
 static int posix_remove(V9fsState *s, V9fsString *path)
 {
-    return s->ops->remove(s->ops->opaque, path->data);
+    return s->ops->remove(s, path->data);
 }
 
 static void v9fs_string_init(V9fsString *str)
@@ -785,7 +715,7 @@ static void v9fs_attach(V9fsState *s, V9fsPDU *pdu)
 
     fidp->uid = n_uname;
 
-    v9fs_string_sprintf(&fidp->path, "%s", s->root);
+    v9fs_string_sprintf(&fidp->path, "%s", "/");
     fid_to_qid(s, fidp, &qid);
 
     offset += pdu_marshal(pdu, offset, "Q", &qid);
@@ -2045,17 +1975,58 @@ static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
 
 static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features)
 {
+    features |= 1 << VIRTIO_9P_MOUNT_TAG;
     return features;
 }
 
-VirtIODevice *virtio_9p_init(DeviceState *dev, const char *path)
+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);
+    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));
+    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;
+    int i, len;
+    struct stat stat;
+
 
     s = (V9fsState *)virtio_common_init("virtio-9p",
-                                        VIRTIO_ID_9P,
-                                        0, sizeof(V9fsState));
+                                    VIRTIO_ID_9P,
+                                    sizeof(struct virtio_9p_config)+
+                                    MAX_TAG_LEN,
+                                    sizeof(V9fsState));
 
     /* initialize pdu allocator */
     s->free_pdu = &s->pdus[0];
@@ -2066,12 +2037,37 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, const char *path)
     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);
+    if (!conf->share_path || !conf->tag) {
+	    /* we haven't specified a mount_tag */
+	    fprintf(stderr, "Virtio-9p devices need share_path "
+		    "and mount_tag arguments\n");
+	    exit(1);
+    }
+    if (lstat(conf->share_path, &stat)) {
+	    fprintf(stderr, "share path %s does not exist\n", conf->share_path);
+	    exit(1);
+    } else if (!S_ISDIR(stat.st_mode)) {
+	    fprintf(stderr, "share path %s is not a directory \n", conf->share_path);
+	    exit(1);
+    }
+    s->fs_root = qemu_strdup(conf->share_path);
+    len = strlen(conf->tag);
+    if (len > MAX_TAG_LEN)
+	    len = MAX_TAG_LEN;
+    /* s->tag is non-NULL terminated string */
+    s->tag = qemu_malloc(len);
+    memcpy(s->tag, conf->tag, len);
+    s->tag_len = len;
+    BUG_ON(s->fs_root == NULL);
     s->uid = -1;
 
-    s->ops = virtio_9p_init_local(path);
+    s->ops = virtio_9p_init_local(conf->share_path);
     s->vdev.get_features = virtio_9p_get_features;
+    s->config_size = sizeof(struct virtio_9p_config) +
+			s->tag_len;
+    s->vdev.get_config = virtio_9p_get_config;
+    s->vdev.set_config = virtio_9p_set_config;
+
 
     return &s->vdev;
 }
diff --git a/hw/virtio-9p.h b/hw/virtio-9p.h
index 8e15bf0..3fc88a4 100644
--- a/hw/virtio-9p.h
+++ b/hw/virtio-9p.h
@@ -6,6 +6,10 @@
 #include <sys/time.h>
 #include <utime.h>
 
+/* The feature bitmap for virtio 9P */
+/* The mount point is specified in a config variable */
+#define VIRTIO_9P_MOUNT_TAG 0
+
 enum {
     P9_TVERSION = 100,
     P9_RVERSION,
@@ -66,35 +70,118 @@ struct V9fsPDU
     V9fsPDU *next;
 };
 
+/* FIXME
+ * 1) change user needs to set groups and stuff
+ */
+
+/* from Linux's linux/virtio_9p.h */
+
+/* The ID for virtio console */
+#define VIRTIO_ID_9P	9
+#define MAX_REQ		128
+#define MAX_TAG_LEN	32
+
+#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;
+};
+
+struct V9fsPosixFileOpertions ;
+typedef struct V9fsState
+{
+    VirtIODevice vdev;
+    VirtQueue *vq;
+    V9fsPDU pdus[MAX_REQ];
+    V9fsPDU *free_pdu;
+    V9fsFidState *fid_list;
+    struct V9fsPosixFileOpertions *ops;
+    char *fs_root;
+    uid_t uid;
+    uint16_t tag_len;
+    uint8_t *tag;
+    size_t config_size;
+} V9fsState;
+
+struct virtio_9p_config
+{
+    /* number of characters in tag */
+    uint16_t tag_len;
+    /* Variable size tag name */
+    uint8_t tag[0];
+} __attribute__((packed));
+
 typedef struct V9fsPosixFileOpertions
 {
-    int (*lstat)(void *, const char *, struct stat *);
-    ssize_t (*readlink)(void *, const char *, char *, size_t);
-    int (*chmod)(void *, const char *, mode_t);
-    int (*chown)(void *, const char *, uid_t, gid_t);
-    int (*mknod)(void *, const char *, mode_t, dev_t);
-    int (*mksock)(void *, const char *);
-    int (*utime)(void *, const char *, const struct utimbuf *);
-    int (*remove)(void *, const char *);
-    int (*symlink)(void *, const char *, const char *);
-    int (*link)(void *, const char *, const char *);
-    int (*setuid)(void *, uid_t);
-    int (*close)(void *, int);
-    int (*closedir)(void *, DIR *);
-    DIR *(*opendir)(void *, const char *);
-    int (*open)(void *, const char *, int);
-    int (*open2)(void *, const char *, int, mode_t);
-    void (*rewinddir)(void *, DIR *);
-    off_t (*telldir)(void *, DIR *);
-    struct dirent *(*readdir)(void *, DIR *);
-    void (*seekdir)(void *, DIR *, off_t);
-    ssize_t (*readv)(void *, int, const struct iovec *, int);
-    ssize_t (*writev)(void *, int, const struct iovec *, int);
-    off_t (*lseek)(void *, int, off_t, int);
-    int (*mkdir)(void *, const char *, mode_t);
-    int (*fstat)(void *, int, struct stat *);
-    int (*rename)(void *, const char *, const char *);
-    int (*truncate)(void *, const char *, off_t);
+    int (*lstat)(V9fsState *, const char *, struct stat *);
+    ssize_t (*readlink)(V9fsState *, const char *, char *, size_t);
+    int (*chmod)(V9fsState *, const char *, mode_t);
+    int (*chown)(V9fsState *, const char *, uid_t, gid_t);
+    int (*mknod)(V9fsState *, const char *, mode_t, dev_t);
+    int (*mksock)(V9fsState *, const char *);
+    int (*utime)(V9fsState *, const char *, const struct utimbuf *);
+    int (*remove)(V9fsState *, const char *);
+    int (*symlink)(V9fsState *, const char *, const char *);
+    int (*link)(V9fsState *, const char *, const char *);
+    int (*setuid)(V9fsState *, uid_t);
+    int (*close)(V9fsState *, int);
+    int (*closedir)(V9fsState *, DIR *);
+    DIR *(*opendir)(V9fsState *, const char *);
+    int (*open)(V9fsState *, const char *, int);
+    int (*open2)(V9fsState *, const char *, int, mode_t);
+    void (*rewinddir)(V9fsState *, DIR *);
+    off_t (*telldir)(V9fsState *, DIR *);
+    struct dirent *(*readdir)(V9fsState *, DIR *);
+    void (*seekdir)(V9fsState *, DIR *, off_t);
+    ssize_t (*readv)(V9fsState *, int, const struct iovec *, int);
+    ssize_t (*writev)(V9fsState *, int, const struct iovec *, int);
+    off_t (*lseek)(V9fsState *, int, off_t, int);
+    int (*mkdir)(V9fsState *, const char *, mode_t);
+    int (*fstat)(V9fsState *, int, struct stat *);
+    int (*rename)(V9fsState *, const char *, const char *);
+    int (*truncate)(V9fsState *, const char *, off_t);
     void *opaque;
 } V9fsPosixFileOperations;
 
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 85879fb..73e7df7 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -86,7 +86,6 @@
 #define wmb() do { } while (0)
 
 /* PCI bindings.  */
-
 typedef struct {
     PCIDevice pci_dev;
     VirtIODevice *vdev;
@@ -96,7 +95,7 @@ typedef struct {
     BlockConf block;
     NICConf nic;
     uint32_t host_features;
-    char *share_path;
+    V9fsConf fsconf;
     /* Max. number of ports we can have for a the virtio-serial device */
     uint32_t max_virtserial_ports;
 } VirtIOPCIProxy;
@@ -558,7 +557,7 @@ 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);
+    vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf);
     virtio_init_pci(proxy, vdev,
 		    PCI_VENDOR_ID_REDHAT_QUMRANET,
 		    0x1009,
@@ -627,7 +626,8 @@ static PCIDeviceInfo virtio_info[] = {
         .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_STRING("share_path", VirtIOPCIProxy, fsconf.share_path),
+            DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
             DEFINE_PROP_END_OF_LIST(),
         },
     },{
diff --git a/hw/virtio.h b/hw/virtio.h
index 4032a96..c11a380 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -19,6 +19,7 @@
 #include "qdev.h"
 #include "sysemu.h"
 #include "block_int.h"
+#include "9p.h"
 
 /* from Linux's linux/virtio_config.h */
 
@@ -174,7 +175,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);
+VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
 
 void virtio_net_exit(VirtIODevice *vdev);
 
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 15/32] virtio-9p: Use little endian format on virtio
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (13 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 14/32] virtio-9p: Add multiple mount point support Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 16/32] virtio-9p: Add support for hardlink Aneesh Kumar K.V
                   ` (16 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V

We need to use platform independent data format as
part of protocol data. 9P uses little endian format
on wire

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p.c |   34 +++++++++++++++++++++++-----------
 1 files changed, 23 insertions(+), 11 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index e095916..e8a9eeb 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -426,23 +426,32 @@ static size_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
     for (i = 0; fmt[i]; i++) {
 	switch (fmt[i]) {
 	case 'b': {
-	    int8_t *valp = va_arg(ap, int8_t *);
+	    uint8_t *valp = va_arg(ap, uint8_t *);
 	    offset += pdu_unpack(valp, pdu, offset, sizeof(*valp));
 	    break;
 	}
 	case 'w': {
-	    int16_t *valp = va_arg(ap, int16_t *);
-	    offset += pdu_unpack(valp, pdu, offset, sizeof(*valp));
+	    uint16_t val, *valp;
+	    valp = va_arg(ap, uint16_t *);
+	    val = le16_to_cpupu(valp);
+	    offset += pdu_unpack(&val, pdu, offset, sizeof(val));
+	    *valp = val;
 	    break;
 	}
 	case 'd': {
-	    int32_t *valp = va_arg(ap, int32_t *);
-	    offset += pdu_unpack(valp, pdu, offset, sizeof(*valp));
+	    uint32_t val, *valp;
+	    valp = va_arg(ap, uint32_t *);
+	    val = le32_to_cpupu(valp);
+	    offset += pdu_unpack(&val, pdu, offset, sizeof(val));
+	    *valp = val;
 	    break;
 	}
 	case 'q': {
-	    int64_t *valp = va_arg(ap, int64_t *);
-	    offset += pdu_unpack(valp, pdu, offset, sizeof(*valp));
+	    uint64_t val, *valp;
+	    valp = va_arg(ap, uint64_t *);
+	    val = le64_to_cpup(valp);
+	    offset += pdu_unpack(&val, pdu, offset, sizeof(val));
+	    *valp = val;
 	    break;
 	}
 	case 'v': {
@@ -498,22 +507,25 @@ static size_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
     for (i = 0; fmt[i]; i++) {
 	switch (fmt[i]) {
 	case 'b': {
-	    int8_t val = va_arg(ap, int);
+	    uint8_t val = va_arg(ap, int);
 	    offset += pdu_pack(pdu, offset, &val, sizeof(val));
 	    break;
 	}
 	case 'w': {
-	    int16_t val = va_arg(ap, int);
+	    uint16_t val;
+	    cpu_to_le16w(&val, va_arg(ap, int));
 	    offset += pdu_pack(pdu, offset, &val, sizeof(val));
 	    break;
 	}
 	case 'd': {
-	    int32_t val = va_arg(ap, int);
+	    uint32_t val;
+	    cpu_to_le32w(&val, va_arg(ap, uint32_t));
 	    offset += pdu_pack(pdu, offset, &val, sizeof(val));
 	    break;
 	}
 	case 'q': {
-	    int64_t val = va_arg(ap, int64_t);
+	    uint64_t val;
+	    cpu_to_le64w(&val, va_arg(ap, uint64_t));
 	    offset += pdu_pack(pdu, offset, &val, sizeof(val));
 	    break;
 	}
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 16/32] virtio-9p: Add support for hardlink
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (14 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 15/32] virtio-9p: Use little endian format on virtio Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 17/32] Implement sync support in 9p server Aneesh Kumar K.V
                   ` (15 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V

link count for files and directories are encoded as
a tagged string in the extension field for a .u protocol
extension.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index e8a9eeb..3ddf2b9 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -674,6 +674,9 @@ static void stat_to_v9stat(V9fsState *s, V9fsString *name,
             v9fs_string_sprintf(&v9stat->extension, "%c %u %u",
                     S_ISCHR(stbuf->st_mode) ? 'c' : 'b',
                     major(stbuf->st_rdev), minor(stbuf->st_rdev));
+        } else if (S_ISDIR(stbuf->st_mode) || S_ISREG(stbuf->st_mode)) {
+            v9fs_string_sprintf(&v9stat->extension, "%s %u",
+                    "HARDLINKCOUNT", stbuf->st_nlink);
         }
     }
 
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 17/32] Implement sync support in 9p server
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (15 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 16/32] virtio-9p: Add support for hardlink Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 18/32] virtio-9p: Fix sg usage in the code Aneesh Kumar K.V
                   ` (14 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, M. Mohan Kumar, Aneesh Kumar K.V

From: M. Mohan Kumar <mohan@in.ibm.com>

When wstat is called with stat field values set to 'don't touch' pattern,
9p Server interprets it as a request to guarantee that the contents of
the associated file are committed to stable storage before the Rwstat
message is returned. Implement this feature in the server side.

[jvrao@linux.vnet.ibm.com:  Proper error handling and state friendliness]

Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p-local.c |    6 ++++++
 hw/virtio-9p.c       |   45 +++++++++++++++++++++++++++++++++++++++++++++
 hw/virtio-9p.h       |    1 +
 3 files changed, 52 insertions(+), 0 deletions(-)

diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 4dd6b22..4584bf6 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -249,6 +249,11 @@ static int local_remove(V9fsState *s, const char *path)
 }
 
 
+static int local_fsync(V9fsState *s, int fd)
+{
+    return fsync(fd);
+}
+
 static V9fsPosixFileOperations ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
@@ -277,6 +282,7 @@ static V9fsPosixFileOperations ops = {
     .chown = local_chown,
     .utime = local_utime,
     .remove = local_remove,
+    .fsync = local_fsync,
 };
 
 V9fsPosixFileOperations *virtio_9p_init_local(const char *path)
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 3ddf2b9..3a5b3f0 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -172,6 +172,11 @@ static int posix_remove(V9fsState *s, V9fsString *path)
     return s->ops->remove(s, path->data);
 }
 
+static int posix_fsync(V9fsState *s, int fd)
+{
+    return s->ops->fsync(s, fd);
+}
+
 static void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -1889,6 +1894,39 @@ out:
     qemu_free(vs);
 }
 
+static void v9fs_wstat_post_fsync(V9fsState *s, V9fsWstatState *vs, int err)
+{
+    if (err == -1) {
+        err = -errno;
+    }
+    v9fs_stat_free(&vs->v9stat);
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
+static int donttouch_stat(V9fsStat *stat)
+{
+    if (stat->type == -1 &&
+	stat->dev == -1 &&
+	stat->qid.type == -1 &&
+	stat->qid.version == -1 &&
+	stat->qid.path == -1 &&
+	stat->mode == -1 &&
+	stat->atime == -1 &&
+	stat->mtime == -1 &&
+	stat->length == -1 &&
+	!stat->name.size &&
+	!stat->uid.size &&
+	!stat->gid.size &&
+	!stat->muid.size &&
+	stat->n_uid == -1 &&
+	stat->n_gid == -1 &&
+	stat->n_muid == -1)
+		return 1;
+	else
+		return 0;
+}
+
 static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
 {
     V9fsWstatState *vs;
@@ -1906,6 +1944,13 @@ static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
         goto out;
     }
 
+    /* do we need to sync the file? */
+    if (donttouch_stat(&vs->v9stat)) {
+        err = posix_fsync(s, vs->fidp->fd);
+        v9fs_wstat_post_fsync(s, vs, err);
+        return;
+    }
+
     if (vs->v9stat.mode != -1) {
         if (vs->v9stat.mode & P9_STAT_MODE_DIR && vs->fidp->dir == NULL) {
             err = -EIO;
diff --git a/hw/virtio-9p.h b/hw/virtio-9p.h
index 3fc88a4..da0aa64 100644
--- a/hw/virtio-9p.h
+++ b/hw/virtio-9p.h
@@ -182,6 +182,7 @@ typedef struct V9fsPosixFileOpertions
     int (*fstat)(V9fsState *, int, struct stat *);
     int (*rename)(V9fsState *, const char *, const char *);
     int (*truncate)(V9fsState *, const char *, off_t);
+    int (*fsync)(V9fsState *, int);
     void *opaque;
 } V9fsPosixFileOperations;
 
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 18/32] virtio-9p: Fix sg usage in the code
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (16 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 17/32] Implement sync support in 9p server Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 19/32] virtio-9p: Get the correct count values from the pdu Aneesh Kumar K.V
                   ` (13 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V

sg list contain more than one element and we need to use the right
element when we are doing the marshaling and unmarshaling of data.
This patch also abstract out the pack/unpack interface and make sure
we use one function for doing both.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p-debug.c |   83 +++++++++++++++++++++++++++++++++----------------
 hw/virtio-9p.c       |   57 ++++++++++++++++++++--------------
 hw/virtio-9p.h       |    9 +++++
 3 files changed, 98 insertions(+), 51 deletions(-)

diff --git a/hw/virtio-9p-debug.c b/hw/virtio-9p-debug.c
index 9230659..ee222db 100644
--- a/hw/virtio-9p-debug.c
+++ b/hw/virtio-9p-debug.c
@@ -29,92 +29,121 @@ static struct iovec *get_sg(V9fsPDU *pdu, int rx)
     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)
 {
-    struct iovec *sg = get_sg(pdu, rx);
+    size_t copied;
+    int count = get_sg_count(pdu, rx);
     size_t offset = *offsetp;
+    struct iovec *sg = get_sg(pdu, rx);
     int8_t value;
 
-    BUG_ON((offset + sizeof(value)) > sg[0].iov_len);
+    copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
 
-    memcpy(&value, sg[0].iov_base + 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;
 
-    BUG_ON((offset + sizeof(value)) > sg[0].iov_len);
 
-    memcpy(&value, sg[0].iov_base + offset, sizeof(value));
-    offset += sizeof(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;
 
-    BUG_ON((offset + sizeof(value)) > sg[0].iov_len);
 
-    memcpy(&value, sg[0].iov_base + offset, sizeof(value));
-    offset += sizeof(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;
 
-    BUG_ON((offset + sizeof(value)) > sg[0].iov_len);
 
-    memcpy(&value, sg[0].iov_base + offset, sizeof(value));
-    offset += sizeof(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;
-    int16_t size;
+    uint16_t tmp_size, size;
     size_t result;
+    size_t copied = 0;
+    int i = 0;
 
-    BUG_ON((offset + 2) > sg[0].iov_len);
-    memcpy(&size, sg[0].iov_base + offset, 2);
-    offset += 2;
+    /* 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;
 
-    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;
+    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)
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 3a5b3f0..1237bac 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -351,42 +351,51 @@ static void free_pdu(V9fsState *s, V9fsPDU *pdu)
     }
 }
 
-static size_t pdu_unpack(void *dst, V9fsPDU *pdu, size_t offset, size_t size)
-{
-    struct iovec *sg = pdu->elem.out_sg;
-    BUG_ON((offset + size) > sg[0].iov_len);
-    memcpy(dst, sg[0].iov_base + offset, size);
-    return size;
-}
-
-/* FIXME i can do this with less variables */
-static size_t pdu_pack(V9fsPDU *pdu, size_t offset, const void *src,
-							size_t size)
+size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
+                        size_t offset, size_t size, int pack)
 {
-    struct iovec *sg = pdu->elem.in_sg;
-    size_t off = 0;
-    size_t copied = 0;
     int i = 0;
+    size_t copied = 0;
 
-    for (i = 0; size && i < pdu->elem.in_num; i++) {
+    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 {
 
-        if (offset >= off && offset < (off + sg[i].iov_len)) {
-            len = MIN(sg[i].iov_len - (offset - off), size);
-            memcpy(sg[i].iov_base + (offset - off), src, len);
+            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;
-            offset += len;
-            off = offset;
             copied += len;
-            src += len;
-        } else {
-            off += sg[i].iov_len;
+            addr += len;
+            if (size) {
+                offset = 0;
+                continue;
+            }
         }
     }
-
     return copied;
 }
 
+static size_t pdu_unpack(void *dst, V9fsPDU *pdu, size_t offset, size_t size)
+{
+    return pdu_packunpack(dst, pdu->elem.out_sg, pdu->elem.out_num,
+                         offset, size, 0);
+}
+
+static size_t pdu_pack(V9fsPDU *pdu, size_t offset, const void *src,
+							size_t size)
+{
+    return pdu_packunpack((void *)src, pdu->elem.in_sg, pdu->elem.in_num,
+                             offset, size, 1);
+}
+
 static int pdu_copy_sg(V9fsPDU *pdu, size_t offset, int rx, struct iovec *sg)
 {
     size_t pos = 0;
diff --git a/hw/virtio-9p.h b/hw/virtio-9p.h
index da0aa64..81c2c59 100644
--- a/hw/virtio-9p.h
+++ b/hw/virtio-9p.h
@@ -187,5 +187,14 @@ typedef struct V9fsPosixFileOpertions
 } V9fsPosixFileOperations;
 
 V9fsPosixFileOperations *virtio_9p_init_local(const char *path);
+extern size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
+                            size_t offset, size_t size, int pack);
+
+static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count,
+                        size_t offset, size_t size)
+{
+    return pdu_packunpack(dst, sg, sg_count, offset, size, 0);
+}
+
 
 #endif
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 19/32] virtio-9p: Get the correct count values from the pdu
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (17 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 18/32] virtio-9p: Fix sg usage in the code Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 20/32] virtio-9p: Remove BUG_ON and add proper error handling Aneesh Kumar K.V
                   ` (12 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Venkateswararao Jujjuri, Aneesh Kumar K.V

From: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>

PDU contain little endian format for integer values. So
we need to make sure we map them to host format. Also the count
value can be in another sg offset other than 0. Use the righ
functions to get the count value

Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p-debug.c |   29 +++++++++++++++++++----------
 1 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/hw/virtio-9p-debug.c b/hw/virtio-9p-debug.c
index ee222db..e8ede8e 100644
--- a/hw/virtio-9p-debug.c
+++ b/hw/virtio-9p-debug.c
@@ -181,20 +181,25 @@ static void pprint_stat(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
 
 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;
-    int16_t count, i;
+    uint16_t tmp_count, count, i;
+    size_t copied = 0;
 
     fprintf(llogfile, "%s={", name);
 
-    BUG_ON((offset + 2) > sg[0].iov_len);
-    memcpy(&count, sg[0].iov_base + offset, 2);
-    offset += 2;
+    /* 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)
+        if (i) {
             fprintf(llogfile, ", ");
+        }
         snprintf(str, sizeof(str), "[%d]", i);
         pprint_str(pdu, rx, &offset, str);
     }
@@ -206,20 +211,24 @@ static void pprint_strs(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
 
 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;
-    int16_t count, i;
+    uint16_t tmp_count, count, i;
+    size_t copied = 0;
 
     fprintf(llogfile, "%s={", name);
 
-    BUG_ON((offset + 2) > sg[0].iov_len);
-    memcpy(&count, sg[0].iov_base + offset, 2);
-    offset += 2;
+    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)
+        if (i) {
             fprintf(llogfile, ", ");
+        }
         snprintf(str, sizeof(str), "[%d]", i);
         pprint_qid(pdu, rx, &offset, str);
     }
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 20/32] virtio-9p: Remove BUG_ON and add proper error handling
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (18 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 19/32] virtio-9p: Get the correct count values from the pdu Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 21/32] virtio-9p: Remove unnecessary definition of fid Aneesh Kumar K.V
                   ` (11 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p.c |  106 ++++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 84 insertions(+), 22 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 1237bac..3ce26ca 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -244,7 +244,6 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid)
         return NULL;
 
     f = qemu_mallocz(sizeof(V9fsFidState));
-    BUG_ON(f == NULL);
 
     f->fid = fid;
     f->fd = -1;
@@ -320,15 +319,18 @@ static void stat_to_qid(const struct stat *stbuf, V9fsQID *qidp)
         qidp->type |= P9_QID_TYPE_SYMLINK;
 }
 
-static void fid_to_qid(V9fsState *s, V9fsFidState *fidp, V9fsQID *qidp)
+static int fid_to_qid(V9fsState *s, V9fsFidState *fidp, V9fsQID *qidp)
 {
     struct stat stbuf;
     int err;
 
     err = posix_lstat(s, &fidp->path, &stbuf);
-    BUG_ON(err == -1);
+    if (err) {
+        return err;
+    }
 
     stat_to_qid(&stbuf, qidp);
+    return 0;
 }
 
 static V9fsPDU *alloc_pdu(V9fsState *s)
@@ -653,7 +655,7 @@ static uint32_t stat_to_v9mode(const struct stat *stbuf)
     return mode;
 }
 
-static void stat_to_v9stat(V9fsState *s, V9fsString *name,
+static int stat_to_v9stat(V9fsState *s, V9fsString *name,
                             const struct stat *stbuf,
                             V9fsStat *v9stat)
 {
@@ -681,7 +683,10 @@ static void stat_to_v9stat(V9fsState *s, V9fsString *name,
 
         if (v9stat->mode & P9_STAT_MODE_SYMLINK) {
             err = posix_readlink(s, name, &v9stat->extension);
-            BUG_ON(err == -1);
+            if (err == -1) {
+                err = -errno;
+                return err;
+            }
             v9stat->extension.data[err] = 0;
             v9stat->extension.size = err;
         } else if (v9stat->mode & P9_STAT_MODE_DEVICE) {
@@ -708,6 +713,7 @@ static void stat_to_v9stat(V9fsState *s, V9fsString *name,
         v9fs_string_size(&v9stat->gid) +
         v9fs_string_size(&v9stat->muid) +
         v9fs_string_size(&v9stat->extension);
+    return 0;
 }
 
 static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
@@ -745,7 +751,12 @@ static void v9fs_attach(V9fsState *s, V9fsPDU *pdu)
     fidp->uid = n_uname;
 
     v9fs_string_sprintf(&fidp->path, "%s", "/");
-    fid_to_qid(s, fidp, &qid);
+    err = fid_to_qid(s, fidp, &qid);
+    if (err) {
+        err = -EINVAL;
+        free_fid(s, fid);
+        goto out;
+    }
 
     offset += pdu_marshal(pdu, offset, "Q", &qid);
 
@@ -772,7 +783,10 @@ static void v9fs_stat_post_lstat(V9fsState *s, V9fsStatState *vs, int err)
         goto out;
     }
 
-    stat_to_v9stat(s, &vs->fidp->path, &vs->stbuf, &vs->v9stat);
+    err = stat_to_v9stat(s, &vs->fidp->path, &vs->stbuf, &vs->v9stat);
+    if (err) {
+        goto out;
+    }
     vs->offset += pdu_marshal(vs->pdu, vs->offset, "wS", 0, &vs->v9stat);
     err = vs->offset;
 
@@ -925,10 +939,8 @@ static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
 
     if(vs->nwnames) {
         vs->wnames = qemu_mallocz(sizeof(vs->wnames[0]) * vs->nwnames);
-        BUG_ON(vs->wnames == NULL);
 
         vs->qids = qemu_mallocz(sizeof(vs->qids[0]) * vs->nwnames);
-        BUG_ON(vs->qids == NULL);
 
         for (i = 0; i < vs->nwnames; i++) {
             vs->offset += pdu_unmarshal(vs->pdu, vs->offset, "s",
@@ -1070,7 +1082,10 @@ out:
 
 static void v9fs_open_post_lstat(V9fsState *s, V9fsOpenState *vs, int err)
 {
-    BUG_ON(err == -1);
+    if (err) {
+        err = -errno;
+        goto out;
+    }
 
     stat_to_qid(&vs->stbuf, &vs->qid);
 
@@ -1082,7 +1097,10 @@ static void v9fs_open_post_lstat(V9fsState *s, V9fsOpenState *vs, int err)
                                     omode_to_uflags(vs->mode));
         v9fs_open_post_open(s, vs, err);
     }
-
+    return;
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
 }
 
 static void v9fs_open(V9fsState *s, V9fsPDU *pdu)
@@ -1186,11 +1204,15 @@ static void v9fs_read_post_readdir(V9fsState *, V9fsReadState *, ssize_t );
 
 static void v9fs_read_post_seekdir(V9fsState *s, V9fsReadState *vs, ssize_t err)
 {
+    if (err) {
+        goto out;
+    }
     v9fs_stat_free(&vs->v9stat);
     v9fs_string_free(&vs->name);
     vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->count);
     vs->offset += vs->count;
     err = vs->offset;
+out:
     complete_pdu(s, vs->pdu, err);
     qemu_free(vs);
     return;
@@ -1199,8 +1221,14 @@ static void v9fs_read_post_seekdir(V9fsState *s, V9fsReadState *vs, ssize_t err)
 static void v9fs_read_post_dir_lstat(V9fsState *s, V9fsReadState *vs,
                                     ssize_t err)
 {
-    BUG_ON(err == -1);
-    stat_to_v9stat(s, &vs->name, &vs->stbuf, &vs->v9stat);
+    if (err) {
+	    err = -errno;
+	    goto out;
+    }
+    err = stat_to_v9stat(s, &vs->name, &vs->stbuf, &vs->v9stat);
+    if (err) {
+        goto out;
+    }
 
     vs->len = pdu_marshal(vs->pdu, vs->offset + 4 + vs->count, "S",
                             &vs->v9stat);
@@ -1217,6 +1245,11 @@ static void v9fs_read_post_dir_lstat(V9fsState *s, V9fsReadState *vs,
     vs->dent = posix_readdir(s, vs->fidp->dir);
     v9fs_read_post_readdir(s, vs, err);
     return;
+out:
+    posix_seekdir(s, vs->fidp->dir, vs->dir_pos);
+    v9fs_read_post_seekdir(s, vs, err);
+    return;
+
 }
 
 static void v9fs_read_post_readdir(V9fsState *s, V9fsReadState *vs, ssize_t err)
@@ -1256,7 +1289,11 @@ static void v9fs_read_post_rewinddir(V9fsState *s, V9fsReadState *vs,
 
 static void v9fs_read_post_readv(V9fsState *s, V9fsReadState *vs, ssize_t err)
 {
-    BUG_ON(vs->len < 0);
+    if (err  < 0) {
+        /* IO error return the error */
+        err = -errno;
+        goto out;
+    }
     vs->total += vs->len;
     vs->sg = adjust_sg(vs->sg, vs->len, &vs->cnt);
     if (vs->total < vs->count && vs->len > 0) {
@@ -1266,19 +1303,27 @@ static void v9fs_read_post_readv(V9fsState *s, V9fsReadState *vs, ssize_t err)
             }
             vs->len = posix_readv(s, vs->fidp->fd, vs->sg, vs->cnt);
         } while (vs->len == -1 && errno == EINTR);
+        if (vs->len == -1) {
+            err  = -errno;
+        }
         v9fs_read_post_readv(s, vs, err);
         return;
     }
     vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->total);
     vs->offset += vs->count;
     err = vs->offset;
+
+out:
     complete_pdu(s, vs->pdu, err);
     qemu_free(vs);
 }
 
 static void v9fs_read_post_lseek(V9fsState *s, V9fsReadState *vs, ssize_t err)
 {
-    BUG_ON(err == -1);
+    if (err == -1) {
+        err = -errno;
+        goto out;
+    }
     vs->sg = cap_sg(vs->sg, vs->count, &vs->cnt);
 
     if (vs->total < vs->count) {
@@ -1288,9 +1333,15 @@ static void v9fs_read_post_lseek(V9fsState *s, V9fsReadState *vs, ssize_t err)
             }
             vs->len = posix_readv(s, vs->fidp->fd, vs->sg, vs->cnt);
         } while (vs->len == -1 && errno == EINTR);
+	if (vs->len == -1) {
+            err  = -errno;
+        }
         v9fs_read_post_readv(s, vs, err);
         return;
     }
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
 }
 
 static void v9fs_read(V9fsState *s, V9fsPDU *pdu)
@@ -1370,7 +1421,11 @@ typedef struct V9fsWriteState {
 static void v9fs_write_post_writev(V9fsState *s, V9fsWriteState *vs,
                                    ssize_t err)
 {
-    BUG_ON(vs->len < 0);
+    if (err  < 0) {
+        /* IO error return the error */
+        err = -errno;
+        goto out;
+    }
     vs->total += vs->len;
     vs->sg = adjust_sg(vs->sg, vs->len, &vs->cnt);
     if (vs->total < vs->count && vs->len > 0) {
@@ -1379,19 +1434,26 @@ static void v9fs_write_post_writev(V9fsState *s, V9fsWriteState *vs,
                 print_sg(vs->sg, vs->cnt);
             vs->len =  posix_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
         } while (vs->len == -1 && errno == EINTR);
+        if (vs->len == -1) {
+            err  = -errno;
+        }
         v9fs_write_post_writev(s, vs, err);
+	return;
     }
     vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->total);
 
     err = vs->offset;
+out:
     complete_pdu(s, vs->pdu, err);
     qemu_free(vs);
 }
 
 static void v9fs_write_post_lseek(V9fsState *s, V9fsWriteState *vs, ssize_t err)
 {
-    BUG_ON(err == -1);
-
+    if (err == -1) {
+        err = -errno;
+        goto out;
+    }
     vs->sg = cap_sg(vs->sg, vs->count, &vs->cnt);
 
     if (vs->total < vs->count) {
@@ -1400,11 +1462,14 @@ static void v9fs_write_post_lseek(V9fsState *s, V9fsWriteState *vs, ssize_t err)
                 print_sg(vs->sg, vs->cnt);
             vs->len = posix_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
         } while (vs->len == -1 && errno == EINTR);
-
+	if (vs->len == -1) {
+            err  = -errno;
+        }
         v9fs_write_post_writev(s, vs, err);
         return;
     }
 
+out:
     complete_pdu(s, vs->pdu, err);
     qemu_free(vs);
 }
@@ -1834,7 +1899,6 @@ static void v9fs_wstat_post_chown(V9fsState *s, V9fsWstatState *vs, int err)
             end = old_name;
 
         new_name = qemu_malloc(end - old_name + vs->v9stat.name.size + 1);
-        BUG_ON(new_name == NULL);
 
         memset(new_name, 0, end - old_name + vs->v9stat.name.size + 1);
         memcpy(new_name, old_name, end - old_name);
@@ -2104,7 +2168,6 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
     s->pdus[i].next = NULL;
 
     s->vq = virtio_add_queue(&s->vdev, MAX_REQ, handle_9p_output);
-    BUG_ON(s->vq == NULL);
 
     if (!conf->share_path || !conf->tag) {
 	    /* we haven't specified a mount_tag */
@@ -2127,7 +2190,6 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
     s->tag = qemu_malloc(len);
     memcpy(s->tag, conf->tag, len);
     s->tag_len = len;
-    BUG_ON(s->fs_root == NULL);
     s->uid = -1;
 
     s->ops = virtio_9p_init_local(conf->share_path);
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 21/32] virtio-9p: Remove unnecessary definition of fid
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (19 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 20/32] virtio-9p: Remove BUG_ON and add proper error handling Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 22/32] virtio-9p: Update existing fid path on rename Aneesh Kumar K.V
                   ` (10 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V

We already have fid as a part of V9fsFidState so use that instead
of defining another variable

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Reviewed-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
---
 hw/virtio-9p.c |   62 ++++++++++++++++++++++++++-----------------------------
 1 files changed, 29 insertions(+), 33 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 3ce26ca..c8ab6b6 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -770,7 +770,6 @@ out:
 typedef struct V9fsStatState {
     V9fsPDU *pdu;
     size_t offset;
-    int32_t fid;
     V9fsStat v9stat;
     V9fsFidState *fidp;
     struct stat stbuf;
@@ -798,6 +797,7 @@ out:
 
 static void v9fs_stat(V9fsState *s, V9fsPDU *pdu)
 {
+    int32_t fid;
     V9fsStatState *vs;
     ssize_t err = 0;
 
@@ -807,9 +807,9 @@ static void v9fs_stat(V9fsState *s, V9fsPDU *pdu)
 
     memset(&vs->v9stat, 0, sizeof(vs->v9stat));
 
-    pdu_unmarshal(vs->pdu, vs->offset, "d", &vs->fid);
+    pdu_unmarshal(vs->pdu, vs->offset, "d", &fid);
 
-    vs->fidp = lookup_fid(s, vs->fid);
+    vs->fidp = lookup_fid(s, fid);
     if (vs->fidp == NULL) {
 	    err = -ENOENT;
         goto out;
@@ -828,8 +828,6 @@ out:
 typedef struct V9fsWalkState {
     V9fsPDU *pdu;
     size_t offset;
-    int32_t fid;
-    int32_t newfid;
     int16_t nwnames;
     int name_idx;
     V9fsQID *qids;
@@ -867,7 +865,7 @@ static void v9fs_walk_post_newfid_lstat(V9fsState *s, V9fsWalkState *vs,
                                                                 int err)
 {
     if (err == -1) {
-        free_fid(s, vs->newfid);
+        free_fid(s, vs->newfidp->fid);
         v9fs_string_free(&vs->path);
         err = -ENOENT;
         goto out;
@@ -924,6 +922,7 @@ out:
 
 static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
 {
+    int32_t fid, newfid;
     V9fsWalkState *vs;
     int err = 0;
     int i;
@@ -934,8 +933,8 @@ static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
     vs->qids = NULL;
     vs->offset = 7;
 
-    vs->offset += pdu_unmarshal(vs->pdu, vs->offset, "ddw", &vs->fid,
-                                            &vs->newfid, &vs->nwnames);
+    vs->offset += pdu_unmarshal(vs->pdu, vs->offset, "ddw", &fid,
+                                            &newfid, &vs->nwnames);
 
     if(vs->nwnames) {
         vs->wnames = qemu_mallocz(sizeof(vs->wnames[0]) * vs->nwnames);
@@ -948,14 +947,14 @@ static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
         }
     }
 
-    vs->fidp = lookup_fid(s, vs->fid);
+    vs->fidp = lookup_fid(s, fid);
     if (vs->fidp == NULL) {
         err = -ENOENT;
         goto out;
     }
 
     /* FIXME: is this really valid? */
-    if (vs->fid == vs->newfid) {
+    if (fid == newfid) {
         v9fs_string_init(&vs->path);
         vs->name_idx = 0;
 
@@ -969,7 +968,7 @@ static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
             return;
         }
     } else {
-        vs->newfidp = alloc_fid(s, vs->newfid);
+        vs->newfidp = alloc_fid(s, newfid);
         if (vs->newfidp == NULL) {
             err = -EINVAL;
             goto out;
@@ -1000,7 +999,6 @@ out:
 typedef struct V9fsOpenState {
     V9fsPDU *pdu;
     size_t offset;
-    int32_t fid;
     int8_t mode;
     V9fsFidState *fidp;
     V9fsQID qid;
@@ -1105,7 +1103,7 @@ out:
 
 static void v9fs_open(V9fsState *s, V9fsPDU *pdu)
 {
-
+    int32_t fid;
     V9fsOpenState *vs;
     ssize_t err = 0;
 
@@ -1114,9 +1112,9 @@ static void v9fs_open(V9fsState *s, V9fsPDU *pdu)
     vs->pdu = pdu;
     vs->offset = 7;
 
-    pdu_unmarshal(vs->pdu, vs->offset, "db", &vs->fid, &vs->mode);
+    pdu_unmarshal(vs->pdu, vs->offset, "db", &fid, &vs->mode);
 
-    vs->fidp = lookup_fid(s, vs->fid);
+    vs->fidp = lookup_fid(s, fid);
     if (vs->fidp == NULL) {
         err = -ENOENT;
         goto out;
@@ -1183,7 +1181,6 @@ static void print_sg(struct iovec *sg, int cnt)
 typedef struct V9fsReadState {
     V9fsPDU *pdu;
     size_t offset;
-    int32_t fid;
     int32_t count;
     int32_t total;
     int64_t off;
@@ -1346,6 +1343,7 @@ out:
 
 static void v9fs_read(V9fsState *s, V9fsPDU *pdu)
 {
+    int32_t fid;
     V9fsReadState *vs;
     ssize_t err = 0;
 
@@ -1356,9 +1354,9 @@ static void v9fs_read(V9fsState *s, V9fsPDU *pdu)
     vs->len = 0;
     vs->count = 0;
 
-    pdu_unmarshal(vs->pdu, vs->offset, "dqd", &vs->fid, &vs->off, &vs->count);
+    pdu_unmarshal(vs->pdu, vs->offset, "dqd", &fid, &vs->off, &vs->count);
 
-    vs->fidp = lookup_fid(s, vs->fid);
+    vs->fidp = lookup_fid(s, fid);
     if (vs->fidp == NULL) {
         err = -EINVAL;
         goto out;
@@ -1407,7 +1405,6 @@ out:
 typedef struct V9fsWriteState {
     V9fsPDU *pdu;
     size_t offset;
-    int32_t fid;
     int32_t len;
     int32_t count;
     int32_t total;
@@ -1476,6 +1473,7 @@ out:
 
 static void v9fs_write(V9fsState *s, V9fsPDU *pdu)
 {
+    int32_t fid;
     V9fsWriteState *vs;
     ssize_t err;
 
@@ -1487,10 +1485,10 @@ static void v9fs_write(V9fsState *s, V9fsPDU *pdu)
     vs->total = 0;
     vs->len = 0;
 
-    pdu_unmarshal(vs->pdu, vs->offset, "dqdv", &vs->fid, &vs->off, &vs->count,
+    pdu_unmarshal(vs->pdu, vs->offset, "dqdv", &fid, &vs->off, &vs->count,
                     vs->sg, &vs->cnt);
 
-    vs->fidp = lookup_fid(s, vs->fid);
+    vs->fidp = lookup_fid(s, fid);
     if (vs->fidp == NULL) {
         err = -EINVAL;
         goto out;
@@ -1514,7 +1512,6 @@ out:
 typedef struct V9fsCreateState {
     V9fsPDU *pdu;
     size_t offset;
-    int32_t fid;
     V9fsFidState *fidp;
     V9fsQID qid;
     int32_t perm;
@@ -1652,12 +1649,10 @@ static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err)
     } else if (vs->perm & P9_STAT_MODE_LINK) {
         int32_t nfid = atoi(vs->extension.data);
         V9fsFidState *nfidp = lookup_fid(s, nfid);
-
         if (nfidp == NULL) {
             err = -errno;
             v9fs_post_create(s, vs, err);
         }
-
         err = posix_link(s, &nfidp->path, &vs->fullname);
         v9fs_create_post_perms(s, vs, err);
     } else if (vs->perm & P9_STAT_MODE_DEVICE) {
@@ -1707,6 +1702,7 @@ out:
 
 static void v9fs_create(V9fsState *s, V9fsPDU *pdu)
 {
+    int32_t fid;
     V9fsCreateState *vs;
     int err = 0;
 
@@ -1716,10 +1712,10 @@ static void v9fs_create(V9fsState *s, V9fsPDU *pdu)
 
     v9fs_string_init(&vs->fullname);
 
-    pdu_unmarshal(vs->pdu, vs->offset, "dsdbs", &vs->fid, &vs->name,
+    pdu_unmarshal(vs->pdu, vs->offset, "dsdbs", &fid, &vs->name,
                                 &vs->perm, &vs->mode, &vs->extension);
 
-    vs->fidp = lookup_fid(s, vs->fid);
+    vs->fidp = lookup_fid(s, fid);
     if (vs->fidp == NULL) {
         err = -EINVAL;
         goto out;
@@ -1749,7 +1745,6 @@ static void v9fs_flush(V9fsState *s, V9fsPDU *pdu)
 typedef struct V9fsRemoveState {
     V9fsPDU *pdu;
     size_t offset;
-    int32_t fid;
     V9fsFidState *fidp;
 } V9fsRemoveState;
 
@@ -1761,7 +1756,7 @@ static void v9fs_remove_post_remove(V9fsState *s, V9fsRemoveState *vs,
         goto out;
     }
 
-    err = free_fid(s, vs->fid);
+    err = free_fid(s, vs->fidp->fid);
     if (err < 0)
         goto out;
 
@@ -1773,6 +1768,7 @@ out:
 
 static void v9fs_remove(V9fsState *s, V9fsPDU *pdu)
 {
+    int32_t fid;
     V9fsRemoveState *vs;
     int err = 0;
 
@@ -1780,9 +1776,9 @@ static void v9fs_remove(V9fsState *s, V9fsPDU *pdu)
     vs->pdu = pdu;
     vs->offset = 7;
 
-    pdu_unmarshal(vs->pdu, vs->offset, "d", &vs->fid);
+    pdu_unmarshal(vs->pdu, vs->offset, "d", &fid);
 
-    vs->fidp = lookup_fid(s, vs->fid);
+    vs->fidp = lookup_fid(s, fid);
     if (vs->fidp == NULL) {
         err = -EINVAL;
         goto out;
@@ -1837,7 +1833,6 @@ typedef struct V9fsWstatState
 {
     V9fsPDU *pdu;
     size_t offset;
-    int32_t fid;
     int16_t unused;
     V9fsStat v9stat;
     V9fsFidState *fidp;
@@ -2002,6 +1997,7 @@ static int donttouch_stat(V9fsStat *stat)
 
 static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
 {
+    int32_t fid;
     V9fsWstatState *vs;
     int err = 0;
 
@@ -2009,9 +2005,9 @@ static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
     vs->pdu = pdu;
     vs->offset = 7;
 
-    pdu_unmarshal(pdu, vs->offset, "dwS", &vs->fid, &vs->unused, &vs->v9stat);
+    pdu_unmarshal(pdu, vs->offset, "dwS", &fid, &vs->unused, &vs->v9stat);
 
-    vs->fidp = lookup_fid(s, vs->fid);
+    vs->fidp = lookup_fid(s, fid);
     if (vs->fidp == NULL) {
         err = -EINVAL;
         goto out;
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 22/32] virtio-9p: Update existing fid path on rename
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (20 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 21/32] virtio-9p: Remove unnecessary definition of fid Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 23/32] vritio-9p: Fix chmod bug with directory Aneesh Kumar K.V
                   ` (9 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V

We need to make sure that we update the path component of the existing
fid's when we rename a file. The client is not expected to clunk these fids
pointing to the old name. If we don't update any operation on the old unopened
fid will point to the old name and will fail

Add BUG_ON to make sure when we clone a fid, we don't have open descriptor
attached to the fid. We also need to make sure that when we open a fid, the
specified fid should not already be opened. Capture the case by adding a BUG_ON

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p.c |   39 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index c8ab6b6..9aa4b72 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -955,6 +955,9 @@ static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
 
     /* FIXME: is this really valid? */
     if (fid == newfid) {
+
+        BUG_ON(vs->fidp->fd != -1);
+        BUG_ON(vs->fidp->dir);
         v9fs_string_init(&vs->path);
         vs->name_idx = 0;
 
@@ -1120,6 +1123,9 @@ static void v9fs_open(V9fsState *s, V9fsPDU *pdu)
         goto out;
     }
 
+    BUG_ON(vs->fidp->fd != -1);
+    BUG_ON(vs->fidp->dir);
+
     err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
 
     v9fs_open_post_lstat(s, vs, err);
@@ -1877,8 +1883,19 @@ out:
     qemu_free(vs);
 }
 
+static void v9fs_fix_path(V9fsString *dst, V9fsString *src, int len)
+{
+    V9fsString str;
+    v9fs_string_init(&str);
+    v9fs_string_copy(&str, dst);
+    v9fs_string_sprintf(dst, "%s%s", src->data, str.data+len);
+    v9fs_string_free(&str);
+}
+
+
 static void v9fs_wstat_post_chown(V9fsState *s, V9fsWstatState *vs, int err)
 {
+    V9fsFidState *fidp;
     if (err < 0) {
         goto out;
     }
@@ -1905,6 +1922,28 @@ static void v9fs_wstat_post_chown(V9fsState *s, V9fsWstatState *vs, int err)
         if (strcmp(new_name, vs->fidp->path.data) != 0) {
             if (posix_rename(s, &vs->fidp->path, &vs->nname)) {
                 err = -errno;
+            } else {
+                /*
+                 * Fixup fid's pointing to the old name to
+                 * start pointing to the new name
+                 */
+                for (fidp = s->fid_list; fidp; fidp = fidp->next) {
+
+                    if (vs->fidp == fidp) {
+                        /*
+                         * we replace name of this fid towards the end
+                         * so that our below strcmp will work
+                         */
+                        continue;
+                    }
+                    if (!strncmp(vs->fidp->path.data, fidp->path.data,
+                                 strlen(vs->fidp->path.data))) {
+                        /* replace the name */
+                        v9fs_fix_path(&fidp->path, &vs->nname,
+                                      strlen(vs->fidp->path.data));
+                    }
+                }
+                v9fs_string_copy(&vs->fidp->path, &vs->nname);
             }
         }
     }
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 23/32] vritio-9p: Fix chmod bug with directory
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (21 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 22/32] virtio-9p: Update existing fid path on rename Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 24/32] qemu-malloc: Add qemu_asprintf Aneesh Kumar K.V
                   ` (8 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Venkateswararao Jujjuri, Aneesh Kumar K.V

chmod 0777 <dir>  fails with EIO.
This is a result of wrong check in server code.
Server code is trying to check if the file type is not being changed by
making sure that fidp->dir is not NULL.
But the fidp->dir is set only on opendir/createdir.

This patch gives proper check to all special files.

Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p.c |   56 +++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 41 insertions(+), 15 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 9aa4b72..e519605 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -298,11 +298,12 @@ static int free_fid(V9fsState *s, int32_t fid)
 #define P9_STAT_MODE_SETGID	0x00040000
 #define P9_STAT_MODE_SETVTX	0x00010000
 
-#define P9_STAT_MODE_SPECIAL	(P9_STAT_MODE_NAMED_PIPE | \
-                                P9_STAT_MODE_SYMLINK | \
-                                P9_STAT_MODE_LINK | \
-                                P9_STAT_MODE_DEVICE)
-
+#define P9_STAT_MODE_TYPE_BITS (P9_STAT_MODE_DIR |		\
+				P9_STAT_MODE_SYMLINK |		\
+				P9_STAT_MODE_LINK |		\
+                                P9_STAT_MODE_DEVICE |		\
+                                P9_STAT_MODE_NAMED_PIPE |	\
+                                P9_STAT_MODE_SOCKET)
 
 /* This is the algorithm from ufs in spfs */
 static void stat_to_qid(const struct stat *stbuf, V9fsQID *qidp)
@@ -1842,6 +1843,7 @@ typedef struct V9fsWstatState
     int16_t unused;
     V9fsStat v9stat;
     V9fsFidState *fidp;
+    struct stat stbuf;
     V9fsString nname;
 } V9fsWstatState;
 
@@ -2034,6 +2036,37 @@ static int donttouch_stat(V9fsStat *stat)
 		return 0;
 }
 
+static void v9fs_wstat_post_lstat(V9fsState *s, V9fsWstatState *vs, int err)
+{
+    uint32_t v9_mode;
+
+    if (err == -1) {
+        err = -errno;
+        goto out;
+    }
+
+    v9_mode = stat_to_v9mode(&vs->stbuf);
+
+    if ((vs->v9stat.mode & P9_STAT_MODE_TYPE_BITS) !=
+        (v9_mode & P9_STAT_MODE_TYPE_BITS)) {
+            /* Attempting to change the type */
+            err = -EIO;
+            goto out;
+    }
+
+    if (posix_chmod(s, &vs->fidp->path, v9mode_to_mode(vs->v9stat.mode,
+                    &vs->v9stat.extension))) {
+            err = -errno;
+     }
+    v9fs_wstat_post_chmod(s, vs, err);
+    return;
+
+out:
+    v9fs_stat_free(&vs->v9stat);
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
 static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
 {
     int32_t fid;
@@ -2060,16 +2093,9 @@ static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
     }
 
     if (vs->v9stat.mode != -1) {
-        if (vs->v9stat.mode & P9_STAT_MODE_DIR && vs->fidp->dir == NULL) {
-            err = -EIO;
-            goto out;
-        }
-
-        if (posix_chmod(s, &vs->fidp->path,
-                    v9mode_to_mode(vs->v9stat.mode,
-                        &vs->v9stat.extension))) {
-            err = -errno;
-        }
+        err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
+        v9fs_wstat_post_lstat(s, vs, err);
+        return;
     }
 
     v9fs_wstat_post_chmod(s, vs, err);
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 24/32] qemu-malloc: Add qemu_asprintf
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (22 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 23/32] vritio-9p: Fix chmod bug with directory Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 25/32] virtio-9p: Move V9fs File system specific options to a separate header file Aneesh Kumar K.V
                   ` (7 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V, Gautham R Shenoy

From: Gautham R Shenoy <ego@in.ibm.com>

Add the API qemu_asprintf() along the lines of qemu_vasprintf()

Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 qemu-common.h |    1 +
 qemu-malloc.c |   12 ++++++++++++
 2 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/qemu-common.h b/qemu-common.h
index 6e925ab..f597f27 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -161,6 +161,7 @@ void qemu_free(void *ptr);
 char *qemu_strdup(const char *str);
 char *qemu_strndup(const char *str, size_t size);
 int qemu_vasprintf(char **strp, const char *fmt, va_list ap);
+int qemu_asprintf(char **strp, const char *fmt, ...);
 
 void *get_mmap_addr(unsigned long size);
 
diff --git a/qemu-malloc.c b/qemu-malloc.c
index d6de067..9bfefb4 100644
--- a/qemu-malloc.c
+++ b/qemu-malloc.c
@@ -103,3 +103,15 @@ int qemu_vasprintf(char **strp, const char *fmt, va_list ap)
 {
     return vasprintf(strp, fmt, ap);
 }
+
+int qemu_asprintf(char **strp, const char *fmt, ...)
+{
+    va_list ap;
+    int err;
+
+    va_start(ap, fmt);
+    err = qemu_vasprintf(strp, fmt, ap);
+    va_end(ap);
+
+    return err;
+}
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 25/32] virtio-9p: Move V9fs File system specific options to a separate header file.
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (23 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 24/32] qemu-malloc: Add qemu_asprintf Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-29  0:52   ` jvrao
  2010-03-29  1:09   ` jvrao
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 26/32] virtio-9p: Create a commandline option -fsdev Aneesh Kumar K.V
                   ` (6 subsequent siblings)
  31 siblings, 2 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V, Gautham R Shenoy

Move the V9fs File System specific operations structs into a different header
file.

Also introduce a new struct named context which is the subset of the V9fsState
to be passed to the individual file-system operations.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
---
 hw/file-op.h         |   60 ++++++++++++++
 hw/virtio-9p-local.c |   64 ++++++++--------
 hw/virtio-9p.c       |  209 +++++++++++++++++++++++++-------------------------
 hw/virtio-9p.h       |   43 +---------
 4 files changed, 202 insertions(+), 174 deletions(-)
 create mode 100644 hw/file-op.h

diff --git a/hw/file-op.h b/hw/file-op.h
new file mode 100644
index 0000000..f84767f
--- /dev/null
+++ b/hw/file-op.h
@@ -0,0 +1,60 @@
+/*
+ * 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 _FILEOP_H
+#define _FILEOP_H
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/time.h>
+#include <utime.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+
+typedef struct FsContext
+{
+    char *fs_root;
+    uid_t uid;
+} FsContext;
+
+typedef struct FileOperations
+{
+    int (*lstat)(FsContext *, const char *, struct stat *);
+    ssize_t (*readlink)(FsContext *, const char *, char *, size_t);
+    int (*chmod)(FsContext *, const char *, mode_t);
+    int (*chown)(FsContext *, const char *, uid_t, gid_t);
+    int (*mknod)(FsContext *, const char *, mode_t, dev_t);
+    int (*mksock)(FsContext *, const char *);
+    int (*utime)(FsContext *, const char *, const struct utimbuf *);
+    int (*remove)(FsContext *, const char *);
+    int (*symlink)(FsContext *, const char *, const char *);
+    int (*link)(FsContext *, const char *, const char *);
+    int (*setuid)(FsContext *, uid_t);
+    int (*close)(FsContext *, int);
+    int (*closedir)(FsContext *, DIR *);
+    DIR *(*opendir)(FsContext *, const char *);
+    int (*open)(FsContext *, const char *, int);
+    int (*open2)(FsContext *, const char *, int, mode_t);
+    void (*rewinddir)(FsContext *, DIR *);
+    off_t (*telldir)(FsContext *, DIR *);
+    struct dirent *(*readdir)(FsContext *, DIR *);
+    void (*seekdir)(FsContext *, DIR *, off_t);
+    ssize_t (*readv)(FsContext *, int, const struct iovec *, int);
+    ssize_t (*writev)(FsContext *, int, const struct iovec *, int);
+    off_t (*lseek)(FsContext *, int, off_t, int);
+    int (*mkdir)(FsContext *, const char *, mode_t);
+    int (*fstat)(FsContext *, int, struct stat *);
+    int (*rename)(FsContext *, const char *, const char *);
+    int (*truncate)(FsContext *, const char *, off_t);
+    int (*fsync)(FsContext *, int);
+    void *opaque;
+} FileOperations;
+#endif
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 4584bf6..690ba3f 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -22,7 +22,7 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 
-static const char *rpath(V9fsState *s, const char *path)
+static const char *rpath(FsContext *s, const char *path)
 {
     /* FIXME: so wrong... */
     static char buffer[4096];
@@ -30,12 +30,12 @@ static const char *rpath(V9fsState *s, const char *path)
     return buffer;
 }
 
-static int local_lstat(V9fsState *s, const char *path, struct stat *stbuf)
+static int local_lstat(FsContext *s, const char *path, struct stat *stbuf)
 {
     return lstat(rpath(s, path), stbuf);
 }
 
-static int local_setuid(V9fsState *s, uid_t uid)
+static int local_setuid(FsContext *s, uid_t uid)
 {
     struct passwd *pw;
     gid_t groups[33];
@@ -70,80 +70,80 @@ static int local_setuid(V9fsState *s, uid_t uid)
     return 0;
 }
 
-static ssize_t local_readlink(V9fsState *s, const char *path,
+static ssize_t local_readlink(FsContext *s, const char *path,
 			      char *buf, size_t bufsz)
 {
     return readlink(rpath(s, path), buf, bufsz);
 }
 
-static int local_close(V9fsState *s, int fd)
+static int local_close(FsContext *s, int fd)
 {
     return close(fd);
 }
 
-static int local_closedir(V9fsState *s, DIR *dir)
+static int local_closedir(FsContext *s, DIR *dir)
 {
     return closedir(dir);
 }
 
-static int local_open(V9fsState *s, const char *path, int flags)
+static int local_open(FsContext *s, const char *path, int flags)
 {
     return open(rpath(s, path), flags);
 }
 
-static DIR *local_opendir(V9fsState *s, const char *path)
+static DIR *local_opendir(FsContext *s, const char *path)
 {
     return opendir(rpath(s, path));
 }
 
-static void local_rewinddir(V9fsState *s, DIR *dir)
+static void local_rewinddir(FsContext *s, DIR *dir)
 {
     return rewinddir(dir);
 }
 
-static off_t local_telldir(V9fsState *s, DIR *dir)
+static off_t local_telldir(FsContext *s, DIR *dir)
 {
     return telldir(dir);
 }
 
-static struct dirent *local_readdir(V9fsState *s, DIR *dir)
+static struct dirent *local_readdir(FsContext *s, DIR *dir)
 {
     return readdir(dir);
 }
 
-static void local_seekdir(V9fsState *s, DIR *dir, off_t off)
+static void local_seekdir(FsContext *s, DIR *dir, off_t off)
 {
     return seekdir(dir, off);
 }
 
-static ssize_t local_readv(V9fsState *s, int fd, const struct iovec *iov,
+static ssize_t local_readv(FsContext *s, int fd, const struct iovec *iov,
 			   int iovcnt)
 {
     return readv(fd, iov, iovcnt);
 }
 
-static off_t local_lseek(V9fsState *s, int fd, off_t offset, int whence)
+static off_t local_lseek(FsContext *s, int fd, off_t offset, int whence)
 {
     return lseek(fd, offset, whence);
 }
 
-static ssize_t local_writev(V9fsState *s, int fd, const struct iovec *iov,
+static ssize_t local_writev(FsContext *s, int fd, const struct iovec *iov,
 			    int iovcnt)
 {
     return writev(fd, iov, iovcnt);
 }
 
-static int local_chmod(V9fsState *s, const char *path, mode_t mode)
+static int local_chmod(FsContext *s, const char *path, mode_t mode)
 {
     return chmod(rpath(s, path), mode);
 }
 
-static int local_mknod(V9fsState *s, const char *path, mode_t mode, dev_t dev)
+static int local_mknod(FsContext *s, const char *path, mode_t mode, dev_t dev)
 {
     return mknod(rpath(s, path), mode, dev);
 }
 
-static int local_mksock(V9fsState *s2, const char *path)
+static int local_mksock(FsContext *s2, const char *path)
 {
     struct sockaddr_un addr;
     int s;
@@ -164,28 +164,28 @@ static int local_mksock(V9fsState *s2, const char *path)
     return 0;
 }
 
-static int local_mkdir(V9fsState *s, const char *path, mode_t mode)
+static int local_mkdir(FsContext *s, const char *path, mode_t mode)
 {
     return mkdir(rpath(s, path), mode);
 }
 
-static int local_fstat(V9fsState *s, int fd, struct stat *stbuf)
+static int local_fstat(FsContext *s, int fd, struct stat *stbuf)
 {
     return fstat(fd, stbuf);
 }
 
-static int local_open2(V9fsState *s, const char *path, int flags, mode_t mode)
+static int local_open2(FsContext *s, const char *path, int flags, mode_t mode)
 {
     return open(rpath(s, path), flags, mode);
 }
 
-static int local_symlink(V9fsState *s, const char *oldpath,
+static int local_symlink(FsContext *s, const char *oldpath,
 			 const char *newpath)
 {
     return symlink(oldpath, rpath(s, newpath));
 }
 
-static int local_link(V9fsState *s, const char *oldpath, const char *newpath)
+static int local_link(FsContext *s, const char *oldpath, const char *newpath)
 {
     char *tmp = qemu_strdup(rpath(s, oldpath));
     int err, serrno = 0;
@@ -205,12 +205,12 @@ static int local_link(V9fsState *s, const char *oldpath, const char *newpath)
     return err;
 }
 
-static int local_truncate(V9fsState *s, const char *path, off_t size)
+static int local_truncate(FsContext *s, const char *path, off_t size)
 {
     return truncate(rpath(s, path), size);
 }
 
-static int local_rename(V9fsState *s, const char *oldpath,
+static int local_rename(FsContext *s, const char *oldpath,
 			const char *newpath)
 {
     char *tmp;
@@ -232,29 +232,29 @@ static int local_rename(V9fsState *s, const char *oldpath,
 
 }
 
-static int local_chown(V9fsState *s, const char *path, uid_t uid, gid_t gid)
+static int local_chown(FsContext *s, const char *path, uid_t uid, gid_t gid)
 {
     return chown(rpath(s, path), uid, gid);
 }
 
-static int local_utime(V9fsState *s, const char *path,
+static int local_utime(FsContext *s, const char *path,
 		       const struct utimbuf *buf)
 {
     return utime(rpath(s, path), buf);
 }
 
-static int local_remove(V9fsState *s, const char *path)
+static int local_remove(FsContext *s, const char *path)
 {
     return remove(rpath(s, path));
 }
 
 
-static int local_fsync(V9fsState *s, int fd)
+static int local_fsync(FsContext *s, int fd)
 {
     return fsync(fd);
 }
 
-static V9fsPosixFileOperations ops = {
+static FileOperations ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
     .readlink = local_readlink,
@@ -285,7 +285,7 @@ static V9fsPosixFileOperations ops = {
     .fsync = local_fsync,
 };
 
-V9fsPosixFileOperations *virtio_9p_init_local(const char *path)
+FileOperations *virtio_9p_init_local(const char *path)
 {
-return &ops;
+    return &ops;
 }
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index e519605..d03693d 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -22,23 +22,23 @@ int debug_9p_pdu = 1;
 
 extern void pprint_pdu(V9fsPDU *pdu);
 
-static int posix_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf)
+static int v9fs_do_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf)
 {
-    return s->ops->lstat(s, path->data, stbuf);
+    return s->ops->lstat(&s->ctx, path->data, stbuf);
 }
 
-static int posix_setuid(V9fsState *s, uid_t uid)
+static int v9fs_do_setuid(V9fsState *s, uid_t uid)
 {
-    return s->ops->setuid(s, uid);
+    return s->ops->setuid(&s->ctx, uid);
 }
 
-static ssize_t posix_readlink(V9fsState *s, V9fsString *path, V9fsString *buf)
+static ssize_t v9fs_do_readlink(V9fsState *s, V9fsString *path, V9fsString *buf)
 {
     ssize_t len;
 
     buf->data = qemu_malloc(1024);
 
-    len = s->ops->readlink(s, path->data, buf->data, 1024 - 1);
+    len = s->ops->readlink(&s->ctx, path->data, buf->data, 1024 - 1);
     if (len > -1) {
         buf->size = len;
         buf->data[len] = 0;
@@ -47,134 +47,134 @@ static ssize_t posix_readlink(V9fsState *s, V9fsString *path, V9fsString *buf)
     return len;
 }
 
-static int posix_close(V9fsState *s, int fd)
+static int v9fs_do_close(V9fsState *s, int fd)
 {
-    return s->ops->close(s, fd);
+    return s->ops->close(&s->ctx, fd);
 }
 
-static int posix_closedir(V9fsState *s, DIR *dir)
+static int v9fs_do_closedir(V9fsState *s, DIR *dir)
 {
-    return s->ops->closedir(s, dir);
+    return s->ops->closedir(&s->ctx, dir);
 }
 
-static int posix_open(V9fsState *s, V9fsString *path, int flags)
+static int v9fs_do_open(V9fsState *s, V9fsString *path, int flags)
 {
-    return s->ops->open(s, path->data, flags);
+    return s->ops->open(&s->ctx, path->data, flags);
 }
 
-static DIR *posix_opendir(V9fsState *s, V9fsString *path)
+static DIR *v9fs_do_opendir(V9fsState *s, V9fsString *path)
 {
-    return s->ops->opendir(s, path->data);
+    return s->ops->opendir(&s->ctx, path->data);
 }
 
-static void posix_rewinddir(V9fsState *s, DIR *dir)
+static void v9fs_do_rewinddir(V9fsState *s, DIR *dir)
 {
-    return s->ops->rewinddir(s, dir);
+    return s->ops->rewinddir(&s->ctx, dir);
 }
 
-static off_t posix_telldir(V9fsState *s, DIR *dir)
+static off_t v9fs_do_telldir(V9fsState *s, DIR *dir)
 {
-    return s->ops->telldir(s, dir);
+    return s->ops->telldir(&s->ctx, dir);
 }
 
-static struct dirent *posix_readdir(V9fsState *s, DIR *dir)
+static struct dirent *v9fs_do_readdir(V9fsState *s, DIR *dir)
 {
-    return s->ops->readdir(s, dir);
+    return s->ops->readdir(&s->ctx, dir);
 }
 
-static void posix_seekdir(V9fsState *s, DIR *dir, off_t off)
+static void v9fs_do_seekdir(V9fsState *s, DIR *dir, off_t off)
 {
-    return s->ops->seekdir(s, dir, off);
+    return s->ops->seekdir(&s->ctx, dir, off);
 }
 
-static int posix_readv(V9fsState *s, int fd, const struct iovec *iov,
+static int v9fs_do_readv(V9fsState *s, int fd, const struct iovec *iov,
 		       int iovcnt)
 {
-    return s->ops->readv(s, fd, iov, iovcnt);
+    return s->ops->readv(&s->ctx, fd, iov, iovcnt);
 }
 
-static off_t posix_lseek(V9fsState *s, int fd, off_t offset, int whence)
+static off_t v9fs_do_lseek(V9fsState *s, int fd, off_t offset, int whence)
 {
-    return s->ops->lseek(s, fd, offset, whence);
+    return s->ops->lseek(&s->ctx, fd, offset, whence);
 }
 
-static int posix_writev(V9fsState *s, int fd, const struct iovec *iov,
+static int v9fs_do_writev(V9fsState *s, int fd, const struct iovec *iov,
                        int iovcnt)
 {
-    return s->ops->writev(s, fd, iov, iovcnt);
+    return s->ops->writev(&s->ctx, fd, iov, iovcnt);
 }
 
-static int posix_chmod(V9fsState *s, V9fsString *path, mode_t mode)
+static int v9fs_do_chmod(V9fsState *s, V9fsString *path, mode_t mode)
 {
-    return s->ops->chmod(s, path->data, mode);
+    return s->ops->chmod(&s->ctx, path->data, mode);
 }
 
-static int posix_mknod(V9fsState *s, V9fsString *path, mode_t mode, dev_t dev)
+static int v9fs_do_mknod(V9fsState *s, V9fsString *path, mode_t mode, dev_t dev)
 {
-    return s->ops->mknod(s, path->data, mode, dev);
+    return s->ops->mknod(&s->ctx, path->data, mode, dev);
 }
 
-static int posix_mksock(V9fsState *s, V9fsString *path)
+static int v9fs_do_mksock(V9fsState *s, V9fsString *path)
 {
-    return s->ops->mksock(s, path->data);
+    return s->ops->mksock(&s->ctx, path->data);
 }
 
-static int posix_mkdir(V9fsState *s, V9fsString *path, mode_t mode)
+static int v9fs_do_mkdir(V9fsState *s, V9fsString *path, mode_t mode)
 {
-    return s->ops->mkdir(s, path->data, mode);
+    return s->ops->mkdir(&s->ctx, path->data, mode);
 }
 
-static int posix_fstat(V9fsState *s, int fd, struct stat *stbuf)
+static int v9fs_do_fstat(V9fsState *s, int fd, struct stat *stbuf)
 {
-    return s->ops->fstat(s, fd, stbuf);
+    return s->ops->fstat(&s->ctx, fd, stbuf);
 }
 
-static int posix_open2(V9fsState *s, V9fsString *path, int flags, mode_t mode)
+static int v9fs_do_open2(V9fsState *s, V9fsString *path, int flags, mode_t mode)
 {
-    return s->ops->open2(s, path->data, flags, mode);
+    return s->ops->open2(&s->ctx, path->data, flags, mode);
 }
 
-static int posix_symlink(V9fsState *s, V9fsString *oldpath,
+static int v9fs_do_symlink(V9fsState *s, V9fsString *oldpath,
 			 V9fsString *newpath)
 {
-    return s->ops->symlink(s, oldpath->data, newpath->data);
+    return s->ops->symlink(&s->ctx, oldpath->data, newpath->data);
 }
 
-static int posix_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
+static int v9fs_do_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
 {
-    return s->ops->link(s, oldpath->data, newpath->data);
+    return s->ops->link(&s->ctx, oldpath->data, newpath->data);
 }
 
-static int posix_truncate(V9fsState *s, V9fsString *path, off_t size)
+static int v9fs_do_truncate(V9fsState *s, V9fsString *path, off_t size)
 {
-    return s->ops->truncate(s, path->data, size);
+    return s->ops->truncate(&s->ctx, path->data, size);
 }
 
-static int posix_rename(V9fsState *s, V9fsString *oldpath,
+static int v9fs_do_rename(V9fsState *s, V9fsString *oldpath,
 			V9fsString *newpath)
 {
-    return s->ops->rename(s, oldpath->data, newpath->data);
+    return s->ops->rename(&s->ctx, oldpath->data, newpath->data);
 }
 
-static int posix_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid)
+static int v9fs_do_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid)
 {
-    return s->ops->chown(s, path->data, uid, gid);
+    return s->ops->chown(&s->ctx, path->data, uid, gid);
 }
 
-static int posix_utime(V9fsState *s, V9fsString *path,
+static int v9fs_do_utime(V9fsState *s, V9fsString *path,
 		       const struct utimbuf *buf)
 {
-    return s->ops->utime(s, path->data, buf);
+    return s->ops->utime(&s->ctx, path->data, buf);
 }
 
-static int posix_remove(V9fsState *s, V9fsString *path)
+static int v9fs_do_remove(V9fsState *s, V9fsString *path)
 {
-    return s->ops->remove(s, path->data);
+    return s->ops->remove(&s->ctx, path->data);
 }
 
-static int posix_fsync(V9fsState *s, int fd)
+static int v9fs_do_fsync(V9fsState *s, int fd)
 {
-    return s->ops->fsync(s, fd);
+    return s->ops->fsync(&s->ctx, fd);
 }
 
 static void v9fs_string_init(V9fsString *str)
@@ -227,7 +227,7 @@ static V9fsFidState *lookup_fid(V9fsState *s, int32_t fid)
 
     for (f = s->fid_list; f; f = f->next) {
         if (f->fid == fid) {
-            posix_setuid(s, f->uid);
+            v9fs_do_setuid(s, f->uid);
             return f;
         }
     }
@@ -271,9 +271,9 @@ static int free_fid(V9fsState *s, int32_t fid)
     *fidpp = fidp->next;
 
     if (fidp->fd != -1)
-        posix_close(s, fidp->fd);
+        v9fs_do_close(s, fidp->fd);
     if (fidp->dir)
-        posix_closedir(s, fidp->dir);
+        v9fs_do_closedir(s, fidp->dir);
     v9fs_string_free(&fidp->path);
     qemu_free(fidp);
 
@@ -325,7 +325,7 @@ static int fid_to_qid(V9fsState *s, V9fsFidState *fidp, V9fsQID *qidp)
     struct stat stbuf;
     int err;
 
-    err = posix_lstat(s, &fidp->path, &stbuf);
+    err = v9fs_do_lstat(s, &fidp->path, &stbuf);
     if (err) {
         return err;
     }
@@ -683,7 +683,7 @@ static int stat_to_v9stat(V9fsState *s, V9fsString *name,
         v9fs_string_null(&v9stat->extension);
 
         if (v9stat->mode & P9_STAT_MODE_SYMLINK) {
-            err = posix_readlink(s, name, &v9stat->extension);
+            err = v9fs_do_readlink(s, name, &v9stat->extension);
             if (err == -1) {
                 err = -errno;
                 return err;
@@ -816,7 +816,7 @@ static void v9fs_stat(V9fsState *s, V9fsPDU *pdu)
         goto out;
     }
 
-    err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
+    err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
     v9fs_stat_post_lstat(s, vs, err);
     return;
 
@@ -880,7 +880,7 @@ static void v9fs_walk_post_newfid_lstat(V9fsState *s, V9fsWalkState *vs,
                                             vs->wnames[vs->name_idx].data);
         v9fs_string_copy(&vs->newfidp->path, &vs->path);
 
-        err = posix_lstat(s, &vs->newfidp->path, &vs->stbuf);
+        err = v9fs_do_lstat(s, &vs->newfidp->path, &vs->stbuf);
         v9fs_walk_post_newfid_lstat(s, vs, err);
         return;
     }
@@ -909,7 +909,7 @@ static void v9fs_walk_post_oldfid_lstat(V9fsState *s, V9fsWalkState *vs,
                 vs->fidp->path.data, vs->wnames[vs->name_idx].data);
         v9fs_string_copy(&vs->fidp->path, &vs->path);
 
-        err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
+        err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
         v9fs_walk_post_oldfid_lstat(s, vs, err);
         return;
     }
@@ -967,7 +967,7 @@ static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
                 vs->fidp->path.data, vs->wnames[vs->name_idx].data);
             v9fs_string_copy(&vs->fidp->path, &vs->path);
 
-            err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
+            err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
             v9fs_walk_post_oldfid_lstat(s, vs, err);
             return;
         }
@@ -988,7 +988,7 @@ static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
                                 vs->wnames[vs->name_idx].data);
             v9fs_string_copy(&vs->newfidp->path, &vs->path);
 
-            err = posix_lstat(s, &vs->newfidp->path, &vs->stbuf);
+            err = v9fs_do_lstat(s, &vs->newfidp->path, &vs->stbuf);
             v9fs_walk_post_newfid_lstat(s, vs, err);
             return;
         }
@@ -1092,10 +1092,10 @@ static void v9fs_open_post_lstat(V9fsState *s, V9fsOpenState *vs, int err)
     stat_to_qid(&vs->stbuf, &vs->qid);
 
     if (S_ISDIR(vs->stbuf.st_mode)) {
-        vs->fidp->dir = posix_opendir(s, &vs->fidp->path);
+        vs->fidp->dir = v9fs_do_opendir(s, &vs->fidp->path);
         v9fs_open_post_opendir(s, vs, err);
     } else {
-        vs->fidp->fd = posix_open(s, &vs->fidp->path,
+        vs->fidp->fd = v9fs_do_open(s, &vs->fidp->path,
                                     omode_to_uflags(vs->mode));
         v9fs_open_post_open(s, vs, err);
     }
@@ -1127,7 +1127,7 @@ static void v9fs_open(V9fsState *s, V9fsPDU *pdu)
     BUG_ON(vs->fidp->fd != -1);
     BUG_ON(vs->fidp->dir);
 
-    err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
+    err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
 
     v9fs_open_post_lstat(s, vs, err);
     return;
@@ -1238,7 +1238,7 @@ static void v9fs_read_post_dir_lstat(V9fsState *s, V9fsReadState *vs,
                             &vs->v9stat);
     if ((vs->len != (vs->v9stat.size + 2)) ||
             ((vs->count + vs->len) > vs->max_count)) {
-        posix_seekdir(s, vs->fidp->dir, vs->dir_pos);
+        v9fs_do_seekdir(s, vs->fidp->dir, vs->dir_pos);
         v9fs_read_post_seekdir(s, vs, err);
         return;
     }
@@ -1246,11 +1246,11 @@ static void v9fs_read_post_dir_lstat(V9fsState *s, V9fsReadState *vs,
     v9fs_stat_free(&vs->v9stat);
     v9fs_string_free(&vs->name);
     vs->dir_pos = vs->dent->d_off;
-    vs->dent = posix_readdir(s, vs->fidp->dir);
+    vs->dent = v9fs_do_readdir(s, vs->fidp->dir);
     v9fs_read_post_readdir(s, vs, err);
     return;
 out:
-    posix_seekdir(s, vs->fidp->dir, vs->dir_pos);
+    v9fs_do_seekdir(s, vs->fidp->dir, vs->dir_pos);
     v9fs_read_post_seekdir(s, vs, err);
     return;
 
@@ -1263,7 +1263,7 @@ static void v9fs_read_post_readdir(V9fsState *s, V9fsReadState *vs, ssize_t err)
         v9fs_string_init(&vs->name);
         v9fs_string_sprintf(&vs->name, "%s/%s", vs->fidp->path.data,
                             vs->dent->d_name);
-        err = posix_lstat(s, &vs->name, &vs->stbuf);
+        err = v9fs_do_lstat(s, &vs->name, &vs->stbuf);
         v9fs_read_post_dir_lstat(s, vs, err);
         return;
     }
@@ -1278,7 +1278,7 @@ static void v9fs_read_post_readdir(V9fsState *s, V9fsReadState *vs, ssize_t err)
 
 static void v9fs_read_post_telldir(V9fsState *s, V9fsReadState *vs, ssize_t err)
 {
-    vs->dent = posix_readdir(s, vs->fidp->dir);
+    vs->dent = v9fs_do_readdir(s, vs->fidp->dir);
     v9fs_read_post_readdir(s, vs, err);
     return;
 }
@@ -1286,7 +1286,7 @@ static void v9fs_read_post_telldir(V9fsState *s, V9fsReadState *vs, ssize_t err)
 static void v9fs_read_post_rewinddir(V9fsState *s, V9fsReadState *vs,
                                        ssize_t err)
 {
-    vs->dir_pos = posix_telldir(s, vs->fidp->dir);
+    vs->dir_pos = v9fs_do_telldir(s, vs->fidp->dir);
     v9fs_read_post_telldir(s, vs, err);
     return;
 }
@@ -1305,7 +1305,7 @@ static void v9fs_read_post_readv(V9fsState *s, V9fsReadState *vs, ssize_t err)
             if (0) {
                 print_sg(vs->sg, vs->cnt);
             }
-            vs->len = posix_readv(s, vs->fidp->fd, vs->sg, vs->cnt);
+            vs->len = v9fs_do_readv(s, vs->fidp->fd, vs->sg, vs->cnt);
         } while (vs->len == -1 && errno == EINTR);
         if (vs->len == -1) {
             err  = -errno;
@@ -1335,7 +1335,7 @@ static void v9fs_read_post_lseek(V9fsState *s, V9fsReadState *vs, ssize_t err)
             if (0) {
                 print_sg(vs->sg, vs->cnt);
             }
-            vs->len = posix_readv(s, vs->fidp->fd, vs->sg, vs->cnt);
+            vs->len = v9fs_do_readv(s, vs->fidp->fd, vs->sg, vs->cnt);
         } while (vs->len == -1 && errno == EINTR);
 	if (vs->len == -1) {
             err  = -errno;
@@ -1373,14 +1373,14 @@ static void v9fs_read(V9fsState *s, V9fsPDU *pdu)
         vs->max_count = vs->count;
         vs->count = 0;
         if (vs->off == 0) {
-            posix_rewinddir(s, vs->fidp->dir);
+            v9fs_do_rewinddir(s, vs->fidp->dir);
         }
         v9fs_read_post_rewinddir(s, vs, err);
         return;
     } else if (vs->fidp->fd != -1) {
         vs->sg = vs->iov;
         pdu_marshal(vs->pdu, vs->offset + 4, "v", vs->sg, &vs->cnt);
-        err = posix_lseek(s, vs->fidp->fd, vs->off, SEEK_SET);
+        err = v9fs_do_lseek(s, vs->fidp->fd, vs->off, SEEK_SET);
         v9fs_read_post_lseek(s, vs, err);
         return;
     } else {
@@ -1436,7 +1436,7 @@ static void v9fs_write_post_writev(V9fsState *s, V9fsWriteState *vs,
         do {
             if (0)
                 print_sg(vs->sg, vs->cnt);
-            vs->len =  posix_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
+            vs->len =  v9fs_do_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
         } while (vs->len == -1 && errno == EINTR);
         if (vs->len == -1) {
             err  = -errno;
@@ -1464,7 +1464,7 @@ static void v9fs_write_post_lseek(V9fsState *s, V9fsWriteState *vs, ssize_t err)
         do {
             if (0)
                 print_sg(vs->sg, vs->cnt);
-            vs->len = posix_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
+            vs->len = v9fs_do_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
         } while (vs->len == -1 && errno == EINTR);
 	if (vs->len == -1) {
             err  = -errno;
@@ -1506,7 +1506,7 @@ static void v9fs_write(V9fsState *s, V9fsPDU *pdu)
         goto out;
     }
 
-    err = posix_lseek(s, vs->fidp->fd, vs->off, SEEK_SET);
+    err = v9fs_do_lseek(s, vs->fidp->fd, vs->off, SEEK_SET);
 
     v9fs_write_post_lseek(s, vs, err);
     return;
@@ -1572,7 +1572,7 @@ static void v9fs_create_post_dir_lstat(V9fsState *s, V9fsCreateState *vs,
         goto out;
     }
 
-    vs->fidp->dir = posix_opendir(s, &vs->fullname);
+    vs->fidp->dir = v9fs_do_opendir(s, &vs->fullname);
     v9fs_create_post_opendir(s, vs, err);
     return;
 
@@ -1587,7 +1587,7 @@ static void v9fs_create_post_mkdir(V9fsState *s, V9fsCreateState *vs, int err)
         goto out;
     }
 
-    err = posix_lstat(s, &vs->fullname, &vs->stbuf);
+    err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf);
     v9fs_create_post_dir_lstat(s, vs, err);
     return;
 
@@ -1603,7 +1603,7 @@ static void v9fs_create_post_mksock(V9fsState *s, V9fsCreateState *vs,
         goto out;
     }
 
-    err = posix_chmod(s, &vs->fullname, vs->perm & 0777);
+    err = v9fs_do_chmod(s, &vs->fullname, vs->perm & 0777);
     v9fs_create_post_perms(s, vs, err);
     return;
 
@@ -1629,7 +1629,7 @@ static void v9fs_create_post_open2(V9fsState *s, V9fsCreateState *vs, int err)
         goto out;
     }
 
-    err = posix_fstat(s, vs->fidp->fd, &vs->stbuf);
+    err = v9fs_do_fstat(s, vs->fidp->fd, &vs->stbuf);
     v9fs_create_post_fstat(s, vs, err);
 
     return;
@@ -1648,10 +1648,10 @@ static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err)
     }
 
     if (vs->perm & P9_STAT_MODE_DIR) {
-        err = posix_mkdir(s, &vs->fullname, vs->perm & 0777);
+        err = v9fs_do_mkdir(s, &vs->fullname, vs->perm & 0777);
         v9fs_create_post_mkdir(s, vs, err);
     } else if (vs->perm & P9_STAT_MODE_SYMLINK) {
-        err = posix_symlink(s, &vs->extension, &vs->fullname);
+        err = v9fs_do_symlink(s, &vs->extension, &vs->fullname);
         v9fs_create_post_perms(s, vs, err);
     } else if (vs->perm & P9_STAT_MODE_LINK) {
         int32_t nfid = atoi(vs->extension.data);
@@ -1660,7 +1660,7 @@ static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err)
             err = -errno;
             v9fs_post_create(s, vs, err);
         }
-        err = posix_link(s, &nfidp->path, &vs->fullname);
+        err = v9fs_do_link(s, &nfidp->path, &vs->fullname);
         v9fs_create_post_perms(s, vs, err);
     } else if (vs->perm & P9_STAT_MODE_DEVICE) {
         char ctype;
@@ -1686,16 +1686,16 @@ static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err)
         }
 
         nmode |= vs->perm & 0777;
-        err = posix_mknod(s, &vs->fullname, nmode, makedev(major, minor));
+        err = v9fs_do_mknod(s, &vs->fullname, nmode, makedev(major, minor));
         v9fs_create_post_perms(s, vs, err);
     } else if (vs->perm & P9_STAT_MODE_NAMED_PIPE) {
-        err = posix_mknod(s, &vs->fullname, S_IFIFO | (vs->mode & 0777), 0);
+        err = v9fs_do_mknod(s, &vs->fullname, S_IFIFO | (vs->mode & 0777), 0);
         v9fs_post_create(s, vs, err);
     } else if (vs->perm & P9_STAT_MODE_SOCKET) {
-        err = posix_mksock(s, &vs->fullname);
+        err = v9fs_do_mksock(s, &vs->fullname);
         v9fs_create_post_mksock(s, vs, err);
     } else {
-        vs->fidp->fd = posix_open2(s, &vs->fullname,
+        vs->fidp->fd = v9fs_do_open2(s, &vs->fullname,
                                 omode_to_uflags(vs->mode) | O_CREAT,
                                 vs->perm & 0777);
         v9fs_create_post_open2(s, vs, err);
@@ -1731,7 +1731,7 @@ static void v9fs_create(V9fsState *s, V9fsPDU *pdu)
     v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->fidp->path.data,
                                                         vs->name.data);
 
-    err = posix_lstat(s, &vs->fullname, &vs->stbuf);
+    err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf);
     v9fs_create_post_lstat(s, vs, err);
     return;
 
@@ -1791,7 +1791,7 @@ static void v9fs_remove(V9fsState *s, V9fsPDU *pdu)
         goto out;
     }
 
-    err = posix_remove(s, &vs->fidp->path);
+    err = v9fs_do_remove(s, &vs->fidp->path);
     v9fs_remove_post_remove(s, vs, err);
     return;
 
@@ -1872,7 +1872,7 @@ static void v9fs_wstat_post_rename(V9fsState *s, V9fsWstatState *vs, int err)
     }
 
     if (vs->v9stat.length != -1) {
-        if (posix_truncate(s, &vs->fidp->path, vs->v9stat.length) < 0) {
+        if (v9fs_do_truncate(s, &vs->fidp->path, vs->v9stat.length) < 0) {
             err = -errno;
         }
     }
@@ -1922,7 +1922,7 @@ static void v9fs_wstat_post_chown(V9fsState *s, V9fsWstatState *vs, int err)
         vs->nname.size = strlen(new_name);
 
         if (strcmp(new_name, vs->fidp->path.data) != 0) {
-            if (posix_rename(s, &vs->fidp->path, &vs->nname)) {
+            if (v9fs_do_rename(s, &vs->fidp->path, &vs->nname)) {
                 err = -errno;
             } else {
                 /*
@@ -1965,7 +1965,7 @@ static void v9fs_wstat_post_utime(V9fsState *s, V9fsWstatState *vs, int err)
     }
 
     if (vs->v9stat.n_gid != -1) {
-        if (posix_chown(s, &vs->fidp->path, vs->v9stat.n_uid,
+        if (v9fs_do_chown(s, &vs->fidp->path, vs->v9stat.n_uid,
                     vs->v9stat.n_gid)) {
             err = -errno;
         }
@@ -1989,7 +1989,7 @@ static void v9fs_wstat_post_chmod(V9fsState *s, V9fsWstatState *vs, int err)
         struct utimbuf tb;
         tb.actime = 0;
         tb.modtime = vs->v9stat.mtime;
-        if (posix_utime(s, &vs->fidp->path, &tb)) {
+        if (v9fs_do_utime(s, &vs->fidp->path, &tb)) {
             err = -errno;
         }
     }
@@ -2054,7 +2054,7 @@ static void v9fs_wstat_post_lstat(V9fsState *s, V9fsWstatState *vs, int err)
             goto out;
     }
 
-    if (posix_chmod(s, &vs->fidp->path, v9mode_to_mode(vs->v9stat.mode,
+    if (v9fs_do_chmod(s, &vs->fidp->path, v9mode_to_mode(vs->v9stat.mode,
                     &vs->v9stat.extension))) {
             err = -errno;
      }
@@ -2087,13 +2087,13 @@ static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
 
     /* do we need to sync the file? */
     if (donttouch_stat(&vs->v9stat)) {
-        err = posix_fsync(s, vs->fidp->fd);
+        err = v9fs_do_fsync(s, vs->fidp->fd);
         v9fs_wstat_post_fsync(s, vs, err);
         return;
     }
 
     if (vs->v9stat.mode != -1) {
-        err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
+        err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
         v9fs_wstat_post_lstat(s, vs, err);
         return;
     }
@@ -2243,7 +2243,8 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
 	    fprintf(stderr, "share path %s is not a directory \n", conf->share_path);
 	    exit(1);
     }
-    s->fs_root = qemu_strdup(conf->share_path);
+
+    s->ctx.fs_root = qemu_strdup(conf->share_path);
     len = strlen(conf->tag);
     if (len > MAX_TAG_LEN)
 	    len = MAX_TAG_LEN;
@@ -2251,7 +2252,7 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
     s->tag = qemu_malloc(len);
     memcpy(s->tag, conf->tag, len);
     s->tag_len = len;
-    s->uid = -1;
+    s->ctx.uid = -1;
 
     s->ops = virtio_9p_init_local(conf->share_path);
     s->vdev.get_features = virtio_9p_get_features;
diff --git a/hw/virtio-9p.h b/hw/virtio-9p.h
index 81c2c59..a249b67 100644
--- a/hw/virtio-9p.h
+++ b/hw/virtio-9p.h
@@ -6,6 +6,8 @@
 #include <sys/time.h>
 #include <utime.h>
 
+#include "file-op.h"
+
 /* The feature bitmap for virtio 9P */
 /* The mount point is specified in a config variable */
 #define VIRTIO_9P_MOUNT_TAG 0
@@ -129,7 +131,6 @@ struct V9fsFidState
     V9fsFidState *next;
 };
 
-struct V9fsPosixFileOpertions ;
 typedef struct V9fsState
 {
     VirtIODevice vdev;
@@ -137,9 +138,8 @@ typedef struct V9fsState
     V9fsPDU pdus[MAX_REQ];
     V9fsPDU *free_pdu;
     V9fsFidState *fid_list;
-    struct V9fsPosixFileOpertions *ops;
-    char *fs_root;
-    uid_t uid;
+    FileOperations *ops;
+    FsContext ctx;
     uint16_t tag_len;
     uint8_t *tag;
     size_t config_size;
@@ -153,40 +153,7 @@ struct virtio_9p_config
     uint8_t tag[0];
 } __attribute__((packed));
 
-typedef struct V9fsPosixFileOpertions
-{
-    int (*lstat)(V9fsState *, const char *, struct stat *);
-    ssize_t (*readlink)(V9fsState *, const char *, char *, size_t);
-    int (*chmod)(V9fsState *, const char *, mode_t);
-    int (*chown)(V9fsState *, const char *, uid_t, gid_t);
-    int (*mknod)(V9fsState *, const char *, mode_t, dev_t);
-    int (*mksock)(V9fsState *, const char *);
-    int (*utime)(V9fsState *, const char *, const struct utimbuf *);
-    int (*remove)(V9fsState *, const char *);
-    int (*symlink)(V9fsState *, const char *, const char *);
-    int (*link)(V9fsState *, const char *, const char *);
-    int (*setuid)(V9fsState *, uid_t);
-    int (*close)(V9fsState *, int);
-    int (*closedir)(V9fsState *, DIR *);
-    DIR *(*opendir)(V9fsState *, const char *);
-    int (*open)(V9fsState *, const char *, int);
-    int (*open2)(V9fsState *, const char *, int, mode_t);
-    void (*rewinddir)(V9fsState *, DIR *);
-    off_t (*telldir)(V9fsState *, DIR *);
-    struct dirent *(*readdir)(V9fsState *, DIR *);
-    void (*seekdir)(V9fsState *, DIR *, off_t);
-    ssize_t (*readv)(V9fsState *, int, const struct iovec *, int);
-    ssize_t (*writev)(V9fsState *, int, const struct iovec *, int);
-    off_t (*lseek)(V9fsState *, int, off_t, int);
-    int (*mkdir)(V9fsState *, const char *, mode_t);
-    int (*fstat)(V9fsState *, int, struct stat *);
-    int (*rename)(V9fsState *, const char *, const char *);
-    int (*truncate)(V9fsState *, const char *, off_t);
-    int (*fsync)(V9fsState *, int);
-    void *opaque;
-} V9fsPosixFileOperations;
-
-V9fsPosixFileOperations *virtio_9p_init_local(const char *path);
+FileOperations *virtio_9p_init_local(const char *path);
 extern size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
                             size_t offset, size_t size, int pack);
 
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 26/32] virtio-9p: Create a commandline option -fsdev
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (24 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 25/32] virtio-9p: Move V9fs File system specific options to a separate header file Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 27/32] virtio-9p: Create qemu_fsdev_opts Aneesh Kumar K.V
                   ` (5 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V, Gautham R Shenoy

From: Gautham R Shenoy <ego@in.ibm.com>

This patch creates a new command line option named -fsdev to hold any file
system specific information.

The option will currently hold the following attributes:

-fsdev fstype id=id,path=path_to_share

The only option for fstype currently is local.

Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 qemu-options.hx |   31 +++++++++++++++++++++++++++++++
 1 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/qemu-options.hx b/qemu-options.hx
index 8450b45..71a6fda 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -469,6 +469,37 @@ To get a help on possible @var{driver}s, @var{option}s or @var{value}s, use
 @code{-device @var{driver},@var{option}=?}. 
 ETEXI
 
+DEFHEADING(File system options:)
+
+DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev,
+    "-fsdev local,id=id,path=path\n")
+
+STEXI
+
+The general form of a File system device option is:
+@table @option
+
+@item -fsdev @var{fstype} ,id=@var{id} [,@var{options}]
+@findex -fsdev
+Fstype is one of:
+@option{local},
+The specific Fstype will determine the applicable options.
+
+Options to each backend are described below.
+
+@item -fsdev local ,id=@var{id} ,path=@var{path}
+
+Create a file-system-"device" for local-filesystem.
+
+@option{local} is only available on Linux.
+
+@option{path} specifies the path to be exported. @option{path} is required.
+
+@end table
+ETEXI
+
+DEFHEADING()
+
 DEF("name", HAS_ARG, QEMU_OPTION_name,
     "-name string1[,process=string2]\n"
     "                set the name of the guest\n"
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 27/32] virtio-9p: Create qemu_fsdev_opts
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (25 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 26/32] virtio-9p: Create a commandline option -fsdev Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 28/32] virtio-9p: Handle the fsdev command line options Aneesh Kumar K.V
                   ` (4 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V, Gautham R Shenoy

From: Gautham R Shenoy <ego@in.ibm.com>

Create qemu_fsdev_opts to store the parsed commandline attributes for fsdev.

Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 qemu-config.c |   16 ++++++++++++++++
 qemu-config.h |    1 +
 2 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/qemu-config.c b/qemu-config.c
index 150157c..0c06e1b 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -151,6 +151,22 @@ QemuOptsList qemu_chardev_opts = {
     },
 };
 
+QemuOptsList qemu_fsdev_opts = {
+    .name = "fsdev",
+    .implied_opt_name = "fstype",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_fsdev_opts.head),
+    .desc = {
+        {
+            .name = "fstype",
+            .type = QEMU_OPT_STRING,
+        },{
+            .name = "path",
+            .type = QEMU_OPT_STRING,
+        },
+        { /*End of list */ }
+    },
+};
+
 QemuOptsList qemu_device_opts = {
     .name = "device",
     .implied_opt_name = "driver",
diff --git a/qemu-config.h b/qemu-config.h
index f217c58..b01306c 100644
--- a/qemu-config.h
+++ b/qemu-config.h
@@ -3,6 +3,7 @@
 
 extern QemuOptsList qemu_drive_opts;
 extern QemuOptsList qemu_chardev_opts;
+extern QemuOptsList qemu_fsdev_opts;
 extern QemuOptsList qemu_device_opts;
 extern QemuOptsList qemu_netdev_opts;
 extern QemuOptsList qemu_net_opts;
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 28/32] virtio-9p: Handle the fsdev command line options.
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (26 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 27/32] virtio-9p: Create qemu_fsdev_opts Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 29/32] virtio-9p: Decouple share_path details from virtio-9p-dev Aneesh Kumar K.V
                   ` (3 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V, Gautham R Shenoy

From: Gautham R Shenoy <ego@in.ibm.com>

This patch handles:
- Parsing of fsdev commandline options.
- Maintaining a list of fsdev entries.
- Providing callbacks for the other subsystems to obtain FsTypeEntries
  for a given fsdev based on it's id.

This will be used later to decouple the share_path attribute from the virtio-9p
device.

Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 Makefile.objs        |    5 +++-
 fsdev/qemu-fsdev.c   |   70 ++++++++++++++++++++++++++++++++++++++++++++++++++
 fsdev/qemu-fsdev.h   |   53 +++++++++++++++++++++++++++++++++++++
 hw/virtio-9p-local.c |    4 +-
 vl.c                 |   18 +++++++++++++
 5 files changed, 147 insertions(+), 3 deletions(-)
 create mode 100644 fsdev/qemu-fsdev.c
 create mode 100644 fsdev/qemu-fsdev.h

diff --git a/Makefile.objs b/Makefile.objs
index 281f7a6..2adfdff 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -35,6 +35,9 @@ net-nested-$(CONFIG_SLIRP) += slirp.o
 net-nested-$(CONFIG_VDE) += vde.o
 net-obj-y += $(addprefix net/, $(net-nested-y))
 
+fsdev-nested-y = qemu-fsdev.o
+fsdev-obj-y += $(addprefix fsdev/, $(fsdev-nested-y))
+
 ######################################################################
 # libqemu_common.a: Target independent part of system emulation. The
 # long term path is to suppress *all* target specific code in case of
@@ -44,8 +47,8 @@ net-obj-y += $(addprefix net/, $(net-nested-y))
 common-obj-y = $(block-obj-y)
 common-obj-y += $(net-obj-y)
 common-obj-y += $(qobject-obj-y)
+common-obj-y += $(fsdev-obj-y)
 common-obj-y += readline.o console.o async.o qemu-error.o
-
 common-obj-y += tcg-runtime.o host-utils.o
 common-obj-y += irq.o ioport.o input.o
 common-obj-$(CONFIG_PTIMER) += ptimer.o
diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
new file mode 100644
index 0000000..cf1629a
--- /dev/null
+++ b/fsdev/qemu-fsdev.c
@@ -0,0 +1,70 @@
+/*
+ * Virtio 9p
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Gautham R Shenoy <ego@in.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 <stdio.h>
+#include <string.h>
+#include "qemu-fsdev.h"
+#include "qemu-queue.h"
+#include "osdep.h"
+#include "qemu-common.h"
+
+static QTAILQ_HEAD(FsTypeEntry_head, FsTypeListEntry) fstype_entries =
+    QTAILQ_HEAD_INITIALIZER(fstype_entries);
+
+extern FileOperations local_ops;
+static FsTypeTable FsTypes[] = {
+    { .name ="local", .ops = &local_ops},
+};
+
+int qemu_fsdev_add(QemuOpts *opts)
+{
+    struct FsTypeListEntry *fsle;
+    int i;
+
+    if (qemu_opts_id(opts) == NULL) {
+        fprintf(stderr, "fsdev: No id specified\n");
+        return -1;
+    }
+
+     for (i = 0; i < ARRAY_SIZE(FsTypes); i++) {
+        if (strcmp(FsTypes[i].name, qemu_opt_get(opts, "fstype")) == 0)
+            break;
+    }
+
+    if (i == ARRAY_SIZE(FsTypes)) {
+        fprintf(stderr, "fsdev: fstype %s not found\n",
+                    qemu_opt_get(opts, "fstype"));
+        return -1;
+    }
+
+    fsle =qemu_malloc(sizeof(*fsle));
+
+    fsle->fse.fsdev_id = qemu_strdup(qemu_opts_id(opts));
+    fsle->fse.path = qemu_strdup(qemu_opt_get(opts, "path"));
+    fsle->fse.ops = FsTypes[i].ops;
+
+    QTAILQ_INSERT_TAIL(&fstype_entries, fsle, next);
+    return 0;
+
+}
+
+FsTypeEntry * get_fsdev_fsentry(char *id)
+{
+    struct FsTypeListEntry *fsle;
+
+    QTAILQ_FOREACH(fsle, &fstype_entries, next) {
+        if (strcmp(fsle->fse.fsdev_id, id) == 0) {
+            return &fsle->fse;
+        }
+    }
+    return NULL;
+}
diff --git a/fsdev/qemu-fsdev.h b/fsdev/qemu-fsdev.h
new file mode 100644
index 0000000..db280bb
--- /dev/null
+++ b/fsdev/qemu-fsdev.h
@@ -0,0 +1,53 @@
+/*
+ * Virtio 9p
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Gautham R Shenoy <ego@in.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_FSDEV_H
+#define QEMU_FSDEV_H
+#include "qemu-option.h"
+#include "hw/file-op.h"
+
+
+/*
+ * A table to store the various file systems and their callback operations.
+ * -----------------
+ * fstype | ops
+ * -----------------
+ *  local | local_ops
+ *  .     |
+ *  .     |
+ *  .     |
+ *  .     |
+ * -----------------
+ *  etc
+ */
+typedef struct FsTypeTable {
+    const char *name;
+    FileOperations *ops;
+} FsTypeTable;
+
+/*
+ * Structure to store the various fsdev's passed through command line.
+ */
+typedef struct FsTypeEntry {
+    char *fsdev_id;
+    char *path;
+    FileOperations *ops;
+} FsTypeEntry;
+
+typedef struct FsTypeListEntry {
+    FsTypeEntry fse;
+    QTAILQ_ENTRY(FsTypeListEntry) next;
+} FsTypeListEntry;
+
+extern int qemu_fsdev_add(QemuOpts *opts);
+extern FsTypeEntry *get_fsdev_fsentry(char *id);
+#endif
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 690ba3f..aae82d2 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -254,7 +254,7 @@ static int local_fsync(FsContext *s, int fd)
     return fsync(fd);
 }
 
-static FileOperations ops = {
+FileOperations local_ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
     .readlink = local_readlink,
@@ -287,5 +287,5 @@ static FileOperations ops = {
 
 FileOperations *virtio_9p_init_local(const char *path)
 {
-    return &ops;
+    return &local_ops;
 }
diff --git a/vl.c b/vl.c
index d69250c..0228045 100644
--- a/vl.c
+++ b/vl.c
@@ -150,6 +150,7 @@ int main(int argc, char **argv)
 #include "qemu-option.h"
 #include "qemu-config.h"
 #include "qemu-objects.h"
+#include "fsdev/qemu-fsdev.h"
 
 #include "disas.h"
 
@@ -3461,6 +3462,14 @@ static int chardev_init_func(QemuOpts *opts, void *opaque)
     return 0;
 }
 
+static int fsdev_init_func(QemuOpts *opts, void *opaque)
+{
+    int ret;
+    ret = qemu_fsdev_add(opts);
+
+    return ret;
+}
+
 static int mon_init_func(QemuOpts *opts, void *opaque)
 {
     CharDriverState *chr;
@@ -4256,6 +4265,13 @@ int main(int argc, char **argv, char **envp)
                     exit(1);
                 }
                 break;
+            case QEMU_OPTION_fsdev:
+                opts = qemu_opts_parse(&qemu_fsdev_opts, optarg, 1);
+                if (!opts) {
+                    fprintf(stderr, "parse error: %s\n", optarg);
+                    exit(1);
+                }
+                break;
             case QEMU_OPTION_serial:
                 add_device_config(DEV_SERIAL, optarg);
                 default_serial = 0;
@@ -4625,6 +4641,8 @@ int main(int argc, char **argv, char **envp)
 
     if (qemu_opts_foreach(&qemu_chardev_opts, chardev_init_func, NULL, 1) != 0)
         exit(1);
+    if (qemu_opts_foreach(&qemu_fsdev_opts, fsdev_init_func, NULL, 1) != 0)
+        exit(1);
 
 #ifndef _WIN32
     if (daemonize) {
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 29/32] virtio-9p: Decouple share_path details from virtio-9p-dev
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (27 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 28/32] virtio-9p: Handle the fsdev command line options Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 30/32] virtio-9p: Create a syntactic shortcut for the file-system pass-thru Aneesh Kumar K.V
                   ` (2 subsequent siblings)
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V, Gautham R Shenoy

From: Gautham R Shenoy <ego@in.ibm.com>

Currently the share_path is an attribute of the virtio-9p device.

This patch makes fsdev object as an attribute of virtio-9p device by decoupling
the latter's association with share_path.

This abstraction would be useful in the future when we want to specify certain
file-system specific operations/flags as a part of the command line.

So, for now, the command line is going to look something like
#qemu -fsdev namefs,id=foo,path="path/to/share" \
      -device virtio-9p-pci,fsdev=foo,mount_tag=mount_tag \
      .
      .

Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/9p.h              |    2 +-
 hw/virtio-9p-local.c |    5 -----
 hw/virtio-9p.c       |   29 +++++++++++++++++++++--------
 hw/virtio-pci.c      |    2 +-
 4 files changed, 23 insertions(+), 15 deletions(-)

diff --git a/hw/9p.h b/hw/9p.h
index f0ff45b..5fdd770 100644
--- a/hw/9p.h
+++ b/hw/9p.h
@@ -18,9 +18,9 @@
 
 typedef struct V9fsConf
 {
-    char *share_path;
     /* tag name for the device */
     char *tag;
+    char *fsdev_id;
 } V9fsConf;
 
 #endif
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index aae82d2..a0cbcc0 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -284,8 +284,3 @@ FileOperations local_ops = {
     .remove = local_remove,
     .fsync = local_fsync,
 };
-
-FileOperations *virtio_9p_init_local(const char *path)
-{
-    return &local_ops;
-}
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index d03693d..5ccaeac 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -15,6 +15,7 @@
 #include "pc.h"
 #include "qemu_socket.h"
 #include "virtio-9p.h"
+#include "fsdev/qemu-fsdev.h"
 #include <assert.h>
 
 int dotu = 1;
@@ -2214,6 +2215,7 @@ 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",
@@ -2230,21 +2232,32 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
 
     s->vq = virtio_add_queue(&s->vdev, MAX_REQ, handle_9p_output);
 
-    if (!conf->share_path || !conf->tag) {
+    fse = get_fsdev_fsentry(conf->fsdev_id);
+
+    if (!fse) {
+        /* We don't have a fsdev identified by fsdev_id */
+        fprintf(stderr, "Virtio-9p device couldn't find fsdev "
+                 "with the id %s\n", conf->fsdev_id);
+        exit(1);
+    }
+
+    if (!fse->path || !conf->tag) {
 	    /* we haven't specified a mount_tag */
-	    fprintf(stderr, "Virtio-9p devices need share_path "
-		    "and mount_tag arguments\n");
+	    fprintf(stderr, "fsdev with id %s needs path "
+		    "and Virtio-9p device needs "
+		     "mount_tag arguments\n", conf->fsdev_id);
 	    exit(1);
     }
-    if (lstat(conf->share_path, &stat)) {
-	    fprintf(stderr, "share path %s does not exist\n", conf->share_path);
+    if (lstat(fse->path, &stat)) {
+	    fprintf(stderr, "share path %s does not exist\n", fse->path);
 	    exit(1);
     } else if (!S_ISDIR(stat.st_mode)) {
-	    fprintf(stderr, "share path %s is not a directory \n", conf->share_path);
+	    fprintf(stderr, "share path %s is not a directory \n",
+                fse->path);
 	    exit(1);
     }
 
-    s->ctx.fs_root = qemu_strdup(conf->share_path);
+    s->ctx.fs_root = qemu_strdup(fse->path);
     len = strlen(conf->tag);
     if (len > MAX_TAG_LEN)
 	    len = MAX_TAG_LEN;
@@ -2254,7 +2267,7 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
     s->tag_len = len;
     s->ctx.uid = -1;
 
-    s->ops = virtio_9p_init_local(conf->share_path);
+    s->ops = fse->ops;
     s->vdev.get_features = virtio_9p_get_features;
     s->config_size = sizeof(struct virtio_9p_config) +
 			s->tag_len;
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 73e7df7..6f26b88 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -626,8 +626,8 @@ static PCIDeviceInfo virtio_info[] = {
         .init      = virtio_9p_init_pci,
         .qdev.props = (Property[]) {
             DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
-            DEFINE_PROP_STRING("share_path", VirtIOPCIProxy, fsconf.share_path),
             DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
+            DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
             DEFINE_PROP_END_OF_LIST(),
         },
     },{
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 30/32] virtio-9p: Create a syntactic shortcut for the file-system pass-thru
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (28 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 29/32] virtio-9p: Decouple share_path details from virtio-9p-dev Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 31/32] virtio-9p: Return proper errors from create paths Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 32/32] virtio-9p: Handle unknown 9P protocol versions as per the standards Aneesh Kumar K.V
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Aneesh Kumar K.V, Gautham R Shenoy

From: Gautham R Shenoy <ego@in.ibm.com>

Currently the commandline to create a virtual-filesystem pass-through between
the guest and the host is as follows:
#qemu -fsdev fstype,id=ID,path=path/to/share \
      -device virtio-9p-pci,fsdev=ID,mount_tag=tag \

This patch provides a syntactic short-cut to achieve the same as follows:
#qemu -virtfs fstype,path=path/to/share,mount_tag=tag

This will be internally expanded as:
#qemu -fsdev fstype,id=tag,path=path/to/share, \
      -device virtio-9p-pci,fsdev=tag,mount_tag=tag \

Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 qemu-config.c   |   20 ++++++++++++++++++++
 qemu-config.h   |    1 +
 qemu-options.hx |   32 ++++++++++++++++++++++++++++++++
 vl.c            |   42 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 95 insertions(+), 0 deletions(-)

diff --git a/qemu-config.c b/qemu-config.c
index 0c06e1b..5564a24 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -167,6 +167,26 @@ QemuOptsList qemu_fsdev_opts = {
     },
 };
 
+QemuOptsList qemu_virtfs_opts = {
+    .name = "virtfs",
+    .implied_opt_name = "fstype",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_virtfs_opts.head),
+    .desc = {
+        {
+            .name = "fstype",
+            .type = QEMU_OPT_STRING,
+        },{
+            .name = "path",
+            .type = QEMU_OPT_STRING,
+        },{
+            .name = "mount_tag",
+            .type = QEMU_OPT_STRING,
+        },
+
+        { /*End of list */ }
+    },
+};
+
 QemuOptsList qemu_device_opts = {
     .name = "device",
     .implied_opt_name = "driver",
diff --git a/qemu-config.h b/qemu-config.h
index b01306c..8612747 100644
--- a/qemu-config.h
+++ b/qemu-config.h
@@ -4,6 +4,7 @@
 extern QemuOptsList qemu_drive_opts;
 extern QemuOptsList qemu_chardev_opts;
 extern QemuOptsList qemu_fsdev_opts;
+extern QemuOptsList qemu_virtfs_opts;
 extern QemuOptsList qemu_device_opts;
 extern QemuOptsList qemu_netdev_opts;
 extern QemuOptsList qemu_net_opts;
diff --git a/qemu-options.hx b/qemu-options.hx
index 71a6fda..cbdc22b 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -498,6 +498,38 @@ Create a file-system-"device" for local-filesystem.
 @end table
 ETEXI
 
+DEFHEADING(Virtual File system pass-through options:)
+
+DEF("virtfs", HAS_ARG, QEMU_OPTION_virtfs,
+    "-virtfs local,path=path,mount_tag=tag\n")
+
+STEXI
+
+The general form of a Virtual File system pass-through option is:
+@table @option
+
+@item -virtfs @var{fstype} [,@var{options}]
+@findex -virtfs
+Fstype is one of:
+@option{local},
+The specific Fstype will determine the applicable options.
+
+Options to each backend are described below.
+
+@item -virtfs local ,path=@var{path} ,mount_tag=@var{mount_tag}
+
+Create a Virtual file-system-pass through for local-filesystem.
+
+@option{local} is only available on Linux.
+
+@option{path} specifies the path to be exported. @option{path} is required.
+
+@option{mount_tag} specifies the tag with which the exported file is mounted.
+@option{mount_tag} is required.
+
+@end table
+ETEXI
+
 DEFHEADING()
 
 DEF("name", HAS_ARG, QEMU_OPTION_name,
diff --git a/vl.c b/vl.c
index 0228045..e9e597b 100644
--- a/vl.c
+++ b/vl.c
@@ -3747,6 +3747,8 @@ int main(int argc, char **argv, char **envp)
     CPUState *env;
     int show_vnc_port = 0;
     int defconfig = 1;
+    char *arg_fsdev = NULL;
+    char *arg_9p = NULL;
 
     error_set_progname(argv[0]);
 
@@ -4272,6 +4274,46 @@ int main(int argc, char **argv, char **envp)
                     exit(1);
                 }
                 break;
+            case QEMU_OPTION_virtfs:
+                opts = qemu_opts_parse(&qemu_virtfs_opts, optarg, 1);
+                if (!opts) {
+                    fprintf(stderr, "parse error: %s\n", optarg);
+                    exit(1);
+                }
+
+                qemu_asprintf(&arg_fsdev, "%s,id=%s,path=%s",
+                                qemu_opt_get(opts, "fstype"),
+                                qemu_opt_get(opts, "mount_tag"),
+                                qemu_opt_get(opts, "path"));
+                if (!arg_fsdev) {
+                    fprintf(stderr, "No memory to parse -fsdev for %s\n",
+                            optarg);
+                    exit(1);
+                }
+
+
+                qemu_asprintf(&arg_9p, "virtio-9p-pci,fsdev=%s,mount_tag=%s",
+                                qemu_opt_get(opts, "mount_tag"),
+                                qemu_opt_get(opts, "mount_tag"));
+                if (!arg_9p) {
+                    fprintf(stderr, "No memory to parse -device for %s\n",
+                            optarg);
+                    exit(1);
+                }
+
+                if (!qemu_opts_parse(&qemu_fsdev_opts, arg_fsdev, 1)) {
+                    fprintf(stderr, "parse error [fsdev]: %s\n", optarg);
+                    exit(1);
+                }
+
+                if (!qemu_opts_parse(&qemu_device_opts, arg_9p, 1)) {
+                    fprintf(stderr, "parse error [device]: %s\n", optarg);
+                    exit(1);
+                }
+
+                qemu_free(arg_fsdev);
+                qemu_free(arg_9p);
+                break;
             case QEMU_OPTION_serial:
                 add_device_config(DEV_SERIAL, optarg);
                 default_serial = 0;
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 31/32] virtio-9p: Return proper errors from create paths.
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (29 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 30/32] virtio-9p: Create a syntactic shortcut for the file-system pass-thru Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 32/32] virtio-9p: Handle unknown 9P protocol versions as per the standards Aneesh Kumar K.V
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, Sripathi Kodi, Aneesh Kumar K.V

From: Sripathi Kodi <sripathik@in.ibm.com>

Create first calls lstat to see if the file exists. Errors from lstat are
not handled properly. For most of the errors we return EEXIST. We should
return the errno instead.

Signed-off-by: Sripathi Kodi <sripathik@in.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 5ccaeac..1b791ca 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -1644,7 +1644,7 @@ static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err)
 {
 
     if ( err == 0 || errno != ENOENT) {
-        err = -EEXIST;
+        err = -errno;
         goto out;
     }
 
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Qemu-devel] [PATCH -V3 32/32] virtio-9p: Handle unknown 9P protocol versions as per the standards.
  2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (30 preceding siblings ...)
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 31/32] virtio-9p: Return proper errors from create paths Aneesh Kumar K.V
@ 2010-03-25 16:43 ` Aneesh Kumar K.V
  31 siblings, 0 replies; 55+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-25 16:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: ericvh, M. Mohan Kumar, aliguori, Sripathi Kodi, Aneesh Kumar K.V

From: Sripathi Kodi <sripathik@in.ibm.com>

Currently the code does BUG_ON if it receives any version other
than 9P2000.u.  However, 9P protocol says:
If the server does not understand the client's version string,
it should respond with an Rversion message (not Rerror) with
the version string the 7 characters "unknown".


Signed-off-by: Sripathi Kodi <sripathik@in.ibm.com>
Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 1b791ca..e6ddb3a 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -725,7 +725,10 @@ static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
     size_t offset = 7;
 
     pdu_unmarshal(pdu, offset, "ds", &msize, &version);
-    BUG_ON(strcmp(version.data, "9P2000.u") != 0);
+
+    if (strcmp(version.data, "9P2000.u")) {
+        v9fs_string_sprintf(&version, "unknown");
+    }
 
     offset += pdu_marshal(pdu, offset, "ds", msize, &version);
     complete_pdu(s, pdu, offset);
-- 
1.7.0.2.323.g0d092

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 01/32] vitio-9p: Add a virtio 9p device to qemu
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 01/32] vitio-9p: Add a virtio 9p device to qemu Aneesh Kumar K.V
@ 2010-03-25 21:04   ` Anthony Liguori
  0 siblings, 0 replies; 55+ messages in thread
From: Anthony Liguori @ 2010-03-25 21:04 UTC (permalink / raw)
  To: Aneesh Kumar K.V; +Cc: ericvh, aliguori, qemu-devel

On 03/25/2010 11:43 AM, Aneesh Kumar K.V wrote:
> From: Anthony Liguori<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 eb4d010..178ddce 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -166,6 +166,7 @@ obj-y += qemu-timer.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-serial-bus.o
> +obj-y += virtio-9p.o virtio-9p-debug.o
>   obj-y += rwhandler.o
>   obj-$(CONFIG_KVM) += kvm.o kvm-all.o
>   LIBS+=-lz
> diff --git a/hw/virtio-9p-debug.c b/hw/virtio-9p-debug.c
> new file mode 100644
> index 0000000..9230659
> --- /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>
>    

Can't directly include sys/uio here (doesn't exist on windows).  
qemu-common.h will do the right thing.

> +
> +#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;
>    

Coding style.

> +    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;
>    

Coding style.diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
> new file mode 100644
> index 0000000..115c93b
> --- /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;
>    

This shouldn't be enabled by default.

> +
> +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)
>    

Whitespace is off.

> +{    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);
> +}
>    

Coding style is consistently off.

> +
> +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);
>    

We shouldn't assume that everything is in the first sg element.diff 
--git a/hw/virtio-9p.h b/hw/virtio-9p.h
>   static PCIDeviceInfo virtio_info[] = {
>       {
>           .qdev.name = "virtio-blk-pci",
> @@ -606,6 +622,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(),
> +        },
>    

It's odd to introduce -fsdev after this and have a transient qdev property.

Regards,

Anthony Liguori

> +    },{
>           /* 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);
>
>    

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 25/32] virtio-9p: Move V9fs File system specific options to a separate header file.
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 25/32] virtio-9p: Move V9fs File system specific options to a separate header file Aneesh Kumar K.V
@ 2010-03-29  0:52   ` jvrao
  2010-03-29  1:09   ` jvrao
  1 sibling, 0 replies; 55+ messages in thread
From: jvrao @ 2010-03-29  0:52 UTC (permalink / raw)
  To: Aneesh Kumar K.V; +Cc: ericvh, aliguori, qemu-devel, Gautham R Shenoy

Aneesh Kumar K.V wrote:
> Move the V9fs File System specific operations structs into a different header
> file.
> 
> Also introduce a new struct named context which is the subset of the V9fsState
> to be passed to the individual file-system operations.
> 
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
> Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
> ---
>  hw/file-op.h         |   60 ++++++++++++++
>  hw/virtio-9p-local.c |   64 ++++++++--------
>  hw/virtio-9p.c       |  209 +++++++++++++++++++++++++-------------------------
>  hw/virtio-9p.h       |   43 +---------

I think we should add 9p to the file-op file too.   

May be fileop-9p.h ?

Thanks,
JV

>  4 files changed, 202 insertions(+), 174 deletions(-)
>  create mode 100644 hw/file-op.h
> 
> diff --git a/hw/file-op.h b/hw/file-op.h
> new file mode 100644
> index 0000000..f84767f
> --- /dev/null
> +++ b/hw/file-op.h
> @@ -0,0 +1,60 @@
> +/*
> + * 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 _FILEOP_H
> +#define _FILEOP_H
> +#include <sys/types.h>
> +#include <dirent.h>
> +#include <sys/time.h>
> +#include <utime.h>
> +#include <sys/stat.h>
> +#include <sys/uio.h>
> +
> +typedef struct FsContext
> +{
> +    char *fs_root;
> +    uid_t uid;
> +} FsContext;
> +
> +typedef struct FileOperations
> +{
> +    int (*lstat)(FsContext *, const char *, struct stat *);
> +    ssize_t (*readlink)(FsContext *, const char *, char *, size_t);
> +    int (*chmod)(FsContext *, const char *, mode_t);
> +    int (*chown)(FsContext *, const char *, uid_t, gid_t);
> +    int (*mknod)(FsContext *, const char *, mode_t, dev_t);
> +    int (*mksock)(FsContext *, const char *);
> +    int (*utime)(FsContext *, const char *, const struct utimbuf *);
> +    int (*remove)(FsContext *, const char *);
> +    int (*symlink)(FsContext *, const char *, const char *);
> +    int (*link)(FsContext *, const char *, const char *);
> +    int (*setuid)(FsContext *, uid_t);
> +    int (*close)(FsContext *, int);
> +    int (*closedir)(FsContext *, DIR *);
> +    DIR *(*opendir)(FsContext *, const char *);
> +    int (*open)(FsContext *, const char *, int);
> +    int (*open2)(FsContext *, const char *, int, mode_t);
> +    void (*rewinddir)(FsContext *, DIR *);
> +    off_t (*telldir)(FsContext *, DIR *);
> +    struct dirent *(*readdir)(FsContext *, DIR *);
> +    void (*seekdir)(FsContext *, DIR *, off_t);
> +    ssize_t (*readv)(FsContext *, int, const struct iovec *, int);
> +    ssize_t (*writev)(FsContext *, int, const struct iovec *, int);
> +    off_t (*lseek)(FsContext *, int, off_t, int);
> +    int (*mkdir)(FsContext *, const char *, mode_t);
> +    int (*fstat)(FsContext *, int, struct stat *);
> +    int (*rename)(FsContext *, const char *, const char *);
> +    int (*truncate)(FsContext *, const char *, off_t);
> +    int (*fsync)(FsContext *, int);
> +    void *opaque;
> +} FileOperations;
> +#endif
> diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
> index 4584bf6..690ba3f 100644
> --- a/hw/virtio-9p-local.c
> +++ b/hw/virtio-9p-local.c
> @@ -22,7 +22,7 @@
>  #include <sys/socket.h>
>  #include <sys/un.h>
> 
> -static const char *rpath(V9fsState *s, const char *path)
> +static const char *rpath(FsContext *s, const char *path)
>  {
>      /* FIXME: so wrong... */
>      static char buffer[4096];
> @@ -30,12 +30,12 @@ static const char *rpath(V9fsState *s, const char *path)
>      return buffer;
>  }
> 
> -static int local_lstat(V9fsState *s, const char *path, struct stat *stbuf)
> +static int local_lstat(FsContext *s, const char *path, struct stat *stbuf)
>  {
>      return lstat(rpath(s, path), stbuf);
>  }
> 
> -static int local_setuid(V9fsState *s, uid_t uid)
> +static int local_setuid(FsContext *s, uid_t uid)
>  {
>      struct passwd *pw;
>      gid_t groups[33];
> @@ -70,80 +70,80 @@ static int local_setuid(V9fsState *s, uid_t uid)
>      return 0;
>  }
> 
> -static ssize_t local_readlink(V9fsState *s, const char *path,
> +static ssize_t local_readlink(FsContext *s, const char *path,
>  			      char *buf, size_t bufsz)
>  {
>      return readlink(rpath(s, path), buf, bufsz);
>  }
> 
> -static int local_close(V9fsState *s, int fd)
> +static int local_close(FsContext *s, int fd)
>  {
>      return close(fd);
>  }
> 
> -static int local_closedir(V9fsState *s, DIR *dir)
> +static int local_closedir(FsContext *s, DIR *dir)
>  {
>      return closedir(dir);
>  }
> 
> -static int local_open(V9fsState *s, const char *path, int flags)
> +static int local_open(FsContext *s, const char *path, int flags)
>  {
>      return open(rpath(s, path), flags);
>  }
> 
> -static DIR *local_opendir(V9fsState *s, const char *path)
> +static DIR *local_opendir(FsContext *s, const char *path)
>  {
>      return opendir(rpath(s, path));
>  }
> 
> -static void local_rewinddir(V9fsState *s, DIR *dir)
> +static void local_rewinddir(FsContext *s, DIR *dir)
>  {
>      return rewinddir(dir);
>  }
> 
> -static off_t local_telldir(V9fsState *s, DIR *dir)
> +static off_t local_telldir(FsContext *s, DIR *dir)
>  {
>      return telldir(dir);
>  }
> 
> -static struct dirent *local_readdir(V9fsState *s, DIR *dir)
> +static struct dirent *local_readdir(FsContext *s, DIR *dir)
>  {
>      return readdir(dir);
>  }
> 
> -static void local_seekdir(V9fsState *s, DIR *dir, off_t off)
> +static void local_seekdir(FsContext *s, DIR *dir, off_t off)
>  {
>      return seekdir(dir, off);
>  }
> 
> -static ssize_t local_readv(V9fsState *s, int fd, const struct iovec *iov,
> +static ssize_t local_readv(FsContext *s, int fd, const struct iovec *iov,
>  			   int iovcnt)
>  {
>      return readv(fd, iov, iovcnt);
>  }
> 
> -static off_t local_lseek(V9fsState *s, int fd, off_t offset, int whence)
> +static off_t local_lseek(FsContext *s, int fd, off_t offset, int whence)
>  {
>      return lseek(fd, offset, whence);
>  }
> 
> -static ssize_t local_writev(V9fsState *s, int fd, const struct iovec *iov,
> +static ssize_t local_writev(FsContext *s, int fd, const struct iovec *iov,
>  			    int iovcnt)
>  {
>      return writev(fd, iov, iovcnt);
>  }
> 
> -static int local_chmod(V9fsState *s, const char *path, mode_t mode)
> +static int local_chmod(FsContext *s, const char *path, mode_t mode)
>  {
>      return chmod(rpath(s, path), mode);
>  }
> 
> -static int local_mknod(V9fsState *s, const char *path, mode_t mode, dev_t dev)
> +static int local_mknod(FsContext *s, const char *path, mode_t mode, dev_t dev)
>  {
>      return mknod(rpath(s, path), mode, dev);
>  }
> 
> -static int local_mksock(V9fsState *s2, const char *path)
> +static int local_mksock(FsContext *s2, const char *path)
>  {
>      struct sockaddr_un addr;
>      int s;
> @@ -164,28 +164,28 @@ static int local_mksock(V9fsState *s2, const char *path)
>      return 0;
>  }
> 
> -static int local_mkdir(V9fsState *s, const char *path, mode_t mode)
> +static int local_mkdir(FsContext *s, const char *path, mode_t mode)
>  {
>      return mkdir(rpath(s, path), mode);
>  }
> 
> -static int local_fstat(V9fsState *s, int fd, struct stat *stbuf)
> +static int local_fstat(FsContext *s, int fd, struct stat *stbuf)
>  {
>      return fstat(fd, stbuf);
>  }
> 
> -static int local_open2(V9fsState *s, const char *path, int flags, mode_t mode)
> +static int local_open2(FsContext *s, const char *path, int flags, mode_t mode)
>  {
>      return open(rpath(s, path), flags, mode);
>  }
> 
> -static int local_symlink(V9fsState *s, const char *oldpath,
> +static int local_symlink(FsContext *s, const char *oldpath,
>  			 const char *newpath)
>  {
>      return symlink(oldpath, rpath(s, newpath));
>  }
> 
> -static int local_link(V9fsState *s, const char *oldpath, const char *newpath)
> +static int local_link(FsContext *s, const char *oldpath, const char *newpath)
>  {
>      char *tmp = qemu_strdup(rpath(s, oldpath));
>      int err, serrno = 0;
> @@ -205,12 +205,12 @@ static int local_link(V9fsState *s, const char *oldpath, const char *newpath)
>      return err;
>  }
> 
> -static int local_truncate(V9fsState *s, const char *path, off_t size)
> +static int local_truncate(FsContext *s, const char *path, off_t size)
>  {
>      return truncate(rpath(s, path), size);
>  }
> 
> -static int local_rename(V9fsState *s, const char *oldpath,
> +static int local_rename(FsContext *s, const char *oldpath,
>  			const char *newpath)
>  {
>      char *tmp;
> @@ -232,29 +232,29 @@ static int local_rename(V9fsState *s, const char *oldpath,
> 
>  }
> 
> -static int local_chown(V9fsState *s, const char *path, uid_t uid, gid_t gid)
> +static int local_chown(FsContext *s, const char *path, uid_t uid, gid_t gid)
>  {
>      return chown(rpath(s, path), uid, gid);
>  }
> 
> -static int local_utime(V9fsState *s, const char *path,
> +static int local_utime(FsContext *s, const char *path,
>  		       const struct utimbuf *buf)
>  {
>      return utime(rpath(s, path), buf);
>  }
> 
> -static int local_remove(V9fsState *s, const char *path)
> +static int local_remove(FsContext *s, const char *path)
>  {
>      return remove(rpath(s, path));
>  }
> 
> 
> -static int local_fsync(V9fsState *s, int fd)
> +static int local_fsync(FsContext *s, int fd)
>  {
>      return fsync(fd);
>  }
> 
> -static V9fsPosixFileOperations ops = {
> +static FileOperations ops = {
>      .lstat = local_lstat,
>      .setuid = local_setuid,
>      .readlink = local_readlink,
> @@ -285,7 +285,7 @@ static V9fsPosixFileOperations ops = {
>      .fsync = local_fsync,
>  };
> 
> -V9fsPosixFileOperations *virtio_9p_init_local(const char *path)
> +FileOperations *virtio_9p_init_local(const char *path)
>  {
> -return &ops;
> +    return &ops;
>  }
> diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
> index e519605..d03693d 100644
> --- a/hw/virtio-9p.c
> +++ b/hw/virtio-9p.c
> @@ -22,23 +22,23 @@ int debug_9p_pdu = 1;
> 
>  extern void pprint_pdu(V9fsPDU *pdu);
> 
> -static int posix_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf)
> +static int v9fs_do_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf)
>  {
> -    return s->ops->lstat(s, path->data, stbuf);
> +    return s->ops->lstat(&s->ctx, path->data, stbuf);
>  }
> 
> -static int posix_setuid(V9fsState *s, uid_t uid)
> +static int v9fs_do_setuid(V9fsState *s, uid_t uid)
>  {
> -    return s->ops->setuid(s, uid);
> +    return s->ops->setuid(&s->ctx, uid);
>  }
> 
> -static ssize_t posix_readlink(V9fsState *s, V9fsString *path, V9fsString *buf)
> +static ssize_t v9fs_do_readlink(V9fsState *s, V9fsString *path, V9fsString *buf)
>  {
>      ssize_t len;
> 
>      buf->data = qemu_malloc(1024);
> 
> -    len = s->ops->readlink(s, path->data, buf->data, 1024 - 1);
> +    len = s->ops->readlink(&s->ctx, path->data, buf->data, 1024 - 1);
>      if (len > -1) {
>          buf->size = len;
>          buf->data[len] = 0;
> @@ -47,134 +47,134 @@ static ssize_t posix_readlink(V9fsState *s, V9fsString *path, V9fsString *buf)
>      return len;
>  }
> 
> -static int posix_close(V9fsState *s, int fd)
> +static int v9fs_do_close(V9fsState *s, int fd)
>  {
> -    return s->ops->close(s, fd);
> +    return s->ops->close(&s->ctx, fd);
>  }
> 
> -static int posix_closedir(V9fsState *s, DIR *dir)
> +static int v9fs_do_closedir(V9fsState *s, DIR *dir)
>  {
> -    return s->ops->closedir(s, dir);
> +    return s->ops->closedir(&s->ctx, dir);
>  }
> 
> -static int posix_open(V9fsState *s, V9fsString *path, int flags)
> +static int v9fs_do_open(V9fsState *s, V9fsString *path, int flags)
>  {
> -    return s->ops->open(s, path->data, flags);
> +    return s->ops->open(&s->ctx, path->data, flags);
>  }
> 
> -static DIR *posix_opendir(V9fsState *s, V9fsString *path)
> +static DIR *v9fs_do_opendir(V9fsState *s, V9fsString *path)
>  {
> -    return s->ops->opendir(s, path->data);
> +    return s->ops->opendir(&s->ctx, path->data);
>  }
> 
> -static void posix_rewinddir(V9fsState *s, DIR *dir)
> +static void v9fs_do_rewinddir(V9fsState *s, DIR *dir)
>  {
> -    return s->ops->rewinddir(s, dir);
> +    return s->ops->rewinddir(&s->ctx, dir);
>  }
> 
> -static off_t posix_telldir(V9fsState *s, DIR *dir)
> +static off_t v9fs_do_telldir(V9fsState *s, DIR *dir)
>  {
> -    return s->ops->telldir(s, dir);
> +    return s->ops->telldir(&s->ctx, dir);
>  }
> 
> -static struct dirent *posix_readdir(V9fsState *s, DIR *dir)
> +static struct dirent *v9fs_do_readdir(V9fsState *s, DIR *dir)
>  {
> -    return s->ops->readdir(s, dir);
> +    return s->ops->readdir(&s->ctx, dir);
>  }
> 
> -static void posix_seekdir(V9fsState *s, DIR *dir, off_t off)
> +static void v9fs_do_seekdir(V9fsState *s, DIR *dir, off_t off)
>  {
> -    return s->ops->seekdir(s, dir, off);
> +    return s->ops->seekdir(&s->ctx, dir, off);
>  }
> 
> -static int posix_readv(V9fsState *s, int fd, const struct iovec *iov,
> +static int v9fs_do_readv(V9fsState *s, int fd, const struct iovec *iov,
>  		       int iovcnt)
>  {
> -    return s->ops->readv(s, fd, iov, iovcnt);
> +    return s->ops->readv(&s->ctx, fd, iov, iovcnt);
>  }
> 
> -static off_t posix_lseek(V9fsState *s, int fd, off_t offset, int whence)
> +static off_t v9fs_do_lseek(V9fsState *s, int fd, off_t offset, int whence)
>  {
> -    return s->ops->lseek(s, fd, offset, whence);
> +    return s->ops->lseek(&s->ctx, fd, offset, whence);
>  }
> 
> -static int posix_writev(V9fsState *s, int fd, const struct iovec *iov,
> +static int v9fs_do_writev(V9fsState *s, int fd, const struct iovec *iov,
>                         int iovcnt)
>  {
> -    return s->ops->writev(s, fd, iov, iovcnt);
> +    return s->ops->writev(&s->ctx, fd, iov, iovcnt);
>  }
> 
> -static int posix_chmod(V9fsState *s, V9fsString *path, mode_t mode)
> +static int v9fs_do_chmod(V9fsState *s, V9fsString *path, mode_t mode)
>  {
> -    return s->ops->chmod(s, path->data, mode);
> +    return s->ops->chmod(&s->ctx, path->data, mode);
>  }
> 
> -static int posix_mknod(V9fsState *s, V9fsString *path, mode_t mode, dev_t dev)
> +static int v9fs_do_mknod(V9fsState *s, V9fsString *path, mode_t mode, dev_t dev)
>  {
> -    return s->ops->mknod(s, path->data, mode, dev);
> +    return s->ops->mknod(&s->ctx, path->data, mode, dev);
>  }
> 
> -static int posix_mksock(V9fsState *s, V9fsString *path)
> +static int v9fs_do_mksock(V9fsState *s, V9fsString *path)
>  {
> -    return s->ops->mksock(s, path->data);
> +    return s->ops->mksock(&s->ctx, path->data);
>  }
> 
> -static int posix_mkdir(V9fsState *s, V9fsString *path, mode_t mode)
> +static int v9fs_do_mkdir(V9fsState *s, V9fsString *path, mode_t mode)
>  {
> -    return s->ops->mkdir(s, path->data, mode);
> +    return s->ops->mkdir(&s->ctx, path->data, mode);
>  }
> 
> -static int posix_fstat(V9fsState *s, int fd, struct stat *stbuf)
> +static int v9fs_do_fstat(V9fsState *s, int fd, struct stat *stbuf)
>  {
> -    return s->ops->fstat(s, fd, stbuf);
> +    return s->ops->fstat(&s->ctx, fd, stbuf);
>  }
> 
> -static int posix_open2(V9fsState *s, V9fsString *path, int flags, mode_t mode)
> +static int v9fs_do_open2(V9fsState *s, V9fsString *path, int flags, mode_t mode)
>  {
> -    return s->ops->open2(s, path->data, flags, mode);
> +    return s->ops->open2(&s->ctx, path->data, flags, mode);
>  }
> 
> -static int posix_symlink(V9fsState *s, V9fsString *oldpath,
> +static int v9fs_do_symlink(V9fsState *s, V9fsString *oldpath,
>  			 V9fsString *newpath)
>  {
> -    return s->ops->symlink(s, oldpath->data, newpath->data);
> +    return s->ops->symlink(&s->ctx, oldpath->data, newpath->data);
>  }
> 
> -static int posix_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
> +static int v9fs_do_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
>  {
> -    return s->ops->link(s, oldpath->data, newpath->data);
> +    return s->ops->link(&s->ctx, oldpath->data, newpath->data);
>  }
> 
> -static int posix_truncate(V9fsState *s, V9fsString *path, off_t size)
> +static int v9fs_do_truncate(V9fsState *s, V9fsString *path, off_t size)
>  {
> -    return s->ops->truncate(s, path->data, size);
> +    return s->ops->truncate(&s->ctx, path->data, size);
>  }
> 
> -static int posix_rename(V9fsState *s, V9fsString *oldpath,
> +static int v9fs_do_rename(V9fsState *s, V9fsString *oldpath,
>  			V9fsString *newpath)
>  {
> -    return s->ops->rename(s, oldpath->data, newpath->data);
> +    return s->ops->rename(&s->ctx, oldpath->data, newpath->data);
>  }
> 
> -static int posix_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid)
> +static int v9fs_do_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid)
>  {
> -    return s->ops->chown(s, path->data, uid, gid);
> +    return s->ops->chown(&s->ctx, path->data, uid, gid);
>  }
> 
> -static int posix_utime(V9fsState *s, V9fsString *path,
> +static int v9fs_do_utime(V9fsState *s, V9fsString *path,
>  		       const struct utimbuf *buf)
>  {
> -    return s->ops->utime(s, path->data, buf);
> +    return s->ops->utime(&s->ctx, path->data, buf);
>  }
> 
> -static int posix_remove(V9fsState *s, V9fsString *path)
> +static int v9fs_do_remove(V9fsState *s, V9fsString *path)
>  {
> -    return s->ops->remove(s, path->data);
> +    return s->ops->remove(&s->ctx, path->data);
>  }
> 
> -static int posix_fsync(V9fsState *s, int fd)
> +static int v9fs_do_fsync(V9fsState *s, int fd)
>  {
> -    return s->ops->fsync(s, fd);
> +    return s->ops->fsync(&s->ctx, fd);
>  }
> 
>  static void v9fs_string_init(V9fsString *str)
> @@ -227,7 +227,7 @@ static V9fsFidState *lookup_fid(V9fsState *s, int32_t fid)
> 
>      for (f = s->fid_list; f; f = f->next) {
>          if (f->fid == fid) {
> -            posix_setuid(s, f->uid);
> +            v9fs_do_setuid(s, f->uid);
>              return f;
>          }
>      }
> @@ -271,9 +271,9 @@ static int free_fid(V9fsState *s, int32_t fid)
>      *fidpp = fidp->next;
> 
>      if (fidp->fd != -1)
> -        posix_close(s, fidp->fd);
> +        v9fs_do_close(s, fidp->fd);
>      if (fidp->dir)
> -        posix_closedir(s, fidp->dir);
> +        v9fs_do_closedir(s, fidp->dir);
>      v9fs_string_free(&fidp->path);
>      qemu_free(fidp);
> 
> @@ -325,7 +325,7 @@ static int fid_to_qid(V9fsState *s, V9fsFidState *fidp, V9fsQID *qidp)
>      struct stat stbuf;
>      int err;
> 
> -    err = posix_lstat(s, &fidp->path, &stbuf);
> +    err = v9fs_do_lstat(s, &fidp->path, &stbuf);
>      if (err) {
>          return err;
>      }
> @@ -683,7 +683,7 @@ static int stat_to_v9stat(V9fsState *s, V9fsString *name,
>          v9fs_string_null(&v9stat->extension);
> 
>          if (v9stat->mode & P9_STAT_MODE_SYMLINK) {
> -            err = posix_readlink(s, name, &v9stat->extension);
> +            err = v9fs_do_readlink(s, name, &v9stat->extension);
>              if (err == -1) {
>                  err = -errno;
>                  return err;
> @@ -816,7 +816,7 @@ static void v9fs_stat(V9fsState *s, V9fsPDU *pdu)
>          goto out;
>      }
> 
> -    err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
> +    err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
>      v9fs_stat_post_lstat(s, vs, err);
>      return;
> 
> @@ -880,7 +880,7 @@ static void v9fs_walk_post_newfid_lstat(V9fsState *s, V9fsWalkState *vs,
>                                              vs->wnames[vs->name_idx].data);
>          v9fs_string_copy(&vs->newfidp->path, &vs->path);
> 
> -        err = posix_lstat(s, &vs->newfidp->path, &vs->stbuf);
> +        err = v9fs_do_lstat(s, &vs->newfidp->path, &vs->stbuf);
>          v9fs_walk_post_newfid_lstat(s, vs, err);
>          return;
>      }
> @@ -909,7 +909,7 @@ static void v9fs_walk_post_oldfid_lstat(V9fsState *s, V9fsWalkState *vs,
>                  vs->fidp->path.data, vs->wnames[vs->name_idx].data);
>          v9fs_string_copy(&vs->fidp->path, &vs->path);
> 
> -        err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
> +        err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
>          v9fs_walk_post_oldfid_lstat(s, vs, err);
>          return;
>      }
> @@ -967,7 +967,7 @@ static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
>                  vs->fidp->path.data, vs->wnames[vs->name_idx].data);
>              v9fs_string_copy(&vs->fidp->path, &vs->path);
> 
> -            err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
> +            err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
>              v9fs_walk_post_oldfid_lstat(s, vs, err);
>              return;
>          }
> @@ -988,7 +988,7 @@ static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
>                                  vs->wnames[vs->name_idx].data);
>              v9fs_string_copy(&vs->newfidp->path, &vs->path);
> 
> -            err = posix_lstat(s, &vs->newfidp->path, &vs->stbuf);
> +            err = v9fs_do_lstat(s, &vs->newfidp->path, &vs->stbuf);
>              v9fs_walk_post_newfid_lstat(s, vs, err);
>              return;
>          }
> @@ -1092,10 +1092,10 @@ static void v9fs_open_post_lstat(V9fsState *s, V9fsOpenState *vs, int err)
>      stat_to_qid(&vs->stbuf, &vs->qid);
> 
>      if (S_ISDIR(vs->stbuf.st_mode)) {
> -        vs->fidp->dir = posix_opendir(s, &vs->fidp->path);
> +        vs->fidp->dir = v9fs_do_opendir(s, &vs->fidp->path);
>          v9fs_open_post_opendir(s, vs, err);
>      } else {
> -        vs->fidp->fd = posix_open(s, &vs->fidp->path,
> +        vs->fidp->fd = v9fs_do_open(s, &vs->fidp->path,
>                                      omode_to_uflags(vs->mode));
>          v9fs_open_post_open(s, vs, err);
>      }
> @@ -1127,7 +1127,7 @@ static void v9fs_open(V9fsState *s, V9fsPDU *pdu)
>      BUG_ON(vs->fidp->fd != -1);
>      BUG_ON(vs->fidp->dir);
> 
> -    err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
> +    err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
> 
>      v9fs_open_post_lstat(s, vs, err);
>      return;
> @@ -1238,7 +1238,7 @@ static void v9fs_read_post_dir_lstat(V9fsState *s, V9fsReadState *vs,
>                              &vs->v9stat);
>      if ((vs->len != (vs->v9stat.size + 2)) ||
>              ((vs->count + vs->len) > vs->max_count)) {
> -        posix_seekdir(s, vs->fidp->dir, vs->dir_pos);
> +        v9fs_do_seekdir(s, vs->fidp->dir, vs->dir_pos);
>          v9fs_read_post_seekdir(s, vs, err);
>          return;
>      }
> @@ -1246,11 +1246,11 @@ static void v9fs_read_post_dir_lstat(V9fsState *s, V9fsReadState *vs,
>      v9fs_stat_free(&vs->v9stat);
>      v9fs_string_free(&vs->name);
>      vs->dir_pos = vs->dent->d_off;
> -    vs->dent = posix_readdir(s, vs->fidp->dir);
> +    vs->dent = v9fs_do_readdir(s, vs->fidp->dir);
>      v9fs_read_post_readdir(s, vs, err);
>      return;
>  out:
> -    posix_seekdir(s, vs->fidp->dir, vs->dir_pos);
> +    v9fs_do_seekdir(s, vs->fidp->dir, vs->dir_pos);
>      v9fs_read_post_seekdir(s, vs, err);
>      return;
> 
> @@ -1263,7 +1263,7 @@ static void v9fs_read_post_readdir(V9fsState *s, V9fsReadState *vs, ssize_t err)
>          v9fs_string_init(&vs->name);
>          v9fs_string_sprintf(&vs->name, "%s/%s", vs->fidp->path.data,
>                              vs->dent->d_name);
> -        err = posix_lstat(s, &vs->name, &vs->stbuf);
> +        err = v9fs_do_lstat(s, &vs->name, &vs->stbuf);
>          v9fs_read_post_dir_lstat(s, vs, err);
>          return;
>      }
> @@ -1278,7 +1278,7 @@ static void v9fs_read_post_readdir(V9fsState *s, V9fsReadState *vs, ssize_t err)
> 
>  static void v9fs_read_post_telldir(V9fsState *s, V9fsReadState *vs, ssize_t err)
>  {
> -    vs->dent = posix_readdir(s, vs->fidp->dir);
> +    vs->dent = v9fs_do_readdir(s, vs->fidp->dir);
>      v9fs_read_post_readdir(s, vs, err);
>      return;
>  }
> @@ -1286,7 +1286,7 @@ static void v9fs_read_post_telldir(V9fsState *s, V9fsReadState *vs, ssize_t err)
>  static void v9fs_read_post_rewinddir(V9fsState *s, V9fsReadState *vs,
>                                         ssize_t err)
>  {
> -    vs->dir_pos = posix_telldir(s, vs->fidp->dir);
> +    vs->dir_pos = v9fs_do_telldir(s, vs->fidp->dir);
>      v9fs_read_post_telldir(s, vs, err);
>      return;
>  }
> @@ -1305,7 +1305,7 @@ static void v9fs_read_post_readv(V9fsState *s, V9fsReadState *vs, ssize_t err)
>              if (0) {
>                  print_sg(vs->sg, vs->cnt);
>              }
> -            vs->len = posix_readv(s, vs->fidp->fd, vs->sg, vs->cnt);
> +            vs->len = v9fs_do_readv(s, vs->fidp->fd, vs->sg, vs->cnt);
>          } while (vs->len == -1 && errno == EINTR);
>          if (vs->len == -1) {
>              err  = -errno;
> @@ -1335,7 +1335,7 @@ static void v9fs_read_post_lseek(V9fsState *s, V9fsReadState *vs, ssize_t err)
>              if (0) {
>                  print_sg(vs->sg, vs->cnt);
>              }
> -            vs->len = posix_readv(s, vs->fidp->fd, vs->sg, vs->cnt);
> +            vs->len = v9fs_do_readv(s, vs->fidp->fd, vs->sg, vs->cnt);
>          } while (vs->len == -1 && errno == EINTR);
>  	if (vs->len == -1) {
>              err  = -errno;
> @@ -1373,14 +1373,14 @@ static void v9fs_read(V9fsState *s, V9fsPDU *pdu)
>          vs->max_count = vs->count;
>          vs->count = 0;
>          if (vs->off == 0) {
> -            posix_rewinddir(s, vs->fidp->dir);
> +            v9fs_do_rewinddir(s, vs->fidp->dir);
>          }
>          v9fs_read_post_rewinddir(s, vs, err);
>          return;
>      } else if (vs->fidp->fd != -1) {
>          vs->sg = vs->iov;
>          pdu_marshal(vs->pdu, vs->offset + 4, "v", vs->sg, &vs->cnt);
> -        err = posix_lseek(s, vs->fidp->fd, vs->off, SEEK_SET);
> +        err = v9fs_do_lseek(s, vs->fidp->fd, vs->off, SEEK_SET);
>          v9fs_read_post_lseek(s, vs, err);
>          return;
>      } else {
> @@ -1436,7 +1436,7 @@ static void v9fs_write_post_writev(V9fsState *s, V9fsWriteState *vs,
>          do {
>              if (0)
>                  print_sg(vs->sg, vs->cnt);
> -            vs->len =  posix_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
> +            vs->len =  v9fs_do_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
>          } while (vs->len == -1 && errno == EINTR);
>          if (vs->len == -1) {
>              err  = -errno;
> @@ -1464,7 +1464,7 @@ static void v9fs_write_post_lseek(V9fsState *s, V9fsWriteState *vs, ssize_t err)
>          do {
>              if (0)
>                  print_sg(vs->sg, vs->cnt);
> -            vs->len = posix_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
> +            vs->len = v9fs_do_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
>          } while (vs->len == -1 && errno == EINTR);
>  	if (vs->len == -1) {
>              err  = -errno;
> @@ -1506,7 +1506,7 @@ static void v9fs_write(V9fsState *s, V9fsPDU *pdu)
>          goto out;
>      }
> 
> -    err = posix_lseek(s, vs->fidp->fd, vs->off, SEEK_SET);
> +    err = v9fs_do_lseek(s, vs->fidp->fd, vs->off, SEEK_SET);
> 
>      v9fs_write_post_lseek(s, vs, err);
>      return;
> @@ -1572,7 +1572,7 @@ static void v9fs_create_post_dir_lstat(V9fsState *s, V9fsCreateState *vs,
>          goto out;
>      }
> 
> -    vs->fidp->dir = posix_opendir(s, &vs->fullname);
> +    vs->fidp->dir = v9fs_do_opendir(s, &vs->fullname);
>      v9fs_create_post_opendir(s, vs, err);
>      return;
> 
> @@ -1587,7 +1587,7 @@ static void v9fs_create_post_mkdir(V9fsState *s, V9fsCreateState *vs, int err)
>          goto out;
>      }
> 
> -    err = posix_lstat(s, &vs->fullname, &vs->stbuf);
> +    err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf);
>      v9fs_create_post_dir_lstat(s, vs, err);
>      return;
> 
> @@ -1603,7 +1603,7 @@ static void v9fs_create_post_mksock(V9fsState *s, V9fsCreateState *vs,
>          goto out;
>      }
> 
> -    err = posix_chmod(s, &vs->fullname, vs->perm & 0777);
> +    err = v9fs_do_chmod(s, &vs->fullname, vs->perm & 0777);
>      v9fs_create_post_perms(s, vs, err);
>      return;
> 
> @@ -1629,7 +1629,7 @@ static void v9fs_create_post_open2(V9fsState *s, V9fsCreateState *vs, int err)
>          goto out;
>      }
> 
> -    err = posix_fstat(s, vs->fidp->fd, &vs->stbuf);
> +    err = v9fs_do_fstat(s, vs->fidp->fd, &vs->stbuf);
>      v9fs_create_post_fstat(s, vs, err);
> 
>      return;
> @@ -1648,10 +1648,10 @@ static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err)
>      }
> 
>      if (vs->perm & P9_STAT_MODE_DIR) {
> -        err = posix_mkdir(s, &vs->fullname, vs->perm & 0777);
> +        err = v9fs_do_mkdir(s, &vs->fullname, vs->perm & 0777);
>          v9fs_create_post_mkdir(s, vs, err);
>      } else if (vs->perm & P9_STAT_MODE_SYMLINK) {
> -        err = posix_symlink(s, &vs->extension, &vs->fullname);
> +        err = v9fs_do_symlink(s, &vs->extension, &vs->fullname);
>          v9fs_create_post_perms(s, vs, err);
>      } else if (vs->perm & P9_STAT_MODE_LINK) {
>          int32_t nfid = atoi(vs->extension.data);
> @@ -1660,7 +1660,7 @@ static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err)
>              err = -errno;
>              v9fs_post_create(s, vs, err);
>          }
> -        err = posix_link(s, &nfidp->path, &vs->fullname);
> +        err = v9fs_do_link(s, &nfidp->path, &vs->fullname);
>          v9fs_create_post_perms(s, vs, err);
>      } else if (vs->perm & P9_STAT_MODE_DEVICE) {
>          char ctype;
> @@ -1686,16 +1686,16 @@ static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err)
>          }
> 
>          nmode |= vs->perm & 0777;
> -        err = posix_mknod(s, &vs->fullname, nmode, makedev(major, minor));
> +        err = v9fs_do_mknod(s, &vs->fullname, nmode, makedev(major, minor));
>          v9fs_create_post_perms(s, vs, err);
>      } else if (vs->perm & P9_STAT_MODE_NAMED_PIPE) {
> -        err = posix_mknod(s, &vs->fullname, S_IFIFO | (vs->mode & 0777), 0);
> +        err = v9fs_do_mknod(s, &vs->fullname, S_IFIFO | (vs->mode & 0777), 0);
>          v9fs_post_create(s, vs, err);
>      } else if (vs->perm & P9_STAT_MODE_SOCKET) {
> -        err = posix_mksock(s, &vs->fullname);
> +        err = v9fs_do_mksock(s, &vs->fullname);
>          v9fs_create_post_mksock(s, vs, err);
>      } else {
> -        vs->fidp->fd = posix_open2(s, &vs->fullname,
> +        vs->fidp->fd = v9fs_do_open2(s, &vs->fullname,
>                                  omode_to_uflags(vs->mode) | O_CREAT,
>                                  vs->perm & 0777);
>          v9fs_create_post_open2(s, vs, err);
> @@ -1731,7 +1731,7 @@ static void v9fs_create(V9fsState *s, V9fsPDU *pdu)
>      v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->fidp->path.data,
>                                                          vs->name.data);
> 
> -    err = posix_lstat(s, &vs->fullname, &vs->stbuf);
> +    err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf);
>      v9fs_create_post_lstat(s, vs, err);
>      return;
> 
> @@ -1791,7 +1791,7 @@ static void v9fs_remove(V9fsState *s, V9fsPDU *pdu)
>          goto out;
>      }
> 
> -    err = posix_remove(s, &vs->fidp->path);
> +    err = v9fs_do_remove(s, &vs->fidp->path);
>      v9fs_remove_post_remove(s, vs, err);
>      return;
> 
> @@ -1872,7 +1872,7 @@ static void v9fs_wstat_post_rename(V9fsState *s, V9fsWstatState *vs, int err)
>      }
> 
>      if (vs->v9stat.length != -1) {
> -        if (posix_truncate(s, &vs->fidp->path, vs->v9stat.length) < 0) {
> +        if (v9fs_do_truncate(s, &vs->fidp->path, vs->v9stat.length) < 0) {
>              err = -errno;
>          }
>      }
> @@ -1922,7 +1922,7 @@ static void v9fs_wstat_post_chown(V9fsState *s, V9fsWstatState *vs, int err)
>          vs->nname.size = strlen(new_name);
> 
>          if (strcmp(new_name, vs->fidp->path.data) != 0) {
> -            if (posix_rename(s, &vs->fidp->path, &vs->nname)) {
> +            if (v9fs_do_rename(s, &vs->fidp->path, &vs->nname)) {
>                  err = -errno;
>              } else {
>                  /*
> @@ -1965,7 +1965,7 @@ static void v9fs_wstat_post_utime(V9fsState *s, V9fsWstatState *vs, int err)
>      }
> 
>      if (vs->v9stat.n_gid != -1) {
> -        if (posix_chown(s, &vs->fidp->path, vs->v9stat.n_uid,
> +        if (v9fs_do_chown(s, &vs->fidp->path, vs->v9stat.n_uid,
>                      vs->v9stat.n_gid)) {
>              err = -errno;
>          }
> @@ -1989,7 +1989,7 @@ static void v9fs_wstat_post_chmod(V9fsState *s, V9fsWstatState *vs, int err)
>          struct utimbuf tb;
>          tb.actime = 0;
>          tb.modtime = vs->v9stat.mtime;
> -        if (posix_utime(s, &vs->fidp->path, &tb)) {
> +        if (v9fs_do_utime(s, &vs->fidp->path, &tb)) {
>              err = -errno;
>          }
>      }
> @@ -2054,7 +2054,7 @@ static void v9fs_wstat_post_lstat(V9fsState *s, V9fsWstatState *vs, int err)
>              goto out;
>      }
> 
> -    if (posix_chmod(s, &vs->fidp->path, v9mode_to_mode(vs->v9stat.mode,
> +    if (v9fs_do_chmod(s, &vs->fidp->path, v9mode_to_mode(vs->v9stat.mode,
>                      &vs->v9stat.extension))) {
>              err = -errno;
>       }
> @@ -2087,13 +2087,13 @@ static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
> 
>      /* do we need to sync the file? */
>      if (donttouch_stat(&vs->v9stat)) {
> -        err = posix_fsync(s, vs->fidp->fd);
> +        err = v9fs_do_fsync(s, vs->fidp->fd);
>          v9fs_wstat_post_fsync(s, vs, err);
>          return;
>      }
> 
>      if (vs->v9stat.mode != -1) {
> -        err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
> +        err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
>          v9fs_wstat_post_lstat(s, vs, err);
>          return;
>      }
> @@ -2243,7 +2243,8 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
>  	    fprintf(stderr, "share path %s is not a directory \n", conf->share_path);
>  	    exit(1);
>      }
> -    s->fs_root = qemu_strdup(conf->share_path);
> +
> +    s->ctx.fs_root = qemu_strdup(conf->share_path);
>      len = strlen(conf->tag);
>      if (len > MAX_TAG_LEN)
>  	    len = MAX_TAG_LEN;
> @@ -2251,7 +2252,7 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
>      s->tag = qemu_malloc(len);
>      memcpy(s->tag, conf->tag, len);
>      s->tag_len = len;
> -    s->uid = -1;
> +    s->ctx.uid = -1;
> 
>      s->ops = virtio_9p_init_local(conf->share_path);
>      s->vdev.get_features = virtio_9p_get_features;
> diff --git a/hw/virtio-9p.h b/hw/virtio-9p.h
> index 81c2c59..a249b67 100644
> --- a/hw/virtio-9p.h
> +++ b/hw/virtio-9p.h
> @@ -6,6 +6,8 @@
>  #include <sys/time.h>
>  #include <utime.h>
> 
> +#include "file-op.h"
> +
>  /* The feature bitmap for virtio 9P */
>  /* The mount point is specified in a config variable */
>  #define VIRTIO_9P_MOUNT_TAG 0
> @@ -129,7 +131,6 @@ struct V9fsFidState
>      V9fsFidState *next;
>  };
> 
> -struct V9fsPosixFileOpertions ;
>  typedef struct V9fsState
>  {
>      VirtIODevice vdev;
> @@ -137,9 +138,8 @@ typedef struct V9fsState
>      V9fsPDU pdus[MAX_REQ];
>      V9fsPDU *free_pdu;
>      V9fsFidState *fid_list;
> -    struct V9fsPosixFileOpertions *ops;
> -    char *fs_root;
> -    uid_t uid;
> +    FileOperations *ops;
> +    FsContext ctx;
>      uint16_t tag_len;
>      uint8_t *tag;
>      size_t config_size;
> @@ -153,40 +153,7 @@ struct virtio_9p_config
>      uint8_t tag[0];
>  } __attribute__((packed));
> 
> -typedef struct V9fsPosixFileOpertions
> -{
> -    int (*lstat)(V9fsState *, const char *, struct stat *);
> -    ssize_t (*readlink)(V9fsState *, const char *, char *, size_t);
> -    int (*chmod)(V9fsState *, const char *, mode_t);
> -    int (*chown)(V9fsState *, const char *, uid_t, gid_t);
> -    int (*mknod)(V9fsState *, const char *, mode_t, dev_t);
> -    int (*mksock)(V9fsState *, const char *);
> -    int (*utime)(V9fsState *, const char *, const struct utimbuf *);
> -    int (*remove)(V9fsState *, const char *);
> -    int (*symlink)(V9fsState *, const char *, const char *);
> -    int (*link)(V9fsState *, const char *, const char *);
> -    int (*setuid)(V9fsState *, uid_t);
> -    int (*close)(V9fsState *, int);
> -    int (*closedir)(V9fsState *, DIR *);
> -    DIR *(*opendir)(V9fsState *, const char *);
> -    int (*open)(V9fsState *, const char *, int);
> -    int (*open2)(V9fsState *, const char *, int, mode_t);
> -    void (*rewinddir)(V9fsState *, DIR *);
> -    off_t (*telldir)(V9fsState *, DIR *);
> -    struct dirent *(*readdir)(V9fsState *, DIR *);
> -    void (*seekdir)(V9fsState *, DIR *, off_t);
> -    ssize_t (*readv)(V9fsState *, int, const struct iovec *, int);
> -    ssize_t (*writev)(V9fsState *, int, const struct iovec *, int);
> -    off_t (*lseek)(V9fsState *, int, off_t, int);
> -    int (*mkdir)(V9fsState *, const char *, mode_t);
> -    int (*fstat)(V9fsState *, int, struct stat *);
> -    int (*rename)(V9fsState *, const char *, const char *);
> -    int (*truncate)(V9fsState *, const char *, off_t);
> -    int (*fsync)(V9fsState *, int);
> -    void *opaque;
> -} V9fsPosixFileOperations;
> -
> -V9fsPosixFileOperations *virtio_9p_init_local(const char *path);
> +FileOperations *virtio_9p_init_local(const char *path);
>  extern size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
>                              size_t offset, size_t size, int pack);
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 25/32] virtio-9p: Move V9fs File system specific options to a separate header file.
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 25/32] virtio-9p: Move V9fs File system specific options to a separate header file Aneesh Kumar K.V
  2010-03-29  0:52   ` jvrao
@ 2010-03-29  1:09   ` jvrao
  1 sibling, 0 replies; 55+ messages in thread
From: jvrao @ 2010-03-29  1:09 UTC (permalink / raw)
  To: Aneesh Kumar K.V; +Cc: ericvh, aliguori, qemu-devel, Gautham R Shenoy

Aneesh Kumar K.V wrote:

Missed one more point in my previous response. 
<SNIP>

> 
> -static int local_lstat(V9fsState *s, const char *path, struct stat *stbuf)
> +static int local_lstat(FsContext *s, const char *path, struct stat *stbuf)

We have been using 's' for V9fsState For FsContext it is better to use something
else (ctx?).. which makes the code easy to read and even for search/cscope.

Thanks,
JV

>  {
>      return lstat(rpath(s, path), stbuf);
>  }
> 
> -static int local_setuid(V9fsState *s, uid_t uid)
> +static int local_setuid(FsContext *s, uid_t uid)
>  {
>      struct passwd *pw;
>      gid_t groups[33];
> @@ -70,80 +70,80 @@ static int local_setuid(V9fsState *s, uid_t uid)
>      return 0;
>  }
> 
> -static ssize_t local_readlink(V9fsState *s, const char *path,
> +static ssize_t local_readlink(FsContext *s, const char *path,
>  			      char *buf, size_t bufsz)
>  {
>      return readlink(rpath(s, path), buf, bufsz);
>  }
> 
> -static int local_close(V9fsState *s, int fd)
> +static int local_close(FsContext *s, int fd)
>  {
>      return close(fd);
>  }
> 
> -static int local_closedir(V9fsState *s, DIR *dir)
> +static int local_closedir(FsContext *s, DIR *dir)
>  {
>      return closedir(dir);
>  }
> 
> -static int local_open(V9fsState *s, const char *path, int flags)
> +static int local_open(FsContext *s, const char *path, int flags)
>  {
>      return open(rpath(s, path), flags);
>  }
> 
> -static DIR *local_opendir(V9fsState *s, const char *path)
> +static DIR *local_opendir(FsContext *s, const char *path)
>  {
>      return opendir(rpath(s, path));
>  }
> 
> -static void local_rewinddir(V9fsState *s, DIR *dir)
> +static void local_rewinddir(FsContext *s, DIR *dir)
>  {
>      return rewinddir(dir);
>  }
> 
> -static off_t local_telldir(V9fsState *s, DIR *dir)
> +static off_t local_telldir(FsContext *s, DIR *dir)
>  {
>      return telldir(dir);
>  }
> 
> -static struct dirent *local_readdir(V9fsState *s, DIR *dir)
> +static struct dirent *local_readdir(FsContext *s, DIR *dir)
>  {
>      return readdir(dir);
>  }
> 
> -static void local_seekdir(V9fsState *s, DIR *dir, off_t off)
> +static void local_seekdir(FsContext *s, DIR *dir, off_t off)
>  {
>      return seekdir(dir, off);
>  }
> 
> -static ssize_t local_readv(V9fsState *s, int fd, const struct iovec *iov,
> +static ssize_t local_readv(FsContext *s, int fd, const struct iovec *iov,
>  			   int iovcnt)
>  {
>      return readv(fd, iov, iovcnt);
>  }
> 
> -static off_t local_lseek(V9fsState *s, int fd, off_t offset, int whence)
> +static off_t local_lseek(FsContext *s, int fd, off_t offset, int whence)
>  {
>      return lseek(fd, offset, whence);
>  }
> 
> -static ssize_t local_writev(V9fsState *s, int fd, const struct iovec *iov,
> +static ssize_t local_writev(FsContext *s, int fd, const struct iovec *iov,
>  			    int iovcnt)
>  {
>      return writev(fd, iov, iovcnt);
>  }
> 
> -static int local_chmod(V9fsState *s, const char *path, mode_t mode)
> +static int local_chmod(FsContext *s, const char *path, mode_t mode)
>  {
>      return chmod(rpath(s, path), mode);
>  }
> 
> -static int local_mknod(V9fsState *s, const char *path, mode_t mode, dev_t dev)
> +static int local_mknod(FsContext *s, const char *path, mode_t mode, dev_t dev)
>  {
>      return mknod(rpath(s, path), mode, dev);
>  }
> 
> -static int local_mksock(V9fsState *s2, const char *path)
> +static int local_mksock(FsContext *s2, const char *path)
>  {
>      struct sockaddr_un addr;
>      int s;
> @@ -164,28 +164,28 @@ static int local_mksock(V9fsState *s2, const char *path)
>      return 0;
>  }
> 
> -static int local_mkdir(V9fsState *s, const char *path, mode_t mode)
> +static int local_mkdir(FsContext *s, const char *path, mode_t mode)
>  {
>      return mkdir(rpath(s, path), mode);
>  }
> 
> -static int local_fstat(V9fsState *s, int fd, struct stat *stbuf)
> +static int local_fstat(FsContext *s, int fd, struct stat *stbuf)
>  {
>      return fstat(fd, stbuf);
>  }
> 
> -static int local_open2(V9fsState *s, const char *path, int flags, mode_t mode)
> +static int local_open2(FsContext *s, const char *path, int flags, mode_t mode)
>  {
>      return open(rpath(s, path), flags, mode);
>  }
> 
> -static int local_symlink(V9fsState *s, const char *oldpath,
> +static int local_symlink(FsContext *s, const char *oldpath,
>  			 const char *newpath)
>  {
>      return symlink(oldpath, rpath(s, newpath));
>  }
> 
> -static int local_link(V9fsState *s, const char *oldpath, const char *newpath)
> +static int local_link(FsContext *s, const char *oldpath, const char *newpath)
>  {
>      char *tmp = qemu_strdup(rpath(s, oldpath));
>      int err, serrno = 0;
> @@ -205,12 +205,12 @@ static int local_link(V9fsState *s, const char *oldpath, const char *newpath)
>      return err;
>  }
> 
> -static int local_truncate(V9fsState *s, const char *path, off_t size)
> +static int local_truncate(FsContext *s, const char *path, off_t size)
>  {
>      return truncate(rpath(s, path), size);
>  }
> 
> -static int local_rename(V9fsState *s, const char *oldpath,
> +static int local_rename(FsContext *s, const char *oldpath,
>  			const char *newpath)
>  {
>      char *tmp;
> @@ -232,29 +232,29 @@ static int local_rename(V9fsState *s, const char *oldpath,
> 
>  }
> 
> -static int local_chown(V9fsState *s, const char *path, uid_t uid, gid_t gid)
> +static int local_chown(FsContext *s, const char *path, uid_t uid, gid_t gid)
>  {
>      return chown(rpath(s, path), uid, gid);
>  }
> 
> -static int local_utime(V9fsState *s, const char *path,
> +static int local_utime(FsContext *s, const char *path,
>  		       const struct utimbuf *buf)
>  {
>      return utime(rpath(s, path), buf);
>  }
> 
> -static int local_remove(V9fsState *s, const char *path)
> +static int local_remove(FsContext *s, const char *path)
>  {
>      return remove(rpath(s, path));
>  }
> 
> 
> -static int local_fsync(V9fsState *s, int fd)
> +static int local_fsync(FsContext *s, int fd)
>  {
>      return fsync(fd);
>  }
> 
> -static V9fsPosixFileOperations ops = {
> +static FileOperations ops = {
>      .lstat = local_lstat,
>      .setuid = local_setuid,
>      .readlink = local_readlink,
> @@ -285,7 +285,7 @@ static V9fsPosixFileOperations ops = {
>      .fsync = local_fsync,
>  };
> 
> -V9fsPosixFileOperations *virtio_9p_init_local(const char *path)
> +FileOperations *virtio_9p_init_local(const char *path)
>  {
> -return &ops;
> +    return &ops;
>  }
> diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
> index e519605..d03693d 100644
> --- a/hw/virtio-9p.c
> +++ b/hw/virtio-9p.c
> @@ -22,23 +22,23 @@ int debug_9p_pdu = 1;
> 
>  extern void pprint_pdu(V9fsPDU *pdu);
> 
> -static int posix_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf)
> +static int v9fs_do_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf)
>  {
> -    return s->ops->lstat(s, path->data, stbuf);
> +    return s->ops->lstat(&s->ctx, path->data, stbuf);
>  }
> 
> -static int posix_setuid(V9fsState *s, uid_t uid)
> +static int v9fs_do_setuid(V9fsState *s, uid_t uid)
>  {
> -    return s->ops->setuid(s, uid);
> +    return s->ops->setuid(&s->ctx, uid);
>  }
> 
> -static ssize_t posix_readlink(V9fsState *s, V9fsString *path, V9fsString *buf)
> +static ssize_t v9fs_do_readlink(V9fsState *s, V9fsString *path, V9fsString *buf)
>  {
>      ssize_t len;
> 
>      buf->data = qemu_malloc(1024);
> 
> -    len = s->ops->readlink(s, path->data, buf->data, 1024 - 1);
> +    len = s->ops->readlink(&s->ctx, path->data, buf->data, 1024 - 1);
>      if (len > -1) {
>          buf->size = len;
>          buf->data[len] = 0;
> @@ -47,134 +47,134 @@ static ssize_t posix_readlink(V9fsState *s, V9fsString *path, V9fsString *buf)
>      return len;
>  }
> 
> -static int posix_close(V9fsState *s, int fd)
> +static int v9fs_do_close(V9fsState *s, int fd)
>  {
> -    return s->ops->close(s, fd);
> +    return s->ops->close(&s->ctx, fd);
>  }
> 
> -static int posix_closedir(V9fsState *s, DIR *dir)
> +static int v9fs_do_closedir(V9fsState *s, DIR *dir)
>  {
> -    return s->ops->closedir(s, dir);
> +    return s->ops->closedir(&s->ctx, dir);
>  }
> 
> -static int posix_open(V9fsState *s, V9fsString *path, int flags)
> +static int v9fs_do_open(V9fsState *s, V9fsString *path, int flags)
>  {
> -    return s->ops->open(s, path->data, flags);
> +    return s->ops->open(&s->ctx, path->data, flags);
>  }
> 
> -static DIR *posix_opendir(V9fsState *s, V9fsString *path)
> +static DIR *v9fs_do_opendir(V9fsState *s, V9fsString *path)
>  {
> -    return s->ops->opendir(s, path->data);
> +    return s->ops->opendir(&s->ctx, path->data);
>  }
> 
> -static void posix_rewinddir(V9fsState *s, DIR *dir)
> +static void v9fs_do_rewinddir(V9fsState *s, DIR *dir)
>  {
> -    return s->ops->rewinddir(s, dir);
> +    return s->ops->rewinddir(&s->ctx, dir);
>  }
> 
> -static off_t posix_telldir(V9fsState *s, DIR *dir)
> +static off_t v9fs_do_telldir(V9fsState *s, DIR *dir)
>  {
> -    return s->ops->telldir(s, dir);
> +    return s->ops->telldir(&s->ctx, dir);
>  }
> 
> -static struct dirent *posix_readdir(V9fsState *s, DIR *dir)
> +static struct dirent *v9fs_do_readdir(V9fsState *s, DIR *dir)
>  {
> -    return s->ops->readdir(s, dir);
> +    return s->ops->readdir(&s->ctx, dir);
>  }
> 
> -static void posix_seekdir(V9fsState *s, DIR *dir, off_t off)
> +static void v9fs_do_seekdir(V9fsState *s, DIR *dir, off_t off)
>  {
> -    return s->ops->seekdir(s, dir, off);
> +    return s->ops->seekdir(&s->ctx, dir, off);
>  }
> 
> -static int posix_readv(V9fsState *s, int fd, const struct iovec *iov,
> +static int v9fs_do_readv(V9fsState *s, int fd, const struct iovec *iov,
>  		       int iovcnt)
>  {
> -    return s->ops->readv(s, fd, iov, iovcnt);
> +    return s->ops->readv(&s->ctx, fd, iov, iovcnt);
>  }
> 
> -static off_t posix_lseek(V9fsState *s, int fd, off_t offset, int whence)
> +static off_t v9fs_do_lseek(V9fsState *s, int fd, off_t offset, int whence)
>  {
> -    return s->ops->lseek(s, fd, offset, whence);
> +    return s->ops->lseek(&s->ctx, fd, offset, whence);
>  }
> 
> -static int posix_writev(V9fsState *s, int fd, const struct iovec *iov,
> +static int v9fs_do_writev(V9fsState *s, int fd, const struct iovec *iov,
>                         int iovcnt)
>  {
> -    return s->ops->writev(s, fd, iov, iovcnt);
> +    return s->ops->writev(&s->ctx, fd, iov, iovcnt);
>  }
> 
> -static int posix_chmod(V9fsState *s, V9fsString *path, mode_t mode)
> +static int v9fs_do_chmod(V9fsState *s, V9fsString *path, mode_t mode)
>  {
> -    return s->ops->chmod(s, path->data, mode);
> +    return s->ops->chmod(&s->ctx, path->data, mode);
>  }
> 
> -static int posix_mknod(V9fsState *s, V9fsString *path, mode_t mode, dev_t dev)
> +static int v9fs_do_mknod(V9fsState *s, V9fsString *path, mode_t mode, dev_t dev)
>  {
> -    return s->ops->mknod(s, path->data, mode, dev);
> +    return s->ops->mknod(&s->ctx, path->data, mode, dev);
>  }
> 
> -static int posix_mksock(V9fsState *s, V9fsString *path)
> +static int v9fs_do_mksock(V9fsState *s, V9fsString *path)
>  {
> -    return s->ops->mksock(s, path->data);
> +    return s->ops->mksock(&s->ctx, path->data);
>  }
> 
> -static int posix_mkdir(V9fsState *s, V9fsString *path, mode_t mode)
> +static int v9fs_do_mkdir(V9fsState *s, V9fsString *path, mode_t mode)
>  {
> -    return s->ops->mkdir(s, path->data, mode);
> +    return s->ops->mkdir(&s->ctx, path->data, mode);
>  }
> 
> -static int posix_fstat(V9fsState *s, int fd, struct stat *stbuf)
> +static int v9fs_do_fstat(V9fsState *s, int fd, struct stat *stbuf)
>  {
> -    return s->ops->fstat(s, fd, stbuf);
> +    return s->ops->fstat(&s->ctx, fd, stbuf);
>  }
> 
> -static int posix_open2(V9fsState *s, V9fsString *path, int flags, mode_t mode)
> +static int v9fs_do_open2(V9fsState *s, V9fsString *path, int flags, mode_t mode)
>  {
> -    return s->ops->open2(s, path->data, flags, mode);
> +    return s->ops->open2(&s->ctx, path->data, flags, mode);
>  }
> 
> -static int posix_symlink(V9fsState *s, V9fsString *oldpath,
> +static int v9fs_do_symlink(V9fsState *s, V9fsString *oldpath,
>  			 V9fsString *newpath)
>  {
> -    return s->ops->symlink(s, oldpath->data, newpath->data);
> +    return s->ops->symlink(&s->ctx, oldpath->data, newpath->data);
>  }
> 
> -static int posix_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
> +static int v9fs_do_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
>  {
> -    return s->ops->link(s, oldpath->data, newpath->data);
> +    return s->ops->link(&s->ctx, oldpath->data, newpath->data);
>  }
> 
> -static int posix_truncate(V9fsState *s, V9fsString *path, off_t size)
> +static int v9fs_do_truncate(V9fsState *s, V9fsString *path, off_t size)
>  {
> -    return s->ops->truncate(s, path->data, size);
> +    return s->ops->truncate(&s->ctx, path->data, size);
>  }
> 
> -static int posix_rename(V9fsState *s, V9fsString *oldpath,
> +static int v9fs_do_rename(V9fsState *s, V9fsString *oldpath,
>  			V9fsString *newpath)
>  {
> -    return s->ops->rename(s, oldpath->data, newpath->data);
> +    return s->ops->rename(&s->ctx, oldpath->data, newpath->data);
>  }
> 
> -static int posix_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid)
> +static int v9fs_do_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid)
>  {
> -    return s->ops->chown(s, path->data, uid, gid);
> +    return s->ops->chown(&s->ctx, path->data, uid, gid);
>  }
> 
> -static int posix_utime(V9fsState *s, V9fsString *path,
> +static int v9fs_do_utime(V9fsState *s, V9fsString *path,
>  		       const struct utimbuf *buf)
>  {
> -    return s->ops->utime(s, path->data, buf);
> +    return s->ops->utime(&s->ctx, path->data, buf);
>  }
> 
> -static int posix_remove(V9fsState *s, V9fsString *path)
> +static int v9fs_do_remove(V9fsState *s, V9fsString *path)
>  {
> -    return s->ops->remove(s, path->data);
> +    return s->ops->remove(&s->ctx, path->data);
>  }
> 
> -static int posix_fsync(V9fsState *s, int fd)
> +static int v9fs_do_fsync(V9fsState *s, int fd)
>  {
> -    return s->ops->fsync(s, fd);
> +    return s->ops->fsync(&s->ctx, fd);
>  }
> 
>  static void v9fs_string_init(V9fsString *str)
> @@ -227,7 +227,7 @@ static V9fsFidState *lookup_fid(V9fsState *s, int32_t fid)
> 
>      for (f = s->fid_list; f; f = f->next) {
>          if (f->fid == fid) {
> -            posix_setuid(s, f->uid);
> +            v9fs_do_setuid(s, f->uid);
>              return f;
>          }
>      }
> @@ -271,9 +271,9 @@ static int free_fid(V9fsState *s, int32_t fid)
>      *fidpp = fidp->next;
> 
>      if (fidp->fd != -1)
> -        posix_close(s, fidp->fd);
> +        v9fs_do_close(s, fidp->fd);
>      if (fidp->dir)
> -        posix_closedir(s, fidp->dir);
> +        v9fs_do_closedir(s, fidp->dir);
>      v9fs_string_free(&fidp->path);
>      qemu_free(fidp);
> 
> @@ -325,7 +325,7 @@ static int fid_to_qid(V9fsState *s, V9fsFidState *fidp, V9fsQID *qidp)
>      struct stat stbuf;
>      int err;
> 
> -    err = posix_lstat(s, &fidp->path, &stbuf);
> +    err = v9fs_do_lstat(s, &fidp->path, &stbuf);
>      if (err) {
>          return err;
>      }
> @@ -683,7 +683,7 @@ static int stat_to_v9stat(V9fsState *s, V9fsString *name,
>          v9fs_string_null(&v9stat->extension);
> 
>          if (v9stat->mode & P9_STAT_MODE_SYMLINK) {
> -            err = posix_readlink(s, name, &v9stat->extension);
> +            err = v9fs_do_readlink(s, name, &v9stat->extension);
>              if (err == -1) {
>                  err = -errno;
>                  return err;
> @@ -816,7 +816,7 @@ static void v9fs_stat(V9fsState *s, V9fsPDU *pdu)
>          goto out;
>      }
> 
> -    err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
> +    err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
>      v9fs_stat_post_lstat(s, vs, err);
>      return;
> 
> @@ -880,7 +880,7 @@ static void v9fs_walk_post_newfid_lstat(V9fsState *s, V9fsWalkState *vs,
>                                              vs->wnames[vs->name_idx].data);
>          v9fs_string_copy(&vs->newfidp->path, &vs->path);
> 
> -        err = posix_lstat(s, &vs->newfidp->path, &vs->stbuf);
> +        err = v9fs_do_lstat(s, &vs->newfidp->path, &vs->stbuf);
>          v9fs_walk_post_newfid_lstat(s, vs, err);
>          return;
>      }
> @@ -909,7 +909,7 @@ static void v9fs_walk_post_oldfid_lstat(V9fsState *s, V9fsWalkState *vs,
>                  vs->fidp->path.data, vs->wnames[vs->name_idx].data);
>          v9fs_string_copy(&vs->fidp->path, &vs->path);
> 
> -        err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
> +        err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
>          v9fs_walk_post_oldfid_lstat(s, vs, err);
>          return;
>      }
> @@ -967,7 +967,7 @@ static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
>                  vs->fidp->path.data, vs->wnames[vs->name_idx].data);
>              v9fs_string_copy(&vs->fidp->path, &vs->path);
> 
> -            err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
> +            err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
>              v9fs_walk_post_oldfid_lstat(s, vs, err);
>              return;
>          }
> @@ -988,7 +988,7 @@ static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
>                                  vs->wnames[vs->name_idx].data);
>              v9fs_string_copy(&vs->newfidp->path, &vs->path);
> 
> -            err = posix_lstat(s, &vs->newfidp->path, &vs->stbuf);
> +            err = v9fs_do_lstat(s, &vs->newfidp->path, &vs->stbuf);
>              v9fs_walk_post_newfid_lstat(s, vs, err);
>              return;
>          }
> @@ -1092,10 +1092,10 @@ static void v9fs_open_post_lstat(V9fsState *s, V9fsOpenState *vs, int err)
>      stat_to_qid(&vs->stbuf, &vs->qid);
> 
>      if (S_ISDIR(vs->stbuf.st_mode)) {
> -        vs->fidp->dir = posix_opendir(s, &vs->fidp->path);
> +        vs->fidp->dir = v9fs_do_opendir(s, &vs->fidp->path);
>          v9fs_open_post_opendir(s, vs, err);
>      } else {
> -        vs->fidp->fd = posix_open(s, &vs->fidp->path,
> +        vs->fidp->fd = v9fs_do_open(s, &vs->fidp->path,
>                                      omode_to_uflags(vs->mode));
>          v9fs_open_post_open(s, vs, err);
>      }
> @@ -1127,7 +1127,7 @@ static void v9fs_open(V9fsState *s, V9fsPDU *pdu)
>      BUG_ON(vs->fidp->fd != -1);
>      BUG_ON(vs->fidp->dir);
> 
> -    err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
> +    err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
> 
>      v9fs_open_post_lstat(s, vs, err);
>      return;
> @@ -1238,7 +1238,7 @@ static void v9fs_read_post_dir_lstat(V9fsState *s, V9fsReadState *vs,
>                              &vs->v9stat);
>      if ((vs->len != (vs->v9stat.size + 2)) ||
>              ((vs->count + vs->len) > vs->max_count)) {
> -        posix_seekdir(s, vs->fidp->dir, vs->dir_pos);
> +        v9fs_do_seekdir(s, vs->fidp->dir, vs->dir_pos);
>          v9fs_read_post_seekdir(s, vs, err);
>          return;
>      }
> @@ -1246,11 +1246,11 @@ static void v9fs_read_post_dir_lstat(V9fsState *s, V9fsReadState *vs,
>      v9fs_stat_free(&vs->v9stat);
>      v9fs_string_free(&vs->name);
>      vs->dir_pos = vs->dent->d_off;
> -    vs->dent = posix_readdir(s, vs->fidp->dir);
> +    vs->dent = v9fs_do_readdir(s, vs->fidp->dir);
>      v9fs_read_post_readdir(s, vs, err);
>      return;
>  out:
> -    posix_seekdir(s, vs->fidp->dir, vs->dir_pos);
> +    v9fs_do_seekdir(s, vs->fidp->dir, vs->dir_pos);
>      v9fs_read_post_seekdir(s, vs, err);
>      return;
> 
> @@ -1263,7 +1263,7 @@ static void v9fs_read_post_readdir(V9fsState *s, V9fsReadState *vs, ssize_t err)
>          v9fs_string_init(&vs->name);
>          v9fs_string_sprintf(&vs->name, "%s/%s", vs->fidp->path.data,
>                              vs->dent->d_name);
> -        err = posix_lstat(s, &vs->name, &vs->stbuf);
> +        err = v9fs_do_lstat(s, &vs->name, &vs->stbuf);
>          v9fs_read_post_dir_lstat(s, vs, err);
>          return;
>      }
> @@ -1278,7 +1278,7 @@ static void v9fs_read_post_readdir(V9fsState *s, V9fsReadState *vs, ssize_t err)
> 
>  static void v9fs_read_post_telldir(V9fsState *s, V9fsReadState *vs, ssize_t err)
>  {
> -    vs->dent = posix_readdir(s, vs->fidp->dir);
> +    vs->dent = v9fs_do_readdir(s, vs->fidp->dir);
>      v9fs_read_post_readdir(s, vs, err);
>      return;
>  }
> @@ -1286,7 +1286,7 @@ static void v9fs_read_post_telldir(V9fsState *s, V9fsReadState *vs, ssize_t err)
>  static void v9fs_read_post_rewinddir(V9fsState *s, V9fsReadState *vs,
>                                         ssize_t err)
>  {
> -    vs->dir_pos = posix_telldir(s, vs->fidp->dir);
> +    vs->dir_pos = v9fs_do_telldir(s, vs->fidp->dir);
>      v9fs_read_post_telldir(s, vs, err);
>      return;
>  }
> @@ -1305,7 +1305,7 @@ static void v9fs_read_post_readv(V9fsState *s, V9fsReadState *vs, ssize_t err)
>              if (0) {
>                  print_sg(vs->sg, vs->cnt);
>              }
> -            vs->len = posix_readv(s, vs->fidp->fd, vs->sg, vs->cnt);
> +            vs->len = v9fs_do_readv(s, vs->fidp->fd, vs->sg, vs->cnt);
>          } while (vs->len == -1 && errno == EINTR);
>          if (vs->len == -1) {
>              err  = -errno;
> @@ -1335,7 +1335,7 @@ static void v9fs_read_post_lseek(V9fsState *s, V9fsReadState *vs, ssize_t err)
>              if (0) {
>                  print_sg(vs->sg, vs->cnt);
>              }
> -            vs->len = posix_readv(s, vs->fidp->fd, vs->sg, vs->cnt);
> +            vs->len = v9fs_do_readv(s, vs->fidp->fd, vs->sg, vs->cnt);
>          } while (vs->len == -1 && errno == EINTR);
>  	if (vs->len == -1) {
>              err  = -errno;
> @@ -1373,14 +1373,14 @@ static void v9fs_read(V9fsState *s, V9fsPDU *pdu)
>          vs->max_count = vs->count;
>          vs->count = 0;
>          if (vs->off == 0) {
> -            posix_rewinddir(s, vs->fidp->dir);
> +            v9fs_do_rewinddir(s, vs->fidp->dir);
>          }
>          v9fs_read_post_rewinddir(s, vs, err);
>          return;
>      } else if (vs->fidp->fd != -1) {
>          vs->sg = vs->iov;
>          pdu_marshal(vs->pdu, vs->offset + 4, "v", vs->sg, &vs->cnt);
> -        err = posix_lseek(s, vs->fidp->fd, vs->off, SEEK_SET);
> +        err = v9fs_do_lseek(s, vs->fidp->fd, vs->off, SEEK_SET);
>          v9fs_read_post_lseek(s, vs, err);
>          return;
>      } else {
> @@ -1436,7 +1436,7 @@ static void v9fs_write_post_writev(V9fsState *s, V9fsWriteState *vs,
>          do {
>              if (0)
>                  print_sg(vs->sg, vs->cnt);
> -            vs->len =  posix_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
> +            vs->len =  v9fs_do_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
>          } while (vs->len == -1 && errno == EINTR);
>          if (vs->len == -1) {
>              err  = -errno;
> @@ -1464,7 +1464,7 @@ static void v9fs_write_post_lseek(V9fsState *s, V9fsWriteState *vs, ssize_t err)
>          do {
>              if (0)
>                  print_sg(vs->sg, vs->cnt);
> -            vs->len = posix_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
> +            vs->len = v9fs_do_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
>          } while (vs->len == -1 && errno == EINTR);
>  	if (vs->len == -1) {
>              err  = -errno;
> @@ -1506,7 +1506,7 @@ static void v9fs_write(V9fsState *s, V9fsPDU *pdu)
>          goto out;
>      }
> 
> -    err = posix_lseek(s, vs->fidp->fd, vs->off, SEEK_SET);
> +    err = v9fs_do_lseek(s, vs->fidp->fd, vs->off, SEEK_SET);
> 
>      v9fs_write_post_lseek(s, vs, err);
>      return;
> @@ -1572,7 +1572,7 @@ static void v9fs_create_post_dir_lstat(V9fsState *s, V9fsCreateState *vs,
>          goto out;
>      }
> 
> -    vs->fidp->dir = posix_opendir(s, &vs->fullname);
> +    vs->fidp->dir = v9fs_do_opendir(s, &vs->fullname);
>      v9fs_create_post_opendir(s, vs, err);
>      return;
> 
> @@ -1587,7 +1587,7 @@ static void v9fs_create_post_mkdir(V9fsState *s, V9fsCreateState *vs, int err)
>          goto out;
>      }
> 
> -    err = posix_lstat(s, &vs->fullname, &vs->stbuf);
> +    err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf);
>      v9fs_create_post_dir_lstat(s, vs, err);
>      return;
> 
> @@ -1603,7 +1603,7 @@ static void v9fs_create_post_mksock(V9fsState *s, V9fsCreateState *vs,
>          goto out;
>      }
> 
> -    err = posix_chmod(s, &vs->fullname, vs->perm & 0777);
> +    err = v9fs_do_chmod(s, &vs->fullname, vs->perm & 0777);
>      v9fs_create_post_perms(s, vs, err);
>      return;
> 
> @@ -1629,7 +1629,7 @@ static void v9fs_create_post_open2(V9fsState *s, V9fsCreateState *vs, int err)
>          goto out;
>      }
> 
> -    err = posix_fstat(s, vs->fidp->fd, &vs->stbuf);
> +    err = v9fs_do_fstat(s, vs->fidp->fd, &vs->stbuf);
>      v9fs_create_post_fstat(s, vs, err);
> 
>      return;
> @@ -1648,10 +1648,10 @@ static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err)
>      }
> 
>      if (vs->perm & P9_STAT_MODE_DIR) {
> -        err = posix_mkdir(s, &vs->fullname, vs->perm & 0777);
> +        err = v9fs_do_mkdir(s, &vs->fullname, vs->perm & 0777);
>          v9fs_create_post_mkdir(s, vs, err);
>      } else if (vs->perm & P9_STAT_MODE_SYMLINK) {
> -        err = posix_symlink(s, &vs->extension, &vs->fullname);
> +        err = v9fs_do_symlink(s, &vs->extension, &vs->fullname);
>          v9fs_create_post_perms(s, vs, err);
>      } else if (vs->perm & P9_STAT_MODE_LINK) {
>          int32_t nfid = atoi(vs->extension.data);
> @@ -1660,7 +1660,7 @@ static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err)
>              err = -errno;
>              v9fs_post_create(s, vs, err);
>          }
> -        err = posix_link(s, &nfidp->path, &vs->fullname);
> +        err = v9fs_do_link(s, &nfidp->path, &vs->fullname);
>          v9fs_create_post_perms(s, vs, err);
>      } else if (vs->perm & P9_STAT_MODE_DEVICE) {
>          char ctype;
> @@ -1686,16 +1686,16 @@ static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err)
>          }
> 
>          nmode |= vs->perm & 0777;
> -        err = posix_mknod(s, &vs->fullname, nmode, makedev(major, minor));
> +        err = v9fs_do_mknod(s, &vs->fullname, nmode, makedev(major, minor));
>          v9fs_create_post_perms(s, vs, err);
>      } else if (vs->perm & P9_STAT_MODE_NAMED_PIPE) {
> -        err = posix_mknod(s, &vs->fullname, S_IFIFO | (vs->mode & 0777), 0);
> +        err = v9fs_do_mknod(s, &vs->fullname, S_IFIFO | (vs->mode & 0777), 0);
>          v9fs_post_create(s, vs, err);
>      } else if (vs->perm & P9_STAT_MODE_SOCKET) {
> -        err = posix_mksock(s, &vs->fullname);
> +        err = v9fs_do_mksock(s, &vs->fullname);
>          v9fs_create_post_mksock(s, vs, err);
>      } else {
> -        vs->fidp->fd = posix_open2(s, &vs->fullname,
> +        vs->fidp->fd = v9fs_do_open2(s, &vs->fullname,
>                                  omode_to_uflags(vs->mode) | O_CREAT,
>                                  vs->perm & 0777);
>          v9fs_create_post_open2(s, vs, err);
> @@ -1731,7 +1731,7 @@ static void v9fs_create(V9fsState *s, V9fsPDU *pdu)
>      v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->fidp->path.data,
>                                                          vs->name.data);
> 
> -    err = posix_lstat(s, &vs->fullname, &vs->stbuf);
> +    err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf);
>      v9fs_create_post_lstat(s, vs, err);
>      return;
> 
> @@ -1791,7 +1791,7 @@ static void v9fs_remove(V9fsState *s, V9fsPDU *pdu)
>          goto out;
>      }
> 
> -    err = posix_remove(s, &vs->fidp->path);
> +    err = v9fs_do_remove(s, &vs->fidp->path);
>      v9fs_remove_post_remove(s, vs, err);
>      return;
> 
> @@ -1872,7 +1872,7 @@ static void v9fs_wstat_post_rename(V9fsState *s, V9fsWstatState *vs, int err)
>      }
> 
>      if (vs->v9stat.length != -1) {
> -        if (posix_truncate(s, &vs->fidp->path, vs->v9stat.length) < 0) {
> +        if (v9fs_do_truncate(s, &vs->fidp->path, vs->v9stat.length) < 0) {
>              err = -errno;
>          }
>      }
> @@ -1922,7 +1922,7 @@ static void v9fs_wstat_post_chown(V9fsState *s, V9fsWstatState *vs, int err)
>          vs->nname.size = strlen(new_name);
> 
>          if (strcmp(new_name, vs->fidp->path.data) != 0) {
> -            if (posix_rename(s, &vs->fidp->path, &vs->nname)) {
> +            if (v9fs_do_rename(s, &vs->fidp->path, &vs->nname)) {
>                  err = -errno;
>              } else {
>                  /*
> @@ -1965,7 +1965,7 @@ static void v9fs_wstat_post_utime(V9fsState *s, V9fsWstatState *vs, int err)
>      }
> 
>      if (vs->v9stat.n_gid != -1) {
> -        if (posix_chown(s, &vs->fidp->path, vs->v9stat.n_uid,
> +        if (v9fs_do_chown(s, &vs->fidp->path, vs->v9stat.n_uid,
>                      vs->v9stat.n_gid)) {
>              err = -errno;
>          }
> @@ -1989,7 +1989,7 @@ static void v9fs_wstat_post_chmod(V9fsState *s, V9fsWstatState *vs, int err)
>          struct utimbuf tb;
>          tb.actime = 0;
>          tb.modtime = vs->v9stat.mtime;
> -        if (posix_utime(s, &vs->fidp->path, &tb)) {
> +        if (v9fs_do_utime(s, &vs->fidp->path, &tb)) {
>              err = -errno;
>          }
>      }
> @@ -2054,7 +2054,7 @@ static void v9fs_wstat_post_lstat(V9fsState *s, V9fsWstatState *vs, int err)
>              goto out;
>      }
> 
> -    if (posix_chmod(s, &vs->fidp->path, v9mode_to_mode(vs->v9stat.mode,
> +    if (v9fs_do_chmod(s, &vs->fidp->path, v9mode_to_mode(vs->v9stat.mode,
>                      &vs->v9stat.extension))) {
>              err = -errno;
>       }
> @@ -2087,13 +2087,13 @@ static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
> 
>      /* do we need to sync the file? */
>      if (donttouch_stat(&vs->v9stat)) {
> -        err = posix_fsync(s, vs->fidp->fd);
> +        err = v9fs_do_fsync(s, vs->fidp->fd);
>          v9fs_wstat_post_fsync(s, vs, err);
>          return;
>      }
> 
>      if (vs->v9stat.mode != -1) {
> -        err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
> +        err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
>          v9fs_wstat_post_lstat(s, vs, err);
>          return;
>      }
> @@ -2243,7 +2243,8 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
>  	    fprintf(stderr, "share path %s is not a directory \n", conf->share_path);
>  	    exit(1);
>      }
> -    s->fs_root = qemu_strdup(conf->share_path);
> +
> +    s->ctx.fs_root = qemu_strdup(conf->share_path);
>      len = strlen(conf->tag);
>      if (len > MAX_TAG_LEN)
>  	    len = MAX_TAG_LEN;
> @@ -2251,7 +2252,7 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
>      s->tag = qemu_malloc(len);
>      memcpy(s->tag, conf->tag, len);
>      s->tag_len = len;
> -    s->uid = -1;
> +    s->ctx.uid = -1;
> 
>      s->ops = virtio_9p_init_local(conf->share_path);
>      s->vdev.get_features = virtio_9p_get_features;
> diff --git a/hw/virtio-9p.h b/hw/virtio-9p.h
> index 81c2c59..a249b67 100644
> --- a/hw/virtio-9p.h
> +++ b/hw/virtio-9p.h
> @@ -6,6 +6,8 @@
>  #include <sys/time.h>
>  #include <utime.h>
> 
> +#include "file-op.h"
> +
>  /* The feature bitmap for virtio 9P */
>  /* The mount point is specified in a config variable */
>  #define VIRTIO_9P_MOUNT_TAG 0
> @@ -129,7 +131,6 @@ struct V9fsFidState
>      V9fsFidState *next;
>  };
> 
> -struct V9fsPosixFileOpertions ;
>  typedef struct V9fsState
>  {
>      VirtIODevice vdev;
> @@ -137,9 +138,8 @@ typedef struct V9fsState
>      V9fsPDU pdus[MAX_REQ];
>      V9fsPDU *free_pdu;
>      V9fsFidState *fid_list;
> -    struct V9fsPosixFileOpertions *ops;
> -    char *fs_root;
> -    uid_t uid;
> +    FileOperations *ops;
> +    FsContext ctx;
>      uint16_t tag_len;
>      uint8_t *tag;
>      size_t config_size;
> @@ -153,40 +153,7 @@ struct virtio_9p_config
>      uint8_t tag[0];
>  } __attribute__((packed));
> 
> -typedef struct V9fsPosixFileOpertions
> -{
> -    int (*lstat)(V9fsState *, const char *, struct stat *);
> -    ssize_t (*readlink)(V9fsState *, const char *, char *, size_t);
> -    int (*chmod)(V9fsState *, const char *, mode_t);
> -    int (*chown)(V9fsState *, const char *, uid_t, gid_t);
> -    int (*mknod)(V9fsState *, const char *, mode_t, dev_t);
> -    int (*mksock)(V9fsState *, const char *);
> -    int (*utime)(V9fsState *, const char *, const struct utimbuf *);
> -    int (*remove)(V9fsState *, const char *);
> -    int (*symlink)(V9fsState *, const char *, const char *);
> -    int (*link)(V9fsState *, const char *, const char *);
> -    int (*setuid)(V9fsState *, uid_t);
> -    int (*close)(V9fsState *, int);
> -    int (*closedir)(V9fsState *, DIR *);
> -    DIR *(*opendir)(V9fsState *, const char *);
> -    int (*open)(V9fsState *, const char *, int);
> -    int (*open2)(V9fsState *, const char *, int, mode_t);
> -    void (*rewinddir)(V9fsState *, DIR *);
> -    off_t (*telldir)(V9fsState *, DIR *);
> -    struct dirent *(*readdir)(V9fsState *, DIR *);
> -    void (*seekdir)(V9fsState *, DIR *, off_t);
> -    ssize_t (*readv)(V9fsState *, int, const struct iovec *, int);
> -    ssize_t (*writev)(V9fsState *, int, const struct iovec *, int);
> -    off_t (*lseek)(V9fsState *, int, off_t, int);
> -    int (*mkdir)(V9fsState *, const char *, mode_t);
> -    int (*fstat)(V9fsState *, int, struct stat *);
> -    int (*rename)(V9fsState *, const char *, const char *);
> -    int (*truncate)(V9fsState *, const char *, off_t);
> -    int (*fsync)(V9fsState *, int);
> -    void *opaque;
> -} V9fsPosixFileOperations;
> -
> -V9fsPosixFileOperations *virtio_9p_init_local(const char *path);
> +FileOperations *virtio_9p_init_local(const char *path);
>  extern size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
>                              size_t offset, size_t size, int pack);
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU
  2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE Aneesh Kumar K.V
@ 2010-03-29  6:36   ` jvrao
  2010-03-29 15:00     ` Anthony Liguori
  0 siblings, 1 reply; 55+ messages in thread
From: jvrao @ 2010-03-29  6:36 UTC (permalink / raw)
  To: Aneesh Kumar K.V, aliguori; +Cc: ericvh, qemu-devel

Aneesh Kumar K.V wrote:
> From: Anthony Liguori <aliguori@us.ibm.com>

We have implemented all the vfs calls in state machine model so that we are prepared
for the model where the VCPU thread(s) does the initial work until it needs to block then it
submits that work (via a function pointer) to a thread pool.  A thread in that thread pool
picks up the work, and completes the blocking call, when blocking call returns a callback is
invoked in the IO thread.  Then the IO thread runs until the next blocking function, and goto start.

Basically the VCPU/IO threads does all the non-blocking work, and let the threads in the
thread pool work on the blocking calls like mkdir() stat() etc.

My question is, why not let the whole work done by the thread in the thread pool?
VCPU thread receives the PDU and hands over the entire job to worker thread.
When all work is completed, either the worker thread or the IO thread(we can switch back at this point if needed) marks the request as completed in the virtqueue and injects an
interrupt to notify the guest.

We can still keep the same number of threads in the thread pool. 
This way, we are not increasing #of threads employed by QEMU...also it makes code lot 
more easy to read/maintain.

I may be missing something..but would like to know more on the advantages of this model.

Thanks,
JV

> 
> This gets write to file to work
> 
> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
> Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
> ---
>  hw/virtio-9p-local.c |    7 ++++
>  hw/virtio-9p.c       |   97 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 102 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
> index d77ecc2..c5d1db3 100644
> --- a/hw/virtio-9p-local.c
> +++ b/hw/virtio-9p-local.c
> @@ -129,6 +129,12 @@ static off_t local_lseek(void *opaque, int fd, off_t offset, int whence)
>      return lseek(fd, offset, whence);
>  }
> 
> +static ssize_t local_writev(void *opaque, int fd, const struct iovec *iov,
> +			    int iovcnt)
> +{
> +    return writev(fd, iov, iovcnt);
> +}
> +
>  static V9fsPosixFileOperations ops = {
>      .lstat = local_lstat,
>      .setuid = local_setuid,
> @@ -143,6 +149,7 @@ static V9fsPosixFileOperations ops = {
>      .seekdir = local_seekdir,
>      .readv = local_readv,
>      .lseek = local_lseek,
> +    .writev = local_writev,
>  };
> 
>  V9fsPosixFileOperations *virtio_9p_init_local(const char *path)
> diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
> index 3ac6255..bc26d66 100644
> --- a/hw/virtio-9p.c
> +++ b/hw/virtio-9p.c
> @@ -168,6 +168,12 @@ static off_t posix_lseek(V9fsState *s, int fd, off_t offset, int whence)
>      return s->ops->lseek(s->ops->opaque, fd, offset, whence);
>  }
> 
> +static int posix_writev(V9fsState *s, int fd, const struct iovec *iov,
> +                       int iovcnt)
> +{
> +    return s->ops->writev(s->ops->opaque, fd, iov, iovcnt);
> +}
> +
>  static void v9fs_string_init(V9fsString *str)
>  {
>      str->data = NULL;
> @@ -1319,10 +1325,97 @@ out:
>      complete_pdu(s, pdu, err);
>  }
> 
> +typedef struct V9fsWriteState {
> +    V9fsPDU *pdu;
> +    size_t offset;
> +    int32_t fid;
> +    int32_t len;
> +    int32_t count;
> +    int32_t total;
> +    int64_t off;
> +    V9fsFidState *fidp;
> +    struct iovec iov[128]; /* FIXME: bad, bad, bad */
> +    struct iovec *sg;
> +    int cnt;
> +} V9fsWriteState;
> +
> +static void v9fs_write_post_writev(V9fsState *s, V9fsWriteState *vs,
> +                                   ssize_t err)
> +{
> +    BUG_ON(vs->len < 0);
> +    vs->total += vs->len;
> +    vs->sg = adjust_sg(vs->sg, vs->len, &vs->cnt);
> +    if (vs->total < vs->count && vs->len > 0) {
> +        do {
> +            if (0)
> +                print_sg(vs->sg, vs->cnt);
> +            vs->len =  posix_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
> +        } while (vs->len == -1 && errno == EINTR);
> +        v9fs_write_post_writev(s, vs, err);
> +    }
> +    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->total);
> +
> +    err = vs->offset;
> +    complete_pdu(s, vs->pdu, err);
> +    qemu_free(vs);
> +}
> +
> +static void v9fs_write_post_lseek(V9fsState *s, V9fsWriteState *vs, ssize_t err)
> +{
> +    BUG_ON(err == -1);
> +
> +    vs->sg = cap_sg(vs->sg, vs->count, &vs->cnt);
> +
> +    if (vs->total < vs->count) {
> +        do {
> +            if (0)
> +                print_sg(vs->sg, vs->cnt);
> +            vs->len = posix_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
> +        } while (vs->len == -1 && errno == EINTR);
> +
> +        v9fs_write_post_writev(s, vs, err);
> +        return;
> +    }
> +
> +    complete_pdu(s, vs->pdu, err);
> +    qemu_free(vs);
> +}
> +
>  static void v9fs_write(V9fsState *s, V9fsPDU *pdu)
>  {
> -    if (debug_9p_pdu)
> -        pprint_pdu(pdu);
> +    V9fsWriteState *vs;
> +    ssize_t err;
> +
> +    vs = qemu_malloc(sizeof(*vs));
> +
> +    vs->pdu = pdu;
> +    vs->offset = 7;
> +    vs->sg = vs->iov;
> +    vs->total = 0;
> +    vs->len = 0;
> +
> +    pdu_unmarshal(vs->pdu, vs->offset, "dqdv", &vs->fid, &vs->off, &vs->count,
> +                    vs->sg, &vs->cnt);
> +
> +    vs->fidp = lookup_fid(s, vs->fid);
> +    if (vs->fidp == NULL) {
> +        err = -EINVAL;
> +        goto out;
> +    }
> +
> +    if (vs->fidp->fd == -1) {
> +        err = -EINVAL;
> +        goto out;
> +    }
> +
> +    err = posix_lseek(s, vs->fidp->fd, vs->off, SEEK_SET);
> +
> +    v9fs_write_post_lseek(s, vs, err);
> +    return;
> +
> +out:
> +    complete_pdu(s, vs->pdu, err);
> +    qemu_free(vs);
>  }
> 
>  static void v9fs_create(V9fsState *s, V9fsPDU *pdu)

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU
  2010-03-29  6:36   ` [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU jvrao
@ 2010-03-29 15:00     ` Anthony Liguori
  2010-03-29 20:31       ` Avi Kivity
  0 siblings, 1 reply; 55+ messages in thread
From: Anthony Liguori @ 2010-03-29 15:00 UTC (permalink / raw)
  To: jvrao; +Cc: ericvh, Avi Kivity, Aneesh Kumar K.V, qemu-devel

On 03/29/2010 01:36 AM, jvrao wrote:
> Aneesh Kumar K.V wrote:
>    
>> From: Anthony Liguori<aliguori@us.ibm.com>
>>      
> We have implemented all the vfs calls in state machine model so that we are prepared
> for the model where the VCPU thread(s) does the initial work until it needs to block then it
> submits that work (via a function pointer) to a thread pool.  A thread in that thread pool
> picks up the work, and completes the blocking call, when blocking call returns a callback is
> invoked in the IO thread.  Then the IO thread runs until the next blocking function, and goto start.
>
> Basically the VCPU/IO threads does all the non-blocking work, and let the threads in the
> thread pool work on the blocking calls like mkdir() stat() etc.
>
> My question is, why not let the whole work done by the thread in the thread pool?
> VCPU thread receives the PDU and hands over the entire job to worker thread.
> When all work is completed, either the worker thread or the IO thread(we can switch back at this point if needed) marks the request as completed in the virtqueue and injects an
> interrupt to notify the guest.
>
> We can still keep the same number of threads in the thread pool.
> This way, we are not increasing #of threads employed by QEMU...also it makes code lot
> more easy to read/maintain.
>
> I may be missing something..but would like to know more on the advantages of this model.
>    

In qemu, we tend to prefer state-machine based code.

There are a few different models that we have discussed at different points:

1) state machines with a thread pool to make blocking functions 
asynchronous (what we have today)

2) co-operative threading

3) pre-emptive threading

All three models are independent of making device models re-entrant.  In 
order to allow VCPU threads to run in qemu simultaneously, we need each 
device to carry a lock and for that lock to be acquired upon any of the 
public functions for the device model.

For individual device models or host services, I think (3) is probably 
the worst model overall.  I personally think that (1) is better in the 
long run but ultimately would need an existence proof to compare against 
(2).  (2) looks appealing until you actually try to have the device 
handle multiple requests at a time.

For virtio-9p, I don't think (1) is much of a burden to be honest.  In 
particular, when the 9p2000.L dialect is used, there should be a 1-1 
correlation between protocol operations and system calls which means 
that for the most part, there's really no advantage to threading from a 
complexity point of view.

Regards,

Anthony Liguori

> Thanks,
> JV
>    

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU
  2010-03-29 15:00     ` Anthony Liguori
@ 2010-03-29 20:31       ` Avi Kivity
  2010-03-29 20:42         ` Anthony Liguori
  0 siblings, 1 reply; 55+ messages in thread
From: Avi Kivity @ 2010-03-29 20:31 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: ericvh, jvrao, Aneesh Kumar K.V, qemu-devel

On 03/29/2010 06:00 PM, Anthony Liguori wrote:
>
> In qemu, we tend to prefer state-machine based code.
>
> There are a few different models that we have discussed at different 
> points:
>
> 1) state machines with a thread pool to make blocking functions 
> asynchronous (what we have today)
>
> 2) co-operative threading
>
> 3) pre-emptive threading
>
> All three models are independent of making device models re-entrant.  
> In order to allow VCPU threads to run in qemu simultaneously, we need 
> each device to carry a lock and for that lock to be acquired upon any 
> of the public functions for the device model.
>
> For individual device models or host services, I think (3) is probably 
> the worst model overall.  I personally think that (1) is better in the 
> long run but ultimately would need an existence proof to compare 
> against (2).  (2) looks appealing until you actually try to have the 
> device handle multiple requests at a time.

Sooner or later nature and the ever more complicated code will force us 
towards (3).  As an example, we've observed live migration to throttle 
vcpus when sending a large guest's zeroed memory over; the bandwidth 
control doesn't kick in since zero pages are compressed, so the iothread 
spends large amounts of time reading memory.

We could fix this by yielding every so often (and a patch will be posted 
soon), but it remains an issue.  We have too much work in the I/O thread 
and that defers I/O completion and timers.

> For virtio-9p, I don't think (1) is much of a burden to be honest.  In 
> particular, when the 9p2000.L dialect is used, there should be a 1-1 
> correlation between protocol operations and system calls which means 
> that for the most part, there's really no advantage to threading from 
> a complexity point of view.

But if those system calls are blocking, you need a thread?

On a philosophical note, threads may be easier to model complex hardware 
that includes a processor, for example our scsi card (and how about 
using tcg as a jit to boost it :)

-- 
Do not meddle in the internals of kernels, for they are subtle and quick to panic.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU
  2010-03-29 20:31       ` Avi Kivity
@ 2010-03-29 20:42         ` Anthony Liguori
  2010-03-29 20:54           ` Avi Kivity
                             ` (2 more replies)
  0 siblings, 3 replies; 55+ messages in thread
From: Anthony Liguori @ 2010-03-29 20:42 UTC (permalink / raw)
  To: Avi Kivity; +Cc: ericvh, jvrao, Aneesh Kumar K.V, qemu-devel

On 03/29/2010 03:31 PM, Avi Kivity wrote:
> On 03/29/2010 06:00 PM, Anthony Liguori wrote:
>>
>> In qemu, we tend to prefer state-machine based code.
>>
>> There are a few different models that we have discussed at different 
>> points:
>>
>> 1) state machines with a thread pool to make blocking functions 
>> asynchronous (what we have today)
>>
>> 2) co-operative threading
>>
>> 3) pre-emptive threading
>>
>> All three models are independent of making device models re-entrant.  
>> In order to allow VCPU threads to run in qemu simultaneously, we need 
>> each device to carry a lock and for that lock to be acquired upon any 
>> of the public functions for the device model.
>>
>> For individual device models or host services, I think (3) is 
>> probably the worst model overall.  I personally think that (1) is 
>> better in the long run but ultimately would need an existence proof 
>> to compare against (2).  (2) looks appealing until you actually try 
>> to have the device handle multiple requests at a time.
>
> Sooner or later nature and the ever more complicated code will force 
> us towards (3).  As an example, we've observed live migration to 
> throttle vcpus when sending a large guest's zeroed memory over; the 
> bandwidth control doesn't kick in since zero pages are compressed, so 
> the iothread spends large amounts of time reading memory.

Making things re-entrant is different than (3) in my mind.

There's no reason that VCPU threads should run in lock-step with live 
migration during the live phase.  Making device models re-entrant and 
making live migration depend not depend on the big global lock is a good 
thing to do.

What I'm skeptical of, is whether converting virtio-9p or qcow2 to 
handle each request in a separate thread is really going to improve 
things.  The VNC server is another area that I think multithreading 
would be a bad idea.

> We could fix this by yielding every so often (and a patch will be 
> posted soon), but it remains an issue.  We have too much work in the 
> I/O thread and that defers I/O completion and timers.
>
>> For virtio-9p, I don't think (1) is much of a burden to be honest.  
>> In particular, when the 9p2000.L dialect is used, there should be a 
>> 1-1 correlation between protocol operations and system calls which 
>> means that for the most part, there's really no advantage to 
>> threading from a complexity point of view.
>
> But if those system calls are blocking, you need a thread?

You can dispatch just the system call to a thread pool.  The advantage 
of doing that is that you don't need to worry about locking since the 
system calls are not (usually) handling shared state.

> On a philosophical note, threads may be easier to model complex 
> hardware that includes a processor, for example our scsi card (and how 
> about using tcg as a jit to boost it :)

Yeah, it's hard to argue that script evaluation shouldn't be done in a 
thread.  But that doesn't prevent me from being very cautious about how 
and where we use threading :-)

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU
  2010-03-29 20:42         ` Anthony Liguori
@ 2010-03-29 20:54           ` Avi Kivity
  2010-03-29 21:23             ` Anthony Liguori
  2010-03-29 21:17           ` jvrao
  2010-04-01 13:14           ` Paul Brook
  2 siblings, 1 reply; 55+ messages in thread
From: Avi Kivity @ 2010-03-29 20:54 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: ericvh, jvrao, Aneesh Kumar K.V, qemu-devel

On 03/29/2010 11:42 PM, Anthony Liguori wrote:
>>> For individual device models or host services, I think (3) is 
>>> probably the worst model overall.  I personally think that (1) is 
>>> better in the long run but ultimately would need an existence proof 
>>> to compare against (2).  (2) looks appealing until you actually try 
>>> to have the device handle multiple requests at a time.
>>
>> Sooner or later nature and the ever more complicated code will force 
>> us towards (3).  As an example, we've observed live migration to 
>> throttle vcpus when sending a large guest's zeroed memory over; the 
>> bandwidth control doesn't kick in since zero pages are compressed, so 
>> the iothread spends large amounts of time reading memory.
>
>
> Making things re-entrant is different than (3) in my mind.
>
> There's no reason that VCPU threads should run in lock-step with live 
> migration during the live phase.  Making device models re-entrant and 
> making live migration depend not depend on the big global lock is a 
> good thing to do.

It's not sufficient.  If you have a single thread that runs both live 
migrations and timers, then timers will be backlogged behind live 
migration, or you'll have to yield often.  This is regardless of the 
locking model (and of course having threads without fixing the locking 
is insufficient as well, live migration accesses guest memory so it 
needs the big qemu lock).

> What I'm skeptical of, is whether converting virtio-9p or qcow2 to 
> handle each request in a separate thread is really going to improve 
> things. 

Currently qcow2 isn't even fullly asynchronous, so it can't fail to 
improve things.

> The VNC server is another area that I think multithreading would be a 
> bad idea.

If the vnc server is stuffing a few megabytes of screen into a socket, 
then timers will be delayed behind it, unless you litter the code with 
calls to bottom halves.  Even worse if it does complicated compression 
and encryption.

>>
>> But if those system calls are blocking, you need a thread?
>
> You can dispatch just the system call to a thread pool.  The advantage 
> of doing that is that you don't need to worry about locking since the 
> system calls are not (usually) handling shared state.

There is always implied shared state.  If you're doing direct guest 
memory access, you need to lock memory against hotunplug, or the syscall 
will end up writing into freed memory.  If the device can be 
hotunplugged, you need to make sure all threads have returned before 
unplugging it.

>> On a philosophical note, threads may be easier to model complex 
>> hardware that includes a processor, for example our scsi card (and 
>> how about using tcg as a jit to boost it :)
>
> Yeah, it's hard to argue that script evaluation shouldn't be done in a 
> thread.  But that doesn't prevent me from being very cautious about 
> how and where we use threading :-)

Caution where threads are involved is a good thing.  They are inevitable 
however, IMO.

-- 
Do not meddle in the internals of kernels, for they are subtle and quick to panic.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU
  2010-03-29 20:42         ` Anthony Liguori
  2010-03-29 20:54           ` Avi Kivity
@ 2010-03-29 21:17           ` jvrao
  2010-03-30 10:28             ` Avi Kivity
  2010-04-01 13:14           ` Paul Brook
  2 siblings, 1 reply; 55+ messages in thread
From: jvrao @ 2010-03-29 21:17 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, ericvh, Avi Kivity, Aneesh Kumar K.V

Anthony Liguori wrote:
> On 03/29/2010 03:31 PM, Avi Kivity wrote:
>> On 03/29/2010 06:00 PM, Anthony Liguori wrote:
>>>
>>> In qemu, we tend to prefer state-machine based code.
>>>
>>> There are a few different models that we have discussed at different
>>> points:
>>>
>>> 1) state machines with a thread pool to make blocking functions
>>> asynchronous (what we have today)
>>>
>>> 2) co-operative threading
>>>
>>> 3) pre-emptive threading
>>>
>>> All three models are independent of making device models re-entrant. 
>>> In order to allow VCPU threads to run in qemu simultaneously, we need
>>> each device to carry a lock and for that lock to be acquired upon any
>>> of the public functions for the device model.
>>>
>>> For individual device models or host services, I think (3) is
>>> probably the worst model overall.  I personally think that (1) is
>>> better in the long run but ultimately would need an existence proof
>>> to compare against (2).  (2) looks appealing until you actually try
>>> to have the device handle multiple requests at a time.
>>
>> Sooner or later nature and the ever more complicated code will force
>> us towards (3).  As an example, we've observed live migration to
>> throttle vcpus when sending a large guest's zeroed memory over; the
>> bandwidth control doesn't kick in since zero pages are compressed, so
>> the iothread spends large amounts of time reading memory.
> 
> Making things re-entrant is different than (3) in my mind.
> 
> There's no reason that VCPU threads should run in lock-step with live
> migration during the live phase.  Making device models re-entrant and
> making live migration depend not depend on the big global lock is a good
> thing to do.
> 
> What I'm skeptical of, is whether converting virtio-9p or qcow2 to
> handle each request in a separate thread is really going to improve
> things.  The VNC server is another area that I think multithreading
> would be a bad idea.

Excuse me for some basic questions..still trying to understand QEMU concepts..

How does IO thread is accounted for? 

If I start a 2 CPU QEMU, we will be occupying two physical CPUs with two VCPU threads
and IO thread runs on other CPUs owned by the host right? If the answer is yes, then
we are good as the fileserver load has to be on the host CPUs. 

> 
>> We could fix this by yielding every so often (and a patch will be
>> posted soon), but it remains an issue.  We have too much work in the
>> I/O thread and that defers I/O completion and timers.
>>
>>> For virtio-9p, I don't think (1) is much of a burden to be honest. 
>>> In particular, when the 9p2000.L dialect is used, there should be a
>>> 1-1 correlation between protocol operations and system calls which
>>> means that for the most part, there's really no advantage to
>>> threading from a complexity point of view.
>>
>> But if those system calls are blocking, you need a thread?
> 
> You can dispatch just the system call to a thread pool.  The advantage
> of doing that is that you don't need to worry about locking since the
> system calls are not (usually) handling shared state.

How is locking avoided in the IO thread model? do we just have 1 IO thread 
irrespective of #VCPU threads? Is is that how the locking is avoided?

I think IO thread is used to do disk/network IO right? 
Putting 9P also on that will have any performance/scalability issues?

Thanks,
JV

> 
>> On a philosophical note, threads may be easier to model complex
>> hardware that includes a processor, for example our scsi card (and how
>> about using tcg as a jit to boost it :)
> 
> Yeah, it's hard to argue that script evaluation shouldn't be done in a
> thread.  But that doesn't prevent me from being very cautious about how
> and where we use threading :-)
> 
> Regards,
> 
> Anthony Liguori
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU
  2010-03-29 20:54           ` Avi Kivity
@ 2010-03-29 21:23             ` Anthony Liguori
  2010-03-30 10:24               ` Avi Kivity
  0 siblings, 1 reply; 55+ messages in thread
From: Anthony Liguori @ 2010-03-29 21:23 UTC (permalink / raw)
  To: Avi Kivity; +Cc: ericvh, jvrao, Aneesh Kumar K.V, qemu-devel

On 03/29/2010 03:54 PM, Avi Kivity wrote:
> On 03/29/2010 11:42 PM, Anthony Liguori wrote:
>>>> For individual device models or host services, I think (3) is 
>>>> probably the worst model overall.  I personally think that (1) is 
>>>> better in the long run but ultimately would need an existence proof 
>>>> to compare against (2).  (2) looks appealing until you actually try 
>>>> to have the device handle multiple requests at a time.
>>>
>>> Sooner or later nature and the ever more complicated code will force 
>>> us towards (3).  As an example, we've observed live migration to 
>>> throttle vcpus when sending a large guest's zeroed memory over; the 
>>> bandwidth control doesn't kick in since zero pages are compressed, 
>>> so the iothread spends large amounts of time reading memory.
>>
>>
>> Making things re-entrant is different than (3) in my mind.
>>
>> There's no reason that VCPU threads should run in lock-step with live 
>> migration during the live phase.  Making device models re-entrant and 
>> making live migration depend not depend on the big global lock is a 
>> good thing to do.
>
> It's not sufficient.  If you have a single thread that runs both live 
> migrations and timers, then timers will be backlogged behind live 
> migration, or you'll have to yield often.  This is regardless of the 
> locking model (and of course having threads without fixing the locking 
> is insufficient as well, live migration accesses guest memory so it 
> needs the big qemu lock).

But what's the solution?  Sending every timer in a separate thread?  
We'll hit the same problem if we implement an arbitrary limit to number 
of threads.

>> What I'm skeptical of, is whether converting virtio-9p or qcow2 to 
>> handle each request in a separate thread is really going to improve 
>> things. 
>
> Currently qcow2 isn't even fullly asynchronous, so it can't fail to 
> improve things.

Unless it introduces more data corruptions which is my concern with any 
significant change to qcow2.

>> The VNC server is another area that I think multithreading would be a 
>> bad idea.
>
> If the vnc server is stuffing a few megabytes of screen into a socket, 
> then timers will be delayed behind it, unless you litter the code with 
> calls to bottom halves.  Even worse if it does complicated compression 
> and encryption.

Sticking the VNC server in it's own thread would be fine.  Trying to 
make the VNC server multithreaded though would be problematic.

Basically, sticking isolated components in a single thread should be 
pretty reasonable.

>>>
>>> But if those system calls are blocking, you need a thread?
>>
>> You can dispatch just the system call to a thread pool.  The 
>> advantage of doing that is that you don't need to worry about locking 
>> since the system calls are not (usually) handling shared state.
>
> There is always implied shared state.  If you're doing direct guest 
> memory access, you need to lock memory against hotunplug, or the 
> syscall will end up writing into freed memory.  If the device can be 
> hotunplugged, you need to make sure all threads have returned before 
> unplugging it.

There are other ways to handle hot unplug (like reference counting) that 
avoid this problem.

Ultimately, this comes down to a question of lock granularity and thread 
granularity.  I don't think it's a good idea to start with the 
assumption that we want extremely fine granularity.  There's certainly 
very low hanging fruit with respect to threading.

>>> On a philosophical note, threads may be easier to model complex 
>>> hardware that includes a processor, for example our scsi card (and 
>>> how about using tcg as a jit to boost it :)
>>
>> Yeah, it's hard to argue that script evaluation shouldn't be done in 
>> a thread.  But that doesn't prevent me from being very cautious about 
>> how and where we use threading :-)
>
> Caution where threads are involved is a good thing.  They are 
> inevitable however, IMO.

We already are using threads so they aren't just inevitable, they're 
reality.  I still don't think using threads would significantly simplify 
virtio-9p.

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU
  2010-03-29 21:23             ` Anthony Liguori
@ 2010-03-30 10:24               ` Avi Kivity
  2010-03-30 13:13                 ` Anthony Liguori
  0 siblings, 1 reply; 55+ messages in thread
From: Avi Kivity @ 2010-03-30 10:24 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: ericvh, jvrao, Aneesh Kumar K.V, qemu-devel

On 03/30/2010 12:23 AM, Anthony Liguori wrote:
>> It's not sufficient.  If you have a single thread that runs both live 
>> migrations and timers, then timers will be backlogged behind live 
>> migration, or you'll have to yield often.  This is regardless of the 
>> locking model (and of course having threads without fixing the 
>> locking is insufficient as well, live migration accesses guest memory 
>> so it needs the big qemu lock).
>
>
> But what's the solution?  Sending every timer in a separate thread?  
> We'll hit the same problem if we implement an arbitrary limit to 
> number of threads.

A completion that's expected to take a couple of microseconds at most 
can live in the iothread.  A completion that's expected to take a couple 
of milliseconds wants its own thread.  We'll have to think about 
anything in between.

vnc and migration can perform large amounts of work in a single 
completion; they're limited only by the socket send rate and our 
internal rate-limiting which are both outside our control.  Most device 
timers are O(1).  virtio completions probably fall into the annoying 
"have to think about it" department.

>>> What I'm skeptical of, is whether converting virtio-9p or qcow2 to 
>>> handle each request in a separate thread is really going to improve 
>>> things. 
>>
>> Currently qcow2 isn't even fullly asynchronous, so it can't fail to 
>> improve things.
>
> Unless it introduces more data corruptions which is my concern with 
> any significant change to qcow2.

It's possible to move qcow2 to a thread without any significant change 
to it (simply run the current code in its own thread, protected by a 
mutex).  Further changes would be very incremental.

>>> The VNC server is another area that I think multithreading would be 
>>> a bad idea.
>>
>> If the vnc server is stuffing a few megabytes of screen into a 
>> socket, then timers will be delayed behind it, unless you litter the 
>> code with calls to bottom halves.  Even worse if it does complicated 
>> compression and encryption.
>
> Sticking the VNC server in it's own thread would be fine.  Trying to 
> make the VNC server multithreaded though would be problematic.

Why would it be problematic?  Each client gets its own threads, they 
don't interact at all do they?

I don't see a need to do it though (beyond dropping it into a thread).

> Basically, sticking isolated components in a single thread should be 
> pretty reasonable.

Now you're doomed.  It's easy to declare things "isolated components" 
one by one, pretty soon the main loop will be gone.

>>>>
>>>> But if those system calls are blocking, you need a thread?
>>>
>>> You can dispatch just the system call to a thread pool.  The 
>>> advantage of doing that is that you don't need to worry about 
>>> locking since the system calls are not (usually) handling shared state.
>>
>> There is always implied shared state.  If you're doing direct guest 
>> memory access, you need to lock memory against hotunplug, or the 
>> syscall will end up writing into freed memory.  If the device can be 
>> hotunplugged, you need to make sure all threads have returned before 
>> unplugging it.
>
> There are other ways to handle hot unplug (like reference counting) 
> that avoid this problem.

That's just more clever locking.

> Ultimately, this comes down to a question of lock granularity and 
> thread granularity.  I don't think it's a good idea to start with the 
> assumption that we want extremely fine granularity.  There's certainly 
> very low hanging fruit with respect to threading.

Sure.  Currently the hotspots are block devices (except raw) and hpet 
(seen with large Windows guests).  The latter includes the bus lookup 
and hpet itself, hpet reads can be performed locklessly if we're clever.

>>>> On a philosophical note, threads may be easier to model complex 
>>>> hardware that includes a processor, for example our scsi card (and 
>>>> how about using tcg as a jit to boost it :)
>>>
>>> Yeah, it's hard to argue that script evaluation shouldn't be done in 
>>> a thread.  But that doesn't prevent me from being very cautious 
>>> about how and where we use threading :-)
>>
>> Caution where threads are involved is a good thing.  They are 
>> inevitable however, IMO.
>
> We already are using threads so they aren't just inevitable, they're 
> reality.  I still don't think using threads would significantly 
> simplify virtio-9p.
>

I meant, exposing qemu core to the threads instead of pretending they 
aren't there.  I'm not familiar with 9p so don't hold much of an 
opinion, but didn't you say you need threads in order to handle async 
syscalls?  That may not be the deep threading we're discussing here.

btw, IIUC currently disk hotunplug will stall a guest, no?  We need 
async aio_flush().

-- 
Do not meddle in the internals of kernels, for they are subtle and quick to panic.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU
  2010-03-29 21:17           ` jvrao
@ 2010-03-30 10:28             ` Avi Kivity
  0 siblings, 0 replies; 55+ messages in thread
From: Avi Kivity @ 2010-03-30 10:28 UTC (permalink / raw)
  To: jvrao; +Cc: ericvh, Anthony Liguori, Aneesh Kumar K.V, qemu-devel

On 03/30/2010 12:17 AM, jvrao wrote:
>
> Excuse me for some basic questions..still trying to understand QEMU concepts..
>
> How does IO thread is accounted for?
>    

It's just another thread, usually a lightly loaded one.

> If I start a 2 CPU QEMU, we will be occupying two physical CPUs with two VCPU threads
> and IO thread runs on other CPUs owned by the host right? If the answer is yes, then
> we are good as the fileserver load has to be on the host CPUs.
>    

It's completely up to the scheduler and determined by how the iothread, 
vcpu threads, and other processes on the host are loaded.

>> You can dispatch just the system call to a thread pool.  The advantage
>> of doing that is that you don't need to worry about locking since the
>> system calls are not (usually) handling shared state.
>>      
> How is locking avoided in the IO thread model? do we just have 1 IO thread
> irrespective of #VCPU threads? Is is that how the locking is avoided?
>    

When you are running qemu code you hold the qemu mutex, except when you 
are in the thread pool.  So the iothread and vcpu threads are all 
mutually excluded, and defer any blocking work to other threads.

> I think IO thread is used to do disk/network IO right?
>    

It's used for completions (disk, network, timers, anything that 
completes asynchronously to a vcpu).

> Putting 9P also on that will have any performance/scalability issues?
>    

Yes.

-- 
Do not meddle in the internals of kernels, for they are subtle and quick to panic.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU
  2010-03-30 10:24               ` Avi Kivity
@ 2010-03-30 13:13                 ` Anthony Liguori
  2010-03-30 13:28                   ` Avi Kivity
  0 siblings, 1 reply; 55+ messages in thread
From: Anthony Liguori @ 2010-03-30 13:13 UTC (permalink / raw)
  To: Avi Kivity; +Cc: ericvh, jvrao, Aneesh Kumar K.V, qemu-devel

On 03/30/2010 05:24 AM, Avi Kivity wrote:
> On 03/30/2010 12:23 AM, Anthony Liguori wrote:
>>> It's not sufficient.  If you have a single thread that runs both 
>>> live migrations and timers, then timers will be backlogged behind 
>>> live migration, or you'll have to yield often.  This is regardless 
>>> of the locking model (and of course having threads without fixing 
>>> the locking is insufficient as well, live migration accesses guest 
>>> memory so it needs the big qemu lock).
>>
>>
>> But what's the solution?  Sending every timer in a separate thread?  
>> We'll hit the same problem if we implement an arbitrary limit to 
>> number of threads.
>
> A completion that's expected to take a couple of microseconds at most 
> can live in the iothread.  A completion that's expected to take a 
> couple of milliseconds wants its own thread.  We'll have to think 
> about anything in between.
>
> vnc and migration can perform large amounts of work in a single 
> completion; they're limited only by the socket send rate and our 
> internal rate-limiting which are both outside our control.  Most 
> device timers are O(1).  virtio completions probably fall into the 
> annoying "have to think about it" department.

I think it may make more sense to have vcpu completions vs. io thread 
completions and make vcpu completions target short lived operations.

>>>> What I'm skeptical of, is whether converting virtio-9p or qcow2 to 
>>>> handle each request in a separate thread is really going to improve 
>>>> things. 
>>>
>>> Currently qcow2 isn't even fullly asynchronous, so it can't fail to 
>>> improve things.
>>
>> Unless it introduces more data corruptions which is my concern with 
>> any significant change to qcow2.
>
> It's possible to move qcow2 to a thread without any significant change 
> to it (simply run the current code in its own thread, protected by a 
> mutex).  Further changes would be very incremental.

But that offers no advantage to what we have which fails the 
proof-by-example that threading makes the situation better.  To convert 
qcow2 to be threaded, I think you would have to wrap the whole thing in 
a lock, then convert the current asynchronous functions to synchronous 
(that's the whole point, right).  At this point, you've regressed 
performance because you can only handle one read/write outstanding at a 
given time.  So now you have to make the locking more granular but 
because we do layered block devices, you've got to make most of the core 
block driver functions thread safe.

Once you get basic data operations concurrent, which I expect won't be 
so bad, to get an improvement over the current code, you have to allow 
simultaneous access to metadata which is where I think the vast majority 
of the complexity will come from.

You could argue that we stick qcow2 into a thread and stop there and 
that fixes the problems with synchronous data access.  If that's the 
argument, then let's not even bother doing at the qcow layer, let's just 
switch the block aio emulation to use a dedicated thread.

>> Sticking the VNC server in it's own thread would be fine.  Trying to 
>> make the VNC server multithreaded though would be problematic.
>
> Why would it be problematic?  Each client gets its own threads, they 
> don't interact at all do they?

Dealing with locking of the core display which each client uses for 
rendering.  Things like CopyRect will get ugly quickly.Ultimately, this 
comes down to a question of lock granularity and thread granularity.  I 
don't think it's a good idea to start with the assumption that we want 
extremely fine granularity.  There's certainly very low hanging fruit 
with respect to threading.

> Sure.  Currently the hotspots are block devices (except raw) and hpet 
> (seen with large Windows guests).  The latter includes the bus lookup 
> and hpet itself, hpet reads can be performed locklessly if we're clever.

I'm all for making devices thread safe and the hpet is probably a good 
candidate for initial converting.

>
> I meant, exposing qemu core to the threads instead of pretending they 
> aren't there.  I'm not familiar with 9p so don't hold much of an 
> opinion, but didn't you say you need threads in order to handle async 
> syscalls?  That may not be the deep threading we're discussing here.
>
> btw, IIUC currently disk hotunplug will stall a guest, no?  We need 
> async aio_flush().

But aio_flush() never takes a very long time, right :-)

We had this discussion in the past re: live migration because we do an 
aio_flush() in the critical stage.

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU
  2010-03-30 13:13                 ` Anthony Liguori
@ 2010-03-30 13:28                   ` Avi Kivity
  2010-03-30 13:54                     ` Anthony Liguori
  0 siblings, 1 reply; 55+ messages in thread
From: Avi Kivity @ 2010-03-30 13:28 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: ericvh, jvrao, Aneesh Kumar K.V, qemu-devel

On 03/30/2010 04:13 PM, Anthony Liguori wrote:
> On 03/30/2010 05:24 AM, Avi Kivity wrote:
>> On 03/30/2010 12:23 AM, Anthony Liguori wrote:
>>>> It's not sufficient.  If you have a single thread that runs both 
>>>> live migrations and timers, then timers will be backlogged behind 
>>>> live migration, or you'll have to yield often.  This is regardless 
>>>> of the locking model (and of course having threads without fixing 
>>>> the locking is insufficient as well, live migration accesses guest 
>>>> memory so it needs the big qemu lock).
>>>
>>>
>>> But what's the solution?  Sending every timer in a separate thread?  
>>> We'll hit the same problem if we implement an arbitrary limit to 
>>> number of threads.
>>
>> A completion that's expected to take a couple of microseconds at most 
>> can live in the iothread.  A completion that's expected to take a 
>> couple of milliseconds wants its own thread.  We'll have to think 
>> about anything in between.
>>
>> vnc and migration can perform large amounts of work in a single 
>> completion; they're limited only by the socket send rate and our 
>> internal rate-limiting which are both outside our control.  Most 
>> device timers are O(1).  virtio completions probably fall into the 
>> annoying "have to think about it" department.
>
> I think it may make more sense to have vcpu completions vs. io thread 
> completions and make vcpu completions target short lived operations.

vcpu completions make sense when you can tell that a completion will 
cause an interrupt injection and you have a good idea which cpu will be 
interrupted.

>
>>>>> What I'm skeptical of, is whether converting virtio-9p or qcow2 to 
>>>>> handle each request in a separate thread is really going to 
>>>>> improve things. 
>>>>
>>>> Currently qcow2 isn't even fullly asynchronous, so it can't fail to 
>>>> improve things.
>>>
>>> Unless it introduces more data corruptions which is my concern with 
>>> any significant change to qcow2.
>>
>> It's possible to move qcow2 to a thread without any significant 
>> change to it (simply run the current code in its own thread, 
>> protected by a mutex).  Further changes would be very incremental.
>
> But that offers no advantage to what we have which fails the 
> proof-by-example that threading makes the situation better. 

It has an advantage, qcow2 is currently synchronous in parts:

block/qcow2-cluster.c:    ret = bdrv_write(s->hd, (cluster_offset >> 9) 
+ n_start,
block/qcow2.c:        bdrv_write(s->hd, (meta.cluster_offset >> 9) + num 
- 1, buf, 1);
block/qcow2.c:        bdrv_write(bs, sector_num, buf, s->cluster_sectors);
block/qcow2-cluster.c:                    ret = 
bdrv_read(bs->backing_hd, sector_num, buf, n1);
block/qcow2-cluster.c:        ret = bdrv_read(s->hd, coffset >> 9, 
s->cluster_data, nb_csectors);

> To convert qcow2 to be threaded, I think you would have to wrap the 
> whole thing in a lock, then convert the current asynchronous functions 
> to synchronous (that's the whole point, right).  At this point, you've 
> regressed performance because you can only handle one read/write 
> outstanding at a given time.  So now you have to make the locking more 
> granular but because we do layered block devices, you've got to make 
> most of the core block driver functions thread safe.

Not at all.  The first conversion will be to keep the current code as 
is, operating asynchronously, but running in its own thread.  It will 
still support multiple outstanding requests using the current state 
machine code; the synchronous parts will be remain synchronous relative 
to the block device, but async relative to everything else.  The second 
stage will convert the state machine code to threaded code.  This is 
more difficult but not overly so - turn every dependency list into a mutex.

> Once you get basic data operations concurrent, which I expect won't be 
> so bad, to get an improvement over the current code, you have to allow 
> simultaneous access to metadata which is where I think the vast 
> majority of the complexity will come from.

I have no plans to do that, all I want is qcow2 not to block vcpus.  
btw, I don't think it's all that complicated, it's simple to lock 
individual L2 blocks and the L1 block.

> You could argue that we stick qcow2 into a thread and stop there and 
> that fixes the problems with synchronous data access.  If that's the 
> argument, then let's not even bother doing at the qcow layer, let's 
> just switch the block aio emulation to use a dedicated thread.

That's certainly the plan for vmdk and friends which are today useless.  
qcow2 deserves better treatment.

>>> Sticking the VNC server in it's own thread would be fine.  Trying to 
>>> make the VNC server multithreaded though would be problematic.
>>
>> Why would it be problematic?  Each client gets its own threads, they 
>> don't interact at all do they?
>
> Dealing with locking of the core display which each client uses for 
> rendering.  Things like CopyRect will get ugly quickly.Ultimately, 
> this comes down to a question of lock granularity and thread 
> granularity.  I don't think it's a good idea to start with the 
> assumption that we want extremely fine granularity.  There's certainly 
> very low hanging fruit with respect to threading.

Not familiar with the code, but doesn't vnc access the display core 
through an API?  Slap a lot onto that.

>>
>> I meant, exposing qemu core to the threads instead of pretending they 
>> aren't there.  I'm not familiar with 9p so don't hold much of an 
>> opinion, but didn't you say you need threads in order to handle async 
>> syscalls?  That may not be the deep threading we're discussing here.
>>
>> btw, IIUC currently disk hotunplug will stall a guest, no?  We need 
>> async aio_flush().
>
> But aio_flush() never takes a very long time, right :-)
>
> We had this discussion in the past re: live migration because we do an 
> aio_flush() in the critical stage.
>

Live migration will stall a guest anyway.  It doesn't matter if 
aio_flush blocks for a few ms, since the final stage will dominate it.

-- 
Do not meddle in the internals of kernels, for they are subtle and quick to panic.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU
  2010-03-30 13:28                   ` Avi Kivity
@ 2010-03-30 13:54                     ` Anthony Liguori
  2010-03-30 14:03                       ` Avi Kivity
  0 siblings, 1 reply; 55+ messages in thread
From: Anthony Liguori @ 2010-03-30 13:54 UTC (permalink / raw)
  To: Avi Kivity; +Cc: ericvh, Kevin Wolf, jvrao, Aneesh Kumar K.V, qemu-devel

On 03/30/2010 08:28 AM, Avi Kivity wrote:
>> But that offers no advantage to what we have which fails the 
>> proof-by-example that threading makes the situation better. 
>
>
> It has an advantage, qcow2 is currently synchronous in parts:
>
> block/qcow2-cluster.c:    ret = bdrv_write(s->hd, (cluster_offset >> 
> 9) + n_start,
 > block/qcow2-cluster.c:                    ret = 
bdrv_read(bs->backing_hd, sector_num, buf, n1);

The two of these happen in copy_sectors().  copy_sectors() runs from 
qcow2_alloc_cluster_link_l2() which is called from qcow_aio_write_cb() 
and preallocate().

> block/qcow2.c:        bdrv_write(s->hd, (meta.cluster_offset >> 9) + 
> num - 1, buf, 1);

This only happens during creation (for preallocation).

> block/qcow2.c:        bdrv_write(bs, sector_num, buf, 
> s->cluster_sectors);
> block/qcow2-cluster.c:        ret = bdrv_read(s->hd, coffset >> 9, 
> s->cluster_data, nb_csectors);

These two are only for compressed images.

So it looks like we really only have one operation 
(qcow2_alloc_cluster_link_l2) that blocks.  Do we really think that it's 
sufficiently difficult to make this function asynchronous that it 
justifies threading the block layer?

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU
  2010-03-30 13:54                     ` Anthony Liguori
@ 2010-03-30 14:03                       ` Avi Kivity
  2010-03-30 14:07                         ` Anthony Liguori
  0 siblings, 1 reply; 55+ messages in thread
From: Avi Kivity @ 2010-03-30 14:03 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: ericvh, Kevin Wolf, jvrao, Aneesh Kumar K.V, qemu-devel

On 03/30/2010 04:54 PM, Anthony Liguori wrote:
> On 03/30/2010 08:28 AM, Avi Kivity wrote:
>>> But that offers no advantage to what we have which fails the 
>>> proof-by-example that threading makes the situation better. 
>>
>>
>> It has an advantage, qcow2 is currently synchronous in parts:
>>
>> block/qcow2-cluster.c:    ret = bdrv_write(s->hd, (cluster_offset >> 
>> 9) + n_start,
> > block/qcow2-cluster.c:                    ret = 
> bdrv_read(bs->backing_hd, sector_num, buf, n1);
>
> The two of these happen in copy_sectors().  copy_sectors() runs from 
> qcow2_alloc_cluster_link_l2() which is called from qcow_aio_write_cb() 
> and preallocate().
>
>> block/qcow2.c:        bdrv_write(s->hd, (meta.cluster_offset >> 9) + 
>> num - 1, buf, 1);
>
> This only happens during creation (for preallocation).
>
>> block/qcow2.c:        bdrv_write(bs, sector_num, buf, 
>> s->cluster_sectors);
>> block/qcow2-cluster.c:        ret = bdrv_read(s->hd, coffset >> 9, 
>> s->cluster_data, nb_csectors);
>
> These two are only for compressed images.

Are compressed images supposed to block vcpus?

>
> So it looks like we really only have one operation 
> (qcow2_alloc_cluster_link_l2) that blocks.  Do we really think that 
> it's sufficiently difficult to make this function asynchronous that it 
> justifies threading the block layer?

There are also tons of bdrv_pread()s and bdrv_pwrite()s.  Isn't growing 
some of the tables synchronous? how about creating a snapshot?

If it were just one operation in qcow2, threading would be a big 
overkill.  But threading also fixes all of the other format drivers, and 
makes working on qcow2 easier.

-- 
Do not meddle in the internals of kernels, for they are subtle and quick to panic.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU
  2010-03-30 14:03                       ` Avi Kivity
@ 2010-03-30 14:07                         ` Anthony Liguori
  2010-03-30 14:23                           ` Avi Kivity
  0 siblings, 1 reply; 55+ messages in thread
From: Anthony Liguori @ 2010-03-30 14:07 UTC (permalink / raw)
  To: Avi Kivity; +Cc: ericvh, Kevin Wolf, jvrao, Aneesh Kumar K.V, qemu-devel

On 03/30/2010 09:03 AM, Avi Kivity wrote:
>>
>> So it looks like we really only have one operation 
>> (qcow2_alloc_cluster_link_l2) that blocks.  Do we really think that 
>> it's sufficiently difficult to make this function asynchronous that 
>> it justifies threading the block layer?
>
> There are also tons of bdrv_pread()s and bdrv_pwrite()s.  Isn't 
> growing some of the tables synchronous? how about creating a snapshot?

Eh, that ruins my whole argument.

>
> If it were just one operation in qcow2, threading would be a big 
> overkill.  But threading also fixes all of the other format drivers, 
> and makes working on qcow2 easier.
>

Yeah, I think the only question is whether to stick threading in the 
generic block layer or within qcow2.

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU
  2010-03-30 14:07                         ` Anthony Liguori
@ 2010-03-30 14:23                           ` Avi Kivity
  2010-03-30 14:59                             ` Anthony Liguori
  0 siblings, 1 reply; 55+ messages in thread
From: Avi Kivity @ 2010-03-30 14:23 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: ericvh, Kevin Wolf, jvrao, Aneesh Kumar K.V, qemu-devel

On 03/30/2010 05:07 PM, Anthony Liguori wrote:
> On 03/30/2010 09:03 AM, Avi Kivity wrote:
>>>
>>> So it looks like we really only have one operation 
>>> (qcow2_alloc_cluster_link_l2) that blocks.  Do we really think that 
>>> it's sufficiently difficult to make this function asynchronous that 
>>> it justifies threading the block layer?
>>
>> There are also tons of bdrv_pread()s and bdrv_pwrite()s.  Isn't 
>> growing some of the tables synchronous? how about creating a snapshot?
>
> Eh, that ruins my whole argument.


But we can keep on arguing regardless, yes?

>
>>
>> If it were just one operation in qcow2, threading would be a big 
>> overkill.  But threading also fixes all of the other format drivers, 
>> and makes working on qcow2 easier.
>>
>
> Yeah, I think the only question is whether to stick threading in the 
> generic block layer or within qcow2.

Both.  My plan is:

(1) some generic infrastructure
(2) kit that turns a synchronous block format driver into an 
asynchronous one using (1), limited to one outstanding request
(3) adaptations to qcow2 using (1) to make it fully asynchronous, 
capable of multiple outstanding requests (except when it issues a sync 
request)

I've mostly done (1) and am contemplating (2).

-- 
Do not meddle in the internals of kernels, for they are subtle and quick to panic.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU
  2010-03-30 14:23                           ` Avi Kivity
@ 2010-03-30 14:59                             ` Anthony Liguori
  0 siblings, 0 replies; 55+ messages in thread
From: Anthony Liguori @ 2010-03-30 14:59 UTC (permalink / raw)
  To: Avi Kivity; +Cc: ericvh, Kevin Wolf, jvrao, Aneesh Kumar K.V, qemu-devel

On 03/30/2010 09:23 AM, Avi Kivity wrote:
> On 03/30/2010 05:07 PM, Anthony Liguori wrote:
>> On 03/30/2010 09:03 AM, Avi Kivity wrote:
>>>>
>>>> So it looks like we really only have one operation 
>>>> (qcow2_alloc_cluster_link_l2) that blocks.  Do we really think that 
>>>> it's sufficiently difficult to make this function asynchronous that 
>>>> it justifies threading the block layer?
>>>
>>> There are also tons of bdrv_pread()s and bdrv_pwrite()s.  Isn't 
>>> growing some of the tables synchronous? how about creating a snapshot?
>>
>> Eh, that ruins my whole argument.
>
>
> But we can keep on arguing regardless, yes?

Of course :-)

> Both.  My plan is:
>
> (1) some generic infrastructure
> (2) kit that turns a synchronous block format driver into an 
> asynchronous one using (1), limited to one outstanding request
> (3) adaptations to qcow2 using (1) to make it fully asynchronous, 
> capable of multiple outstanding requests (except when it issues a sync 
> request)
>
> I've mostly done (1) and am contemplating (2).

Sounds reasonable.

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU
  2010-03-29 20:42         ` Anthony Liguori
  2010-03-29 20:54           ` Avi Kivity
  2010-03-29 21:17           ` jvrao
@ 2010-04-01 13:14           ` Paul Brook
  2010-04-01 14:34             ` Avi Kivity
  2 siblings, 1 reply; 55+ messages in thread
From: Paul Brook @ 2010-04-01 13:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, Anthony Liguori, jvrao, Avi Kivity, Aneesh Kumar K.V

>>> 1) state machines with a thread pool to make blocking functions
>>> asynchronous (what we have today)
>>>
>>> 2) co-operative threading
>>>
>>> 3) pre-emptive threading

> > On a philosophical note, threads may be easier to model complex
> > hardware that includes a processor, for example our scsi card (and how
> > about using tcg as a jit to boost it :)
> 
> Yeah, it's hard to argue that script evaluation shouldn't be done in a
> thread.  But that doesn't prevent me from being very cautious about how
> and where we use threading :-)

I agree that making script execution asynchronous is a good thing, however I'm 
not convinced that (3) is the best way to do this. It's certainly the most 
flexible model, however it also places responsibility for locking/correctness 
on the device developer.

A more limited scheme (e.g. asynchronous callbacks) can actually be 
significant advantage. By forcing the developer to solve the problem in a 
particular way we significantly reduce the scope for race conditions, and 
hopefully restrict all locking concerns to common code/APIs.

Paul

[1] This issue may come from accidental misuse of terminology, but it's an 
important distinction.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU
  2010-04-01 13:14           ` Paul Brook
@ 2010-04-01 14:34             ` Avi Kivity
  2010-04-01 15:30               ` Paul Brook
  0 siblings, 1 reply; 55+ messages in thread
From: Avi Kivity @ 2010-04-01 14:34 UTC (permalink / raw)
  To: Paul Brook; +Cc: ericvh, Anthony Liguori, jvrao, qemu-devel, Aneesh Kumar K.V

On 04/01/2010 04:14 PM, Paul Brook wrote:
>
>>> On a philosophical note, threads may be easier to model complex
>>> hardware that includes a processor, for example our scsi card (and how
>>> about using tcg as a jit to boost it :)
>>>        
>> Yeah, it's hard to argue that script evaluation shouldn't be done in a
>> thread.  But that doesn't prevent me from being very cautious about how
>> and where we use threading :-)
>>      
> I agree that making script execution asynchronous is a good thing, however I'm
> not convinced that (3) is the best way to do this. It's certainly the most
> flexible model, however it also places responsibility for locking/correctness
> on the device developer.
>
> A more limited scheme (e.g. asynchronous callbacks) can actually be
> significant advantage. By forcing the developer to solve the problem in a
> particular way we significantly reduce the scope for race conditions, and
> hopefully restrict all locking concerns to common code/APIs.
>    

Can you elaborate?  When would the callbacks be called?  When would the 
callbacks yield back?

If the script isn't run to completion (a halt instruction), there isn't 
really a good answer to these questions.

> [1] This issue may come from accidental misuse of terminology, but it's an
> important distinction.
>    

Missing reference to footnote.

-- 
error compiling committee.c: too many arguments to function

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU
  2010-04-01 14:34             ` Avi Kivity
@ 2010-04-01 15:30               ` Paul Brook
  0 siblings, 0 replies; 55+ messages in thread
From: Paul Brook @ 2010-04-01 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, Anthony Liguori, jvrao, Avi Kivity, Aneesh Kumar K.V

> On 04/01/2010 04:14 PM, Paul Brook wrote:
> >>> On a philosophical note, threads may be easier to model complex
> >>> hardware that includes a processor, for example our scsi card (and how
> >>> about using tcg as a jit to boost it :)
> >>
> >> Yeah, it's hard to argue that script evaluation shouldn't be done in a
> >> thread.  But that doesn't prevent me from being very cautious about how
> >> and where we use threading :-)
> >
> > I agree that making script execution asynchronous is a good thing,
> > however I'm not convinced that (3) is the best way to do this. It's
> > certainly the most flexible model, however it also places responsibility
> > for locking/correctness on the device developer.
> >
> > A more limited scheme (e.g. asynchronous callbacks) can actually be
> > significant advantage. By forcing the developer to solve the problem in a
> > particular way we significantly reduce the scope for race conditions, and
> > hopefully restrict all locking concerns to common code/APIs.
> 
> Can you elaborate?  When would the callbacks be called?  When would the
> callbacks yield back? If the script isn't run to completion (a halt 
instruction), there isn't really a good answer to these questions.

In practice I don't think pre-emtive multithreading actually solves all that 
many problems. If a script enters an indefinite loop then you want to be 
terminating or throttling it anyway.  The difference is whether you 
yield/return or drop locks and performing a blocking operation.

I suppose what I'm getting at is the difference between explicit 
multithreading and event based programming.  In the latter case I believe it's 
much easier to have individual devices use a sequential model, but have the 
whole system be concurrent.

> > [1] This issue may come from accidental misuse of terminology, but it's
> > an important distinction.
> 
> Missing reference to footnote.

I was going to comment on the difference between re-entrancy and concurrency, 
but decided against it.

Paul

^ permalink raw reply	[flat|nested] 55+ messages in thread

end of thread, other threads:[~2010-04-01 15:30 UTC | newest]

Thread overview: 55+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-25 16:43 [Qemu-devel] [PATCH -V3 00/32] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 01/32] vitio-9p: Add a virtio 9p device to qemu Aneesh Kumar K.V
2010-03-25 21:04   ` Anthony Liguori
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 02/32] vrtio-9p: Implement P9_TVERSION for 9P Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 03/32] virtio-9p: Implement P9_TATTACH Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 04/32] virtio-9p: Implement P9_TSTAT Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 05/32] virtio-9p: Implement P9_TWALK Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 06/32] virtio-9p: Implement P9_TOPEN Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 07/32] virtio-9p: Implement P9_TREAD Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 08/32] virtio-9p: Implement P9_TCLUNK Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE Aneesh Kumar K.V
2010-03-29  6:36   ` [Qemu-devel] [PATCH -V3 09/32] virtio-9p: Implement P9_TWRITE/ Thread model in QEMU jvrao
2010-03-29 15:00     ` Anthony Liguori
2010-03-29 20:31       ` Avi Kivity
2010-03-29 20:42         ` Anthony Liguori
2010-03-29 20:54           ` Avi Kivity
2010-03-29 21:23             ` Anthony Liguori
2010-03-30 10:24               ` Avi Kivity
2010-03-30 13:13                 ` Anthony Liguori
2010-03-30 13:28                   ` Avi Kivity
2010-03-30 13:54                     ` Anthony Liguori
2010-03-30 14:03                       ` Avi Kivity
2010-03-30 14:07                         ` Anthony Liguori
2010-03-30 14:23                           ` Avi Kivity
2010-03-30 14:59                             ` Anthony Liguori
2010-03-29 21:17           ` jvrao
2010-03-30 10:28             ` Avi Kivity
2010-04-01 13:14           ` Paul Brook
2010-04-01 14:34             ` Avi Kivity
2010-04-01 15:30               ` Paul Brook
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 10/32] virtio-9p: Implement P9_TCREATE Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 11/32] virtio-9p: Implement P9_TWSTAT Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 12/32] virtio-9p: Implement P9_TREMOVE Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 13/32] virtio-9p: Implement P9_TFLUSH Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 14/32] virtio-9p: Add multiple mount point support Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 15/32] virtio-9p: Use little endian format on virtio Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 16/32] virtio-9p: Add support for hardlink Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 17/32] Implement sync support in 9p server Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 18/32] virtio-9p: Fix sg usage in the code Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 19/32] virtio-9p: Get the correct count values from the pdu Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 20/32] virtio-9p: Remove BUG_ON and add proper error handling Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 21/32] virtio-9p: Remove unnecessary definition of fid Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 22/32] virtio-9p: Update existing fid path on rename Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 23/32] vritio-9p: Fix chmod bug with directory Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 24/32] qemu-malloc: Add qemu_asprintf Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 25/32] virtio-9p: Move V9fs File system specific options to a separate header file Aneesh Kumar K.V
2010-03-29  0:52   ` jvrao
2010-03-29  1:09   ` jvrao
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 26/32] virtio-9p: Create a commandline option -fsdev Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 27/32] virtio-9p: Create qemu_fsdev_opts Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 28/32] virtio-9p: Handle the fsdev command line options Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 29/32] virtio-9p: Decouple share_path details from virtio-9p-dev Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 30/32] virtio-9p: Create a syntactic shortcut for the file-system pass-thru Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 31/32] virtio-9p: Return proper errors from create paths Aneesh Kumar K.V
2010-03-25 16:43 ` [Qemu-devel] [PATCH -V3 32/32] virtio-9p: Handle unknown 9P protocol versions as per the standards Aneesh Kumar K.V

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.