All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough
@ 2010-04-09 11:43 Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 01/21] virtio-9p: Create a commandline option -fsdev Aneesh Kumar K.V
                   ` (20 more replies)
  0 siblings, 21 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar

This patch series adds VirtFS to QEMU. VirtFS is code named for a 9P filesystem
server in QEMU enabling paravirtual filesystem pass-trhough between KVM host and guest.

VirtFS is intended to offer an alternative to using NFS/CIFS to share host filesystems on
guest and provides better performance. Initial tests showed significantly better performance
than NFS and CIFS. Performance numbers are provided towards end of the mail. 

With the current implementation, all I/O is implemented in the VCPU thread.  
We've modified the protocol handlers so that we can support dispatch I/O in a thread pool. 
The actual thread pool implementation will be posted later. 

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

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

-virtfs fstype,path=path/to/share,mount_tag=tag

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

Changes from V3:
1) Makefiles are modified so that this code is compiled only on Linux.
2) Replaced vasprintf() with qemu_malloc() followed by sprintf().
3) Formatting changes per QEMU coding standards.
4) Folded bug fixes to original patches
c) configure option to enable/disable virtfs

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

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

Performance details:

# Host

    * 3650M2
    * 16 CPU, 32 GB RAM
    * 28 JBOD disks (18G each)
    * DM striped to make a single 400GB disk/filesystem
    * 400 GB ext3 filesystem exported/serving data in the host
    * RHEL5.5, QEMU + 9p Server patches 

# Guest

    * 1 vCPU, 4GB memory
    * virtio network access for CIFS, NFS
    * virtio transport for virtfs mount
    * 2.6.33-rc8 + v9 fixes (either on mainline or on 9p-devel list)

# Tests:

    * Created 16 20-GB files on the filesystem
    * Guest mounts filesystem through v9 (virtio), NFS (virtio), CIFS (virtio)
    * Perform sequential read and sequential write tests on these 16 20-GB files from the guest
    * Repeat the tests with various threads/processes (dd) counts
    * Between each test host and guest unmounts and mounts the filesystem to eliminate any caching affects. 

# read tests (sample):
for i in 1 2 3 4 5 6 7 8 do; time dd of=/dev/null if=./file$i bs=2M count=10240 & ; done 

#of Threads  |  1          2         4         8
----------------------------------------------------
VirtFs(MB/S) |  172        170       168       162
CIFS(MB/S)   |  10         12        22        35
NFS(MB/S)    |  80         70        62        42

# write tests (sample):
for i in 1 2 3 4 5 6 7 8 do; time dd if=/dev/zero of=./file$i bs=2M count=10240 & ; done 

#of Threads  |  1          2         4          8
-------------------------------------------------------
VirtFs(MB/S) |  190        182       150       138
CIFS(MB/S)   |  30         38        78        100
NFS(MB/S)    |  35         35        38        37

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

* [Qemu-devel] [PATCH -V4 01/21] virtio-9p: Create a commandline option -fsdev
  2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
@ 2010-04-09 11:43 ` Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 02/21] virtio-9p: Add a virtio 9p device to qemu Aneesh Kumar K.V
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar, Gautham R Shenoy

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

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

The option will currently hold the following attributes:
-fsdev fstype id=id,path=path_to_share
where
fstype: Type of the file system.
id:     Identifier used to refer to this fsdev
path:   The path on the host that is identified by this fsdev.

[aneesh.kumar@linux.vnet.ibm.com: Abstraction using FsContext]
Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 Makefile.objs      |    5 +++-
 configure          |   25 ++++++++++++++++++-
 fsdev/qemu-fsdev.c |   70 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 fsdev/qemu-fsdev.h |   53 +++++++++++++++++++++++++++++++++++++++
 hw/file-op-9p.h    |   32 +++++++++++++++++++++++
 qemu-config.c      |   18 +++++++++++++
 qemu-config.h      |    3 ++
 qemu-options.hx    |   33 ++++++++++++++++++++++++
 vl.c               |   27 ++++++++++++++++++++
 9 files changed, 264 insertions(+), 2 deletions(-)
 create mode 100644 fsdev/qemu-fsdev.c
 create mode 100644 fsdev/qemu-fsdev.h
 create mode 100644 hw/file-op-9p.h

diff --git a/Makefile.objs b/Makefile.objs
index 281f7a6..41c3c6c 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -35,6 +35,9 @@ net-nested-$(CONFIG_SLIRP) += slirp.o
 net-nested-$(CONFIG_VDE) += vde.o
 net-obj-y += $(addprefix net/, $(net-nested-y))
 
+fsdev-nested-$(CONFIG_LINUX_VIRTFS) = qemu-fsdev.o
+fsdev-obj-$(CONFIG_LINUX_VIRTFS) += $(addprefix fsdev/, $(fsdev-nested-y))
+
 ######################################################################
 # libqemu_common.a: Target independent part of system emulation. The
 # long term path is to suppress *all* target specific code in case of
@@ -44,8 +47,8 @@ net-obj-y += $(addprefix net/, $(net-nested-y))
 common-obj-y = $(block-obj-y)
 common-obj-y += $(net-obj-y)
 common-obj-y += $(qobject-obj-y)
+common-obj-$(CONFIG_LINUX_VIRTFS) += $(fsdev-obj-$(CONFIG_LINUX_VIRTFS))
 common-obj-y += readline.o console.o async.o qemu-error.o
-
 common-obj-y += tcg-runtime.o host-utils.o
 common-obj-y += irq.o ioport.o input.o
 common-obj-$(CONFIG_PTIMER) += ptimer.o
diff --git a/configure b/configure
index 6bc40a3..171c1f0 100755
--- a/configure
+++ b/configure
@@ -263,6 +263,7 @@ vnc_tls=""
 vnc_sasl=""
 xen=""
 linux_aio=""
+linux_virtfs=""
 
 gprof="no"
 debug_tcg="no"
@@ -651,6 +652,11 @@ for opt do
   ;;
   --enable-docs) docs="yes"
   ;;
+  --disable-linux-virtfs) linux_virtfs="no"
+  ;;
+  --enable-linux-virtfs) linux_virtfs="yes"
+
+  ;;
   *) echo "ERROR: unknown option $opt"; show_help="yes"
   ;;
   esac
@@ -806,6 +812,8 @@ echo "  --disable-blobs          disable installing provided firmware blobs"
 echo "  --kerneldir=PATH         look for kernel includes in PATH"
 echo "  --enable-docs            enable documentation build"
 echo "  --disable-docs           disable documentation build"
+echo "  --disable-linux-virtfs   disable Linux VIRTFS support"
+echo "  --enable-linux-virtfs    enable Linux VIRTFS support"
 echo ""
 echo "NOTE: The object files are built at the place where configure is launched"
 exit 1
@@ -1541,7 +1549,18 @@ EOF
     linux_aio=no
   fi
 fi
-
+########################################
+# linux-virtfs probe
+if test "$linux_virtfs" != "no" ; then
+    if test "$linux" = "no" ; then
+	if test "$linux_virtfs" = "yes" ; then
+	    feature_not_found "linux virtfs"
+	fi
+	linux_virtfs="no"
+    else
+	linux_virtfs="yes"
+    fi
+fi
 ##########################################
 # iovec probe
 cat > $TMPC <<EOF
@@ -1968,6 +1987,7 @@ echo "fdt support       $fdt"
 echo "preadv support    $preadv"
 echo "fdatasync         $fdatasync"
 echo "uuid support      $uuid"
+echo "Linux VIRTFS      $linux_virtfs"
 
 if test $sdl_too_old = "yes"; then
 echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -2183,6 +2203,9 @@ fi
 if test "$fdatasync" = "yes" ; then
   echo "CONFIG_FDATASYNC=y" >> $config_host_mak
 fi
+if test "$linux_virtfs" = "yes" ; then
+  echo "CONFIG_LINUX_VIRTFS=y" >> $config_host_mak
+fi
 
 # XXX: suppress that
 if [ "$bsd" = "yes" ] ; then
diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
new file mode 100644
index 0000000..48bbfd9
--- /dev/null
+++ b/fsdev/qemu-fsdev.c
@@ -0,0 +1,70 @@
+/*
+ * Virtio 9p
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Gautham R Shenoy <ego@in.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include "qemu-fsdev.h"
+#include "qemu-queue.h"
+#include "osdep.h"
+#include "qemu-common.h"
+
+static QTAILQ_HEAD(FsTypeEntry_head, FsTypeListEntry) fstype_entries =
+    QTAILQ_HEAD_INITIALIZER(fstype_entries);
+
+static FsTypeTable FsTypes[] = {
+    { .name = "local", .ops = NULL},
+};
+
+int qemu_fsdev_add(QemuOpts *opts)
+{
+    struct FsTypeListEntry *fsle;
+    int i;
+
+    if (qemu_opts_id(opts) == NULL) {
+        fprintf(stderr, "fsdev: No id specified\n");
+        return -1;
+    }
+
+     for (i = 0; i < ARRAY_SIZE(FsTypes); i++) {
+        if (strcmp(FsTypes[i].name, qemu_opt_get(opts, "fstype")) == 0) {
+            break;
+        }
+    }
+
+    if (i == ARRAY_SIZE(FsTypes)) {
+        fprintf(stderr, "fsdev: fstype %s not found\n",
+                    qemu_opt_get(opts, "fstype"));
+        return -1;
+    }
+
+    fsle = qemu_malloc(sizeof(*fsle));
+
+    fsle->fse.fsdev_id = qemu_strdup(qemu_opts_id(opts));
+    fsle->fse.path = qemu_strdup(qemu_opt_get(opts, "path"));
+    fsle->fse.ops = FsTypes[i].ops;
+
+    QTAILQ_INSERT_TAIL(&fstype_entries, fsle, next);
+    return 0;
+
+}
+
+FsTypeEntry *get_fsdev_fsentry(char *id)
+{
+    struct FsTypeListEntry *fsle;
+
+    QTAILQ_FOREACH(fsle, &fstype_entries, next) {
+        if (strcmp(fsle->fse.fsdev_id, id) == 0) {
+            return &fsle->fse;
+        }
+    }
+    return NULL;
+}
diff --git a/fsdev/qemu-fsdev.h b/fsdev/qemu-fsdev.h
new file mode 100644
index 0000000..7fa4f60
--- /dev/null
+++ b/fsdev/qemu-fsdev.h
@@ -0,0 +1,53 @@
+/*
+ * Virtio 9p
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Gautham R Shenoy <ego@in.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+#ifndef QEMU_FSDEV_H
+#define QEMU_FSDEV_H
+#include "qemu-option.h"
+#include "hw/file-op-9p.h"
+
+
+/*
+ * A table to store the various file systems and their callback operations.
+ * -----------------
+ * fstype | ops
+ * -----------------
+ *  local | local_ops
+ *  .     |
+ *  .     |
+ *  .     |
+ *  .     |
+ * -----------------
+ *  etc
+ */
+typedef struct FsTypeTable {
+    const char *name;
+    FileOperations *ops;
+} FsTypeTable;
+
+/*
+ * Structure to store the various fsdev's passed through command line.
+ */
+typedef struct FsTypeEntry {
+    char *fsdev_id;
+    char *path;
+    FileOperations *ops;
+} FsTypeEntry;
+
+typedef struct FsTypeListEntry {
+    FsTypeEntry fse;
+    QTAILQ_ENTRY(FsTypeListEntry) next;
+} FsTypeListEntry;
+
+extern int qemu_fsdev_add(QemuOpts *opts);
+extern FsTypeEntry *get_fsdev_fsentry(char *id);
+#endif
diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
new file mode 100644
index 0000000..7cde63c
--- /dev/null
+++ b/hw/file-op-9p.h
@@ -0,0 +1,32 @@
+/*
+ * Virtio 9p
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+#ifndef _FILEOP_H
+#define _FILEOP_H
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/time.h>
+#include <utime.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+
+typedef struct FsContext
+{
+    char *fs_root;
+    uid_t uid;
+} FsContext;
+
+typedef struct FileOperations
+{
+    void *opaque;
+} FileOperations;
+#endif
diff --git a/qemu-config.c b/qemu-config.c
index 150157c..0fb5105 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -151,6 +151,24 @@ QemuOptsList qemu_chardev_opts = {
     },
 };
 
+#ifdef CONFIG_LINUX_VIRTFS
+QemuOptsList qemu_fsdev_opts = {
+    .name = "fsdev",
+    .implied_opt_name = "fstype",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_fsdev_opts.head),
+    .desc = {
+        {
+            .name = "fstype",
+            .type = QEMU_OPT_STRING,
+        }, {
+            .name = "path",
+            .type = QEMU_OPT_STRING,
+        },
+        { /*End of list */ }
+    },
+};
+#endif
+
 QemuOptsList qemu_device_opts = {
     .name = "device",
     .implied_opt_name = "driver",
diff --git a/qemu-config.h b/qemu-config.h
index f217c58..d85bde7 100644
--- a/qemu-config.h
+++ b/qemu-config.h
@@ -3,6 +3,9 @@
 
 extern QemuOptsList qemu_drive_opts;
 extern QemuOptsList qemu_chardev_opts;
+#ifdef CONFIG_LINUX_VIRTFS
+extern QemuOptsList qemu_fsdev_opts;
+#endif
 extern QemuOptsList qemu_device_opts;
 extern QemuOptsList qemu_netdev_opts;
 extern QemuOptsList qemu_net_opts;
diff --git a/qemu-options.hx b/qemu-options.hx
index 8450b45..e007df8 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -469,6 +469,39 @@ To get a help on possible @var{driver}s, @var{option}s or @var{value}s, use
 @code{-device @var{driver},@var{option}=?}. 
 ETEXI
 
+#ifdef CONFIG_LINUX_VIRTFS
+DEFHEADING(File system options:)
+
+DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev,
+    "-fsdev local,id=id,path=path\n")
+
+STEXI
+
+The general form of a File system device option is:
+@table @option
+
+@item -fsdev @var{fstype} ,id=@var{id} [,@var{options}]
+@findex -fsdev
+Fstype is one of:
+@option{local},
+The specific Fstype will determine the applicable options.
+
+Options to each backend are described below.
+
+@item -fsdev local ,id=@var{id} ,path=@var{path}
+
+Create a file-system-"device" for local-filesystem.
+
+@option{local} is only available on Linux.
+
+@option{path} specifies the path to be exported. @option{path} is required.
+
+@end table
+ETEXI
+#endif
+
+DEFHEADING()
+
 DEF("name", HAS_ARG, QEMU_OPTION_name,
     "-name string1[,process=string2]\n"
     "                set the name of the guest\n"
diff --git a/vl.c b/vl.c
index d69250c..4359825 100644
--- a/vl.c
+++ b/vl.c
@@ -150,6 +150,9 @@ int main(int argc, char **argv)
 #include "qemu-option.h"
 #include "qemu-config.h"
 #include "qemu-objects.h"
+#ifdef CONFIG_LINUX_VIRTFS
+#include "fsdev/qemu-fsdev.h"
+#endif
 
 #include "disas.h"
 
@@ -3461,6 +3464,16 @@ static int chardev_init_func(QemuOpts *opts, void *opaque)
     return 0;
 }
 
+#ifdef CONFIG_LINUX_VIRTFS
+static int fsdev_init_func(QemuOpts *opts, void *opaque)
+{
+    int ret;
+    ret = qemu_fsdev_add(opts);
+
+    return ret;
+}
+#endif
+
 static int mon_init_func(QemuOpts *opts, void *opaque)
 {
     CharDriverState *chr;
@@ -4256,6 +4269,15 @@ int main(int argc, char **argv, char **envp)
                     exit(1);
                 }
                 break;
+#ifdef CONFIG_LINUX_VIRTFS
+            case QEMU_OPTION_fsdev:
+                opts = qemu_opts_parse(&qemu_fsdev_opts, optarg, 1);
+                if (!opts) {
+                    fprintf(stderr, "parse error: %s\n", optarg);
+                    exit(1);
+                }
+                break;
+#endif
             case QEMU_OPTION_serial:
                 add_device_config(DEV_SERIAL, optarg);
                 default_serial = 0;
@@ -4625,6 +4647,11 @@ int main(int argc, char **argv, char **envp)
 
     if (qemu_opts_foreach(&qemu_chardev_opts, chardev_init_func, NULL, 1) != 0)
         exit(1);
+#ifdef CONFIG_LINUX_VIRTFS
+    if (qemu_opts_foreach(&qemu_fsdev_opts, fsdev_init_func, NULL, 1) != 0) {
+        exit(1);
+    }
+#endif
 
 #ifndef _WIN32
     if (daemonize) {
-- 
1.7.0.4.360.g11766c

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

* [Qemu-devel] [PATCH -V4 02/21] virtio-9p: Add a virtio 9p device to qemu
  2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 01/21] virtio-9p: Create a commandline option -fsdev Aneesh Kumar K.V
@ 2010-04-09 11:43 ` Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 03/21] virtio-9p: pdu processing support Aneesh Kumar K.V
                   ` (18 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar

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

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

[jvrao@linux.vnet.ibm.com: Little-Endian to host format conversion]
[aneesh.kumar@linux.vnet.ibm.com: Multiple-mounts support]

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 Makefile.target      |    1 +
 fsdev/qemu-fsdev.c   |    2 +-
 fsdev/qemu-fsdev.h   |    1 +
 hw/9p.h              |   26 +++
 hw/virtio-9p-debug.c |  484 ++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/virtio-9p-local.c |   17 ++
 hw/virtio-9p.c       |  329 ++++++++++++++++++++++++++++++++++
 hw/virtio-9p.h       |  166 +++++++++++++++++
 hw/virtio-pci.c      |   32 ++++
 hw/virtio.h          |    7 +
 10 files changed, 1064 insertions(+), 1 deletions(-)
 create mode 100644 hw/9p.h
 create mode 100644 hw/virtio-9p-debug.c
 create mode 100644 hw/virtio-9p-local.c
 create mode 100644 hw/virtio-9p.c
 create mode 100644 hw/virtio-9p.h

diff --git a/Makefile.target b/Makefile.target
index eb4d010..b7f8965 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -166,6 +166,7 @@ obj-y += qemu-timer.o
 # virtio has to be here due to weird dependency between PCI and virtio-net.
 # need to fix this properly
 obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
+obj-$(CONFIG_LINUX_VIRTFS) += virtio-9p.o virtio-9p-debug.o virtio-9p-local.o
 obj-y += rwhandler.o
 obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 LIBS+=-lz
diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
index 48bbfd9..813e1f7 100644
--- a/fsdev/qemu-fsdev.c
+++ b/fsdev/qemu-fsdev.c
@@ -21,7 +21,7 @@ static QTAILQ_HEAD(FsTypeEntry_head, FsTypeListEntry) fstype_entries =
     QTAILQ_HEAD_INITIALIZER(fstype_entries);
 
 static FsTypeTable FsTypes[] = {
-    { .name = "local", .ops = NULL},
+    { .name = "local", .ops = &local_ops},
 };
 
 int qemu_fsdev_add(QemuOpts *opts)
diff --git a/fsdev/qemu-fsdev.h b/fsdev/qemu-fsdev.h
index 7fa4f60..b50fbe0 100644
--- a/fsdev/qemu-fsdev.h
+++ b/fsdev/qemu-fsdev.h
@@ -50,4 +50,5 @@ typedef struct FsTypeListEntry {
 
 extern int qemu_fsdev_add(QemuOpts *opts);
 extern FsTypeEntry *get_fsdev_fsentry(char *id);
+extern FileOperations local_ops;
 #endif
diff --git a/hw/9p.h b/hw/9p.h
new file mode 100644
index 0000000..5fdd770
--- /dev/null
+++ b/hw/9p.h
@@ -0,0 +1,26 @@
+/*
+ * Virtio 9p
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_9P_H
+#define QEMU_9P_H
+
+#include <stdbool.h>
+
+typedef struct V9fsConf
+{
+    /* tag name for the device */
+    char *tag;
+    char *fsdev_id;
+} V9fsConf;
+
+#endif
diff --git a/hw/virtio-9p-debug.c b/hw/virtio-9p-debug.c
new file mode 100644
index 0000000..2fb2673
--- /dev/null
+++ b/hw/virtio-9p-debug.c
@@ -0,0 +1,484 @@
+/*
+ * Virtio 9p PDU debug
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+#include "virtio.h"
+#include "pc.h"
+#include "virtio-9p.h"
+#include "virtio-9p-debug.h"
+
+#define BUG_ON(cond) assert(!(cond))
+
+static FILE *llogfile;
+
+static struct iovec *get_sg(V9fsPDU *pdu, int rx)
+{
+    if (rx) {
+        return pdu->elem.in_sg;
+    }
+    return pdu->elem.out_sg;
+}
+
+static int get_sg_count(V9fsPDU *pdu, int rx)
+{
+    if (rx) {
+        return pdu->elem.in_num;
+    }
+    return pdu->elem.out_num;
+
+}
+
+static void pprint_int8(V9fsPDU *pdu, int rx, size_t *offsetp,
+                        const char *name)
+{
+    size_t copied;
+    int count = get_sg_count(pdu, rx);
+    size_t offset = *offsetp;
+    struct iovec *sg = get_sg(pdu, rx);
+    int8_t value;
+
+    copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
+
+    BUG_ON(copied != sizeof(value));
+    offset += sizeof(value);
+    fprintf(llogfile, "%s=0x%x", name, value);
+    *offsetp = offset;
+}
+
+static void pprint_int16(V9fsPDU *pdu, int rx, size_t *offsetp,
+                        const char *name)
+{
+    size_t copied;
+    int count = get_sg_count(pdu, rx);
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    int16_t value;
+
+
+    copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
+
+    BUG_ON(copied != sizeof(value));
+    offset += sizeof(value);
+    fprintf(llogfile, "%s=0x%x", name, value);
+    *offsetp = offset;
+}
+
+static void pprint_int32(V9fsPDU *pdu, int rx, size_t *offsetp,
+                        const char *name)
+{
+    size_t copied;
+    int count = get_sg_count(pdu, rx);
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    int32_t value;
+
+
+    copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
+
+    BUG_ON(copied != sizeof(value));
+    offset += sizeof(value);
+    fprintf(llogfile, "%s=0x%x", name, value);
+    *offsetp = offset;
+}
+
+static void pprint_int64(V9fsPDU *pdu, int rx, size_t *offsetp,
+                        const char *name)
+{
+    size_t copied;
+    int count = get_sg_count(pdu, rx);
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    int64_t value;
+
+
+    copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
+
+    BUG_ON(copied != sizeof(value));
+    offset += sizeof(value);
+    fprintf(llogfile, "%s=0x%" PRIx64, name, value);
+    *offsetp = offset;
+}
+
+static void pprint_str(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
+{
+    int sg_count = get_sg_count(pdu, rx);
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    uint16_t tmp_size, size;
+    size_t result;
+    size_t copied = 0;
+    int i = 0;
+
+    /* get the size */
+    copied = do_pdu_unpack(&tmp_size, sg, sg_count, offset, sizeof(tmp_size));
+    BUG_ON(copied != sizeof(tmp_size));
+    size = le16_to_cpupu(&tmp_size);
+    offset += copied;
+
+    fprintf(llogfile, "%s=", name);
+    for (i = 0; size && i < sg_count; i++) {
+        size_t len;
+        if (offset >= sg[i].iov_len) {
+            /* skip this sg */
+            offset -= sg[i].iov_len;
+            continue;
+        } else {
+            len = MIN(sg[i].iov_len - offset, size);
+            result = fwrite(sg[i].iov_base + offset, 1, len, llogfile);
+            BUG_ON(result != len);
+            size -= len;
+            copied += len;
+            if (size) {
+                offset = 0;
+                continue;
+            }
+        }
+    }
+    *offsetp += copied;
+}
+
+static void pprint_qid(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
+{
+    fprintf(llogfile, "%s={", name);
+    pprint_int8(pdu, rx, offsetp, "type");
+    pprint_int32(pdu, rx, offsetp, ", version");
+    pprint_int64(pdu, rx, offsetp, ", path");
+    fprintf(llogfile, "}");
+}
+
+static void pprint_stat(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
+{
+    fprintf(llogfile, "%s={", name);
+    pprint_int16(pdu, rx, offsetp, "size");
+    pprint_int16(pdu, rx, offsetp, ", type");
+    pprint_int32(pdu, rx, offsetp, ", dev");
+    pprint_qid(pdu, rx, offsetp, ", qid");
+    pprint_int32(pdu, rx, offsetp, ", mode");
+    pprint_int32(pdu, rx, offsetp, ", atime");
+    pprint_int32(pdu, rx, offsetp, ", mtime");
+    pprint_int64(pdu, rx, offsetp, ", length");
+    pprint_str(pdu, rx, offsetp, ", name");
+    pprint_str(pdu, rx, offsetp, ", uid");
+    pprint_str(pdu, rx, offsetp, ", gid");
+    pprint_str(pdu, rx, offsetp, ", muid");
+    if (dotu) {
+        pprint_str(pdu, rx, offsetp, ", extension");
+        pprint_int32(pdu, rx, offsetp, ", uid");
+        pprint_int32(pdu, rx, offsetp, ", gid");
+        pprint_int32(pdu, rx, offsetp, ", muid");
+    }
+    fprintf(llogfile, "}");
+}
+
+static void pprint_strs(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
+{
+    int sg_count = get_sg_count(pdu, rx);
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    uint16_t tmp_count, count, i;
+    size_t copied = 0;
+
+    fprintf(llogfile, "%s={", name);
+
+    /* Get the count */
+    copied = do_pdu_unpack(&tmp_count, sg, sg_count, offset, sizeof(tmp_count));
+    BUG_ON(copied != sizeof(tmp_count));
+    count = le16_to_cpupu(&tmp_count);
+    offset += copied;
+
+    for (i = 0; i < count; i++) {
+        char str[512];
+        if (i) {
+            fprintf(llogfile, ", ");
+        }
+        snprintf(str, sizeof(str), "[%d]", i);
+        pprint_str(pdu, rx, &offset, str);
+    }
+
+    fprintf(llogfile, "}");
+
+    *offsetp = offset;
+}
+
+static void pprint_qids(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
+{
+    int sg_count = get_sg_count(pdu, rx);
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    uint16_t tmp_count, count, i;
+    size_t copied = 0;
+
+    fprintf(llogfile, "%s={", name);
+
+    copied = do_pdu_unpack(&tmp_count, sg, sg_count, offset, sizeof(tmp_count));
+    BUG_ON(copied != sizeof(tmp_count));
+    count = le16_to_cpupu(&tmp_count);
+    offset += copied;
+
+    for (i = 0; i < count; i++) {
+        char str[512];
+        if (i) {
+            fprintf(llogfile, ", ");
+        }
+        snprintf(str, sizeof(str), "[%d]", i);
+        pprint_qid(pdu, rx, &offset, str);
+    }
+
+    fprintf(llogfile, "}");
+
+    *offsetp = offset;
+}
+
+static void pprint_sg(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
+{
+    struct iovec *sg = get_sg(pdu, rx);
+    unsigned int count;
+    int i;
+
+    if (rx) {
+        count = pdu->elem.in_num;
+    } else {
+        count = pdu->elem.out_num;
+    }
+
+    fprintf(llogfile, "%s={", name);
+    for (i = 0; i < count; i++) {
+        if (i) {
+            fprintf(llogfile, ", ");
+        }
+        fprintf(llogfile, "(%p, 0x%zx)", sg[i].iov_base, sg[i].iov_len);
+    }
+    fprintf(llogfile, "}");
+}
+
+/* FIXME: read from a directory fid returns serialized stat_t's */
+#ifdef DEBUG_DATA
+static void pprint_data(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
+{
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    unsigned int count;
+    int32_t size;
+    int total, i, j;
+    ssize_t len;
+
+    if (rx) {
+        count = pdu->elem.in_num;
+    } else
+        count = pdu->elem.out_num;
+    }
+
+    BUG_ON((offset + sizeof(size)) > sg[0].iov_len);
+
+    memcpy(&size, sg[0].iov_base + offset, sizeof(size));
+    offset += sizeof(size);
+
+    fprintf(llogfile, "size: %x\n", size);
+
+    sg[0].iov_base += 11; /* skip header */
+    sg[0].iov_len -= 11;
+
+    total = 0;
+    for (i = 0; i < count; i++) {
+        total += sg[i].iov_len;
+        if (total >= size) {
+            /* trim sg list so writev does the right thing */
+            sg[i].iov_len -= (total - size);
+            i++;
+            break;
+        }
+    }
+
+    fprintf(llogfile, "%s={\"", name);
+    fflush(llogfile);
+    for (j = 0; j < i; j++) {
+        if (j) {
+            fprintf(llogfile, "\", \"");
+            fflush(llogfile);
+        }
+
+        do {
+            len = writev(fileno(llogfile), &sg[j], 1);
+        } while (len == -1 && errno == EINTR);
+        fprintf(llogfile, "len == %ld: %m\n", len);
+        BUG_ON(len != sg[j].iov_len);
+    }
+    fprintf(llogfile, "\"}");
+
+    sg[0].iov_base -= 11;
+    sg[0].iov_len += 11;
+
+}
+#endif
+
+void pprint_pdu(V9fsPDU *pdu)
+{
+    size_t offset = 7;
+
+    if (llogfile == NULL) {
+        llogfile = fopen("/tmp/pdu.log", "w");
+    }
+
+    switch (pdu->id) {
+    case P9_TVERSION:
+        fprintf(llogfile, "TVERSION: (");
+        pprint_int32(pdu, 0, &offset, "msize");
+        pprint_str(pdu, 0, &offset, ", version");
+        break;
+    case P9_RVERSION:
+        fprintf(llogfile, "RVERSION: (");
+        pprint_int32(pdu, 1, &offset, "msize");
+        pprint_str(pdu, 1, &offset, ", version");
+        break;
+    case P9_TAUTH:
+        fprintf(llogfile, "TAUTH: (");
+        pprint_int32(pdu, 0, &offset, "afid");
+        pprint_str(pdu, 0, &offset, ", uname");
+        pprint_str(pdu, 0, &offset, ", aname");
+        if (dotu) {
+            pprint_int32(pdu, 0, &offset, ", n_uname");
+        }
+        break;
+    case P9_RAUTH:
+        fprintf(llogfile, "RAUTH: (");
+        pprint_qid(pdu, 1, &offset, "qid");
+        break;
+    case P9_TATTACH:
+        fprintf(llogfile, "TATTACH: (");
+        pprint_int32(pdu, 0, &offset, "fid");
+        pprint_int32(pdu, 0, &offset, ", afid");
+        pprint_str(pdu, 0, &offset, ", uname");
+        pprint_str(pdu, 0, &offset, ", aname");
+        if (dotu) {
+            pprint_int32(pdu, 0, &offset, ", n_uname");
+        }
+        break;
+    case P9_RATTACH:
+        fprintf(llogfile, "RATTACH: (");
+        pprint_qid(pdu, 1, &offset, "qid");
+        break;
+    case P9_TERROR:
+        fprintf(llogfile, "TERROR: (");
+        break;
+    case P9_RERROR:
+        fprintf(llogfile, "RERROR: (");
+        pprint_str(pdu, 1, &offset, "ename");
+        if (dotu) {
+            pprint_int32(pdu, 1, &offset, ", ecode");
+        }
+        break;
+    case P9_TFLUSH:
+        fprintf(llogfile, "TFLUSH: (");
+        pprint_int16(pdu, 0, &offset, "oldtag");
+        break;
+    case P9_RFLUSH:
+        fprintf(llogfile, "RFLUSH: (");
+        break;
+    case P9_TWALK:
+        fprintf(llogfile, "TWALK: (");
+        pprint_int32(pdu, 0, &offset, "fid");
+        pprint_int32(pdu, 0, &offset, ", newfid");
+        pprint_strs(pdu, 0, &offset, ", wnames");
+        break;
+    case P9_RWALK:
+        fprintf(llogfile, "RWALK: (");
+        pprint_qids(pdu, 1, &offset, "wqids");
+        break;
+    case P9_TOPEN:
+        fprintf(llogfile, "TOPEN: (");
+        pprint_int32(pdu, 0, &offset, "fid");
+        pprint_int8(pdu, 0, &offset, ", mode");
+        break;
+    case P9_ROPEN:
+        fprintf(llogfile, "ROPEN: (");
+        pprint_qid(pdu, 1, &offset, "qid");
+        pprint_int32(pdu, 1, &offset, ", iounit");
+        break;
+    case P9_TCREATE:
+        fprintf(llogfile, "TCREATE: (");
+        pprint_int32(pdu, 0, &offset, "fid");
+        pprint_str(pdu, 0, &offset, ", name");
+        pprint_int32(pdu, 0, &offset, ", perm");
+        pprint_int8(pdu, 0, &offset, ", mode");
+        if (dotu) {
+            pprint_str(pdu, 0, &offset, ", extension");
+        }
+        break;
+    case P9_RCREATE:
+        fprintf(llogfile, "RCREATE: (");
+        pprint_qid(pdu, 1, &offset, "qid");
+        pprint_int32(pdu, 1, &offset, ", iounit");
+        break;
+    case P9_TREAD:
+        fprintf(llogfile, "TREAD: (");
+        pprint_int32(pdu, 0, &offset, "fid");
+        pprint_int64(pdu, 0, &offset, ", offset");
+        pprint_int32(pdu, 0, &offset, ", count");
+        pprint_sg(pdu, 0, &offset, ", sg");
+        break;
+    case P9_RREAD:
+        fprintf(llogfile, "RREAD: (");
+        pprint_int32(pdu, 1, &offset, "count");
+        pprint_sg(pdu, 1, &offset, ", sg");
+        offset = 7;
+#ifdef DEBUG_DATA
+        pprint_data(pdu, 1, &offset, ", data");
+#endif
+        break;
+    case P9_TWRITE:
+        fprintf(llogfile, "TWRITE: (");
+        pprint_int32(pdu, 0, &offset, "fid");
+        pprint_int64(pdu, 0, &offset, ", offset");
+        pprint_int32(pdu, 0, &offset, ", count");
+        break;
+    case P9_RWRITE:
+        fprintf(llogfile, "RWRITE: (");
+        pprint_int32(pdu, 1, &offset, "count");
+        break;
+    case P9_TCLUNK:
+        fprintf(llogfile, "TCLUNK: (");
+        pprint_int32(pdu, 0, &offset, "fid");
+        break;
+    case P9_RCLUNK:
+        fprintf(llogfile, "RCLUNK: (");
+        break;
+    case P9_TREMOVE:
+        fprintf(llogfile, "TREMOVE: (");
+        pprint_int32(pdu, 0, &offset, "fid");
+        break;
+    case P9_RREMOVE:
+        fprintf(llogfile, "RREMOVE: (");
+        break;
+    case P9_TSTAT:
+        fprintf(llogfile, "TSTAT: (");
+        pprint_int32(pdu, 0, &offset, "fid");
+        break;
+    case P9_RSTAT:
+        fprintf(llogfile, "RSTAT: (");
+        offset += 2; /* ignored */
+        pprint_stat(pdu, 1, &offset, "stat");
+        break;
+    case P9_TWSTAT:
+        fprintf(llogfile, "TWSTAT: (");
+        pprint_int32(pdu, 0, &offset, "fid");
+        offset += 2; /* ignored */
+        pprint_stat(pdu, 0, &offset, ", stat");
+        break;
+    case P9_RWSTAT:
+        fprintf(llogfile, "RWSTAT: (");
+        break;
+    default:
+        fprintf(llogfile, "unknown(%d): (", pdu->id);
+        break;
+    }
+
+    fprintf(llogfile, ")\n");
+}
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
new file mode 100644
index 0000000..379af60
--- /dev/null
+++ b/hw/virtio-9p-local.c
@@ -0,0 +1,17 @@
+/*
+ * Virtio 9p Posix callback
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+#include "virtio.h"
+#include "virtio-9p.h"
+
+FileOperations local_ops = {
+};
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
new file mode 100644
index 0000000..0685c2d
--- /dev/null
+++ b/hw/virtio-9p.c
@@ -0,0 +1,329 @@
+/*
+ * Virtio 9p backend
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "virtio.h"
+#include "pc.h"
+#include "qemu_socket.h"
+#include "virtio-9p.h"
+#include "fsdev/qemu-fsdev.h"
+#include "virtio-9p-debug.h"
+
+int dotu = 1;
+int debug_9p_pdu;
+
+static V9fsPDU *alloc_pdu(V9fsState *s)
+{
+    V9fsPDU *pdu = NULL;
+
+    if (s->free_pdu) {
+        pdu = s->free_pdu;
+        s->free_pdu = pdu->next;
+    }
+
+    return pdu;
+}
+
+static void free_pdu(V9fsState *s, V9fsPDU *pdu)
+{
+    if (pdu) {
+        pdu->next = s->free_pdu;
+        s->free_pdu = pdu;
+    }
+}
+
+size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
+                        size_t offset, size_t size, int pack)
+{
+    int i = 0;
+    size_t copied = 0;
+
+    for (i = 0; size && i < sg_count; i++) {
+        size_t len;
+        if (offset >= sg[i].iov_len) {
+            /* skip this sg */
+            offset -= sg[i].iov_len;
+            continue;
+        } else {
+            len = MIN(sg[i].iov_len - offset, size);
+            if (pack) {
+                memcpy(sg[i].iov_base + offset, addr, len);
+            } else {
+                memcpy(addr, sg[i].iov_base + offset, len);
+            }
+            size -= len;
+            copied += len;
+            addr += len;
+            if (size) {
+                offset = 0;
+                continue;
+            }
+        }
+    }
+
+    return copied;
+}
+
+static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+static void v9fs_attach(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+static void v9fs_stat(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+static void v9fs_open(V9fsState *s, V9fsPDU *pdu)
+{    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+     }
+}
+
+static void v9fs_read(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+static void v9fs_write(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+static void v9fs_create(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+static void v9fs_flush(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+static void v9fs_remove(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+typedef void (pdu_handler_t)(V9fsState *s, V9fsPDU *pdu);
+
+static pdu_handler_t *pdu_handlers[] = {
+    [P9_TVERSION] = v9fs_version,
+    [P9_TATTACH] = v9fs_attach,
+    [P9_TSTAT] = v9fs_stat,
+    [P9_TWALK] = v9fs_walk,
+    [P9_TCLUNK] = v9fs_clunk,
+    [P9_TOPEN] = v9fs_open,
+    [P9_TREAD] = v9fs_read,
+#if 0
+    [P9_TAUTH] = v9fs_auth,
+#endif
+    [P9_TFLUSH] = v9fs_flush,
+    [P9_TCREATE] = v9fs_create,
+    [P9_TWRITE] = v9fs_write,
+    [P9_TWSTAT] = v9fs_wstat,
+    [P9_TREMOVE] = v9fs_remove,
+};
+
+static void submit_pdu(V9fsState *s, V9fsPDU *pdu)
+{
+    pdu_handler_t *handler;
+
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+
+    BUG_ON(pdu->id >= ARRAY_SIZE(pdu_handlers));
+
+    handler = pdu_handlers[pdu->id];
+    BUG_ON(handler == NULL);
+
+    handler(s, pdu);
+}
+
+static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
+{
+    V9fsState *s = (V9fsState *)vdev;
+    V9fsPDU *pdu;
+    ssize_t len;
+
+    while ((pdu = alloc_pdu(s)) &&
+            (len = virtqueue_pop(vq, &pdu->elem)) != 0) {
+        uint8_t *ptr;
+
+        BUG_ON(pdu->elem.out_num == 0 || pdu->elem.in_num == 0);
+        BUG_ON(pdu->elem.out_sg[0].iov_len < 7);
+
+        ptr = pdu->elem.out_sg[0].iov_base;
+
+        memcpy(&pdu->size, ptr, 4);
+        pdu->id = ptr[4];
+        memcpy(&pdu->tag, ptr + 5, 2);
+
+        submit_pdu(s, pdu);
+    }
+
+    free_pdu(s, pdu);
+}
+
+static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features)
+{
+    features |= 1 << VIRTIO_9P_MOUNT_TAG;
+    return features;
+}
+
+static V9fsState *to_virtio_9p(VirtIODevice *vdev)
+{
+    return (V9fsState *)vdev;
+}
+
+static void virtio_9p_set_config(VirtIODevice *vdev, const uint8_t *config)
+{
+    uint16_t tag_len;
+    struct virtio_9p_config *cfg;
+    V9fsState *s = to_virtio_9p(vdev);
+
+    memcpy(&tag_len, config, sizeof(tag_len));
+    cfg = qemu_mallocz(sizeof(struct virtio_9p_config) + tag_len);
+
+    memcpy(cfg, config, s->config_size);
+    memcpy(&s->tag_len, &cfg->tag_len, sizeof(uint16_t));
+    /* free the old config details */
+    qemu_free(s->tag);
+    s->tag = qemu_malloc(tag_len);
+    memcpy(s->tag, cfg->tag, cfg->tag_len);
+    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, len;
+    struct stat stat;
+    FsTypeEntry *fse;
+
+
+    s = (V9fsState *)virtio_common_init("virtio-9p",
+                                    VIRTIO_ID_9P,
+                                    sizeof(struct virtio_9p_config)+
+                                    MAX_TAG_LEN,
+                                    sizeof(V9fsState));
+
+    /* initialize pdu allocator */
+    s->free_pdu = &s->pdus[0];
+    for (i = 0; i < (MAX_REQ - 1); i++) {
+        s->pdus[i].next = &s->pdus[i + 1];
+    }
+    s->pdus[i].next = NULL;
+
+    s->vq = virtio_add_queue(&s->vdev, MAX_REQ, handle_9p_output);
+
+    fse = get_fsdev_fsentry(conf->fsdev_id);
+
+    if (!fse) {
+        /* We don't have a fsdev identified by fsdev_id */
+        fprintf(stderr, "Virtio-9p device couldn't find fsdev "
+                    "with the id %s\n", conf->fsdev_id);
+        exit(1);
+    }
+
+    if (!fse->path || !conf->tag) {
+        /* we haven't specified a mount_tag or the path */
+        fprintf(stderr, "fsdev with id %s needs path "
+                "and Virtio-9p device needs mount_tag arguments\n",
+                conf->fsdev_id);
+        exit(1);
+    }
+
+    if (lstat(fse->path, &stat)) {
+        fprintf(stderr, "share path %s does not exist\n", fse->path);
+        exit(1);
+    } else if (!S_ISDIR(stat.st_mode)) {
+        fprintf(stderr, "share path %s is not a directory \n", fse->path);
+        exit(1);
+    }
+
+    s->ctx.fs_root = qemu_strdup(fse->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;
+    s->ctx.uid = -1;
+
+    s->ops = fse->ops;
+    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
new file mode 100644
index 0000000..48ff23e
--- /dev/null
+++ b/hw/virtio-9p.h
@@ -0,0 +1,166 @@
+#ifndef _QEMU_VIRTIO_9P_H
+#define _QEMU_VIRTIO_9P_H
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/time.h>
+#include <utime.h>
+
+#include "file-op-9p.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,
+    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;
+};
+
+
+/* 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;
+};
+
+typedef struct V9fsState
+{
+    VirtIODevice vdev;
+    VirtQueue *vq;
+    V9fsPDU pdus[MAX_REQ];
+    V9fsPDU *free_pdu;
+    V9fsFidState *fid_list;
+    FileOperations *ops;
+    FsContext ctx;
+    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));
+
+extern size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
+                            size_t offset, size_t size, int pack);
+
+static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count,
+                        size_t offset, size_t size)
+{
+    return pdu_packunpack(dst, sg, sg_count, offset, size, 0);
+}
+
+#endif
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 6eb19cd..042cf26 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -96,6 +96,9 @@ typedef struct {
     BlockConf block;
     NICConf nic;
     uint32_t host_features;
+#ifdef CONFIG_LINUX_VIRTFS
+    V9fsConf fsconf;
+#endif
     /* Max. number of ports we can have for a the virtio-serial device */
     uint32_t max_virtserial_ports;
 } VirtIOPCIProxy;
@@ -552,6 +555,23 @@ static int virtio_balloon_init_pci(PCIDevice *pci_dev)
     return 0;
 }
 
+#ifdef CONFIG_LINUX_VIRTFS
+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->fsconf);
+    virtio_init_pci(proxy, vdev,
+                    PCI_VENDOR_ID_REDHAT_QUMRANET,
+                    0x1009,
+                    0x2,
+                    0x00);
+
+    return 0;
+}
+#endif
+
 static PCIDeviceInfo virtio_info[] = {
     {
         .qdev.name = "virtio-blk-pci",
@@ -606,6 +626,18 @@ static PCIDeviceInfo virtio_info[] = {
         },
         .qdev.reset = virtio_pci_reset,
     },{
+#ifdef CONFIG_LINUX_VIRTFS
+        .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("mount_tag", VirtIOPCIProxy, fsconf.tag),
+            DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
+            DEFINE_PROP_END_OF_LIST(),
+        },
+    }, {
+#endif
         /* end of list */
     }
 };
diff --git a/hw/virtio.h b/hw/virtio.h
index 3baa2a3..41d0538 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -19,6 +19,9 @@
 #include "qdev.h"
 #include "sysemu.h"
 #include "block_int.h"
+#ifdef CONFIG_LINUX_VIRTFS
+#include "9p.h"
+#endif
 
 /* from Linux's linux/virtio_config.h */
 
@@ -174,6 +177,10 @@ 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);
+#ifdef CONFIG_LINUX_VIRTFS
+VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
+#endif
+
 
 void virtio_net_exit(VirtIODevice *vdev);
 
-- 
1.7.0.4.360.g11766c

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

* [Qemu-devel] [PATCH -V4 03/21] virtio-9p: pdu processing support.
  2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 01/21] virtio-9p: Create a commandline option -fsdev Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 02/21] virtio-9p: Add a virtio 9p device to qemu Aneesh Kumar K.V
@ 2010-04-09 11:43 ` Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 04/21] virtio-9p: Add string manipulation support Aneesh Kumar K.V
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar

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

Add helpers to process the PDUs.

[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-debug.h |    7 ++
 hw/virtio-9p.c       |  243 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 250 insertions(+), 0 deletions(-)
 create mode 100644 hw/virtio-9p-debug.h

diff --git a/hw/virtio-9p-debug.h b/hw/virtio-9p-debug.h
new file mode 100644
index 0000000..0104be5
--- /dev/null
+++ b/hw/virtio-9p-debug.h
@@ -0,0 +1,7 @@
+#ifndef _QEMU_VIRTIO_9P_DEBUG_H
+#define _QEMU_VIRTIO_9P_DEBUG_H
+
+extern int dotu;
+void pprint_pdu(V9fsPDU *pdu);
+
+#endif
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 0685c2d..0b95eeb 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -73,6 +73,248 @@ size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
     return copied;
 }
 
+static size_t pdu_unpack(void *dst, V9fsPDU *pdu, size_t offset, size_t size)
+{
+    return pdu_packunpack(dst, pdu->elem.out_sg, pdu->elem.out_num,
+                         offset, size, 0);
+}
+
+static size_t pdu_pack(V9fsPDU *pdu, size_t offset, const void *src,
+                        size_t size)
+{
+    return pdu_packunpack((void *)src, pdu->elem.in_sg, pdu->elem.in_num,
+                             offset, size, 1);
+}
+
+static int pdu_copy_sg(V9fsPDU *pdu, size_t offset, int rx, struct iovec *sg)
+{
+    size_t pos = 0;
+    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': {
+            uint8_t *valp = va_arg(ap, uint8_t *);
+            offset += pdu_unpack(valp, pdu, offset, sizeof(*valp));
+            break;
+        }
+        case 'w': {
+            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': {
+            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': {
+            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': {
+            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': {
+            uint8_t val = va_arg(ap, int);
+            offset += pdu_pack(pdu, offset, &val, sizeof(val));
+            break;
+        }
+        case 'w': {
+            uint16_t val;
+            cpu_to_le16w(&val, va_arg(ap, int));
+            offset += pdu_pack(pdu, offset, &val, sizeof(val));
+            break;
+        }
+        case 'd': {
+            uint32_t val;
+            cpu_to_le32w(&val, va_arg(ap, uint32_t));
+            offset += pdu_pack(pdu, offset, &val, sizeof(val));
+            break;
+        }
+        case 'q': {
+            uint64_t val;
+            cpu_to_le64w(&val, va_arg(ap, uint64_t));
+            offset += pdu_pack(pdu, offset, &val, sizeof(val));
+            break;
+        }
+        case 'v': {
+            struct iovec *iov = va_arg(ap, struct iovec *);
+            int *iovcnt = va_arg(ap, int *);
+            *iovcnt = pdu_copy_sg(pdu, offset, 1, iov);
+            break;
+        }
+        case 's': {
+            V9fsString *str = va_arg(ap, V9fsString *);
+            offset += pdu_marshal(pdu, offset, "w", str->size);
+            offset += pdu_pack(pdu, offset, str->data, str->size);
+            break;
+        }
+        case 'Q': {
+            V9fsQID *qidp = va_arg(ap, V9fsQID *);
+            offset += pdu_marshal(pdu, offset, "bdq",
+                        qidp->type, qidp->version, qidp->path);
+            break;
+        }
+        case 'S': {
+            V9fsStat *statp = va_arg(ap, V9fsStat *);
+            offset += pdu_marshal(pdu, offset, "wwdQdddqsssssddd",
+                        statp->size, statp->type, statp->dev,
+                        &statp->qid, statp->mode, statp->atime,
+                        statp->mtime, statp->length, &statp->name,
+                        &statp->uid, &statp->gid, &statp->muid,
+                        &statp->extension, statp->n_uid,
+                        statp->n_gid, statp->n_muid);
+            break;
+        }
+        default:
+            break;
+        }
+    }
+    va_end(ap);
+
+    return offset - old_offset;
+}
+
+static void complete_pdu(V9fsState *s, V9fsPDU *pdu, ssize_t len)
+{
+    int8_t id = pdu->id + 1; /* Response */
+
+    if (len < 0) {
+        V9fsString str;
+        int err = -len;
+
+        str.data = strerror(err);
+        str.size = strlen(str.data);
+
+        len = 7;
+        len += pdu_marshal(pdu, len, "s", &str);
+        if (dotu) {
+            len += pdu_marshal(pdu, len, "d", err);
+        }
+
+        id = P9_RERROR;
+    }
+
+    /* fill out the header */
+    pdu_marshal(pdu, 0, "dbw", (int32_t)len, id, pdu->tag);
+
+    /* keep these in sync */
+    pdu->size = len;
+    pdu->id = id;
+
+    /* push onto queue and notify */
+    virtqueue_push(s->vq, &pdu->elem, len);
+
+    /* FIXME: we should batch these completions */
+    virtio_notify(&s->vdev, s->vq);
+
+    free_pdu(s, pdu);
+}
+
+static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
+{
+    /* Note: The following have been added to prevent GCC from complaining
+     * They will be removed in the subsequent patches */
+    (void)pdu_unmarshal;
+    (void) complete_pdu;
+
+}
 static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
 {
     if (debug_9p_pdu) {
@@ -137,6 +379,7 @@ static void v9fs_create(V9fsState *s, V9fsPDU *pdu)
 
 static void v9fs_flush(V9fsState *s, V9fsPDU *pdu)
 {
+    v9fs_dummy(s, pdu);
     if (debug_9p_pdu) {
         pprint_pdu(pdu);
     }
-- 
1.7.0.4.360.g11766c

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

* [Qemu-devel] [PATCH -V4 04/21] virtio-9p: Add string manipulation support.
  2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (2 preceding siblings ...)
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 03/21] virtio-9p: pdu processing support Aneesh Kumar K.V
@ 2010-04-09 11:43 ` Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 05/21] virtio-9p: Add minimal set of FileOperations Aneesh Kumar K.V
                   ` (16 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar

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

Add helpers to do string manipulation.

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 |  127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 127 insertions(+), 0 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 0b95eeb..08df084 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -21,6 +21,126 @@
 int dotu = 1;
 int debug_9p_pdu;
 
+static void v9fs_string_init(V9fsString *str)
+{
+    str->data = NULL;
+    str->size = 0;
+}
+
+static void v9fs_string_free(V9fsString *str)
+{
+    qemu_free(str->data);
+    str->data = NULL;
+    str->size = 0;
+}
+
+static void v9fs_string_null(V9fsString *str)
+{
+    v9fs_string_free(str);
+}
+
+static int number_to_string(void *arg, char type)
+{
+    unsigned int ret = 0;
+
+    switch (type) {
+    case 'u': {
+        unsigned int num = *(unsigned int *)arg;
+
+        do {
+            ret++;
+            num = num/10;
+        } while (num);
+        break;
+    }
+    default:
+        printf("Number_to_string: Unknown number format\n");
+        return -1;
+    }
+
+    return ret;
+}
+
+static int v9fs_string_alloc_printf(char **strp, const char *fmt, va_list ap)
+{
+    va_list ap2;
+    char *iter = (char *)fmt;
+    int len = 0;
+    int nr_args = 0;
+    char *arg_char_ptr;
+    unsigned int arg_uint;
+
+    /* Find the number of %'s that denotes an argument */
+    for (iter = strstr(iter, "%"); iter; iter = strstr(iter, "%")) {
+        nr_args++;
+        iter++;
+    }
+
+    len = strlen(fmt) - 2*nr_args;
+
+    if (!nr_args) {
+        goto alloc_print;
+    }
+
+    va_copy(ap2, ap);
+
+    iter = (char *)fmt;
+
+    /* Now parse the format string */
+    for (iter = strstr(iter, "%"); iter; iter = strstr(iter, "%")) {
+        iter++;
+        switch (*iter) {
+        case 'u':
+            arg_uint = va_arg(ap2, unsigned int);
+            len += number_to_string((void *)&arg_uint, 'u');
+            break;
+        case 's':
+            arg_char_ptr = va_arg(ap2, char *);
+            len += strlen(arg_char_ptr);
+            break;
+        case 'c':
+            len += 1;
+            break;
+        default:
+            fprintf(stderr,
+		    "v9fs_string_alloc_printf:Incorrect format %c", *iter);
+            return -1;
+        }
+        iter++;
+    }
+
+alloc_print:
+    *strp = qemu_malloc((len + 1) * sizeof(**strp));
+
+    return vsprintf(*strp, fmt, ap);
+}
+
+static void v9fs_string_sprintf(V9fsString *str, const char *fmt, ...)
+{
+    va_list ap;
+    int err;
+
+    v9fs_string_free(str);
+
+    va_start(ap, fmt);
+    err = v9fs_string_alloc_printf(&str->data, fmt, ap);
+    BUG_ON(err == -1);
+    va_end(ap);
+
+    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;
+}
+
 static V9fsPDU *alloc_pdu(V9fsState *s)
 {
     V9fsPDU *pdu = NULL;
@@ -313,6 +433,13 @@ static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
      * They will be removed in the subsequent patches */
     (void)pdu_unmarshal;
     (void) complete_pdu;
+    (void) v9fs_string_init;
+    (void) v9fs_string_free;
+    (void) v9fs_string_null;
+    (void) v9fs_string_sprintf;
+    (void) v9fs_string_copy;
+    (void) v9fs_string_size;
+
 
 }
 static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
-- 
1.7.0.4.360.g11766c

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

* [Qemu-devel] [PATCH -V4 05/21] virtio-9p: Add minimal set of FileOperations
  2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (3 preceding siblings ...)
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 04/21] virtio-9p: Add string manipulation support Aneesh Kumar K.V
@ 2010-04-09 11:43 ` Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 06/21] virtio-9p: Add fid and qid management support Aneesh Kumar K.V
                   ` (15 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar

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

Add minimal set of FileOperations and the corresponding implementations for
local fstype. These will be required for the FID management patches later on.

[aneesh.kumar@linux.vnet.ibm.com: rpath fix ]
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/file-op-9p.h      |    5 +++
 hw/virtio-9p-local.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/virtio-9p.c       |   43 ++++++++++++++++++++++++++-
 3 files changed, 124 insertions(+), 2 deletions(-)

diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index 7cde63c..461df9e 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -27,6 +27,11 @@ typedef struct FsContext
 
 typedef struct FileOperations
 {
+    int (*lstat)(FsContext *, const char *, struct stat *);
+    ssize_t (*readlink)(FsContext *, const char *, char *, size_t);
+    int (*setuid)(FsContext *, uid_t);
+    int (*close)(FsContext *, int);
+    int (*closedir)(FsContext *, DIR *);
     void *opaque;
 } FileOperations;
 #endif
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 379af60..880cd0a 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -12,6 +12,84 @@
  */
 #include "virtio.h"
 #include "virtio-9p.h"
+#include <pwd.h>
+#include <grp.h>
+
+static const char *rpath(FsContext *ctx, const char *path)
+{
+    /* FIXME: so wrong... */
+    static char buffer[4096];
+    snprintf(buffer, sizeof(buffer), "%s/%s", ctx->fs_root, path);
+    return buffer;
+}
+
+static int local_lstat(FsContext *ctx, const char *path, struct stat *stbuf)
+{
+    return lstat(rpath(ctx, path), stbuf);
+}
+
+static int local_setuid(FsContext *ctx, 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 ssize_t local_readlink(FsContext *ctx, const char *path,
+                                char *buf, size_t bufsz)
+{
+    return readlink(rpath(ctx, path), buf, bufsz);
+}
+
+static int local_close(FsContext *ctx, int fd)
+{
+    return close(fd);
+}
+
+static int local_closedir(FsContext *ctx, DIR *dir)
+{
+    return closedir(dir);
+}
 
 FileOperations local_ops = {
+    .lstat = local_lstat,
+    .setuid = local_setuid,
+    .readlink = local_readlink,
+    .close = local_close,
+    .closedir = local_closedir,
 };
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 08df084..528c9cc 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -21,6 +21,41 @@
 int dotu = 1;
 int debug_9p_pdu;
 
+static int v9fs_do_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf)
+{
+    return s->ops->lstat(&s->ctx, path->data, stbuf);
+}
+
+static int v9fs_do_setuid(V9fsState *s, uid_t uid)
+{
+    return s->ops->setuid(&s->ctx, uid);
+}
+
+static ssize_t v9fs_do_readlink(V9fsState *s, V9fsString *path, V9fsString *buf)
+{
+    ssize_t len;
+
+    buf->data = qemu_malloc(1024);
+
+    len = s->ops->readlink(&s->ctx, path->data, buf->data, 1024 - 1);
+    if (len > -1) {
+        buf->size = len;
+        buf->data[len] = 0;
+    }
+
+    return len;
+}
+
+static int v9fs_do_close(V9fsState *s, int fd)
+{
+    return s->ops->close(&s->ctx, fd);
+}
+
+static int v9fs_do_closedir(V9fsState *s, DIR *dir)
+{
+    return s->ops->closedir(&s->ctx, dir);
+}
+
 static void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -439,9 +474,13 @@ static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
     (void) v9fs_string_sprintf;
     (void) v9fs_string_copy;
     (void) v9fs_string_size;
-
-
+    (void) v9fs_do_lstat;
+    (void) v9fs_do_setuid;
+    (void) v9fs_do_readlink;
+    (void) v9fs_do_close;
+    (void) v9fs_do_closedir;
 }
+
 static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
 {
     if (debug_9p_pdu) {
-- 
1.7.0.4.360.g11766c

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

* [Qemu-devel] [PATCH -V4 06/21] virtio-9p: Add fid and qid management support.
  2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (4 preceding siblings ...)
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 05/21] virtio-9p: Add minimal set of FileOperations Aneesh Kumar K.V
@ 2010-04-09 11:43 ` Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 07/21] virtio-9p: Add stat and mode related helper functions Aneesh Kumar K.V
                   ` (14 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar

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

Helper APIs for FID and QID management.

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 |  123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 123 insertions(+), 0 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 528c9cc..7db157a 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -176,6 +176,126 @@ static size_t v9fs_string_size(V9fsString *str)
     return str->size;
 }
 
+static V9fsFidState *lookup_fid(V9fsState *s, int32_t fid)
+{
+    V9fsFidState *f;
+
+    for (f = s->fid_list; f; f = f->next) {
+        if (f->fid == fid) {
+            v9fs_do_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));
+
+    f->fid = fid;
+    f->fd = -1;
+    f->dir = NULL;
+
+    f->next = s->fid_list;
+    s->fid_list = f;
+
+    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) {
+        v9fs_do_close(s, fidp->fd);
+    }
+    if (fidp->dir) {
+        v9fs_do_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
+
+#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_TYPE_BITS (P9_STAT_MODE_DIR |          \
+                                P9_STAT_MODE_SYMLINK |      \
+                                P9_STAT_MODE_LINK |         \
+                                P9_STAT_MODE_DEVICE |       \
+                                P9_STAT_MODE_NAMED_PIPE |   \
+                                P9_STAT_MODE_SOCKET)
+
+/* This is the algorithm from ufs in spfs */
+static void stat_to_qid(const struct stat *stbuf, V9fsQID *qidp)
+{
+    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 int fid_to_qid(V9fsState *s, V9fsFidState *fidp, V9fsQID *qidp)
+{
+    struct stat stbuf;
+    int err;
+
+    err = v9fs_do_lstat(s, &fidp->path, &stbuf);
+    if (err) {
+        return err;
+    }
+
+    stat_to_qid(&stbuf, qidp);
+    return 0;
+}
+
 static V9fsPDU *alloc_pdu(V9fsState *s)
 {
     V9fsPDU *pdu = NULL;
@@ -479,6 +599,9 @@ static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
     (void) v9fs_do_readlink;
     (void) v9fs_do_close;
     (void) v9fs_do_closedir;
+    (void) alloc_fid;
+    (void) free_fid;
+    (void) fid_to_qid;
 }
 
 static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
-- 
1.7.0.4.360.g11766c

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

* [Qemu-devel] [PATCH -V4 07/21] virtio-9p: Add stat and mode related helper functions.
  2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (5 preceding siblings ...)
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 06/21] virtio-9p: Add fid and qid management support Aneesh Kumar K.V
@ 2010-04-09 11:43 ` Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 08/21] virtio-9p: Add sg " Aneesh Kumar K.V
                   ` (13 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar

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

Add helpers to obtain file stat and mode details.

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 |  186 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 186 insertions(+), 0 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 7db157a..4b3ce2f 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -582,6 +582,188 @@ static void complete_pdu(V9fsState *s, V9fsPDU *pdu, ssize_t len)
     free_pdu(s, 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;
+}
+
+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;
+    }
+
+    return 0;
+}
+
+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 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 int 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 = v9fs_do_readlink(s, name, &v9stat->extension);
+            if (err == -1) {
+                err = -errno;
+                return err;
+            }
+            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));
+        } else if (S_ISDIR(stbuf->st_mode) || S_ISREG(stbuf->st_mode)) {
+            v9fs_string_sprintf(&v9stat->extension, "%s %u",
+                    "HARDLINKCOUNT", stbuf->st_nlink);
+        }
+    }
+
+    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);
+    return 0;
+}
+
 static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
 {
     /* Note: The following have been added to prevent GCC from complaining
@@ -602,6 +784,10 @@ static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
     (void) alloc_fid;
     (void) free_fid;
     (void) fid_to_qid;
+    (void) v9mode_to_mode;
+    (void) donttouch_stat;
+    (void) v9fs_stat_free;
+    (void) stat_to_v9stat;
 }
 
 static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
-- 
1.7.0.4.360.g11766c

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

* [Qemu-devel] [PATCH -V4 08/21] virtio-9p: Add sg helper functions
  2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (6 preceding siblings ...)
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 07/21] virtio-9p: Add stat and mode related helper functions Aneesh Kumar K.V
@ 2010-04-09 11:43 ` Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 09/21] virtio-9p: Add P9_TVERSION support Aneesh Kumar K.V
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar

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

Add scatter-gather helper functions.

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 |   53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 53 insertions(+), 0 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 4b3ce2f..5dab1d3 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -764,6 +764,56 @@ static int stat_to_v9stat(V9fsState *s, V9fsString *name,
     return 0;
 }
 
+static struct iovec *adjust_sg(struct iovec *sg, int len, int *iovcnt)
+{
+    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");
+}
+
 static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
 {
     /* Note: The following have been added to prevent GCC from complaining
@@ -788,6 +838,9 @@ static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
     (void) donttouch_stat;
     (void) v9fs_stat_free;
     (void) stat_to_v9stat;
+    (void) adjust_sg;
+    (void) cap_sg;
+    (void) print_sg;
 }
 
 static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
-- 
1.7.0.4.360.g11766c

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

* [Qemu-devel] [PATCH -V4 09/21] virtio-9p: Add P9_TVERSION support
  2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (7 preceding siblings ...)
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 08/21] virtio-9p: Add sg " Aneesh Kumar K.V
@ 2010-04-09 11:43 ` Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 10/21] virtio-9p: Add P9_TATTACH support Aneesh Kumar K.V
                   ` (11 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar

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

Implement P9_TVERSION support.

[sripathik@in.ibm.com: Handle unknown 9P versions as per the standards]

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 |   15 +++++++++++++--
 1 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 5dab1d3..ccc45a3 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -845,9 +845,20 @@ static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
 
 static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu) {
-        pprint_pdu(pdu);
+    int32_t msize;
+    V9fsString version;
+    size_t offset = 7;
+
+    pdu_unmarshal(pdu, offset, "ds", &msize, &version);
+
+    if (strcmp(version.data, "9P2000.u")) {
+        v9fs_string_sprintf(&version, "unknown");
     }
+
+    offset += pdu_marshal(pdu, offset, "ds", msize, &version);
+    complete_pdu(s, pdu, offset);
+
+    v9fs_string_free(&version);
 }
 
 static void v9fs_attach(V9fsState *s, V9fsPDU *pdu)
-- 
1.7.0.4.360.g11766c

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

* [Qemu-devel] [PATCH -V4 10/21] virtio-9p: Add P9_TATTACH support.
  2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (8 preceding siblings ...)
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 09/21] virtio-9p: Add P9_TVERSION support Aneesh Kumar K.V
@ 2010-04-09 11:43 ` Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 11/21] virtio-9p: Add P9_TSTAT support Aneesh Kumar K.V
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar

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

Implement P9_TATTACH support.

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 |   33 +++++++++++++++++++++++++++++++--
 1 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index ccc45a3..4ab4f9a 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -863,9 +863,38 @@ 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", "/");
+    err = fid_to_qid(s, fidp, &qid);
+    if (err) {
+        err = -EINVAL;
+        free_fid(s, fid);
+        goto out;
+    }
+
+    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)
-- 
1.7.0.4.360.g11766c

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

* [Qemu-devel] [PATCH -V4 11/21] virtio-9p: Add P9_TSTAT support
  2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (9 preceding siblings ...)
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 10/21] virtio-9p: Add P9_TATTACH support Aneesh Kumar K.V
@ 2010-04-09 11:43 ` Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 12/21] virtio-9p: Add P9_TWALK support Aneesh Kumar K.V
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar

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

Implement P9_TSTAT support. 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: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p.c |   55 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 4ab4f9a..342eb5e 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -897,11 +897,62 @@ out:
     v9fs_string_free(&aname);
 }
 
+typedef struct V9fsStatState {
+    V9fsPDU *pdu;
+    size_t offset;
+    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;
+    }
+
+    err = stat_to_v9stat(s, &vs->fidp->path, &vs->stbuf, &vs->v9stat);
+    if (err) {
+        goto out;
+    }
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "wS", 0, &vs->v9stat);
+    err = vs->offset;
+
+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);
+    int32_t fid;
+    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", &fid);
+
+    vs->fidp = lookup_fid(s, fid);
+    if (vs->fidp == NULL) {
+        err = -ENOENT;
+        goto out;
     }
+
+    err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
+    v9fs_stat_post_lstat(s, vs, err);
+    return;
+
+out:
+    complete_pdu(s, vs->pdu, err);
+    v9fs_stat_free(&vs->v9stat);
+    qemu_free(vs);
 }
 
 static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
-- 
1.7.0.4.360.g11766c

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

* [Qemu-devel] [PATCH -V4 12/21] virtio-9p: Add P9_TWALK support
  2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (10 preceding siblings ...)
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 11/21] virtio-9p: Add P9_TSTAT support Aneesh Kumar K.V
@ 2010-04-09 11:43 ` Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 13/21] virtio-9p: Add P9_TOPEN support Aneesh Kumar K.V
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar

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

Implement P9_TWALK support.

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 |  173 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 171 insertions(+), 2 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 342eb5e..572f341 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -955,11 +955,180 @@ out:
     qemu_free(vs);
 }
 
+typedef struct V9fsWalkState {
+    V9fsPDU *pdu;
+    size_t offset;
+    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->newfidp->fid);
+        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 = v9fs_do_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 = v9fs_do_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);
+    int32_t fid, newfid;
+    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", &fid,
+                                            &newfid, &vs->nwnames);
+
+    if (vs->nwnames) {
+        vs->wnames = qemu_mallocz(sizeof(vs->wnames[0]) * vs->nwnames);
+
+        vs->qids = qemu_mallocz(sizeof(vs->qids[0]) * vs->nwnames);
+
+        for (i = 0; i < vs->nwnames; i++) {
+            vs->offset += pdu_unmarshal(vs->pdu, vs->offset, "s",
+                                            &vs->wnames[i]);
+        }
+    }
+
+    vs->fidp = lookup_fid(s, fid);
+    if (vs->fidp == NULL) {
+        err = -ENOENT;
+        goto out;
+    }
+
+    /* FIXME: is this really valid? */
+    if (fid == newfid) {
+
+        BUG_ON(vs->fidp->fd != -1);
+        BUG_ON(vs->fidp->dir);
+        v9fs_string_init(&vs->path);
+        vs->name_idx = 0;
+
+        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 = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
+            v9fs_walk_post_oldfid_lstat(s, vs, err);
+            return;
+        }
+    } else {
+        vs->newfidp = alloc_fid(s, 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 = v9fs_do_lstat(s, &vs->newfidp->path, &vs->stbuf);
+            v9fs_walk_post_newfid_lstat(s, vs, err);
+            return;
+        }
     }
+
+    v9fs_walk_marshal(vs);
+    err = vs->offset;
+out:
+    v9fs_walk_complete(s, vs, err);
 }
 
 static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
-- 
1.7.0.4.360.g11766c

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

* [Qemu-devel] [PATCH -V4 13/21] virtio-9p: Add P9_TOPEN support.
  2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (11 preceding siblings ...)
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 12/21] virtio-9p: Add P9_TWALK support Aneesh Kumar K.V
@ 2010-04-09 11:43 ` Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 14/21] virtio-9p: Add P9_TREAD support Aneesh Kumar K.V
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar

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

Implement P9_TOPEN support.

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

diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index 461df9e..715f2d0 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -32,6 +32,8 @@ typedef struct FileOperations
     int (*setuid)(FsContext *, uid_t);
     int (*close)(FsContext *, int);
     int (*closedir)(FsContext *, DIR *);
+    DIR *(*opendir)(FsContext *, const char *);
+    int (*open)(FsContext *, const char *, int);
     void *opaque;
 } FileOperations;
 #endif
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 880cd0a..3788d4e 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -86,10 +86,22 @@ static int local_closedir(FsContext *ctx, DIR *dir)
     return closedir(dir);
 }
 
+static int local_open(FsContext *ctx, const char *path, int flags)
+{
+    return open(rpath(ctx, path), flags);
+}
+
+static DIR *local_opendir(FsContext *ctx, const char *path)
+{
+    return opendir(rpath(ctx, path));
+}
+
 FileOperations local_ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
     .readlink = local_readlink,
     .close = local_close,
     .closedir = local_closedir,
+    .open = local_open,
+    .opendir = local_opendir,
 };
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 572f341..f4b7889 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -56,6 +56,16 @@ static int v9fs_do_closedir(V9fsState *s, DIR *dir)
     return s->ops->closedir(&s->ctx, dir);
 }
 
+static int v9fs_do_open(V9fsState *s, V9fsString *path, int flags)
+{
+    return s->ops->open(&s->ctx, path->data, flags);
+}
+
+static DIR *v9fs_do_opendir(V9fsState *s, V9fsString *path)
+{
+    return s->ops->opendir(&s->ctx, path->data);
+}
+
 static void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -1131,17 +1141,150 @@ out:
     v9fs_walk_complete(s, vs, err);
 }
 
-static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
+typedef struct V9fsOpenState {
+    V9fsPDU *pdu;
+    size_t offset;
+    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)
+{
+    if (err) {
+        err = -errno;
+        goto out;
+    }
+
+    stat_to_qid(&vs->stbuf, &vs->qid);
+
+    if (S_ISDIR(vs->stbuf.st_mode)) {
+        vs->fidp->dir = v9fs_do_opendir(s, &vs->fidp->path);
+        v9fs_open_post_opendir(s, vs, err);
+    } else {
+        vs->fidp->fd = v9fs_do_open(s, &vs->fidp->path,
+                                    omode_to_uflags(vs->mode));
+        v9fs_open_post_open(s, vs, err);
+    }
+    return;
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
 }
 
 static void v9fs_open(V9fsState *s, V9fsPDU *pdu)
-{    if (debug_9p_pdu) {
+{
+    int32_t fid;
+    V9fsOpenState *vs;
+    ssize_t err = 0;
+
+
+    vs = qemu_malloc(sizeof(*vs));
+    vs->pdu = pdu;
+    vs->offset = 7;
+
+    pdu_unmarshal(vs->pdu, vs->offset, "db", &fid, &vs->mode);
+
+    vs->fidp = lookup_fid(s, fid);
+    if (vs->fidp == NULL) {
+        err = -ENOENT;
+        goto out;
+    }
+
+    BUG_ON(vs->fidp->fd != -1);
+    BUG_ON(vs->fidp->dir);
+
+    err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
+
+    v9fs_open_post_lstat(s, vs, err);
+    return;
+out:
+    complete_pdu(s, pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
         pprint_pdu(pdu);
-     }
+    }
 }
 
 static void v9fs_read(V9fsState *s, V9fsPDU *pdu)
-- 
1.7.0.4.360.g11766c

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

* [Qemu-devel] [PATCH -V4 14/21] virtio-9p: Add P9_TREAD support
  2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (12 preceding siblings ...)
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 13/21] virtio-9p: Add P9_TOPEN support Aneesh Kumar K.V
@ 2010-04-09 11:43 ` Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 15/21] virtio-9p: Add P9_TCLUNK support Aneesh Kumar K.V
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar

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

Implement P9_TREAD support.

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

diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index 715f2d0..c1f5e45 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -34,6 +34,12 @@ typedef struct FileOperations
     int (*closedir)(FsContext *, DIR *);
     DIR *(*opendir)(FsContext *, const char *);
     int (*open)(FsContext *, const char *, int);
+    void (*rewinddir)(FsContext *, DIR *);
+    off_t (*telldir)(FsContext *, DIR *);
+    struct dirent *(*readdir)(FsContext *, DIR *);
+    void (*seekdir)(FsContext *, DIR *, off_t);
+    ssize_t (*readv)(FsContext *, int, const struct iovec *, int);
+    off_t (*lseek)(FsContext *, int, off_t, int);
     void *opaque;
 } FileOperations;
 #endif
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 3788d4e..81d1971 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -96,6 +96,37 @@ static DIR *local_opendir(FsContext *ctx, const char *path)
     return opendir(rpath(ctx, path));
 }
 
+static void local_rewinddir(FsContext *ctx, DIR *dir)
+{
+    return rewinddir(dir);
+}
+
+static off_t local_telldir(FsContext *ctx, DIR *dir)
+{
+    return telldir(dir);
+}
+
+static struct dirent *local_readdir(FsContext *ctx, DIR *dir)
+{
+    return readdir(dir);
+}
+
+static void local_seekdir(FsContext *ctx, DIR *dir, off_t off)
+{
+    return seekdir(dir, off);
+}
+
+static ssize_t local_readv(FsContext *ctx, int fd, const struct iovec *iov,
+                            int iovcnt)
+{
+    return readv(fd, iov, iovcnt);
+}
+
+static off_t local_lseek(FsContext *ctx, int fd, off_t offset, int whence)
+{
+    return lseek(fd, offset, whence);
+}
+
 FileOperations local_ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
@@ -104,4 +135,10 @@ FileOperations local_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,
 };
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index f4b7889..e702c5c 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -66,6 +66,37 @@ static DIR *v9fs_do_opendir(V9fsState *s, V9fsString *path)
     return s->ops->opendir(&s->ctx, path->data);
 }
 
+static void v9fs_do_rewinddir(V9fsState *s, DIR *dir)
+{
+    return s->ops->rewinddir(&s->ctx, dir);
+}
+
+static off_t v9fs_do_telldir(V9fsState *s, DIR *dir)
+{
+    return s->ops->telldir(&s->ctx, dir);
+}
+
+static struct dirent *v9fs_do_readdir(V9fsState *s, DIR *dir)
+{
+    return s->ops->readdir(&s->ctx, dir);
+}
+
+static void v9fs_do_seekdir(V9fsState *s, DIR *dir, off_t off)
+{
+    return s->ops->seekdir(&s->ctx, dir, off);
+}
+
+static int v9fs_do_readv(V9fsState *s, int fd, const struct iovec *iov,
+                            int iovcnt)
+{
+    return s->ops->readv(&s->ctx, fd, iov, iovcnt);
+}
+
+static off_t v9fs_do_lseek(V9fsState *s, int fd, off_t offset, int whence)
+{
+    return s->ops->lseek(&s->ctx, fd, offset, whence);
+}
+
 static void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -1287,11 +1318,210 @@ static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
     }
 }
 
+typedef struct V9fsReadState {
+    V9fsPDU *pdu;
+    size_t offset;
+    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)
+{
+    if (err) {
+        goto out;
+    }
+    v9fs_stat_free(&vs->v9stat);
+    v9fs_string_free(&vs->name);
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->count);
+    vs->offset += vs->count;
+    err = vs->offset;
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+    return;
+}
+
+static void v9fs_read_post_dir_lstat(V9fsState *s, V9fsReadState *vs,
+                                    ssize_t err)
+{
+    if (err) {
+        err = -errno;
+        goto out;
+    }
+    err = stat_to_v9stat(s, &vs->name, &vs->stbuf, &vs->v9stat);
+    if (err) {
+        goto out;
+    }
+
+    vs->len = pdu_marshal(vs->pdu, vs->offset + 4 + vs->count, "S",
+                            &vs->v9stat);
+    if ((vs->len != (vs->v9stat.size + 2)) ||
+            ((vs->count + vs->len) > vs->max_count)) {
+        v9fs_do_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 = v9fs_do_readdir(s, vs->fidp->dir);
+    v9fs_read_post_readdir(s, vs, err);
+    return;
+out:
+    v9fs_do_seekdir(s, vs->fidp->dir, vs->dir_pos);
+    v9fs_read_post_seekdir(s, vs, err);
+    return;
+
+}
+
+static void v9fs_read_post_readdir(V9fsState *s, V9fsReadState *vs, ssize_t err)
+{
+    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 = v9fs_do_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 = v9fs_do_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 = v9fs_do_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)
+{
+    if (err  < 0) {
+        /* IO error return the error */
+        err = -errno;
+        goto out;
+    }
+    vs->total += vs->len;
+    vs->sg = adjust_sg(vs->sg, vs->len, &vs->cnt);
+    if (vs->total < vs->count && vs->len > 0) {
+        do {
+            if (0) {
+                print_sg(vs->sg, vs->cnt);
+            }
+            vs->len = v9fs_do_readv(s, vs->fidp->fd, vs->sg, vs->cnt);
+        } while (vs->len == -1 && errno == EINTR);
+        if (vs->len == -1) {
+            err  = -errno;
+        }
+        v9fs_read_post_readv(s, vs, err);
+        return;
+    }
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->total);
+    vs->offset += vs->count;
+    err = vs->offset;
+
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_read_post_lseek(V9fsState *s, V9fsReadState *vs, ssize_t err)
+{
+    if (err == -1) {
+        err = -errno;
+        goto out;
+    }
+    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 = v9fs_do_readv(s, vs->fidp->fd, vs->sg, vs->cnt);
+        } while (vs->len == -1 && errno == EINTR);
+        if (vs->len == -1) {
+            err  = -errno;
+        }
+        v9fs_read_post_readv(s, vs, err);
+        return;
+    }
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
 static void v9fs_read(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu) {
-        pprint_pdu(pdu);
+    int32_t fid;
+    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", &fid, &vs->off, &vs->count);
+
+    vs->fidp = lookup_fid(s, 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) {
+            v9fs_do_rewinddir(s, vs->fidp->dir);
+        }
+        v9fs_read_post_rewinddir(s, vs, err);
+        return;
+    } else if (vs->fidp->fd != -1) {
+        vs->sg = vs->iov;
+        pdu_marshal(vs->pdu, vs->offset + 4, "v", vs->sg, &vs->cnt);
+        err = v9fs_do_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_write(V9fsState *s, V9fsPDU *pdu)
-- 
1.7.0.4.360.g11766c

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

* [Qemu-devel] [PATCH -V4 15/21] virtio-9p: Add P9_TCLUNK support
  2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (13 preceding siblings ...)
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 14/21] virtio-9p: Add P9_TREAD support Aneesh Kumar K.V
@ 2010-04-09 11:43 ` Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 16/21] virtio-9p: Add P9_TWRITE support Aneesh Kumar K.V
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar

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

Implement P9_TCLUNK support.
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 e702c5c..480f68b 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -1313,9 +1313,21 @@ 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);
 }
 
 typedef struct V9fsReadState {
-- 
1.7.0.4.360.g11766c

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

* [Qemu-devel] [PATCH -V4 16/21] virtio-9p: Add P9_TWRITE support
  2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (14 preceding siblings ...)
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 15/21] virtio-9p: Add P9_TCLUNK support Aneesh Kumar K.V
@ 2010-04-09 11:43 ` Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 17/21] virtio-9p: Add P9_TCREATE support Aneesh Kumar K.V
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar

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

Implement P9_TWRITE support.
This gets write to file 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/file-op-9p.h      |    1 +
 hw/virtio-9p-local.c |    7 +++
 hw/virtio-9p.c       |  112 +++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 118 insertions(+), 2 deletions(-)

diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index c1f5e45..12503c1 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -39,6 +39,7 @@ typedef struct FileOperations
     struct dirent *(*readdir)(FsContext *, DIR *);
     void (*seekdir)(FsContext *, DIR *, off_t);
     ssize_t (*readv)(FsContext *, int, const struct iovec *, int);
+    ssize_t (*writev)(FsContext *, int, const struct iovec *, int);
     off_t (*lseek)(FsContext *, int, off_t, int);
     void *opaque;
 } FileOperations;
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 81d1971..87aeba8 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -127,6 +127,12 @@ static off_t local_lseek(FsContext *ctx, int fd, off_t offset, int whence)
     return lseek(fd, offset, whence);
 }
 
+static ssize_t local_writev(FsContext *ctx, int fd, const struct iovec *iov,
+                            int iovcnt)
+{
+    return writev(fd, iov, iovcnt);
+}
+
 FileOperations local_ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
@@ -141,4 +147,5 @@ FileOperations local_ops = {
     .seekdir = local_seekdir,
     .readv = local_readv,
     .lseek = local_lseek,
+    .writev = local_writev,
 };
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 480f68b..03d8696 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -97,6 +97,12 @@ static off_t v9fs_do_lseek(V9fsState *s, int fd, off_t offset, int whence)
     return s->ops->lseek(&s->ctx, fd, offset, whence);
 }
 
+static int v9fs_do_writev(V9fsState *s, int fd, const struct iovec *iov,
+                       int iovcnt)
+{
+    return s->ops->writev(&s->ctx, fd, iov, iovcnt);
+}
+
 static void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -1536,11 +1542,113 @@ out:
     qemu_free(vs);
 }
 
+typedef struct V9fsWriteState {
+    V9fsPDU *pdu;
+    size_t offset;
+    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)
+{
+    if (err  < 0) {
+        /* IO error return the error */
+        err = -errno;
+        goto out;
+    }
+    vs->total += vs->len;
+    vs->sg = adjust_sg(vs->sg, vs->len, &vs->cnt);
+    if (vs->total < vs->count && vs->len > 0) {
+        do {
+            if (0) {
+                print_sg(vs->sg, vs->cnt);
+            }
+            vs->len =  v9fs_do_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
+        } while (vs->len == -1 && errno == EINTR);
+        if (vs->len == -1) {
+            err  = -errno;
+        }
+        v9fs_write_post_writev(s, vs, err);
+        return;
+    }
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->total);
+
+    err = vs->offset;
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_write_post_lseek(V9fsState *s, V9fsWriteState *vs, ssize_t err)
+{
+    if (err == -1) {
+        err = -errno;
+        goto out;
+    }
+    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 = v9fs_do_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
+        } while (vs->len == -1 && errno == EINTR);
+        if (vs->len == -1) {
+            err  = -errno;
+        }
+        v9fs_write_post_writev(s, vs, err);
+        return;
+    }
+
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
 static void v9fs_write(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu) {
-        pprint_pdu(pdu);
+    int32_t fid;
+    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", &fid, &vs->off, &vs->count,
+                    vs->sg, &vs->cnt);
+
+    vs->fidp = lookup_fid(s, fid);
+    if (vs->fidp == NULL) {
+        err = -EINVAL;
+        goto out;
     }
+
+    if (vs->fidp->fd == -1) {
+        err = -EINVAL;
+        goto out;
+    }
+
+    err = v9fs_do_lseek(s, vs->fidp->fd, vs->off, SEEK_SET);
+
+    v9fs_write_post_lseek(s, vs, err);
+    return;
+
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
 }
 
 static void v9fs_create(V9fsState *s, V9fsPDU *pdu)
-- 
1.7.0.4.360.g11766c

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

* [Qemu-devel] [PATCH -V4 17/21] virtio-9p: Add P9_TCREATE support
  2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (15 preceding siblings ...)
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 16/21] virtio-9p: Add P9_TWRITE support Aneesh Kumar K.V
@ 2010-04-09 11:43 ` Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 18/21] virtio-9p: Add P9_TWSTAT support Aneesh Kumar K.V
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar

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

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

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

diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index 12503c1..5049b2e 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -29,11 +29,17 @@ typedef struct FileOperations
 {
     int (*lstat)(FsContext *, const char *, struct stat *);
     ssize_t (*readlink)(FsContext *, const char *, char *, size_t);
+    int (*chmod)(FsContext *, const char *, mode_t);
+    int (*mknod)(FsContext *, const char *, mode_t, dev_t);
+    int (*mksock)(FsContext *, const char *);
+    int (*symlink)(FsContext *, const char *, const char *);
+    int (*link)(FsContext *, const char *, const char *);
     int (*setuid)(FsContext *, uid_t);
     int (*close)(FsContext *, int);
     int (*closedir)(FsContext *, DIR *);
     DIR *(*opendir)(FsContext *, const char *);
     int (*open)(FsContext *, const char *, int);
+    int (*open2)(FsContext *, const char *, int, mode_t);
     void (*rewinddir)(FsContext *, DIR *);
     off_t (*telldir)(FsContext *, DIR *);
     struct dirent *(*readdir)(FsContext *, DIR *);
@@ -41,6 +47,8 @@ typedef struct FileOperations
     ssize_t (*readv)(FsContext *, int, const struct iovec *, int);
     ssize_t (*writev)(FsContext *, int, const struct iovec *, int);
     off_t (*lseek)(FsContext *, int, off_t, int);
+    int (*mkdir)(FsContext *, const char *, mode_t);
+    int (*fstat)(FsContext *, int, struct stat *);
     void *opaque;
 } FileOperations;
 #endif
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 87aeba8..f6781ca 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -12,8 +12,11 @@
  */
 #include "virtio.h"
 #include "virtio-9p.h"
+#include <arpa/inet.h>
 #include <pwd.h>
 #include <grp.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 
 static const char *rpath(FsContext *ctx, const char *path)
 {
@@ -133,6 +136,82 @@ static ssize_t local_writev(FsContext *ctx, int fd, const struct iovec *iov,
     return writev(fd, iov, iovcnt);
 }
 
+static int local_chmod(FsContext *ctx, const char *path, mode_t mode)
+{
+    return chmod(rpath(ctx, path), mode);
+}
+
+static int local_mknod(FsContext *ctx, const char *path, mode_t mode, dev_t dev)
+{
+    return mknod(rpath(ctx, path), mode, dev);
+}
+
+static int local_mksock(FsContext *ctx2, const char *path)
+{
+    struct sockaddr_un addr;
+    int s;
+
+    addr.sun_family = AF_UNIX;
+    snprintf(addr.sun_path, 108, "%s", rpath(ctx2, 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(FsContext *ctx, const char *path, mode_t mode)
+{
+    return mkdir(rpath(ctx, path), mode);
+}
+
+static int local_fstat(FsContext *ctx, int fd, struct stat *stbuf)
+{
+    return fstat(fd, stbuf);
+}
+
+static int local_open2(FsContext *ctx, const char *path, int flags, mode_t mode)
+{
+    return open(rpath(ctx, path), flags, mode);
+}
+
+static int local_symlink(FsContext *ctx, const char *oldpath,
+                            const char *newpath)
+{
+    return symlink(oldpath, rpath(ctx, newpath));
+}
+
+static int local_link(FsContext *ctx, const char *oldpath, const char *newpath)
+{
+    char *tmp = qemu_strdup(rpath(ctx, oldpath));
+    int err, serrno = 0;
+
+    if (tmp == NULL) {
+        return -ENOMEM;
+    }
+
+    err = link(tmp, rpath(ctx, newpath));
+    if (err == -1) {
+        serrno = errno;
+    }
+
+    qemu_free(tmp);
+
+    if (err == -1) {
+        errno = serrno;
+    }
+
+    return err;
+}
+
 FileOperations local_ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
@@ -148,4 +227,12 @@ FileOperations local_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,
 };
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 03d8696..faf13b2 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -103,6 +103,47 @@ static int v9fs_do_writev(V9fsState *s, int fd, const struct iovec *iov,
     return s->ops->writev(&s->ctx, fd, iov, iovcnt);
 }
 
+static int v9fs_do_chmod(V9fsState *s, V9fsString *path, mode_t mode)
+{
+    return s->ops->chmod(&s->ctx, path->data, mode);
+}
+
+static int v9fs_do_mknod(V9fsState *s, V9fsString *path, mode_t mode, dev_t dev)
+{
+    return s->ops->mknod(&s->ctx, path->data, mode, dev);
+}
+
+static int v9fs_do_mksock(V9fsState *s, V9fsString *path)
+{
+    return s->ops->mksock(&s->ctx, path->data);
+}
+
+static int v9fs_do_mkdir(V9fsState *s, V9fsString *path, mode_t mode)
+{
+    return s->ops->mkdir(&s->ctx, path->data, mode);
+}
+
+static int v9fs_do_fstat(V9fsState *s, int fd, struct stat *stbuf)
+{
+    return s->ops->fstat(&s->ctx, fd, stbuf);
+}
+
+static int v9fs_do_open2(V9fsState *s, V9fsString *path, int flags, mode_t mode)
+{
+    return s->ops->open2(&s->ctx, path->data, flags, mode);
+}
+
+static int v9fs_do_symlink(V9fsState *s, V9fsString *oldpath,
+                            V9fsString *newpath)
+{
+    return s->ops->symlink(&s->ctx, oldpath->data, newpath->data);
+}
+
+static int v9fs_do_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
+{
+    return s->ops->link(&s->ctx, oldpath->data, newpath->data);
+}
+
 static void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -1651,11 +1692,230 @@ out:
     qemu_free(vs);
 }
 
+typedef struct V9fsCreateState {
+    V9fsPDU *pdu;
+    size_t offset;
+    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 = v9fs_do_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 = v9fs_do_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 = v9fs_do_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 = v9fs_do_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 = -errno;
+        goto out;
+    }
+
+    if (vs->perm & P9_STAT_MODE_DIR) {
+        err = v9fs_do_mkdir(s, &vs->fullname, vs->perm & 0777);
+        v9fs_create_post_mkdir(s, vs, err);
+    } else if (vs->perm & P9_STAT_MODE_SYMLINK) {
+        err = v9fs_do_symlink(s, &vs->extension, &vs->fullname);
+        v9fs_create_post_perms(s, vs, err);
+    } else if (vs->perm & P9_STAT_MODE_LINK) {
+        int32_t nfid = atoi(vs->extension.data);
+        V9fsFidState *nfidp = lookup_fid(s, nfid);
+        if (nfidp == NULL) {
+            err = -errno;
+            v9fs_post_create(s, vs, err);
+        }
+        err = v9fs_do_link(s, &nfidp->path, &vs->fullname);
+        v9fs_create_post_perms(s, vs, err);
+    } else if (vs->perm & P9_STAT_MODE_DEVICE) {
+        char ctype;
+        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 = v9fs_do_mknod(s, &vs->fullname, nmode, makedev(major, minor));
+        v9fs_create_post_perms(s, vs, err);
+    } else if (vs->perm & P9_STAT_MODE_NAMED_PIPE) {
+        err = v9fs_do_mknod(s, &vs->fullname, S_IFIFO | (vs->mode & 0777), 0);
+        v9fs_post_create(s, vs, err);
+    } else if (vs->perm & P9_STAT_MODE_SOCKET) {
+        err = v9fs_do_mksock(s, &vs->fullname);
+        v9fs_create_post_mksock(s, vs, err);
+    } else {
+        vs->fidp->fd = v9fs_do_open2(s, &vs->fullname,
+                                omode_to_uflags(vs->mode) | O_CREAT,
+                                vs->perm & 0777);
+        v9fs_create_post_open2(s, vs, err);
+    }
+
+    return;
+
+out:
+    v9fs_post_create(s, vs, err);
+}
+
 static void v9fs_create(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu) {
-        pprint_pdu(pdu);
+    int32_t fid;
+    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", &fid, &vs->name,
+                                &vs->perm, &vs->mode, &vs->extension);
+
+    vs->fidp = lookup_fid(s, fid);
+    if (vs->fidp == NULL) {
+        err = -EINVAL;
+        goto out;
     }
+
+    v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->fidp->path.data,
+                                                        vs->name.data);
+
+    err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf);
+    v9fs_create_post_lstat(s, vs, err);
+    return;
+
+out:
+    complete_pdu(s, vs->pdu, err);
+    v9fs_string_free(&vs->name);
+    v9fs_string_free(&vs->extension);
+    qemu_free(vs);
 }
 
 static void v9fs_flush(V9fsState *s, V9fsPDU *pdu)
-- 
1.7.0.4.360.g11766c

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

* [Qemu-devel] [PATCH -V4 18/21] virtio-9p: Add P9_TWSTAT support
  2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (16 preceding siblings ...)
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 17/21] virtio-9p: Add P9_TCREATE support Aneesh Kumar K.V
@ 2010-04-09 11:43 ` Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 19/21] virtio-9p: Add P9_TREMOVE support Aneesh Kumar K.V
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar

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

Implement P9_TWSTAT support.
This gets file and directory creation to work.

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

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

diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index 5049b2e..8ba1927 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -30,8 +30,10 @@ typedef struct FileOperations
     int (*lstat)(FsContext *, const char *, struct stat *);
     ssize_t (*readlink)(FsContext *, const char *, char *, size_t);
     int (*chmod)(FsContext *, const char *, mode_t);
+    int (*chown)(FsContext *, const char *, uid_t, gid_t);
     int (*mknod)(FsContext *, const char *, mode_t, dev_t);
     int (*mksock)(FsContext *, const char *);
+    int (*utime)(FsContext *, const char *, const struct utimbuf *);
     int (*symlink)(FsContext *, const char *, const char *);
     int (*link)(FsContext *, const char *, const char *);
     int (*setuid)(FsContext *, uid_t);
@@ -49,6 +51,9 @@ typedef struct FileOperations
     off_t (*lseek)(FsContext *, int, off_t, int);
     int (*mkdir)(FsContext *, const char *, mode_t);
     int (*fstat)(FsContext *, int, struct stat *);
+    int (*rename)(FsContext *, const char *, const char *);
+    int (*truncate)(FsContext *, const char *, off_t);
+    int (*fsync)(FsContext *, int);
     void *opaque;
 } FileOperations;
 #endif
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index f6781ca..5a011f3 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -212,6 +212,51 @@ static int local_link(FsContext *ctx, const char *oldpath, const char *newpath)
     return err;
 }
 
+static int local_truncate(FsContext *ctx, const char *path, off_t size)
+{
+    return truncate(rpath(ctx, path), size);
+}
+
+static int local_rename(FsContext *ctx, const char *oldpath,
+                        const char *newpath)
+{
+    char *tmp;
+    int err;
+
+    tmp = qemu_strdup(rpath(ctx, oldpath));
+    if (tmp == NULL) {
+        return -1;
+    }
+
+    err = rename(tmp, rpath(ctx, newpath));
+    if (err == -1) {
+        int serrno = errno;
+        qemu_free(tmp);
+        errno = serrno;
+    } else {
+        qemu_free(tmp);
+    }
+
+    return err;
+
+}
+
+static int local_chown(FsContext *ctx, const char *path, uid_t uid, gid_t gid)
+{
+    return chown(rpath(ctx, path), uid, gid);
+}
+
+static int local_utime(FsContext *ctx, const char *path,
+                        const struct utimbuf *buf)
+{
+    return utime(rpath(ctx, path), buf);
+}
+
+static int local_fsync(FsContext *ctx, int fd)
+{
+    return fsync(fd);
+}
+
 FileOperations local_ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
@@ -235,4 +280,9 @@ FileOperations local_ops = {
     .open2 = local_open2,
     .symlink = local_symlink,
     .link = local_link,
+    .truncate = local_truncate,
+    .rename = local_rename,
+    .chown = local_chown,
+    .utime = local_utime,
+    .fsync = local_fsync,
 };
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index faf13b2..b6a635b 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -144,6 +144,33 @@ static int v9fs_do_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
     return s->ops->link(&s->ctx, oldpath->data, newpath->data);
 }
 
+static int v9fs_do_truncate(V9fsState *s, V9fsString *path, off_t size)
+{
+    return s->ops->truncate(&s->ctx, path->data, size);
+}
+
+static int v9fs_do_rename(V9fsState *s, V9fsString *oldpath,
+                            V9fsString *newpath)
+{
+    return s->ops->rename(&s->ctx, oldpath->data, newpath->data);
+}
+
+static int v9fs_do_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid)
+{
+    return s->ops->chown(&s->ctx, path->data, uid, gid);
+}
+
+static int v9fs_do_utime(V9fsState *s, V9fsString *path,
+                            const struct utimbuf *buf)
+{
+    return s->ops->utime(&s->ctx, path->data, buf);
+}
+
+static int v9fs_do_fsync(V9fsState *s, int fd)
+{
+    return s->ops->fsync(&s->ctx, fd);
+}
+
 static void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -931,6 +958,15 @@ static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
     (void) print_sg;
 }
 
+static void v9fs_fix_path(V9fsString *dst, V9fsString *src, int len)
+{
+    V9fsString str;
+    v9fs_string_init(&str);
+    v9fs_string_copy(&str, dst);
+    v9fs_string_sprintf(dst, "%s%s", src->data, str.data+len);
+    v9fs_string_free(&str);
+}
+
 static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
 {
     int32_t msize;
@@ -1933,11 +1969,244 @@ static void v9fs_remove(V9fsState *s, V9fsPDU *pdu)
     }
 }
 
+typedef struct V9fsWstatState
+{
+    V9fsPDU *pdu;
+    size_t offset;
+    int16_t unused;
+    V9fsStat v9stat;
+    V9fsFidState *fidp;
+    struct stat stbuf;
+    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 (v9fs_do_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)
+{
+    V9fsFidState *fidp;
+    if (err < 0) {
+        goto out;
+    }
+
+    if (vs->v9stat.name.size != 0) {
+        char *old_name, *new_name;
+        char *end;
+
+        old_name = vs->fidp->path.data;
+        end = strrchr(old_name, '/');
+        if (end) {
+            end++;
+        } else {
+            end = old_name;
+        }
+
+        new_name = qemu_malloc(end - old_name + vs->v9stat.name.size + 1);
+
+        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 (v9fs_do_rename(s, &vs->fidp->path, &vs->nname)) {
+                err = -errno;
+            } else {
+                /*
+                 * Fixup fid's pointing to the old name to
+                 * start pointing to the new name
+                 */
+                for (fidp = s->fid_list; fidp; fidp = fidp->next) {
+
+                    if (vs->fidp == fidp) {
+                        /*
+                         * we replace name of this fid towards the end
+                         * so that our below strcmp will work
+                         */
+                        continue;
+                    }
+                    if (!strncmp(vs->fidp->path.data, fidp->path.data,
+                                 strlen(vs->fidp->path.data))) {
+                        /* replace the name */
+                        v9fs_fix_path(&fidp->path, &vs->nname,
+                                      strlen(vs->fidp->path.data));
+                    }
+                }
+                v9fs_string_copy(&vs->fidp->path, &vs->nname);
+            }
+        }
+    }
+    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 (v9fs_do_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 (v9fs_do_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_post_fsync(V9fsState *s, V9fsWstatState *vs, int err)
+{
+    if (err == -1) {
+        err = -errno;
+    }
+    v9fs_stat_free(&vs->v9stat);
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_wstat_post_lstat(V9fsState *s, V9fsWstatState *vs, int err)
+{
+    uint32_t v9_mode;
+
+    if (err == -1) {
+        err = -errno;
+        goto out;
+    }
+
+    v9_mode = stat_to_v9mode(&vs->stbuf);
+
+    if ((vs->v9stat.mode & P9_STAT_MODE_TYPE_BITS) !=
+        (v9_mode & P9_STAT_MODE_TYPE_BITS)) {
+            /* Attempting to change the type */
+            err = -EIO;
+            goto out;
+    }
+
+    if (v9fs_do_chmod(s, &vs->fidp->path, v9mode_to_mode(vs->v9stat.mode,
+                    &vs->v9stat.extension))) {
+            err = -errno;
+     }
+    v9fs_wstat_post_chmod(s, vs, err);
+    return;
+
+out:
+    v9fs_stat_free(&vs->v9stat);
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
 static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu) {
-        pprint_pdu(pdu);
+    int32_t fid;
+    V9fsWstatState *vs;
+    int err = 0;
+
+    vs = qemu_malloc(sizeof(*vs));
+    vs->pdu = pdu;
+    vs->offset = 7;
+
+    pdu_unmarshal(pdu, vs->offset, "dwS", &fid, &vs->unused, &vs->v9stat);
+
+    vs->fidp = lookup_fid(s, fid);
+    if (vs->fidp == NULL) {
+        err = -EINVAL;
+        goto out;
     }
+
+    /* do we need to sync the file? */
+    if (donttouch_stat(&vs->v9stat)) {
+        err = v9fs_do_fsync(s, vs->fidp->fd);
+        v9fs_wstat_post_fsync(s, vs, err);
+        return;
+    }
+
+    if (vs->v9stat.mode != -1) {
+        err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
+        v9fs_wstat_post_lstat(s, vs, err);
+        return;
+    }
+
+    v9fs_wstat_post_chmod(s, vs, err);
+    return;
+
+out:
+    v9fs_stat_free(&vs->v9stat);
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
 }
 
 typedef void (pdu_handler_t)(V9fsState *s, V9fsPDU *pdu);
-- 
1.7.0.4.360.g11766c

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

* [Qemu-devel] [PATCH -V4 19/21] virtio-9p: Add P9_TREMOVE support.
  2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (17 preceding siblings ...)
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 18/21] virtio-9p: Add P9_TWSTAT support Aneesh Kumar K.V
@ 2010-04-09 11:43 ` Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 20/21] virtio-9p: Add P9_TFLUSH support Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 21/21] virtio-9p: Create a syntactic shortcut for the file-system pass-thru Aneesh Kumar K.V
  20 siblings, 0 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar

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

Implement P9_TREMOVE support.
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: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/file-op-9p.h      |    1 +
 hw/virtio-9p-local.c |    6 +++++
 hw/virtio-9p.c       |   54 ++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index 8ba1927..f84767f 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -34,6 +34,7 @@ typedef struct FileOperations
     int (*mknod)(FsContext *, const char *, mode_t, dev_t);
     int (*mksock)(FsContext *, const char *);
     int (*utime)(FsContext *, const char *, const struct utimbuf *);
+    int (*remove)(FsContext *, const char *);
     int (*symlink)(FsContext *, const char *, const char *);
     int (*link)(FsContext *, const char *, const char *);
     int (*setuid)(FsContext *, uid_t);
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 5a011f3..1afb731 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -252,6 +252,11 @@ static int local_utime(FsContext *ctx, const char *path,
     return utime(rpath(ctx, path), buf);
 }
 
+static int local_remove(FsContext *ctx, const char *path)
+{
+    return remove(rpath(ctx, path));
+}
+
 static int local_fsync(FsContext *ctx, int fd)
 {
     return fsync(fd);
@@ -284,5 +289,6 @@ FileOperations local_ops = {
     .rename = local_rename,
     .chown = local_chown,
     .utime = local_utime,
+    .remove = local_remove,
     .fsync = local_fsync,
 };
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index b6a635b..a2a9cd8 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -166,6 +166,11 @@ static int v9fs_do_utime(V9fsState *s, V9fsString *path,
     return s->ops->utime(&s->ctx, path->data, buf);
 }
 
+static int v9fs_do_remove(V9fsState *s, V9fsString *path)
+{
+    return s->ops->remove(&s->ctx, path->data);
+}
+
 static int v9fs_do_fsync(V9fsState *s, int fd)
 {
     return s->ops->fsync(&s->ctx, fd);
@@ -1962,11 +1967,56 @@ static void v9fs_flush(V9fsState *s, V9fsPDU *pdu)
     }
 }
 
+typedef struct V9fsRemoveState {
+    V9fsPDU *pdu;
+    size_t offset;
+    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->fidp->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);
+    int32_t fid;
+    V9fsRemoveState *vs;
+    int err = 0;
+
+    vs = qemu_malloc(sizeof(*vs));
+    vs->pdu = pdu;
+    vs->offset = 7;
+
+    pdu_unmarshal(vs->pdu, vs->offset, "d", &fid);
+
+    vs->fidp = lookup_fid(s, fid);
+    if (vs->fidp == NULL) {
+        err = -EINVAL;
+        goto out;
     }
+
+    err = v9fs_do_remove(s, &vs->fidp->path);
+    v9fs_remove_post_remove(s, vs, err);
+    return;
+
+out:
+    complete_pdu(s, pdu, err);
+    qemu_free(vs);
 }
 
 typedef struct V9fsWstatState
-- 
1.7.0.4.360.g11766c

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

* [Qemu-devel] [PATCH -V4 20/21] virtio-9p: Add P9_TFLUSH support
  2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (18 preceding siblings ...)
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 19/21] virtio-9p: Add P9_TREMOVE support Aneesh Kumar K.V
@ 2010-04-09 11:43 ` Aneesh Kumar K.V
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 21/21] virtio-9p: Create a syntactic shortcut for the file-system pass-thru Aneesh Kumar K.V
  20 siblings, 0 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar

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

Don't do anything special for flush.

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

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index a2a9cd8..9a97d4a 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -934,35 +934,6 @@ static void print_sg(struct iovec *sg, int cnt)
     printf("}\n");
 }
 
-static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
-{
-    /* Note: The following have been added to prevent GCC from complaining
-     * They will be removed in the subsequent patches */
-    (void)pdu_unmarshal;
-    (void) complete_pdu;
-    (void) v9fs_string_init;
-    (void) v9fs_string_free;
-    (void) v9fs_string_null;
-    (void) v9fs_string_sprintf;
-    (void) v9fs_string_copy;
-    (void) v9fs_string_size;
-    (void) v9fs_do_lstat;
-    (void) v9fs_do_setuid;
-    (void) v9fs_do_readlink;
-    (void) v9fs_do_close;
-    (void) v9fs_do_closedir;
-    (void) alloc_fid;
-    (void) free_fid;
-    (void) fid_to_qid;
-    (void) v9mode_to_mode;
-    (void) donttouch_stat;
-    (void) v9fs_stat_free;
-    (void) stat_to_v9stat;
-    (void) adjust_sg;
-    (void) cap_sg;
-    (void) print_sg;
-}
-
 static void v9fs_fix_path(V9fsString *dst, V9fsString *src, int len)
 {
     V9fsString str;
@@ -1961,10 +1932,8 @@ out:
 
 static void v9fs_flush(V9fsState *s, V9fsPDU *pdu)
 {
-    v9fs_dummy(s, pdu);
-    if (debug_9p_pdu) {
-        pprint_pdu(pdu);
-    }
+    /* A nop call with no return */
+    complete_pdu(s, pdu, 7);
 }
 
 typedef struct V9fsRemoveState {
-- 
1.7.0.4.360.g11766c

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

* [Qemu-devel] [PATCH -V4 21/21] virtio-9p: Create a syntactic shortcut for the file-system pass-thru
  2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
                   ` (19 preceding siblings ...)
  2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 20/21] virtio-9p: Add P9_TFLUSH support Aneesh Kumar K.V
@ 2010-04-09 11:43 ` Aneesh Kumar K.V
  20 siblings, 0 replies; 22+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-09 11:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: ericvh, aliguori, aneesh.kumar, Gautham R Shenoy

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

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

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

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

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

diff --git a/qemu-config.c b/qemu-config.c
index 0fb5105..06a59eb 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -169,6 +169,28 @@ QemuOptsList qemu_fsdev_opts = {
 };
 #endif
 
+#ifdef CONFIG_LINUX_VIRTFS
+QemuOptsList qemu_virtfs_opts = {
+    .name = "virtfs",
+    .implied_opt_name = "fstype",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_virtfs_opts.head),
+    .desc = {
+        {
+            .name = "fstype",
+            .type = QEMU_OPT_STRING,
+        }, {
+            .name = "path",
+            .type = QEMU_OPT_STRING,
+        }, {
+            .name = "mount_tag",
+            .type = QEMU_OPT_STRING,
+        },
+
+        { /*End of list */ }
+    },
+};
+#endif
+
 QemuOptsList qemu_device_opts = {
     .name = "device",
     .implied_opt_name = "driver",
diff --git a/qemu-config.h b/qemu-config.h
index d85bde7..546fc01 100644
--- a/qemu-config.h
+++ b/qemu-config.h
@@ -5,6 +5,7 @@ extern QemuOptsList qemu_drive_opts;
 extern QemuOptsList qemu_chardev_opts;
 #ifdef CONFIG_LINUX_VIRTFS
 extern QemuOptsList qemu_fsdev_opts;
+extern QemuOptsList qemu_virtfs_opts;
 #endif
 extern QemuOptsList qemu_device_opts;
 extern QemuOptsList qemu_netdev_opts;
diff --git a/qemu-options.hx b/qemu-options.hx
index e007df8..5da36c6 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -500,6 +500,40 @@ Create a file-system-"device" for local-filesystem.
 ETEXI
 #endif
 
+#ifdef CONFIG_LINUX_VIRTFS
+DEFHEADING(Virtual File system pass-through options:)
+
+DEF("virtfs", HAS_ARG, QEMU_OPTION_virtfs,
+    "-virtfs local,path=path,mount_tag=tag\n")
+
+STEXI
+
+The general form of a Virtual File system pass-through option is:
+@table @option
+
+@item -virtfs @var{fstype} [,@var{options}]
+@findex -virtfs
+Fstype is one of:
+@option{local},
+The specific Fstype will determine the applicable options.
+
+Options to each backend are described below.
+
+@item -virtfs local ,path=@var{path} ,mount_tag=@var{mount_tag}
+
+Create a Virtual file-system-pass through for local-filesystem.
+
+@option{local} is only available on Linux.
+
+@option{path} specifies the path to be exported. @option{path} is required.
+
+@option{mount_tag} specifies the tag with which the exported file is mounted.
+@option{mount_tag} is required.
+
+@end table
+ETEXI
+#endif
+
 DEFHEADING()
 
 DEF("name", HAS_ARG, QEMU_OPTION_name,
diff --git a/vl.c b/vl.c
index 4359825..8e71c94 100644
--- a/vl.c
+++ b/vl.c
@@ -4277,6 +4277,62 @@ int main(int argc, char **argv, char **envp)
                     exit(1);
                 }
                 break;
+            case QEMU_OPTION_virtfs: {
+                char *arg_fsdev = NULL;
+                char *arg_9p = NULL;
+                int len = 0;
+
+                opts = qemu_opts_parse(&qemu_virtfs_opts, optarg, 1);
+                if (!opts) {
+                    fprintf(stderr, "parse error: %s\n", optarg);
+                    exit(1);
+                }
+
+                len = strlen(",id=,path=");
+                len += strlen(qemu_opt_get(opts, "fstype"));
+                len += strlen(qemu_opt_get(opts, "mount_tag"));
+                len += strlen(qemu_opt_get(opts, "path"));
+                arg_fsdev = qemu_malloc((len + 1) * sizeof(*arg_fsdev));
+
+                if (!arg_fsdev) {
+                    fprintf(stderr, "No memory to parse -fsdev for %s\n",
+                            optarg);
+                    exit(1);
+                }
+
+                sprintf(arg_fsdev, "%s,id=%s,path=%s",
+                                qemu_opt_get(opts, "fstype"),
+                                qemu_opt_get(opts, "mount_tag"),
+                                qemu_opt_get(opts, "path"));
+
+                len = strlen("virtio-9p-pci,fsdev=,mount_tag=");
+                len += 2*strlen(qemu_opt_get(opts, "mount_tag"));
+                arg_9p = qemu_malloc((len + 1) * sizeof(*arg_9p));
+
+                if (!arg_9p) {
+                    fprintf(stderr, "No memory to parse -device for %s\n",
+                            optarg);
+                    exit(1);
+                }
+
+                sprintf(arg_9p, "virtio-9p-pci,fsdev=%s,mount_tag=%s",
+                                qemu_opt_get(opts, "mount_tag"),
+                                qemu_opt_get(opts, "mount_tag"));
+
+                if (!qemu_opts_parse(&qemu_fsdev_opts, arg_fsdev, 1)) {
+                    fprintf(stderr, "parse error [fsdev]: %s\n", optarg);
+                    exit(1);
+                }
+
+                if (!qemu_opts_parse(&qemu_device_opts, arg_9p, 1)) {
+                    fprintf(stderr, "parse error [device]: %s\n", optarg);
+                    exit(1);
+                }
+
+                qemu_free(arg_fsdev);
+                qemu_free(arg_9p);
+                break;
+            }
 #endif
             case QEMU_OPTION_serial:
                 add_device_config(DEV_SERIAL, optarg);
-- 
1.7.0.4.360.g11766c

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

end of thread, other threads:[~2010-04-09 11:44 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 01/21] virtio-9p: Create a commandline option -fsdev Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 02/21] virtio-9p: Add a virtio 9p device to qemu Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 03/21] virtio-9p: pdu processing support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 04/21] virtio-9p: Add string manipulation support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 05/21] virtio-9p: Add minimal set of FileOperations Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 06/21] virtio-9p: Add fid and qid management support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 07/21] virtio-9p: Add stat and mode related helper functions Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 08/21] virtio-9p: Add sg " Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 09/21] virtio-9p: Add P9_TVERSION support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 10/21] virtio-9p: Add P9_TATTACH support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 11/21] virtio-9p: Add P9_TSTAT support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 12/21] virtio-9p: Add P9_TWALK support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 13/21] virtio-9p: Add P9_TOPEN support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 14/21] virtio-9p: Add P9_TREAD support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 15/21] virtio-9p: Add P9_TCLUNK support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 16/21] virtio-9p: Add P9_TWRITE support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 17/21] virtio-9p: Add P9_TCREATE support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 18/21] virtio-9p: Add P9_TWSTAT support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 19/21] virtio-9p: Add P9_TREMOVE support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 20/21] virtio-9p: Add P9_TFLUSH support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 21/21] virtio-9p: Create a syntactic shortcut for the file-system pass-thru Aneesh Kumar K.V

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.