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

Hi,


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.

-device virtio-9p-pci,share_path=/mnt/,mount_tag=v_mnt

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 V1:
a) fsstress test suite runs successfully with the patches. That should indicate patches are stable
enough to be merged.
b) Added proper error handling to all posix_* calls.
c) Fixed code to follow Qemu coding style.
d) Other bug fixes most of which are folded back into the original patches
e) rebased to qemu master 0aef4261ac0ec9089ade0e3a92f986cb4ba7317e


-aneesh

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

* [Qemu-devel] [PATCH -v2 01/22] vitio-9p: Add a virtio 9p device to qemu
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
@ 2010-03-16  9:14 ` Aneesh Kumar K.V
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 02/22] vrtio-9p: Implement P9_TVERSION for 9P Aneesh Kumar K.V
                   ` (21 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:14 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 320f807..33f9fcb 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -172,6 +172,7 @@ obj-y = vl.o async.o monitor.o pci.o pci_host.o pcie_host.o machine.o gdbstub.o
 # virtio has to be here due to weird dependency between PCI and virtio-net.
 # need to fix this properly
 obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-pci.o virtio-serial-bus.o
+obj-y += virtio-9p.o virtio-9p-debug.o
 obj-y += rwhandler.o
 obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
diff --git a/hw/virtio-9p-debug.c b/hw/virtio-9p-debug.c
new file mode 100644
index 0000000..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 799f664..228dded 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.273.gc2413

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

* [Qemu-devel] [PATCH -v2 02/22] vrtio-9p: Implement P9_TVERSION for 9P
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
  2010-03-16  9:14 ` [Qemu-devel] [PATCH -v2 01/22] vitio-9p: Add a virtio 9p device to qemu Aneesh Kumar K.V
@ 2010-03-16  9:15 ` Aneesh Kumar K.V
  2010-03-26 16:15   ` Anthony Liguori
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 03/22] virtio-9p: Implement P9_TATTACH Aneesh Kumar K.V
                   ` (20 subsequent siblings)
  22 siblings, 1 reply; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:15 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.273.gc2413

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

* [Qemu-devel] [PATCH -v2 03/22] virtio-9p: Implement P9_TATTACH
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
  2010-03-16  9:14 ` [Qemu-devel] [PATCH -v2 01/22] vitio-9p: Add a virtio 9p device to qemu Aneesh Kumar K.V
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 02/22] vrtio-9p: Implement P9_TVERSION for 9P Aneesh Kumar K.V
@ 2010-03-16  9:15 ` Aneesh Kumar K.V
  2010-03-26 16:17   ` Anthony Liguori
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 04/22] virtio-9p: Implement P9_TSTAT Aneesh Kumar K.V
                   ` (19 subsequent siblings)
  22 siblings, 1 reply; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:15 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 33f9fcb..97f32a9 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -172,7 +172,7 @@ obj-y = vl.o async.o monitor.o pci.o pci_host.o pcie_host.o machine.o gdbstub.o
 # virtio has to be here due to weird dependency between PCI and virtio-net.
 # need to fix this properly
 obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-pci.o virtio-serial-bus.o
-obj-y += virtio-9p.o virtio-9p-debug.o
+obj-y += virtio-9p.o virtio-9p-debug.o virtio-9p-local.o
 obj-y += rwhandler.o
 obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
diff --git a/hw/virtio-9p-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 805be1a..ebe7088 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -159,6 +159,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.273.gc2413

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

* [Qemu-devel] [PATCH -v2 04/22] virtio-9p: Implement P9_TSTAT
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (2 preceding siblings ...)
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 03/22] virtio-9p: Implement P9_TATTACH Aneesh Kumar K.V
@ 2010-03-16  9:15 ` Aneesh Kumar K.V
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 05/22] virtio-9p: Implement P9_TWALK Aneesh Kumar K.V
                   ` (18 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:15 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.273.gc2413

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

* [Qemu-devel] [PATCH -v2 05/22] virtio-9p: Implement P9_TWALK
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (3 preceding siblings ...)
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 04/22] virtio-9p: Implement P9_TSTAT Aneesh Kumar K.V
@ 2010-03-16  9:15 ` Aneesh Kumar K.V
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 06/22] virtio-9p: Implement P9_TOPEN Aneesh Kumar K.V
                   ` (17 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:15 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.273.gc2413

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

* [Qemu-devel] [PATCH -v2 06/22] virtio-9p: Implement P9_TOPEN
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (4 preceding siblings ...)
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 05/22] virtio-9p: Implement P9_TWALK Aneesh Kumar K.V
@ 2010-03-16  9:15 ` Aneesh Kumar K.V
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 07/22] virtio-9p: Implement P9_TREAD Aneesh Kumar K.V
                   ` (16 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:15 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.273.gc2413

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

* [Qemu-devel] [PATCH -v2 07/22] virtio-9p: Implement P9_TREAD
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (5 preceding siblings ...)
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 06/22] virtio-9p: Implement P9_TOPEN Aneesh Kumar K.V
@ 2010-03-16  9:15 ` Aneesh Kumar K.V
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 08/22] virtio-9p: Implement P9_TCLUNK Aneesh Kumar K.V
                   ` (15 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:15 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.273.gc2413

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

* [Qemu-devel] [PATCH -v2 08/22] virtio-9p: Implement P9_TCLUNK
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (6 preceding siblings ...)
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 07/22] virtio-9p: Implement P9_TREAD Aneesh Kumar K.V
@ 2010-03-16  9:15 ` Aneesh Kumar K.V
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 09/22] virtio-9p: Implement P9_TWRITE Aneesh Kumar K.V
                   ` (14 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:15 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.273.gc2413

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

* [Qemu-devel] [PATCH -v2 09/22] virtio-9p: Implement P9_TWRITE
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (7 preceding siblings ...)
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 08/22] virtio-9p: Implement P9_TCLUNK Aneesh Kumar K.V
@ 2010-03-16  9:15 ` Aneesh Kumar K.V
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 10/22] virtio-9p: Implement P9_TCREATE Aneesh Kumar K.V
                   ` (13 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:15 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.273.gc2413

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

* [Qemu-devel] [PATCH -v2 10/22] virtio-9p: Implement P9_TCREATE
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (8 preceding siblings ...)
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 09/22] virtio-9p: Implement P9_TWRITE Aneesh Kumar K.V
@ 2010-03-16  9:15 ` Aneesh Kumar K.V
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 11/22] virtio-9p: Implement P9_TWSTAT Aneesh Kumar K.V
                   ` (12 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:15 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.273.gc2413

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

* [Qemu-devel] [PATCH -v2 11/22] virtio-9p: Implement P9_TWSTAT
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (9 preceding siblings ...)
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 10/22] virtio-9p: Implement P9_TCREATE Aneesh Kumar K.V
@ 2010-03-16  9:15 ` Aneesh Kumar K.V
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 12/22] virtio-9p: Implement P9_TREMOVE Aneesh Kumar K.V
                   ` (11 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:15 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.273.gc2413

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

* [Qemu-devel] [PATCH -v2 12/22] virtio-9p: Implement P9_TREMOVE
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (10 preceding siblings ...)
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 11/22] virtio-9p: Implement P9_TWSTAT Aneesh Kumar K.V
@ 2010-03-16  9:15 ` Aneesh Kumar K.V
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 13/22] virtio-9p: Implement P9_TFLUSH Aneesh Kumar K.V
                   ` (10 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:15 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.273.gc2413

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

* [Qemu-devel] [PATCH -v2 13/22] virtio-9p: Implement P9_TFLUSH
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (11 preceding siblings ...)
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 12/22] virtio-9p: Implement P9_TREMOVE Aneesh Kumar K.V
@ 2010-03-16  9:15 ` Aneesh Kumar K.V
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 14/22] virtio-9p: Add multiple mount point support Aneesh Kumar K.V
                   ` (9 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:15 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.273.gc2413

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

* [Qemu-devel] [PATCH -v2 14/22] virtio-9p: Add multiple mount point support
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (12 preceding siblings ...)
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 13/22] virtio-9p: Implement P9_TFLUSH Aneesh Kumar K.V
@ 2010-03-16  9:15 ` Aneesh Kumar K.V
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 15/22] virtio-9p: Use little endian format on virtio Aneesh Kumar K.V
                   ` (8 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:15 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 228dded..859f610 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.273.gc2413

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

* [Qemu-devel] [PATCH -v2 15/22] virtio-9p: Use little endian format on virtio
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (13 preceding siblings ...)
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 14/22] virtio-9p: Add multiple mount point support Aneesh Kumar K.V
@ 2010-03-16  9:15 ` Aneesh Kumar K.V
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 16/22] virtio-9p: Add support for hardlink Aneesh Kumar K.V
                   ` (7 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:15 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.273.gc2413

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

* [Qemu-devel] [PATCH -v2 16/22] virtio-9p: Add support for hardlink
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (14 preceding siblings ...)
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 15/22] virtio-9p: Use little endian format on virtio Aneesh Kumar K.V
@ 2010-03-16  9:15 ` Aneesh Kumar K.V
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 17/22] Implement sync support in 9p server Aneesh Kumar K.V
                   ` (6 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:15 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.273.gc2413

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

* [Qemu-devel] [PATCH -v2 17/22] Implement sync support in 9p server
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (15 preceding siblings ...)
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 16/22] virtio-9p: Add support for hardlink Aneesh Kumar K.V
@ 2010-03-16  9:15 ` Aneesh Kumar K.V
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 18/22] virtio-9p: Fix sg usage in the code Aneesh Kumar K.V
                   ` (5 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:15 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.273.gc2413

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

* [Qemu-devel] [PATCH -v2 18/22] virtio-9p: Fix sg usage in the code
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (16 preceding siblings ...)
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 17/22] Implement sync support in 9p server Aneesh Kumar K.V
@ 2010-03-16  9:15 ` Aneesh Kumar K.V
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 19/22] virtio-9p: Get the correct count values from the pdu Aneesh Kumar K.V
                   ` (4 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:15 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.273.gc2413

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

* [Qemu-devel] [PATCH -v2 19/22] virtio-9p: Get the correct count values from the pdu
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (17 preceding siblings ...)
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 18/22] virtio-9p: Fix sg usage in the code Aneesh Kumar K.V
@ 2010-03-16  9:15 ` Aneesh Kumar K.V
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 20/22] virtio-9p: Remove BUG_ON and add proper error handling Aneesh Kumar K.V
                   ` (3 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:15 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.273.gc2413

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

* [Qemu-devel] [PATCH -v2 20/22] virtio-9p: Remove BUG_ON and add proper error handling
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (18 preceding siblings ...)
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 19/22] virtio-9p: Get the correct count values from the pdu Aneesh Kumar K.V
@ 2010-03-16  9:15 ` Aneesh Kumar K.V
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 21/22] virtio-9p: Remove unnecessary definition of fid Aneesh Kumar K.V
                   ` (2 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:15 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.273.gc2413

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

* [Qemu-devel] [PATCH -v2 21/22] virtio-9p: Remove unnecessary definition of fid
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (19 preceding siblings ...)
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 20/22] virtio-9p: Remove BUG_ON and add proper error handling Aneesh Kumar K.V
@ 2010-03-16  9:15 ` Aneesh Kumar K.V
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 22/22] virtio-9p: Update existing fid path on rename Aneesh Kumar K.V
  2010-03-23 23:17 ` [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Luiz Capitulino
  22 siblings, 0 replies; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:15 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.273.gc2413

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

* [Qemu-devel] [PATCH -v2 22/22] virtio-9p: Update existing fid path on rename
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (20 preceding siblings ...)
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 21/22] virtio-9p: Remove unnecessary definition of fid Aneesh Kumar K.V
@ 2010-03-16  9:15 ` Aneesh Kumar K.V
  2010-03-23 23:17 ` [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Luiz Capitulino
  22 siblings, 0 replies; 32+ messages in thread
From: Aneesh Kumar K.V @ 2010-03-16  9:15 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.273.gc2413

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

* Re: [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough
  2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (21 preceding siblings ...)
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 22/22] virtio-9p: Update existing fid path on rename Aneesh Kumar K.V
@ 2010-03-23 23:17 ` Luiz Capitulino
  2010-03-24  3:58   ` Aneesh Kumar K. V
  22 siblings, 1 reply; 32+ messages in thread
From: Luiz Capitulino @ 2010-03-23 23:17 UTC (permalink / raw)
  To: Aneesh Kumar K.V; +Cc: ericvh, aliguori, qemu-devel

On Tue, 16 Mar 2010 14:44:58 +0530
"Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> wrote:

> Hi,
> 
> 
> 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.
> 
> -device virtio-9p-pci,share_path=/mnt/,mount_tag=v_mnt
> 
> 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.

 I tried this very '-device' line and I can see that the guest has loaded
the virtio modules, but there isn't anything in the virtio0 directory other
than standard sysfs files.

 Is there a way to debug this?

 Something possibly related is that, I had to rewind the tree by some commits
because this series doesn't apply against current HEAD.

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

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

* Re: [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough
  2010-03-23 23:17 ` [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Luiz Capitulino
@ 2010-03-24  3:58   ` Aneesh Kumar K. V
  2010-03-24 15:04     ` Luiz Capitulino
  0 siblings, 1 reply; 32+ messages in thread
From: Aneesh Kumar K. V @ 2010-03-24  3:58 UTC (permalink / raw)
  To: Luiz Capitulino; +Cc: ericvh, aliguori, qemu-devel

On Tue, 23 Mar 2010 20:17:33 -0300, Luiz Capitulino <lcapitulino@redhat.com> wrote:
> On Tue, 16 Mar 2010 14:44:58 +0530
> "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> wrote:
> 
> > Hi,
> > 
> > 
> > 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.
> > 
> > -device virtio-9p-pci,share_path=/mnt/,mount_tag=v_mnt
> > 
> > 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.
> 
>  I tried this very '-device' line and I can see that the guest has loaded
> the virtio modules, but there isn't anything in the virtio0 directory other
> than standard sysfs files.
> 
>  Is there a way to debug this?
> 

which version of the kernel ? The latest linus tree have all the needed
changes. You should have  /sys/bus/virtio/drivers/9pnet_virtio/ if you
have CONFIG_NET_9P_VIRTIO enabled. You can then find mount tag at
virtio<n>/mount_tag 


>  Something possibly related is that, I had to rewind the tree by some commits
> because this series doesn't apply against current HEAD.



The patches are against 0aef4261ac0ec9089ade0e3a92f986cb4ba7317e of the
master branch 


-aneesh

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

* Re: [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough
  2010-03-24  3:58   ` Aneesh Kumar K. V
@ 2010-03-24 15:04     ` Luiz Capitulino
  0 siblings, 0 replies; 32+ messages in thread
From: Luiz Capitulino @ 2010-03-24 15:04 UTC (permalink / raw)
  To: Aneesh Kumar K. V; +Cc: ericvh, aliguori, qemu-devel

On Wed, 24 Mar 2010 09:28:36 +0530
"Aneesh Kumar K. V" <aneesh.kumar@linux.vnet.ibm.com> wrote:

> On Tue, 23 Mar 2010 20:17:33 -0300, Luiz Capitulino <lcapitulino@redhat.com> wrote:
> > On Tue, 16 Mar 2010 14:44:58 +0530
> > "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> wrote:
> > 
> > > Hi,
> > > 
> > > 
> > > 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.
> > > 
> > > -device virtio-9p-pci,share_path=/mnt/,mount_tag=v_mnt
> > > 
> > > 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.
> > 
> >  I tried this very '-device' line and I can see that the guest has loaded
> > the virtio modules, but there isn't anything in the virtio0 directory other
> > than standard sysfs files.
> > 
> >  Is there a way to debug this?
> > 
> 
> which version of the kernel ? 

2.6.31.5

> The latest linus tree have all the needed
> changes. You should have  /sys/bus/virtio/drivers/9pnet_virtio/ if you
> have CONFIG_NET_9P_VIRTIO enabled.

 I have it, but still no mount_tag. I'll try with a more recent
kernel but this will take more time.

> You can then find mount tag at virtio<n>/mount_tag 
> 
> 
> >  Something possibly related is that, I had to rewind the tree by some commits
> > because this series doesn't apply against current HEAD.
> 
> 
> 
> The patches are against 0aef4261ac0ec9089ade0e3a92f986cb4ba7317e of the
> master branch 
> 
> 
> -aneesh

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

* Re: [Qemu-devel] [PATCH -v2 02/22] vrtio-9p: Implement P9_TVERSION for 9P
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 02/22] vrtio-9p: Implement P9_TVERSION for 9P Aneesh Kumar K.V
@ 2010-03-26 16:15   ` Anthony Liguori
  2010-03-29  7:01     ` Aneesh Kumar K. V
  0 siblings, 1 reply; 32+ messages in thread
From: Anthony Liguori @ 2010-03-26 16:15 UTC (permalink / raw)
  To: Aneesh Kumar K.V; +Cc: ericvh, aliguori, qemu-devel

On 03/16/2010 04:15 AM, Aneesh Kumar K.V wrote:
> 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);
>    

qemu_free.
> +    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;
> +}
>    

Adding the marshalling in  patch to implement P9_TVERSION is probably 
not ideal.

Regards,

Anthony Liguori

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

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

* Re: [Qemu-devel] [PATCH -v2 03/22] virtio-9p: Implement P9_TATTACH
  2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 03/22] virtio-9p: Implement P9_TATTACH Aneesh Kumar K.V
@ 2010-03-26 16:17   ` Anthony Liguori
  2010-03-26 19:12     ` jvrao
  2010-03-26 20:06     ` jvrao
  0 siblings, 2 replies; 32+ messages in thread
From: Anthony Liguori @ 2010-03-26 16:17 UTC (permalink / raw)
  To: Aneesh Kumar K.V; +Cc: ericvh, aliguori, qemu-devel

On 03/16/2010 04:15 AM, Aneesh Kumar K.V wrote:
> 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 33f9fcb..97f32a9 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -172,7 +172,7 @@ obj-y = vl.o async.o monitor.o pci.o pci_host.o pcie_host.o machine.o gdbstub.o
>   # virtio has to be here due to weird dependency between PCI and virtio-net.
>   # need to fix this properly
>   obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-pci.o virtio-serial-bus.o
> -obj-y += virtio-9p.o virtio-9p-debug.o
> +obj-y += virtio-9p.o virtio-9p-debug.o virtio-9p-local.o
>   obj-y += rwhandler.o
>   obj-$(CONFIG_KVM) += kvm.o kvm-all.o
>   obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
> diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
> new file mode 100644
> index 0000000..1d2523b
> --- /dev/null
> +++ b/hw/virtio-9p-local.c
>    

This should be a logically separate patch.

> @@ -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>
>    

These headers are almost certainly going to break the build on windows.  
Some care is needed here.

> +
> +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 805be1a..ebe7088 100644
> --- a/qemu-common.h
> +++ b/qemu-common.h
> @@ -159,6 +159,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);
> +}
>    

asprintf() is not universally available so it cannot be wrapped this 
naively.

Regards,

Anthony Liguori

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

* Re: [Qemu-devel] [PATCH -v2 03/22] virtio-9p: Implement P9_TATTACH
  2010-03-26 16:17   ` Anthony Liguori
@ 2010-03-26 19:12     ` jvrao
  2010-03-26 20:06     ` jvrao
  1 sibling, 0 replies; 32+ messages in thread
From: jvrao @ 2010-03-26 19:12 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: ericvh, aliguori, Aneesh Kumar K.V, qemu-devel

Anthony Liguori wrote:
> On 03/16/2010 04:15 AM, Aneesh Kumar K.V wrote:
>> 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 33f9fcb..97f32a9 100644
>> --- a/Makefile.target
>> +++ b/Makefile.target
>> @@ -172,7 +172,7 @@ obj-y = vl.o async.o monitor.o pci.o pci_host.o
>> pcie_host.o machine.o gdbstub.o
>>   # virtio has to be here due to weird dependency between PCI and
>> virtio-net.
>>   # need to fix this properly
>>   obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-pci.o
>> virtio-serial-bus.o
>> -obj-y += virtio-9p.o virtio-9p-debug.o
>> +obj-y += virtio-9p.o virtio-9p-debug.o virtio-9p-local.o
>>   obj-y += rwhandler.o
>>   obj-$(CONFIG_KVM) += kvm.o kvm-all.o
>>   obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
>> diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
>> new file mode 100644
>> index 0000000..1d2523b
>> --- /dev/null
>> +++ b/hw/virtio-9p-local.c
>>    
> 
> This should be a logically separate patch.
> 
>> @@ -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>
>>    
> 
> These headers are almost certainly going to break the build on windows. 
> Some care is needed here.
> 
>> +
>> +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 805be1a..ebe7088 100644
>> --- a/qemu-common.h
>> +++ b/qemu-common.h
>> @@ -159,6 +159,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);
>> +}
>>    
> 
> asprintf() is not universally available so it cannot be wrapped this
> naively.

Is there a way to find out what is generally available..and what is not?
I know QEMU need to work with different OSes, do we have OS specific plug-ins
to address these OS specific/dependent calls? 

Thanks,
JV

 
> 
> Regards,
> 
> Anthony Liguori
> 
> 
> 

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

* Re: [Qemu-devel] [PATCH -v2 03/22] virtio-9p: Implement P9_TATTACH
  2010-03-26 16:17   ` Anthony Liguori
  2010-03-26 19:12     ` jvrao
@ 2010-03-26 20:06     ` jvrao
  1 sibling, 0 replies; 32+ messages in thread
From: jvrao @ 2010-03-26 20:06 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: ericvh, aliguori, Aneesh Kumar K.V, qemu-devel

Anthony Liguori wrote:
> On 03/16/2010 04:15 AM, Aneesh Kumar K.V wrote:
>> 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 33f9fcb..97f32a9 100644
>> --- a/Makefile.target
>> +++ b/Makefile.target
>> @@ -172,7 +172,7 @@ obj-y = vl.o async.o monitor.o pci.o pci_host.o
>> pcie_host.o machine.o gdbstub.o
>>   # virtio has to be here due to weird dependency between PCI and
>> virtio-net.
>>   # need to fix this properly
>>   obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-pci.o
>> virtio-serial-bus.o
>> -obj-y += virtio-9p.o virtio-9p-debug.o
>> +obj-y += virtio-9p.o virtio-9p-debug.o virtio-9p-local.o
>>   obj-y += rwhandler.o
>>   obj-$(CONFIG_KVM) += kvm.o kvm-all.o
>>   obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
>> diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
>> new file mode 100644
>> index 0000000..1d2523b
>> --- /dev/null
>> +++ b/hw/virtio-9p-local.c
>>    
> 
> This should be a logically separate patch.
> 
>> @@ -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>
>>    
> 
> These headers are almost certainly going to break the build on windows. 
> Some care is needed here.

I don't think we are going to build this on Windows. Will it be OK if we
make changes to Makefile so that it is valid only on Linux?

Thanks,
JV



> 
>> +
>> +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 805be1a..ebe7088 100644
>> --- a/qemu-common.h
>> +++ b/qemu-common.h
>> @@ -159,6 +159,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);
>> +}
>>    
> 
> asprintf() is not universally available so it cannot be wrapped this
> naively.
> 
> Regards,
> 
> Anthony Liguori
> 
> 
> 

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

* Re: [Qemu-devel] [PATCH -v2 02/22] vrtio-9p: Implement P9_TVERSION for 9P
  2010-03-26 16:15   ` Anthony Liguori
@ 2010-03-29  7:01     ` Aneesh Kumar K. V
  2010-03-29 14:51       ` Anthony Liguori
  0 siblings, 1 reply; 32+ messages in thread
From: Aneesh Kumar K. V @ 2010-03-29  7:01 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: ericvh, aliguori, qemu-devel

On Fri, 26 Mar 2010 11:15:47 -0500, Anthony Liguori <aliguori@linux.vnet.ibm.com> wrote:
> On 03/16/2010 04:15 AM, Aneesh Kumar K.V wrote:
> > 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);
> >    
> 
> qemu_free.
> > +    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;
> > +}
> >    
> 
> Adding the marshalling in  patch to implement P9_TVERSION is probably 
> not ideal.
> 

Qemu Makefile rules won't allow to add functions that are not used. The
error checking is strict. So there is not an easy way i can add these
functional logically and let each of the changeset successfully build.
Any suggestions how to do the above ?

-aneesh

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

* Re: [Qemu-devel] [PATCH -v2 02/22] vrtio-9p: Implement P9_TVERSION for 9P
  2010-03-29  7:01     ` Aneesh Kumar K. V
@ 2010-03-29 14:51       ` Anthony Liguori
  0 siblings, 0 replies; 32+ messages in thread
From: Anthony Liguori @ 2010-03-29 14:51 UTC (permalink / raw)
  To: Aneesh Kumar K. V; +Cc: ericvh, Anthony Liguori, qemu-devel

On 03/29/2010 02:01 AM, Aneesh Kumar K. V wrote:
> On Fri, 26 Mar 2010 11:15:47 -0500, Anthony Liguori<aliguori@linux.vnet.ibm.com>  wrote:
>    
>> On 03/16/2010 04:15 AM, Aneesh Kumar K.V wrote:
>>      
>>> 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);
>>>
>>>        
>> qemu_free.
>>      
>>> +    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;
>>> +}
>>>
>>>        
>> Adding the marshalling in  patch to implement P9_TVERSION is probably
>> not ideal.
>>
>>      
> Qemu Makefile rules won't allow to add functions that are not used. The
> error checking is strict. So there is not an easy way i can add these
> functional logically and let each of the changeset successfully build.
>    

Something like (void)pdu_marshal; should keep GCC happy.

Regards,

Anthony Liguori

> Any suggestions how to do the above ?
>
> -aneesh
>    

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

end of thread, other threads:[~2010-03-29 14:51 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-16  9:14 [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
2010-03-16  9:14 ` [Qemu-devel] [PATCH -v2 01/22] vitio-9p: Add a virtio 9p device to qemu Aneesh Kumar K.V
2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 02/22] vrtio-9p: Implement P9_TVERSION for 9P Aneesh Kumar K.V
2010-03-26 16:15   ` Anthony Liguori
2010-03-29  7:01     ` Aneesh Kumar K. V
2010-03-29 14:51       ` Anthony Liguori
2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 03/22] virtio-9p: Implement P9_TATTACH Aneesh Kumar K.V
2010-03-26 16:17   ` Anthony Liguori
2010-03-26 19:12     ` jvrao
2010-03-26 20:06     ` jvrao
2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 04/22] virtio-9p: Implement P9_TSTAT Aneesh Kumar K.V
2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 05/22] virtio-9p: Implement P9_TWALK Aneesh Kumar K.V
2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 06/22] virtio-9p: Implement P9_TOPEN Aneesh Kumar K.V
2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 07/22] virtio-9p: Implement P9_TREAD Aneesh Kumar K.V
2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 08/22] virtio-9p: Implement P9_TCLUNK Aneesh Kumar K.V
2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 09/22] virtio-9p: Implement P9_TWRITE Aneesh Kumar K.V
2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 10/22] virtio-9p: Implement P9_TCREATE Aneesh Kumar K.V
2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 11/22] virtio-9p: Implement P9_TWSTAT Aneesh Kumar K.V
2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 12/22] virtio-9p: Implement P9_TREMOVE Aneesh Kumar K.V
2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 13/22] virtio-9p: Implement P9_TFLUSH Aneesh Kumar K.V
2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 14/22] virtio-9p: Add multiple mount point support Aneesh Kumar K.V
2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 15/22] virtio-9p: Use little endian format on virtio Aneesh Kumar K.V
2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 16/22] virtio-9p: Add support for hardlink Aneesh Kumar K.V
2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 17/22] Implement sync support in 9p server Aneesh Kumar K.V
2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 18/22] virtio-9p: Fix sg usage in the code Aneesh Kumar K.V
2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 19/22] virtio-9p: Get the correct count values from the pdu Aneesh Kumar K.V
2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 20/22] virtio-9p: Remove BUG_ON and add proper error handling Aneesh Kumar K.V
2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 21/22] virtio-9p: Remove unnecessary definition of fid Aneesh Kumar K.V
2010-03-16  9:15 ` [Qemu-devel] [PATCH -v2 22/22] virtio-9p: Update existing fid path on rename Aneesh Kumar K.V
2010-03-23 23:17 ` [Qemu-devel] [PATCH -V2 00/22] virtio-9p: paravirtual file system passthrough Luiz Capitulino
2010-03-24  3:58   ` Aneesh Kumar K. V
2010-03-24 15:04     ` Luiz Capitulino

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.