All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough
@ 2010-03-03 19:00 Anthony Liguori
  2010-03-03 19:00 ` Anthony Liguori
                   ` (17 more replies)
  0 siblings, 18 replies; 28+ messages in thread
From: Anthony Liguori @ 2010-03-03 19:00 UTC (permalink / raw)
  To: qemu-devel
  Cc: Eric Van Hensbergen, M. Mohan Kumar, Venkateswararao Jujjuri,
	Aneesh Kumar K.V.,
	Gautham R Shenoy

This patch series adds a paravirtual file system passthrough mechanism to QEMU
based on the 9P protocol.  This an RFC series with a few known issues.  Right
now, 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 but we wanted to
send out the series for initial review before completing that work.

We also do not have a very good mechanism for specifying the share path.
Suggestions would be welcome here.

This patch set should work with any recent Linux kernel as virtio-9p has been
supported for a few kernel releases now.

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

* [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough
  2010-03-03 19:00 [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough Anthony Liguori
@ 2010-03-03 19:00 ` Anthony Liguori
  2010-03-03 19:00 ` [Qemu-devel] [PATCH 01/17] vitio-9p: Add a virtio 9p device to qemu Anthony Liguori
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: Anthony Liguori @ 2010-03-03 19:00 UTC (permalink / raw)
  To: qemu-devel
  Cc: Eric Van Hensbergen, M. Mohan Kumar, Venkateswararao Jujjuri,
	Aneesh Kumar K.V.,
	Gautham R Shenoy

This is a refresh of an older series 

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

* [Qemu-devel] [PATCH 01/17] vitio-9p: Add a virtio 9p device to qemu
  2010-03-03 19:00 [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough Anthony Liguori
  2010-03-03 19:00 ` Anthony Liguori
@ 2010-03-03 19:00 ` Anthony Liguori
  2010-03-03 19:00 ` [Qemu-devel] [PATCH 02/17] vrtio-9p: Implement P9_TVERSION for 9P Anthony Liguori
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: Anthony Liguori @ 2010-03-03 19:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Aneesh Kumar K.V

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 4c4d397..8f240ea 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -173,6 +173,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..060337f
--- /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..93402c5
--- /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..3945f81
--- /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 bcd40f7..f837376 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;
@@ -551,6 +552,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",
@@ -604,6 +620,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.6.5.2

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

* [Qemu-devel] [PATCH 02/17] vrtio-9p: Implement P9_TVERSION for 9P
  2010-03-03 19:00 [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough Anthony Liguori
  2010-03-03 19:00 ` Anthony Liguori
  2010-03-03 19:00 ` [Qemu-devel] [PATCH 01/17] vitio-9p: Add a virtio 9p device to qemu Anthony Liguori
@ 2010-03-03 19:00 ` Anthony Liguori
  2010-03-04  9:23   ` [Qemu-devel] " Michael S. Tsirkin
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 03/17] virtio-9p: Implement P9_TATTACH Anthony Liguori
                   ` (14 subsequent siblings)
  17 siblings, 1 reply; 28+ messages in thread
From: Anthony Liguori @ 2010-03-03 19:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Aneesh Kumar K.V

[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, 262 insertions(+), 1 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 93402c5..a057fbb 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -111,10 +111,271 @@ static void free_pdu(V9fsState *s, V9fsPDU *pdu)
     }
 }
 
-static void v9fs_version(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;
+
     if (debug_9p_pdu)
 	pprint_pdu(pdu);
+
+    /* 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)
+{
+    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.6.5.2

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

* [Qemu-devel] [PATCH 03/17] virtio-9p: Implement P9_TATTACH
  2010-03-03 19:00 [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough Anthony Liguori
                   ` (2 preceding siblings ...)
  2010-03-03 19:00 ` [Qemu-devel] [PATCH 02/17] vrtio-9p: Implement P9_TVERSION for 9P Anthony Liguori
@ 2010-03-03 19:01 ` Anthony Liguori
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 04/17] virtio-9p: Implement P9_TSTAT Anthony Liguori
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: Anthony Liguori @ 2010-03-03 19:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Aneesh Kumar K.V

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 +++++++++++
 4 files changed, 264 insertions(+), 10 deletions(-)
 create mode 100644 hw/virtio-9p-local.c

diff --git a/Makefile.target b/Makefile.target
index 8f240ea..ff5fc4b 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -173,7 +173,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..204437c
--- /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 a057fbb..c63ac80 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)
+{
+    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 = 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;
@@ -380,8 +491,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)
@@ -530,6 +666,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 3945f81..10a084a 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
-- 
1.6.5.2

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

* [Qemu-devel] [PATCH 04/17] virtio-9p: Implement P9_TSTAT
  2010-03-03 19:00 [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough Anthony Liguori
                   ` (3 preceding siblings ...)
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 03/17] virtio-9p: Implement P9_TATTACH Anthony Liguori
@ 2010-03-03 19:01 ` Anthony Liguori
  2010-03-03 20:35   ` malc
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 05/17] virtio-9p: Implement P9_TWALK Anthony Liguori
                   ` (12 subsequent siblings)
  17 siblings, 1 reply; 28+ messages in thread
From: Anthony Liguori @ 2010-03-03 19:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Aneesh Kumar K.V, Gautham R Shenoy

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 204437c..9752f76 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 c63ac80..10bcd89 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)
 {
     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;
@@ -436,6 +461,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 */
@@ -474,6 +508,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;
@@ -520,10 +636,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.6.5.2

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

* [Qemu-devel] [PATCH 05/17] virtio-9p: Implement P9_TWALK
  2010-03-03 19:00 [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough Anthony Liguori
                   ` (4 preceding siblings ...)
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 04/17] virtio-9p: Implement P9_TSTAT Anthony Liguori
@ 2010-03-03 19:01 ` Anthony Liguori
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 06/17] virtio-9p: Implement P9_TOPEN Anthony Liguori
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: Anthony Liguori @ 2010-03-03 19:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Aneesh Kumar K.V, Gautham R Shenoy

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 9752f76..ac0dce5 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 10bcd89..685646a 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)
 {
     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
 
@@ -691,10 +738,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.6.5.2

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

* [Qemu-devel] [PATCH 06/17] virtio-9p: Implement P9_TOPEN
  2010-03-03 19:00 [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough Anthony Liguori
                   ` (5 preceding siblings ...)
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 05/17] virtio-9p: Implement P9_TWALK Anthony Liguori
@ 2010-03-03 19:01 ` Anthony Liguori
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 07/17] virtio-9p: Implement P9_TREAD Anthony Liguori
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: Anthony Liguori @ 2010-03-03 19:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Aneesh Kumar K.V, Gautham R Shenoy

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       |  141 ++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 149 insertions(+), 4 deletions(-)

diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index ac0dce5..803b0ea 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 685646a..7709e4c 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;
@@ -912,14 +922,137 @@ 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_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)
-{    if (debug_9p_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);
 }
 
-- 
1.6.5.2

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

* [Qemu-devel] [PATCH 07/17] virtio-9p: Implement P9_TREAD
  2010-03-03 19:00 [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough Anthony Liguori
                   ` (6 preceding siblings ...)
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 06/17] virtio-9p: Implement P9_TOPEN Anthony Liguori
@ 2010-03-03 19:01 ` Anthony Liguori
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 08/17] virtio-9p: Implement P9_TCLUNK Anthony Liguori
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: Anthony Liguori @ 2010-03-03 19:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Venkateswararao Jujjuri, Aneesh Kumar K.V

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 803b0ea..90664a0 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 7709e4c..b30933a 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;
@@ -1050,14 +1081,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.6.5.2

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

* [Qemu-devel] [PATCH 08/17] virtio-9p: Implement P9_TCLUNK
  2010-03-03 19:00 [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough Anthony Liguori
                   ` (7 preceding siblings ...)
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 07/17] virtio-9p: Implement P9_TREAD Anthony Liguori
@ 2010-03-03 19:01 ` Anthony Liguori
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 09/17] virtio-9p: Implement P9_TWRITE Anthony Liguori
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: Anthony Liguori @ 2010-03-03 19:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Aneesh Kumar K.V

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 b30933a..7822a00 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -1305,8 +1305,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.6.5.2

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

* [Qemu-devel] [PATCH 09/17] virtio-9p: Implement P9_TWRITE
  2010-03-03 19:00 [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough Anthony Liguori
                   ` (8 preceding siblings ...)
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 08/17] virtio-9p: Implement P9_TCLUNK Anthony Liguori
@ 2010-03-03 19:01 ` Anthony Liguori
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 10/17] virtio-9p: Implement P9_TCREATE Anthony Liguori
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: Anthony Liguori @ 2010-03-03 19:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Venkateswararao Jujjuri, Aneesh Kumar K.V

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 90664a0..441d22d 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 7822a00..b0662ba 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;
@@ -1321,10 +1327,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.6.5.2

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

* [Qemu-devel] [PATCH 10/17] virtio-9p: Implement P9_TCREATE
  2010-03-03 19:00 [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough Anthony Liguori
                   ` (9 preceding siblings ...)
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 09/17] virtio-9p: Implement P9_TWRITE Anthony Liguori
@ 2010-03-03 19:01 ` Anthony Liguori
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 11/17] virtio-9p: Implement P9_TWSTAT Anthony Liguori
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: Anthony Liguori @ 2010-03-03 19:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Aneesh Kumar K.V, Gautham R Shenoy

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       |  267 +++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 345 insertions(+), 2 deletions(-)

diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 441d22d..606f5be 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 = strdup(rpath(oldpath));
+    int err, serrno = 0;
+
+    if (tmp == NULL)
+	return -ENOMEM;
+
+    err = link(tmp, rpath(newpath));
+    if (err == -1)
+	serrno = errno;
+
+    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 b0662ba..841fcde 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;
@@ -1420,10 +1461,232 @@ 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.6.5.2

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

* [Qemu-devel] [PATCH 11/17] virtio-9p: Implement P9_TWSTAT
  2010-03-03 19:00 [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough Anthony Liguori
                   ` (10 preceding siblings ...)
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 10/17] virtio-9p: Implement P9_TCREATE Anthony Liguori
@ 2010-03-03 19:01 ` Anthony Liguori
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 12/17] virtio-9p: Implement P9_TREMOVE Anthony Liguori
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: Anthony Liguori @ 2010-03-03 19:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Aneesh Kumar K.V, Gautham R Shenoy

This gets file and directory creation to work

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 606f5be..0a9f111 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 = strdup(rpath(oldpath));
+    if (tmp == NULL)
+	return -1;
+
+    err = rename(tmp, rpath(newpath));
+    if (err == -1) {
+	int serrno = errno;
+	free(tmp);
+	errno = serrno;
+    } else
+	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 841fcde..836d65b 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;
@@ -1615,7 +1638,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);
         }
@@ -1701,10 +1725,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.6.5.2

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

* [Qemu-devel] [PATCH 12/17] virtio-9p: Implement P9_TREMOVE
  2010-03-03 19:00 [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough Anthony Liguori
                   ` (11 preceding siblings ...)
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 11/17] virtio-9p: Implement P9_TWSTAT Anthony Liguori
@ 2010-03-03 19:01 ` Anthony Liguori
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 13/17] virtio-9p: Implement P9_TFLUSH Anthony Liguori
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: Anthony Liguori @ 2010-03-03 19:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Aneesh Kumar K.V, Gautham R Shenoy

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 0a9f111..43867be 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 836d65b..50ee82a 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;
@@ -1719,10 +1724,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.6.5.2

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

* [Qemu-devel] [PATCH 13/17] virtio-9p: Implement P9_TFLUSH
  2010-03-03 19:00 [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough Anthony Liguori
                   ` (12 preceding siblings ...)
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 12/17] virtio-9p: Implement P9_TREMOVE Anthony Liguori
@ 2010-03-03 19:01 ` Anthony Liguori
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 14/17] virtio-9p: Add multiple mount point support Anthony Liguori
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: Anthony Liguori @ 2010-03-03 19:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Aneesh Kumar K.V

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 50ee82a..72e0339 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -1720,10 +1720,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.6.5.2

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

* [Qemu-devel] [PATCH 14/17] virtio-9p: Add multiple mount point support
  2010-03-03 19:00 [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough Anthony Liguori
                   ` (13 preceding siblings ...)
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 13/17] virtio-9p: Implement P9_TFLUSH Anthony Liguori
@ 2010-03-03 19:01 ` Anthony Liguori
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 15/17] virtio-9p: Use little endian format on virtio Anthony Liguori
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: Anthony Liguori @ 2010-03-03 19:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: Aneesh Kumar K.V

From: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>

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 |   97 ++++++++++++------------
 hw/virtio-9p.c       |  204 ++++++++++++++++++++++++-------------------------
 hw/virtio-9p.h       |  141 ++++++++++++++++++++++++++++-------
 hw/virtio-pci.c      |    8 +-
 hw/virtio.h          |    3 +-
 6 files changed, 293 insertions(+), 186 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 43867be..d89a735 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,
+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 = strdup(rpath(oldpath));
+    char *tmp = 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 = strdup(rpath(oldpath));
+    tmp = 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;
 	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;
 }
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 72e0339..97fcb8a 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)
@@ -787,7 +717,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);
@@ -2048,17 +1978,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));
+				    sizeof(struct virtio_9p_config)+
+				    MAX_TAG_LEN,
+				    sizeof(V9fsState));
 
     /* initialize pdu allocator */
     s->free_pdu = &s->pdus[0];
@@ -2069,12 +2040,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 = 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 10a084a..42ca887 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 f837376..e48a49d 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;
@@ -557,7 +556,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,
@@ -625,7 +624,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.6.5.2

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

* [Qemu-devel] [PATCH 15/17] virtio-9p: Use little endian format on virtio
  2010-03-03 19:00 [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough Anthony Liguori
                   ` (14 preceding siblings ...)
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 14/17] virtio-9p: Add multiple mount point support Anthony Liguori
@ 2010-03-03 19:01 ` Anthony Liguori
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 16/17] virtio-9p: Add support for hardlink Anthony Liguori
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 17/17] Implement sync support in 9p server Anthony Liguori
  17 siblings, 0 replies; 28+ messages in thread
From: Anthony Liguori @ 2010-03-03 19:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: Aneesh Kumar K.V

From: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>

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 97fcb8a..65f5827 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -425,23 +425,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': {
@@ -497,22 +506,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.6.5.2

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

* [Qemu-devel] [PATCH 16/17] virtio-9p: Add support for hardlink
  2010-03-03 19:00 [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough Anthony Liguori
                   ` (15 preceding siblings ...)
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 15/17] virtio-9p: Use little endian format on virtio Anthony Liguori
@ 2010-03-03 19:01 ` Anthony Liguori
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 17/17] Implement sync support in 9p server Anthony Liguori
  17 siblings, 0 replies; 28+ messages in thread
From: Anthony Liguori @ 2010-03-03 19:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: Aneesh Kumar K.V

From: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>

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 65f5827..8a96645 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -676,6 +676,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.6.5.2

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

* [Qemu-devel] [PATCH 17/17] Implement sync support in 9p server
  2010-03-03 19:00 [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough Anthony Liguori
                   ` (16 preceding siblings ...)
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 16/17] virtio-9p: Add support for hardlink Anthony Liguori
@ 2010-03-03 19:01 ` Anthony Liguori
  17 siblings, 0 replies; 28+ messages in thread
From: Anthony Liguori @ 2010-03-03 19:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: 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.

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       |   34 ++++++++++++++++++++++++++++++++++
 hw/virtio-9p.h       |    1 +
 3 files changed, 41 insertions(+), 0 deletions(-)

diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index d89a735..4317ea3 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 8a96645..94c9c58 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;
@@ -1892,6 +1897,29 @@ out:
     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;
@@ -1909,6 +1937,12 @@ static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
 	goto out;
     }
 
+    /* do we need to sync the file? */
+    if (donttouch_stat(&vs->v9stat)) {
+        posix_fsync(s, vs->fidp->fd);
+        goto out;
+    }
+
     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 42ca887..113b0d5 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.6.5.2

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

* Re: [Qemu-devel] [PATCH 04/17] virtio-9p: Implement P9_TSTAT
  2010-03-03 19:01 ` [Qemu-devel] [PATCH 04/17] virtio-9p: Implement P9_TSTAT Anthony Liguori
@ 2010-03-03 20:35   ` malc
  2010-03-04 14:15     ` Aneesh Kumar K. V
  0 siblings, 1 reply; 28+ messages in thread
From: malc @ 2010-03-03 20:35 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Gautham R Shenoy, qemu-devel, Aneesh Kumar K.V

On Wed, 3 Mar 2010, Anthony Liguori wrote:

> 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 204437c..9752f76 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 c63ac80..10bcd89 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)
>  {
>      free(str->data);

Should be qemu_free, no?

[..snip..]

-- 
mailto:av1474@comtv.ru

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

* [Qemu-devel] Re: [PATCH 02/17] vrtio-9p: Implement P9_TVERSION for 9P
  2010-03-03 19:00 ` [Qemu-devel] [PATCH 02/17] vrtio-9p: Implement P9_TVERSION for 9P Anthony Liguori
@ 2010-03-04  9:23   ` Michael S. Tsirkin
  2010-03-04 14:30     ` Aneesh Kumar K. V
  0 siblings, 1 reply; 28+ messages in thread
From: Michael S. Tsirkin @ 2010-03-04  9:23 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, Aneesh Kumar K.V

On Wed, Mar 03, 2010 at 01:00:59PM -0600, Anthony Liguori wrote:
> [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, 262 insertions(+), 1 deletions(-)
> 
> diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
> index 93402c5..a057fbb 100644
> --- a/hw/virtio-9p.c
> +++ b/hw/virtio-9p.c
> @@ -111,10 +111,271 @@ static void free_pdu(V9fsState *s, V9fsPDU *pdu)
>      }
>  }
>  
> -static void v9fs_version(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)

Is the point of this functuion to copy size bytes starting
at offset? Maybe generalize this to work on any iovec?

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

indentation by tabs.

> +
> +	if (offset >= off && offset < (off + sg[i].iov_len)) {

The above math might overflow. Not sure what the result will be.

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

Maybe generalize this to work on any iovec?

> +    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;
> +
>      if (debug_9p_pdu)
>  	pprint_pdu(pdu);
> +
> +    /* 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)
> +{
> +    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.6.5.2
> 
> 

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

* Re: [Qemu-devel] [PATCH 04/17] virtio-9p: Implement P9_TSTAT
  2010-03-03 20:35   ` malc
@ 2010-03-04 14:15     ` Aneesh Kumar K. V
  2010-03-09  2:08       ` jvrao
  0 siblings, 1 reply; 28+ messages in thread
From: Aneesh Kumar K. V @ 2010-03-04 14:15 UTC (permalink / raw)
  To: malc, Anthony Liguori; +Cc: qemu-devel, Gautham R Shenoy

On Wed, 3 Mar 2010 23:35:36 +0300 (MSK), malc <av1474@comtv.ru> wrote:
> On Wed, 3 Mar 2010, Anthony Liguori wrote:
> 
> > 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 204437c..9752f76 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 c63ac80..10bcd89 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)
> >  {
> >      free(str->data);
> 
> Should be qemu_free, no?
> 


Updated the patch

-aneesh

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

* [Qemu-devel] Re: [PATCH 02/17] vrtio-9p: Implement P9_TVERSION for 9P
  2010-03-04  9:23   ` [Qemu-devel] " Michael S. Tsirkin
@ 2010-03-04 14:30     ` Aneesh Kumar K. V
  0 siblings, 0 replies; 28+ messages in thread
From: Aneesh Kumar K. V @ 2010-03-04 14:30 UTC (permalink / raw)
  To: Michael S. Tsirkin, Anthony Liguori; +Cc: qemu-devel

On Thu, 4 Mar 2010 11:23:24 +0200, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> On Wed, Mar 03, 2010 at 01:00:59PM -0600, Anthony Liguori wrote:
> > [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, 262 insertions(+), 1 deletions(-)
> > 
> > diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
> > index 93402c5..a057fbb 100644
> > --- a/hw/virtio-9p.c
> > +++ b/hw/virtio-9p.c
> > @@ -111,10 +111,271 @@ static void free_pdu(V9fsState *s, V9fsPDU *pdu)
> >      }
> >  }
> >  
> > -static void v9fs_version(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)
> 
> Is the point of this functuion to copy size bytes starting
> at offset? Maybe generalize this to work on any iovec?

The 9p debug code also need a similar function. I have a bug fix patch
that make sure we use all the elem.out_num elements in elem.out_sg
array. That patch already does abstract this out for any iovec. But
still keep the function in virtio-9p.c.


> 
> > +{
> > +    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;
> 
> indentation by tabs.

Fixed

> 
> > +
> > +	if (offset >= off && offset < (off + sg[i].iov_len)) {
> 
> The above math might overflow. Not sure what the result will be.
> 
> > +	    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;
> 
> {}

Fixed 

> 
> > +    }
> > +
> > +    return copied;
> > +}
> > +
> > +static int pdu_copy_sg(V9fsPDU *pdu, size_t offset, int rx, struct iovec *sg)
> > +{
> 
> Maybe generalize this to work on any iovec?
> 
> > +    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;

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

* Re: [Qemu-devel] [PATCH 04/17] virtio-9p: Implement P9_TSTAT
  2010-03-04 14:15     ` Aneesh Kumar K. V
@ 2010-03-09  2:08       ` jvrao
  2010-03-09 12:30         ` Paul Brook
  0 siblings, 1 reply; 28+ messages in thread
From: jvrao @ 2010-03-09  2:08 UTC (permalink / raw)
  To: Aneesh Kumar K. V; +Cc: Anthony Liguori, qemu-devel, Gautham R Shenoy

Aneesh Kumar K. V wrote:
> On Wed, 3 Mar 2010 23:35:36 +0300 (MSK), malc <av1474@comtv.ru> wrote:
>> On Wed, 3 Mar 2010, Anthony Liguori wrote:
>>
>>> 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 204437c..9752f76 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 c63ac80..10bcd89 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)
>>>  {
>>>      free(str->data);
>> Should be qemu_free, no?
>>
> 
> 
> Updated the patch

Is  there any reason (other than being coding style) in using qemu_free() 
instead of free()? As per qem-malloc.c qemu_free() is nothing but free().

The reason I am asking is.. tracking string allocs become tricky 
if some of them were defined using qemu_alloc() and others are allocated through
sprintf().

Thanks,
JV


> 
> -aneesh
> 
> 

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

* Re: [Qemu-devel] [PATCH 04/17] virtio-9p: Implement P9_TSTAT
  2010-03-09  2:08       ` jvrao
@ 2010-03-09 12:30         ` Paul Brook
  2010-03-09 14:35           ` Aneesh Kumar K. V
  2010-03-09 15:59           ` jvrao
  0 siblings, 2 replies; 28+ messages in thread
From: Paul Brook @ 2010-03-09 12:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, jvrao, Aneesh Kumar K. V, Gautham R Shenoy

> Is  there any reason (other than being coding style) in using qemu_free()
> instead of free()? As per qem-malloc.c qemu_free() is nothing but free().

The whole point of qemu_{malloc,free} is to isolate code from the system 
implementation of malloc/free. It's entirely possible that future versions of 
qemu_malloc will use a different memory allocation strategy.
 
> The reason I am asking is.. tracking string allocs become tricky
> if some of them were defined using qemu_alloc() and others are allocated
>  through sprintf().

sprintf does not allocate memory.
If you mean strdup, then you shouldn't be using that (use qemu_strdup).

Paul

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

* Re: [Qemu-devel] [PATCH 04/17] virtio-9p: Implement P9_TSTAT
  2010-03-09 12:30         ` Paul Brook
@ 2010-03-09 14:35           ` Aneesh Kumar K. V
  2010-03-09 15:59           ` jvrao
  1 sibling, 0 replies; 28+ messages in thread
From: Aneesh Kumar K. V @ 2010-03-09 14:35 UTC (permalink / raw)
  To: Paul Brook, qemu-devel; +Cc: Anthony Liguori, jvrao, Gautham R Shenoy

On Tue, 9 Mar 2010 12:30:08 +0000, Paul Brook <paul@codesourcery.com> wrote:
> > Is  there any reason (other than being coding style) in using qemu_free()
> > instead of free()? As per qem-malloc.c qemu_free() is nothing but free().
> 
> The whole point of qemu_{malloc,free} is to isolate code from the system 
> implementation of malloc/free. It's entirely possible that future versions of 
> qemu_malloc will use a different memory allocation strategy.
> 
> > The reason I am asking is.. tracking string allocs become tricky
> > if some of them were defined using qemu_alloc() and others are allocated
> >  through sprintf().
> 
> sprintf does not allocate memory.
> If you mean strdup, then you shouldn't be using that (use qemu_strdup).

we have code that does

static void v9fs_string_sprintf(V9fsString *str, const char *fmt, ...)
{
    va_list ap;
    int err;

    v9fs_string_free(str);

    va_start(ap, fmt);
    err = vasprintf(&str->data, fmt, ap);
    BUG_ON(err == -1);
    va_end(ap);

    str->size = err;
}


I guess we should not be using vasprint. What alternatives are
available today ?

-aneesh

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

* Re: [Qemu-devel] [PATCH 04/17] virtio-9p: Implement P9_TSTAT
  2010-03-09 12:30         ` Paul Brook
  2010-03-09 14:35           ` Aneesh Kumar K. V
@ 2010-03-09 15:59           ` jvrao
  2010-03-11 16:37             ` Paul Brook
  1 sibling, 1 reply; 28+ messages in thread
From: jvrao @ 2010-03-09 15:59 UTC (permalink / raw)
  To: Paul Brook
  Cc: Anthony Liguori, Gautham R Shenoy, qemu-devel, Aneesh Kumar K. V

Paul Brook wrote:
>> Is  there any reason (other than being coding style) in using qemu_free()
>> instead of free()? As per qem-malloc.c qemu_free() is nothing but free().
> 
> The whole point of qemu_{malloc,free} is to isolate code from the system 
> implementation of malloc/free. It's entirely possible that future versions of 
> qemu_malloc will use a different memory allocation strategy.
> 
>> The reason I am asking is.. tracking string allocs become tricky
>> if some of them were defined using qemu_alloc() and others are allocated
>>  through sprintf().
> 
> sprintf does not allocate memory.
> If you mean strdup, then you shouldn't be using that (use qemu_strdup).

Thanks for correcting Paul.. I was talking about vasprintf() .. not really the sprintf()
In any case.. right way to do it may be adding a new qemu_vasprintf() for and use it
along with qemu_free() Right?

Thanks,
JV

> 
> Paul

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

* Re: [Qemu-devel] [PATCH 04/17] virtio-9p: Implement P9_TSTAT
  2010-03-09 15:59           ` jvrao
@ 2010-03-11 16:37             ` Paul Brook
  0 siblings, 0 replies; 28+ messages in thread
From: Paul Brook @ 2010-03-11 16:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, jvrao, Aneesh Kumar K. V, Gautham R Shenoy

> Paul Brook wrote:
> >> Is  there any reason (other than being coding style) in using
> >> qemu_free() instead of free()? As per qem-malloc.c qemu_free() is
> >> nothing but free().
> >
> > The whole point of qemu_{malloc,free} is to isolate code from the system
> > implementation of malloc/free. It's entirely possible that future
> > versions of qemu_malloc will use a different memory allocation strategy.
> >
> >> The reason I am asking is.. tracking string allocs become tricky
> >> if some of them were defined using qemu_alloc() and others are allocated
> >>  through sprintf().
> >
> > sprintf does not allocate memory.
> > If you mean strdup, then you shouldn't be using that (use qemu_strdup).
> 
> Thanks for correcting Paul.. I was talking about vasprintf() .. not really
>  the sprintf() In any case.. right way to do it may be adding a new
>  qemu_vasprintf() for and use it along with qemu_free() Right?

Something like that, yes.  Any use of [v]asprintf is incorrect.

Paul

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

end of thread, other threads:[~2010-03-11 16:48 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-03 19:00 [Qemu-devel] [PATCH 00/17][RFC] virtio-9p: paravirtual filesystem passthrough Anthony Liguori
2010-03-03 19:00 ` Anthony Liguori
2010-03-03 19:00 ` [Qemu-devel] [PATCH 01/17] vitio-9p: Add a virtio 9p device to qemu Anthony Liguori
2010-03-03 19:00 ` [Qemu-devel] [PATCH 02/17] vrtio-9p: Implement P9_TVERSION for 9P Anthony Liguori
2010-03-04  9:23   ` [Qemu-devel] " Michael S. Tsirkin
2010-03-04 14:30     ` Aneesh Kumar K. V
2010-03-03 19:01 ` [Qemu-devel] [PATCH 03/17] virtio-9p: Implement P9_TATTACH Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 04/17] virtio-9p: Implement P9_TSTAT Anthony Liguori
2010-03-03 20:35   ` malc
2010-03-04 14:15     ` Aneesh Kumar K. V
2010-03-09  2:08       ` jvrao
2010-03-09 12:30         ` Paul Brook
2010-03-09 14:35           ` Aneesh Kumar K. V
2010-03-09 15:59           ` jvrao
2010-03-11 16:37             ` Paul Brook
2010-03-03 19:01 ` [Qemu-devel] [PATCH 05/17] virtio-9p: Implement P9_TWALK Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 06/17] virtio-9p: Implement P9_TOPEN Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 07/17] virtio-9p: Implement P9_TREAD Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 08/17] virtio-9p: Implement P9_TCLUNK Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 09/17] virtio-9p: Implement P9_TWRITE Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 10/17] virtio-9p: Implement P9_TCREATE Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 11/17] virtio-9p: Implement P9_TWSTAT Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 12/17] virtio-9p: Implement P9_TREMOVE Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 13/17] virtio-9p: Implement P9_TFLUSH Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 14/17] virtio-9p: Add multiple mount point support Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 15/17] virtio-9p: Use little endian format on virtio Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 16/17] virtio-9p: Add support for hardlink Anthony Liguori
2010-03-03 19:01 ` [Qemu-devel] [PATCH 17/17] Implement sync support in 9p server Anthony Liguori

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.