All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] DAPL v2.0: common: remove assert for incorrect events during cm_request
From: Davis, Arlin R @ 2011-10-31 20:53 UTC (permalink / raw)
  To: linux-rdma; +Cc: ofw-ZwoEplunGu1OwGhvXhtEPSCwEArCW2h5@public.gmane.org

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 1006 bytes --]

Simply print a warning message. Connection callback doesn't
forward invalid events to consumer so no need to assert.

Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
---
 dapl/common/dapl_evd_connection_callb.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/dapl/common/dapl_evd_connection_callb.c b/dapl/common/dapl_evd_connection_callb.c
index 3166702..a28d8d6 100644
--- a/dapl/common/dapl_evd_connection_callb.c
+++ b/dapl/common/dapl_evd_connection_callb.c
@@ -181,9 +181,10 @@ dapl_evd_connection_callback(IN dp_ib_cm_handle_t ib_cm_handle,
 	default:
 		{
 			dapl_os_unlock(&ep_ptr->header.lock);
+			dapl_log(DAPL_DBG_TYPE_WARN,
+				"dapl_evd_conn_cb() unknown event 0x%x\n",
+				dat_event_num);
 			evd_ptr = NULL;
-
-			dapl_os_assert(0);	/* shouldn't happen */
 			break;
 		}
 	}
-- 
1.7.3



N‹§²æìr¸›yúèšØb²X¬¶Ç§vØ^–)Þº{.nÇ+‰·¥Š{±­ÙšŠ{ayº\x1dʇڙë,j\a­¢f£¢·hš‹»öì\x17/oSc¾™Ú³9˜uÀ¦æå‰È&jw¨®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿïêäz¹Þ–Šàþf£¢·hšˆ§~ˆmš

^ permalink raw reply related

* [PATCH] DAPL v2.0: dat: dat_cno_query with NULL cno_handle causes segmentation fault
From: Davis, Arlin R @ 2011-10-31 20:53 UTC (permalink / raw)
  To: linux-rdma; +Cc: ofw-ZwoEplunGu1OwGhvXhtEPSCwEArCW2h5@public.gmane.org

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 823 bytes --]

add check for NULL handle in dat library

Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
---
 dat/udat/udat_api.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/dat/udat/udat_api.c b/dat/udat/udat_api.c
index 5948a4f..6c1549a 100644
--- a/dat/udat/udat_api.c
+++ b/dat/udat/udat_api.c
@@ -161,6 +161,9 @@ DAT_RETURN DAT_API dat_cno_query(IN DAT_CNO_HANDLE cno_handle,
 				 IN DAT_CNO_PARAM_MASK cno_param_mask,
 				 OUT DAT_CNO_PARAM * cno_param)
 {
+	if (cno_handle == NULL) {
+		return DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_CNO);
+	}
 	return DAT_CNO_QUERY(cno_handle, cno_param_mask, cno_param);
 }
 
-- 
1.7.3



N‹§²æìr¸›yúèšØb²X¬¶Ç§vØ^–)Þº{.nÇ+‰·¥Š{±­ÙšŠ{ayº\x1dʇڙë,j\a­¢f£¢·hš‹»öì\x17/oSc¾™Ú³9˜uÀ¦æå‰È&jw¨®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿïêäz¹Þ–Šàþf£¢·hšˆ§~ˆmš

^ permalink raw reply related

* [Qemu-devel] [PATCH 01/13] hw/9pfs: Move opt validation to FsDriver callback
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
  To: qemu-devel, aneesh.kumar
In-Reply-To: <1320094412-19091-1-git-send-email-mohan@in.ibm.com>

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

This remove all conditional code from common code path and
make opt validation a FSDriver callback.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
 fsdev/file-op-9p.h         |   15 +++++++++++++--
 fsdev/qemu-fsdev.c         |   44 ++++++--------------------------------------
 fsdev/qemu-fsdev.h         |   10 ----------
 hw/9pfs/virtio-9p-device.c |   13 ++++++++-----
 hw/9pfs/virtio-9p-handle.c |   20 ++++++++++++++++++++
 hw/9pfs/virtio-9p-local.c  |   34 ++++++++++++++++++++++++++++++++++
 vl.c                       |    8 ++------
 7 files changed, 83 insertions(+), 61 deletions(-)

diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 1928da2..22849c9 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -61,6 +61,16 @@ typedef struct extended_ops {
 #define V9FS_SEC_MASK               0x0000001C
 
 
+typedef struct FileOperations FileOperations;
+/*
+ * Structure to store the various fsdev's passed through command line.
+ */
+typedef struct FsDriverEntry {
+    char *fsdev_id;
+    char *path;
+    int export_flags;
+    FileOperations *ops;
+} FsDriverEntry;
 
 typedef struct FsContext
 {
@@ -82,8 +92,9 @@ typedef union V9fsFidOpenState V9fsFidOpenState;
 
 void cred_init(FsCred *);
 
-typedef struct FileOperations
+struct FileOperations
 {
+    int (*parse_opts)(QemuOpts *, struct FsDriverEntry *);
     int (*init)(struct FsContext *);
     int (*lstat)(FsContext *, V9fsPath *, struct stat *);
     ssize_t (*readlink)(FsContext *, V9fsPath *, char *, size_t);
@@ -128,6 +139,6 @@ typedef struct FileOperations
                     V9fsPath *newdir, const char *new_name);
     int (*unlinkat)(FsContext *ctx, V9fsPath *dir, const char *name, int flags);
     void *opaque;
-} FileOperations;
+};
 
 #endif
diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
index 7fd2aa7..efbfea1 100644
--- a/fsdev/qemu-fsdev.c
+++ b/fsdev/qemu-fsdev.c
@@ -29,12 +29,10 @@ static FsDriverTable FsDrivers[] = {
 
 int qemu_fsdev_add(QemuOpts *opts)
 {
-    struct FsDriverListEntry *fsle;
     int i;
+    struct FsDriverListEntry *fsle;
     const char *fsdev_id = qemu_opts_id(opts);
     const char *fsdriver = qemu_opt_get(opts, "fsdriver");
-    const char *path = qemu_opt_get(opts, "path");
-    const char *sec_model = qemu_opt_get(opts, "security_model");
     const char *writeout = qemu_opt_get(opts, "writeout");
     bool ro = qemu_opt_get_bool(opts, "readonly", 0);
 
@@ -59,29 +57,9 @@ int qemu_fsdev_add(QemuOpts *opts)
         return -1;
     }
 
-    if (!strcmp(fsdriver, "local") && !sec_model) {
-        fprintf(stderr, "security model not specified, "
-                "local fs needs security model\nvalid options are:"
-                "\tsecurity_model=[passthrough|mapped|none]\n");
-        return -1;
-    }
-
-    if (strcmp(fsdriver, "local") && sec_model) {
-        fprintf(stderr, "only local fs driver needs security model\n");
-        return -1;
-    }
-
-    if (!path) {
-        fprintf(stderr, "fsdev: No path specified.\n");
-        return -1;
-    }
-
-    fsle = g_malloc(sizeof(*fsle));
-
+    fsle = g_malloc0(sizeof(*fsle));
     fsle->fse.fsdev_id = g_strdup(fsdev_id);
-    fsle->fse.path = g_strdup(path);
     fsle->fse.ops = FsDrivers[i].ops;
-    fsle->fse.export_flags = 0;
     if (writeout) {
         if (!strcmp(writeout, "immediate")) {
             fsle->fse.export_flags |= V9FS_IMMEDIATE_WRITEOUT;
@@ -93,22 +71,12 @@ int qemu_fsdev_add(QemuOpts *opts)
         fsle->fse.export_flags &= ~V9FS_RDONLY;
     }
 
-    if (strcmp(fsdriver, "local")) {
-        goto done;
+    if (fsle->fse.ops->parse_opts) {
+        if (fsle->fse.ops->parse_opts(opts, &fsle->fse)) {
+            return -1;
+        }
     }
 
-    if (!strcmp(sec_model, "passthrough")) {
-        fsle->fse.export_flags |= V9FS_SM_PASSTHROUGH;
-    } else if (!strcmp(sec_model, "mapped")) {
-        fsle->fse.export_flags |= V9FS_SM_MAPPED;
-    } else if (!strcmp(sec_model, "none")) {
-        fsle->fse.export_flags |= V9FS_SM_NONE;
-    } else {
-        fprintf(stderr, "Invalid security model %s specified, valid options are"
-                "\n\t [passthrough|mapped|none]\n", sec_model);
-        return -1;
-    }
-done:
     QTAILQ_INSERT_TAIL(&fsdriver_entries, fsle, next);
     return 0;
 }
diff --git a/fsdev/qemu-fsdev.h b/fsdev/qemu-fsdev.h
index 8ef8473..921452d 100644
--- a/fsdev/qemu-fsdev.h
+++ b/fsdev/qemu-fsdev.h
@@ -34,16 +34,6 @@ typedef struct FsDriverTable {
     FileOperations *ops;
 } FsDriverTable;
 
-/*
- * Structure to store the various fsdev's passed through command line.
- */
-typedef struct FsDriverEntry {
-    char *fsdev_id;
-    char *path;
-    int export_flags;
-    FileOperations *ops;
-} FsDriverEntry;
-
 typedef struct FsDriverListEntry {
     FsDriverEntry fse;
     QTAILQ_ENTRY(FsDriverListEntry) next;
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index bba4c54..d5cfae0 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -75,16 +75,19 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
         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",
+    if (!conf->tag) {
+        /* we haven't specified a mount_tag */
+        fprintf(stderr, "fsdev with id %s needs mount_tag arguments\n",
                 conf->fsdev_id);
         exit(1);
     }
 
     s->ctx.export_flags = fse->export_flags;
-    s->ctx.fs_root = g_strdup(fse->path);
+    if (fse->path) {
+        s->ctx.fs_root = g_strdup(fse->path);
+    } else {
+        s->ctx.fs_root = NULL;
+    }
     s->ctx.exops.get_st_gen = NULL;
 
     if (fse->export_flags & V9FS_SM_PASSTHROUGH) {
diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c
index c38e0e7..456ebc1 100644
--- a/hw/9pfs/virtio-9p-handle.c
+++ b/hw/9pfs/virtio-9p-handle.c
@@ -647,7 +647,27 @@ out:
     return ret;
 }
 
+static int handle_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
+{
+    const char *sec_model = qemu_opt_get(opts, "security_model");
+    const char *path = qemu_opt_get(opts, "path");
+
+    if (sec_model) {
+        fprintf(stderr, "Invalid argument security_model specified with handle fsdriver\n");
+        return -1;
+    }
+
+    if (!path) {
+        fprintf(stderr, "fsdev: No path specified.\n");
+        return -1;
+    }
+    fse->path = g_strdup(path);
+    return 0;
+
+}
+
 FileOperations handle_ops = {
+    .parse_opts   = handle_parse_opts,
     .init         = handle_init,
     .lstat        = handle_lstat,
     .readlink     = handle_readlink,
diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index 782dc0a..41bcdf7 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -732,7 +732,41 @@ static int local_init(FsContext *ctx)
     return err;
 }
 
+static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
+{
+    const char *sec_model = qemu_opt_get(opts, "security_model");
+    const char *path = qemu_opt_get(opts, "path");
+
+    if (!sec_model) {
+        fprintf(stderr, "security model not specified, "
+                "local fs needs security model\nvalid options are:"
+                "\tsecurity_model=[passthrough|mapped|none]\n");
+        return -1;
+    }
+
+    if (!strcmp(sec_model, "passthrough")) {
+        fse->export_flags |= V9FS_SM_PASSTHROUGH;
+    } else if (!strcmp(sec_model, "mapped")) {
+        fse->export_flags |= V9FS_SM_MAPPED;
+    } else if (!strcmp(sec_model, "none")) {
+        fse->export_flags |= V9FS_SM_NONE;
+    } else {
+        fprintf(stderr, "Invalid security model %s specified, valid options are"
+                "\n\t [passthrough|mapped|none]\n", sec_model);
+        return -1;
+    }
+
+    if (!path) {
+        fprintf(stderr, "fsdev: No path specified.\n");
+        return -1;
+    }
+    fse->path = g_strdup(path);
+
+    return 0;
+}
+
 FileOperations local_ops = {
+    .parse_opts = local_parse_opts,
     .init  = local_init,
     .lstat = local_lstat,
     .readlink = local_readlink,
diff --git a/vl.c b/vl.c
index 37a79e5..cf538b2 100644
--- a/vl.c
+++ b/vl.c
@@ -2677,11 +2677,8 @@ int main(int argc, char **argv, char **envp)
                 }
 
                 if (qemu_opt_get(opts, "fsdriver") == NULL ||
-                        qemu_opt_get(opts, "mount_tag") == NULL ||
-                        qemu_opt_get(opts, "path") == NULL) {
-                    fprintf(stderr, "Usage: -virtfs fsdriver,path=/share_path/,"
-                            "[security_model={mapped|passthrough|none}],"
-                            "mount_tag=tag.\n");
+                    qemu_opt_get(opts, "mount_tag") == NULL) {
+                    fprintf(stderr, "Usage: -virtfs fsdriver,mount_tag=tag.\n");
                     exit(1);
                 }
                 fsdev = qemu_opts_create(qemu_find_opts("fsdev"),
@@ -2727,7 +2724,6 @@ int main(int argc, char **argv, char **envp)
                     exit(1);
                 }
                 qemu_opt_set(fsdev, "fsdriver", "synth");
-                qemu_opt_set(fsdev, "path", "/"); /* ignored */
 
                 device = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
                 qemu_opt_set(device, "driver", "virtio-9p-pci");
-- 
1.7.6

^ permalink raw reply related

* [Qemu-devel] [PATCH 04/13] hw/9pfs: File system helper process for qemu 9p proxy FS
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
  To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
In-Reply-To: <1320094412-19091-1-git-send-email-mohan@in.ibm.com>

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

Provide root privilege access to QEMU 9p proxy filesystem using socket
communication.

Proxy helper is started by root user as:
~ # virtfs-proxy-helper
 {{-s|--socket <socketname> -u|--uid -g|--gid}|{-f|--fd <socket descriptor>}}
 -p <path-to-share>   [-r <runasuid> -t <runasgid>]

Where uid:gid gives socket access to uid:gid, -r:t combination drops the
privilege to given uid:gid

Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
 Makefile                      |    2 +
 configure                     |   25 ++++
 hw/9pfs/proxy.h               |    6 +
 hw/9pfs/virtfs-proxy-helper.c |  262 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 295 insertions(+), 0 deletions(-)
 create mode 100644 hw/9pfs/virtfs-proxy-helper.c

diff --git a/Makefile b/Makefile
index f63fc02..1fd443d 100644
--- a/Makefile
+++ b/Makefile
@@ -153,6 +153,8 @@ qemu-img$(EXESUF): qemu-img.o $(tools-obj-y)
 qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y)
 qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y)
 
+hw/9pfs/virtfs-proxy-helper$(EXESUF): LIBS+=$(LIBS_PROXY)
+
 qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"  GEN   $@")
 
diff --git a/configure b/configure
index 19e8394..8abd17c 100755
--- a/configure
+++ b/configure
@@ -1866,6 +1866,23 @@ else
 fi
 
 ##########################################
+# libcap probe
+
+if test "$cap" != "no" ; then
+  cat > $TMPC <<EOF
+#include <stdio.h>
+#include <sys/capability.h>
+int main(void) { cap_t caps; caps = cap_init(); }
+EOF
+  if compile_prog "" "-lcap" ; then
+    cap=yes
+    libs_proxy="-lcap"
+  else
+    cap=no
+  fi
+fi
+
+##########################################
 # pthread probe
 PTHREADLIBS_LIST="-pthread -lpthread -lpthreadGC2"
 
@@ -2636,6 +2653,9 @@ confdir=$sysconfdir$confsuffix
 tools=
 if test "$softmmu" = yes ; then
   tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools"
+if test "$cap" = yes; then
+  tools="$tools hw/9pfs/virtfs-proxy-helper\$(EXESUF)"
+fi
   if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
       tools="qemu-nbd\$(EXESUF) $tools"
     if [ "$guest_agent" = "yes" ]; then
@@ -3068,6 +3088,10 @@ if test "$linux_magic_h" = "yes" ; then
   echo "CONFIG_LINUX_MAGIC_H=y" >> $config_host_mak
 fi
 
+if test "$cap" = "yes" ; then
+  echo "CONFIG_CAPABILITY=y" >> $config_host_mak
+fi
+
 # USB host support
 case "$usb" in
 linux)
@@ -3143,6 +3167,7 @@ echo "LIBS+=$LIBS" >> $config_host_mak
 echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak
 echo "EXESUF=$EXESUF" >> $config_host_mak
 echo "LIBS_QGA+=$libs_qga" >> $config_host_mak
+echo "LIBS_PROXY+=$libs_proxy" >> $config_host_mak
 
 # generate list of library paths for linker script
 
diff --git a/hw/9pfs/proxy.h b/hw/9pfs/proxy.h
index 1a47509..205d7b7 100644
--- a/hw/9pfs/proxy.h
+++ b/hw/9pfs/proxy.h
@@ -2,6 +2,12 @@
 #define __PROXY_HELP_H
 
 #define BUFF_SZ (4 * 1024)
+#define V9FS_FD_VALID INT_MAX
+
+union MsgControl {
+    struct cmsghdr cmsg;
+    char control[CMSG_SPACE(sizeof(int))];
+};
 
 typedef struct {
     int type;
diff --git a/hw/9pfs/virtfs-proxy-helper.c b/hw/9pfs/virtfs-proxy-helper.c
new file mode 100644
index 0000000..8e82ca7
--- /dev/null
+++ b/hw/9pfs/virtfs-proxy-helper.c
@@ -0,0 +1,262 @@
+#include <stdio.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <sys/un.h>
+#include <limits.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <sys/prctl.h>
+#include <sys/capability.h>
+#include <sys/fsuid.h>
+#include <stdarg.h>
+#include "bswap.h"
+#include <sys/socket.h>
+#include "qemu-common.h"
+#include "hw/9pfs/proxy.h"
+
+#define PROGNAME "virtfs-proxy-helper"
+
+static struct option helper_opts[] = {
+    {"fd", required_argument, NULL, 'f'},
+    {"path", required_argument, NULL, 'p'},
+    {"nodaemon", no_argument, NULL, 'n'},
+};
+
+int is_daemon;
+
+static void do_perror(const char *string)
+{
+    if (is_daemon) {
+        syslog(LOG_CRIT, "%s:%s", string, strerror(errno));
+    } else {
+        fprintf(stderr, "%s:%s\n", string, strerror(errno));
+    }
+}
+
+static void do_log(int level, const char *string)
+{
+    if (is_daemon) {
+        syslog(level, "%s", string);
+    } else {
+        fprintf(stderr, "%s\n", string);
+    }
+}
+
+static int cap_set(void)
+{
+    int retval;
+    cap_t caps;
+    cap_value_t cap_list[10];
+
+    /* helper needs following capbabilities only */
+    cap_list[0] = CAP_CHOWN;
+    cap_list[1] = CAP_DAC_OVERRIDE;
+    cap_list[2] = CAP_DAC_READ_SEARCH;
+    cap_list[3] = CAP_FOWNER;
+    cap_list[4] = CAP_FSETID;
+    cap_list[5] = CAP_SETGID;
+    cap_list[6] = CAP_MKNOD;
+    cap_list[7] = CAP_SETUID;
+
+    caps = cap_init();
+    if (caps == NULL) {
+        do_perror("cap_init");
+        return -1;
+    }
+    retval = cap_set_flag(caps, CAP_PERMITTED, 8, cap_list, CAP_SET);
+    if (retval < 0) {
+        do_perror("cap_set_flag");
+        goto error;
+    }
+    retval = cap_set_proc(caps);
+    if (retval < 0) {
+        do_perror("cap_set_proc");
+    }
+    retval = cap_set_flag(caps, CAP_EFFECTIVE, 8, cap_list, CAP_SET);
+    if (retval < 0) {
+        do_perror("cap_set_flag");
+        goto error;
+    }
+    retval = cap_set_proc(caps);
+    if (retval < 0) {
+        do_perror("cap_set_proc");
+    }
+
+error:
+    cap_free(caps);
+    return retval;
+}
+
+static int init_capabilities(void)
+{
+    if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
+        do_perror("prctl");
+        return -1;
+    }
+    if (cap_set() < 0) {
+        return -1;
+    }
+    return 0;
+}
+
+static int socket_read(int sockfd, void *buff, ssize_t size)
+{
+    int retval;
+
+    do {
+        retval = read(sockfd, buff, size);
+    } while (retval < 0 && errno == EINTR);
+    if (retval != size) {
+        if (errno != ENOENT) {
+            do_perror("socket read");
+        }
+        return -EIO;
+    }
+    return retval;
+}
+
+static int socket_write(int sockfd, void *buff, ssize_t size)
+{
+    int retval;
+
+    do {
+        retval = write(sockfd, buff, size);
+    } while (retval < 0 && errno == EINTR);
+    if (retval != size) {
+        do_perror("socket_write");
+        return -EIO;
+    }
+    return retval;
+}
+
+static int read_request(int sockfd, struct iovec *iovec)
+{
+    int retval;
+    ProxyHeader header;
+
+    do {
+        retval = socket_read(sockfd, &header, sizeof(header));
+        if (retval != sizeof(header)) {
+            return -EIO;
+        }
+        retval = socket_read(sockfd, iovec->iov_base, header.size);
+        if (retval != header.size) {
+            return -EIO;
+        }
+        return header.type;
+    } while (1);
+}
+
+static void usage(char *prog)
+{
+    fprintf(stderr, "usage: %s\n"
+        " -p|--path <path> 9p path to export\n"
+        " {-f|--fd <socket-descriptor>} socket file descriptor to be used\n"
+        " [-n|--nodaemon] Run as a normal program\n",
+        basename(prog));
+}
+
+static int process_requests(int sock)
+{
+    int type;
+    struct iovec iovec;
+
+    iovec.iov_base = g_malloc(BUFF_SZ);
+    iovec.iov_len = BUFF_SZ;
+    while (1) {
+        type = read_request(sock, &iovec);
+        if (type <= 0) {
+            goto error;
+        }
+    }
+    (void)socket_write;
+error:
+    g_free(iovec.iov_base);
+    return -1;
+}
+
+int main(int argc, char **argv)
+{
+    int sock;
+    char rpath[PATH_MAX];
+    struct stat stbuf;
+    int c, option_index;
+
+    is_daemon = 1;
+    rpath[0] = '\0';
+    sock = -1;
+    while (1) {
+        option_index = 0;
+        c = getopt_long(argc, argv, "p:nh?f:", helper_opts,
+                        &option_index);
+        if (c == -1) {
+            break;
+        }
+        switch (c) {
+        case 'p':
+            strcpy(rpath, optarg);
+            break;
+        case 'n':
+            is_daemon = 0;
+            break;
+	case 'f':
+            sock = atoi(optarg);
+            break;
+        case '?':
+        case 'h':
+        default:
+            usage(argv[0]);
+            return -1;
+            break;
+        }
+    }
+
+    /* Parameter validation */
+    if (sock == -1 || rpath[0] == '\0') {
+        fprintf(stderr, "socket descriptor or path not specified\n");
+        usage(argv[0]);
+        return -1;
+    }
+
+    if (lstat(rpath, &stbuf) < 0) {
+        fprintf(stderr, "invalid path \"%s\" specified?\n", rpath);
+        return -1;
+    }
+
+    if (!S_ISDIR(stbuf.st_mode)) {
+        fprintf(stderr, "specified path \"%s\" is not directory\n", rpath);
+        return -1;
+    }
+
+    if (is_daemon) {
+        if (daemon(1, 0) < 0) {
+            fprintf(stderr, "deamon error\n");
+            return -1;
+        }
+        openlog(PROGNAME, LOG_PID, LOG_DAEMON);
+    }
+
+    do_log(LOG_INFO, "Started");
+
+    if (chroot(rpath) < 0) {
+        do_perror("chroot");
+        goto error;
+    }
+    umask(0);
+
+    if (init_capabilities() < 0) {
+        goto error;
+    }
+
+    process_requests(sock);
+error:
+    do_log(LOG_INFO, "Done");
+    closelog();
+    return 0;
+}
-- 
1.7.6

^ permalink raw reply related

* [Qemu-devel] [PATCH 02/13] hw/9pfs: Move pdu_marshal/unmarshal code to a seperate file
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
  To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
In-Reply-To: <1320094412-19091-1-git-send-email-mohan@in.ibm.com>

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

Move p9 marshaling/unmarshaling code to a separate file so that
proxy filesytem driver can use these calls. Also made marshaling
code generic to accept "struct iovec" instead of V9fsPDU.

Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 Makefile.objs               |    2 +-
 hw/9pfs/virtio-9p-marshal.c |  257 ++++++++++++++++++++++++++++++++++++++++++
 hw/9pfs/virtio-9p.c         |  258 +------------------------------------------
 hw/9pfs/virtio-9p.h         |   12 ++
 4 files changed, 274 insertions(+), 255 deletions(-)
 create mode 100644 hw/9pfs/virtio-9p-marshal.c

diff --git a/Makefile.objs b/Makefile.objs
index 3dead4e..804bc3c 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -310,7 +310,7 @@ hw-obj-$(CONFIG_SOUND) += $(sound-obj-y)
 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o
 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-coth.o cofs.o codir.o cofile.o
 9pfs-nested-$(CONFIG_VIRTFS) += coxattr.o virtio-9p-handle.o
-9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-synth.o
+9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-synth.o virtio-9p-marshal.o
 
 hw-obj-$(CONFIG_REALLY_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y))
 $(addprefix 9pfs/, $(9pfs-nested-y)): QEMU_CFLAGS+=$(GLIB_CFLAGS)
diff --git a/hw/9pfs/virtio-9p-marshal.c b/hw/9pfs/virtio-9p-marshal.c
new file mode 100644
index 0000000..1a21254
--- /dev/null
+++ b/hw/9pfs/virtio-9p-marshal.c
@@ -0,0 +1,257 @@
+/*
+ * 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-9p.h"
+
+static size_t v9fs_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 size_t v9fs_unpack(void *dst, struct iovec *out_sg, int out_num,
+                          size_t offset, size_t size)
+{
+    return v9fs_packunpack(dst, out_sg, out_num, offset, size, 0);
+}
+
+size_t v9fs_pack(struct iovec *in_sg, int in_num, size_t offset, const void *src,
+                 size_t size)
+{
+    return v9fs_packunpack((void *)src, in_sg, in_num, offset, size, 1);
+}
+
+static int v9fs_copy_sg(struct iovec *src_sg, unsigned int num,
+                        size_t offset, struct iovec *sg)
+{
+    size_t pos = 0;
+    int i, j;
+
+    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;
+}
+
+size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, 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 += v9fs_unpack(valp, out_sg, out_num, offset, sizeof(*valp));
+            break;
+        }
+        case 'w': {
+            uint16_t val, *valp;
+            valp = va_arg(ap, uint16_t *);
+            offset += v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val));
+            *valp = le16_to_cpu(val);
+            break;
+        }
+        case 'd': {
+            uint32_t val, *valp;
+            valp = va_arg(ap, uint32_t *);
+            offset += v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val));
+            *valp = le32_to_cpu(val);
+            break;
+        }
+        case 'q': {
+            uint64_t val, *valp;
+            valp = va_arg(ap, uint64_t *);
+            offset += v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val));
+            *valp = le64_to_cpu(val);
+            break;
+        }
+        case 'v': {
+            struct iovec *iov = va_arg(ap, struct iovec *);
+            int *iovcnt = va_arg(ap, int *);
+            *iovcnt = v9fs_copy_sg(out_sg, out_num, offset, iov);
+            break;
+        }
+        case 's': {
+            V9fsString *str = va_arg(ap, V9fsString *);
+            offset += v9fs_unmarshal(out_sg, out_num, offset, "w", &str->size);
+            /* FIXME: sanity check str->size */
+            str->data = g_malloc(str->size + 1);
+            offset += v9fs_unpack(str->data, out_sg, out_num, offset, str->size);
+            str->data[str->size] = 0;
+            break;
+        }
+        case 'Q': {
+            V9fsQID *qidp = va_arg(ap, V9fsQID *);
+            offset += v9fs_unmarshal(out_sg, out_num, offset, "bdq",
+                                     &qidp->type, &qidp->version, &qidp->path);
+            break;
+        }
+        case 'S': {
+            V9fsStat *statp = va_arg(ap, V9fsStat *);
+            offset += v9fs_unmarshal(out_sg, out_num, 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;
+        }
+        case 'I': {
+            V9fsIattr *iattr = va_arg(ap, V9fsIattr *);
+            offset += v9fs_unmarshal(out_sg, out_num, offset, "ddddqqqqq",
+                                     &iattr->valid, &iattr->mode,
+                                     &iattr->uid, &iattr->gid, &iattr->size,
+                                     &iattr->atime_sec, &iattr->atime_nsec,
+                                     &iattr->mtime_sec, &iattr->mtime_nsec);
+            break;
+        }
+        default:
+            break;
+        }
+    }
+
+    va_end(ap);
+
+    return offset - old_offset;
+}
+
+size_t v9fs_marshal(struct iovec *in_sg, int in_num, 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 += v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
+            break;
+        }
+        case 'w': {
+            uint16_t val;
+            cpu_to_le16w(&val, va_arg(ap, int));
+            offset += v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
+            break;
+        }
+        case 'd': {
+            uint32_t val;
+            cpu_to_le32w(&val, va_arg(ap, uint32_t));
+            offset += v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
+            break;
+        }
+        case 'q': {
+            uint64_t val;
+            cpu_to_le64w(&val, va_arg(ap, uint64_t));
+            offset += v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
+            break;
+        }
+        case 'v': {
+            struct iovec *iov = va_arg(ap, struct iovec *);
+            int *iovcnt = va_arg(ap, int *);
+            *iovcnt = v9fs_copy_sg(in_sg, in_num, offset, iov);
+            break;
+        }
+        case 's': {
+            V9fsString *str = va_arg(ap, V9fsString *);
+            offset += v9fs_marshal(in_sg, in_num, offset, "w", str->size);
+            offset += v9fs_pack(in_sg, in_num, offset, str->data, str->size);
+            break;
+        }
+        case 'Q': {
+            V9fsQID *qidp = va_arg(ap, V9fsQID *);
+            offset += v9fs_marshal(in_sg, in_num, offset, "bdq",
+                                   qidp->type, qidp->version, qidp->path);
+            break;
+        }
+        case 'S': {
+            V9fsStat *statp = va_arg(ap, V9fsStat *);
+            offset += v9fs_marshal(in_sg, in_num, 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;
+        }
+        case 'A': {
+            V9fsStatDotl *statp = va_arg(ap, V9fsStatDotl *);
+            offset += v9fs_marshal(in_sg, in_num, offset, "qQdddqqqqqqqqqqqqqqq",
+                                   statp->st_result_mask,
+                                   &statp->qid, statp->st_mode,
+                                   statp->st_uid, statp->st_gid,
+                                   statp->st_nlink, statp->st_rdev,
+                                   statp->st_size, statp->st_blksize,
+                                   statp->st_blocks, statp->st_atime_sec,
+                                   statp->st_atime_nsec, statp->st_mtime_sec,
+                                   statp->st_mtime_nsec, statp->st_ctime_sec,
+                                   statp->st_ctime_nsec, statp->st_btime_sec,
+                                   statp->st_btime_nsec, statp->st_gen,
+                                   statp->st_data_version);
+            break;
+        }
+        default:
+            break;
+        }
+    }
+    va_end(ap);
+
+    return offset - old_offset;
+}
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index 0777ece..177c0ee 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -695,257 +695,6 @@ static void free_pdu(V9fsState *s, V9fsPDU *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 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 *);
-            offset += pdu_unpack(&val, pdu, offset, sizeof(val));
-            *valp = le16_to_cpu(val);
-            break;
-        }
-        case 'd': {
-            uint32_t val, *valp;
-            valp = va_arg(ap, uint32_t *);
-            offset += pdu_unpack(&val, pdu, offset, sizeof(val));
-            *valp = le32_to_cpu(val);
-            break;
-        }
-        case 'q': {
-            uint64_t val, *valp;
-            valp = va_arg(ap, uint64_t *);
-            offset += pdu_unpack(&val, pdu, offset, sizeof(val));
-            *valp = le64_to_cpu(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 = g_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;
-        }
-        case 'I': {
-            V9fsIattr *iattr = va_arg(ap, V9fsIattr *);
-            offset += pdu_unmarshal(pdu, offset, "ddddqqqqq",
-                        &iattr->valid, &iattr->mode,
-                        &iattr->uid, &iattr->gid, &iattr->size,
-                        &iattr->atime_sec, &iattr->atime_nsec,
-                        &iattr->mtime_sec, &iattr->mtime_nsec);
-            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;
-        }
-        case 'A': {
-            V9fsStatDotl *statp = va_arg(ap, V9fsStatDotl *);
-            offset += pdu_marshal(pdu, offset, "qQdddqqqqqqqqqqqqqqq",
-                        statp->st_result_mask,
-                        &statp->qid, statp->st_mode,
-                        statp->st_uid, statp->st_gid,
-                        statp->st_nlink, statp->st_rdev,
-                        statp->st_size, statp->st_blksize, statp->st_blocks,
-                        statp->st_atime_sec, statp->st_atime_nsec,
-                        statp->st_mtime_sec, statp->st_mtime_nsec,
-                        statp->st_ctime_sec, statp->st_ctime_nsec,
-                        statp->st_btime_sec, statp->st_btime_nsec,
-                        statp->st_gen, statp->st_data_version);
-            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 */
@@ -1853,9 +1602,10 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu,
         read_count = 0;
     }
     offset += pdu_marshal(pdu, offset, "d", read_count);
-    offset += pdu_pack(pdu, offset,
-                       ((char *)fidp->fs.xattr.value) + off,
-                       read_count);
+    offset += v9fs_pack(pdu->elem.in_sg, pdu->elem.in_num, offset,
+                        ((char *)fidp->fs.xattr.value) + off,
+                        read_count);
+
     return offset;
 }
 
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index 7f88356..1d8665e 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -468,4 +468,16 @@ extern void v9fs_path_free(V9fsPath *path);
 extern void v9fs_path_copy(V9fsPath *lhs, V9fsPath *rhs);
 extern int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath,
                              const char *name, V9fsPath *path);
+
+size_t v9fs_pack(struct iovec *in_sg, int in_num, size_t offset,
+                 const void *src, size_t size);
+size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset,
+                      const char *fmt, ...);
+size_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset,
+                    const char *fmt, ...);
+#define pdu_marshal(pdu, offset, fmt, args...)  \
+    v9fs_marshal(pdu->elem.in_sg, pdu->elem.in_num, offset, fmt, ##args)
+#define pdu_unmarshal(pdu, offset, fmt, args...)  \
+    v9fs_unmarshal(pdu->elem.out_sg, pdu->elem.out_num, offset, fmt, ##args)
+
 #endif
-- 
1.7.6

^ permalink raw reply related

* [Qemu-devel] [PATCH 00/13] Proxy FS driver for VirtFS
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
  To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar

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

Pass-through security model in QEMU 9p server needs root privilege to do
few file operations (like chown, chmod to any mode/uid:gid).  There are two
issues in pass-through security model

1) TOCTTOU vulnerability: Following symbolic links in the server could
provide access to files beyond 9p export path.

2) Running QEMU with root privilege could be a security issue.

To overcome above issues, following approach is used: A new filesytem
type 'proxy' is introduced. Proxy FS uses chroot + socket combination
for securing the vulnerability known with following symbolic links.
Intention of adding a new filesystem type is to allow qemu to run
in non-root mode, but doing privileged operations using socket IO.

Proxy helper(a stand alone binary part of qemu) is invoked with
root privileges. Proxy helper chroots into 9p export path and creates
a socket pair or a named socket based on the command line parameter.
Qemu and proxy helper communicate using this socket. QEMU proxy fs
driver sends filesystem request to proxy helper and receives the
response from it.

Proxy helper is designed so that it can drop the root privilege but
retaining capbilities that are needed for doing filesystem operations
(like CAP_DAC_OVERRIDE, CAP_FOWNER etc)

Aneesh Kumar K.V (1):
  hw/9pfs: Move opt validation to FsDriver callback

M. Mohan Kumar (12):
  hw/9pfs: Move pdu_marshal/unmarshal code to a seperate file
  hw/9pfs: Add new proxy filesystem driver
  hw/9pfs: File system helper process for qemu 9p proxy FS
  hw/9pfs: Add support to use named socket for proxy FS
  hw/9pfs: Open and create files
  hw/9pfs: Create other filesystem objects
  hw/9pfs: Add stat/readlink/statfs for proxy FS
  hw/9pfs: File ownership and others
  hw/9pfs: xattr interfaces in proxy filesystem driver
  hw/9pfs: Proxy getversion
  hw/9pfs: Documentation changes related to proxy fs
  hw/9pfs: man page for proxy helper

 Makefile                         |   16 +-
 Makefile.objs                    |    3 +-
 configure                        |   26 +
 fsdev/file-op-9p.h               |   15 +-
 fsdev/qemu-fsdev.c               |   45 +--
 fsdev/qemu-fsdev.h               |   11 +-
 hw/9pfs/proxy.h                  |   40 ++
 hw/9pfs/virtfs-proxy-helper.c    |  792 +++++++++++++++++++++++++++++++
 hw/9pfs/virtfs-proxy-helper.texi |   63 +++
 hw/9pfs/virtio-9p-device.c       |   13 +-
 hw/9pfs/virtio-9p-handle.c       |   20 +
 hw/9pfs/virtio-9p-local.c        |   34 ++
 hw/9pfs/virtio-9p-marshal.c      |  269 +++++++++++
 hw/9pfs/virtio-9p-proxy.c        |  974 ++++++++++++++++++++++++++++++++++++++
 hw/9pfs/virtio-9p.c              |  270 +-----------
 hw/9pfs/virtio-9p.h              |   12 +
 qemu-config.c                    |   13 +
 qemu-options.hx                  |   30 +-
 vl.c                             |   18 +-
 19 files changed, 2326 insertions(+), 338 deletions(-)
 create mode 100644 hw/9pfs/proxy.h
 create mode 100644 hw/9pfs/virtfs-proxy-helper.c
 create mode 100644 hw/9pfs/virtfs-proxy-helper.texi
 create mode 100644 hw/9pfs/virtio-9p-marshal.c
 create mode 100644 hw/9pfs/virtio-9p-proxy.c

-- 
1.7.6

^ permalink raw reply

* [Qemu-devel] [PATCH 06/13] hw/9pfs: Open and create files
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
  To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
In-Reply-To: <1320094412-19091-1-git-send-email-mohan@in.ibm.com>

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

Add interfaces to open and create files for proxy file system driver.

Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
 Makefile                      |    2 +
 configure                     |    1 +
 hw/9pfs/proxy.h               |    6 ++
 hw/9pfs/virtfs-proxy-helper.c |  135 ++++++++++++++++++++++++++++++-
 hw/9pfs/virtio-9p-marshal.c   |   12 +++
 hw/9pfs/virtio-9p-proxy.c     |  178 +++++++++++++++++++++++++++++++++++++++--
 hw/9pfs/virtio-9p.c           |   12 ---
 7 files changed, 325 insertions(+), 21 deletions(-)

diff --git a/Makefile b/Makefile
index 1fd443d..d13b167 100644
--- a/Makefile
+++ b/Makefile
@@ -153,6 +153,8 @@ qemu-img$(EXESUF): qemu-img.o $(tools-obj-y)
 qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y)
 qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y)
 
+hw/9pfs/virtfs-proxy-helper$(EXESUF): QEMU_CFLAGS += -DTARGET_PHYS_ADDR_BITS=$(PROXY_PHYS_ADDR_BITS)
+hw/9pfs/virtfs-proxy-helper$(EXESUF): hw/9pfs/virtfs-proxy-helper.o hw/9pfs/virtio-9p-marshal.o
 hw/9pfs/virtfs-proxy-helper$(EXESUF): LIBS+=$(LIBS_PROXY)
 
 qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
diff --git a/configure b/configure
index 8abd17c..ae64f84 100755
--- a/configure
+++ b/configure
@@ -3474,6 +3474,7 @@ if test "$smartcard_nss" = "yes" ; then
   echo "libcacard_libs=$libcacard_libs" >> $config_host_mak
   echo "libcacard_cflags=$libcacard_cflags" >> $config_host_mak
 fi
+echo "PROXY_PHYS_ADDR_BITS=$target_phys_bits" >> $config_host_mak
 list=""
 if test ! -z "$gdb_xml_files" ; then
   for x in $gdb_xml_files; do
diff --git a/hw/9pfs/proxy.h b/hw/9pfs/proxy.h
index 205d7b7..69e7baa 100644
--- a/hw/9pfs/proxy.h
+++ b/hw/9pfs/proxy.h
@@ -13,4 +13,10 @@ typedef struct {
     int type;
     int size;
 } ProxyHeader;
+
+enum {
+    T_OPEN = 1,
+    T_CREATE,
+};
+
 #endif
diff --git a/hw/9pfs/virtfs-proxy-helper.c b/hw/9pfs/virtfs-proxy-helper.c
index 9d925e0..73609e1 100644
--- a/hw/9pfs/virtfs-proxy-helper.c
+++ b/hw/9pfs/virtfs-proxy-helper.c
@@ -18,6 +18,7 @@
 #include "bswap.h"
 #include <sys/socket.h>
 #include "qemu-common.h"
+#include "virtio-9p.h"
 #include "hw/9pfs/proxy.h"
 
 #define PROGNAME "virtfs-proxy-helper"
@@ -202,6 +203,110 @@ static int proxy_socket(const char *path, uid_t uid, gid_t gid)
     return client;
 }
 
+static void sendfd(int sockfd, int fd, int fd_valid)
+{
+    struct msghdr msg = { };
+    struct iovec iov;
+    struct cmsghdr *cmsg;
+    int retval, data;
+    union MsgControl msg_control;
+
+    iov.iov_base = &data;
+    iov.iov_len = sizeof(data);
+
+    memset(&msg, 0, sizeof(msg));
+    msg.msg_iov = &iov;
+    msg.msg_iovlen = 1;
+    /* No ancillary data on error */
+    if (!fd_valid) {
+        /*
+         * fd is really negative errno if the request failed. Or simply
+        * zero if the request is successful and it doesn't need a file
+        * descriptor.
+        */
+        data = fd;
+    } else {
+        data = V9FS_FD_VALID;
+        msg.msg_control = &msg_control;
+        msg.msg_controllen = sizeof(msg_control);
+
+        cmsg = &msg_control.cmsg;
+        cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+        cmsg->cmsg_level = SOL_SOCKET;
+        cmsg->cmsg_type = SCM_RIGHTS;
+        memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
+    }
+
+    do {
+        retval = sendmsg(sockfd, &msg, 0);
+    } while (retval < 0 && errno == EINTR);
+    if (retval < 0) {
+        do_perror("sendmsg");
+        exit(1);
+    }
+    if (fd_valid) {
+        close(fd);
+    }
+}
+
+/*
+ * from man 7 capabilities, section
+ * Effect of User ID Changes on Capabilities:
+ * 4. If the file system user ID is changed from 0 to nonzero (see setfsuid(2))
+ * then the following capabilities are cleared from the effective set:
+ * CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH,  CAP_FOWNER, CAP_FSETID,
+ * CAP_LINUX_IMMUTABLE  (since  Linux 2.2.30), CAP_MAC_OVERRIDE, and CAP_MKNOD
+ * (since Linux 2.2.30). If the file system UID is changed from nonzero to 0,
+ * then any of these capabilities that are enabled in the permitted set
+ * are enabled in the effective set.
+ */
+static int setfsugid(int uid, int gid)
+{
+    setfsgid(gid);
+    setfsuid(uid);
+    return cap_set();
+}
+
+/*
+ * create a file and send fd on success
+ * return -errno on error
+ */
+static int do_create(struct iovec *iovec)
+{
+    V9fsString path;
+    int flags, fd, mode, uid, gid, cur_uid, cur_gid;
+    v9fs_unmarshal(iovec, 1, 0, "sdddd", &path, &flags, &mode, &uid, &gid);
+    cur_uid = geteuid();
+    cur_gid = getegid();
+    if (setfsugid(uid, gid) < 0) {
+        return -EPERM;
+    }
+    fd = open(path.data, flags, mode);
+    if (fd < 0) {
+        fd = -errno;
+    }
+    v9fs_string_free(&path);
+    setfsugid(cur_uid, cur_gid);
+    return fd;
+}
+
+/*
+ * open a file and send fd on success
+ * return -errno on error
+ */
+static int do_open(struct iovec *iovec)
+{
+    V9fsString path;
+    int flags, fd;
+    v9fs_unmarshal(iovec, 1, 0, "sd", &path, &flags);
+    fd = open(path.data, flags);
+    if (fd < 0) {
+        fd = -errno;
+    }
+    v9fs_string_free(&path);
+    return fd;
+}
+
 static void usage(char *prog)
 {
     fprintf(stderr, "usage: %s\n"
@@ -217,15 +322,41 @@ static void usage(char *prog)
 
 static int process_requests(int sock)
 {
-    int type;
+    int type, retval;
     struct iovec iovec;
+    int valid_fd;
 
     iovec.iov_base = g_malloc(BUFF_SZ);
     iovec.iov_len = BUFF_SZ;
     while (1) {
+        valid_fd = 0;
         type = read_request(sock, &iovec);
-        if (type <= 0) {
+        switch (type) {
+        case T_OPEN:
+            retval = do_open(&iovec);
+            if (retval >= 0) {
+                valid_fd = 1;
+            }
+           break;
+        case T_CREATE:
+            retval = do_create(&iovec);
+            if (retval >= 0) {
+                valid_fd = 1;
+            }
+            break;
+        default:
             goto error;
+            break;
+        }
+
+        /* Send response */
+        switch (type) {
+        case T_OPEN:
+        case T_CREATE:
+            sendfd(sock, retval, valid_fd);
+            break;
+        default:
+            break;
         }
     }
     (void)socket_write;
diff --git a/hw/9pfs/virtio-9p-marshal.c b/hw/9pfs/virtio-9p-marshal.c
index 1a21254..364e4df 100644
--- a/hw/9pfs/virtio-9p-marshal.c
+++ b/hw/9pfs/virtio-9p-marshal.c
@@ -12,6 +12,18 @@
  */
 #include "virtio-9p.h"
 
+void v9fs_string_free(V9fsString *str)
+{
+    g_free(str->data);
+    str->data = NULL;
+    str->size = 0;
+}
+
+void v9fs_string_null(V9fsString *str)
+{
+    v9fs_string_free(str);
+}
+
 static size_t v9fs_packunpack(void *addr, struct iovec *sg, int sg_count,
                               size_t offset, size_t size, int pack)
 {
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 0ec686c..d686454 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -26,6 +26,145 @@ typedef struct V9fsProxy {
     struct iovec iovec;
 } V9fsProxy;
 
+/*
+ * Return received file descriptor on success and -errno on failure.
+ * sock_error is set to 1 whenever there is error in socket IO
+ */
+static int v9fs_receivefd(int sockfd, int *sock_error)
+{
+    struct msghdr msg = { };
+    struct iovec iov;
+    union MsgControl msg_control;
+    struct cmsghdr *cmsg;
+    int retval, data, fd;
+
+    iov.iov_base = &data;
+    iov.iov_len = sizeof(data);
+
+    *sock_error = 0;
+    memset(&msg, 0, sizeof(msg));
+    msg.msg_iov = &iov;
+    msg.msg_iovlen = 1;
+    msg.msg_control = &msg_control;
+    msg.msg_controllen = sizeof(msg_control);
+
+    do {
+        retval = recvmsg(sockfd, &msg, 0);
+    } while (retval < 0 && errno == EINTR);
+    if (retval <= 0) {
+        *sock_error = 1;
+        return -EIO;
+    }
+
+    /*
+     * data is set to V9FS_FD_VALID, if ancillary data is sent.  If this
+     * request doesn't need ancillary data (fd) or an error occurred,
+     * data is set to negative errno value.
+     */
+    if (data != V9FS_FD_VALID) {
+        return data;
+    }
+
+    /*
+     * File descriptor (fd) is sent in the ancillary data. Check if we
+     * indeed received it. One of the reasons to fail to receive it is if
+     * we exceeded the maximum number of file descriptors!
+     */
+    for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+        if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
+            cmsg->cmsg_level != SOL_SOCKET ||
+            cmsg->cmsg_type != SCM_RIGHTS) {
+                continue;
+    }
+        fd = *((int *)CMSG_DATA(cmsg));
+        return fd;
+    }
+
+    return -ENFILE; /* Ancillary data sent but not received */
+}
+
+/*
+ * Proxy->header and proxy->buff written into the socket by QEMU process.
+ * This request read by proxy helper process
+ * @proxy: v9fsproxy
+ * @message: buffer where the response is written
+ * @size: size of request structure
+ * returns 0 on success and -errno on error
+ */
+static int v9fs_request(V9fsProxy *proxy, int type,
+                void *response, const char *fmt, ...)
+{
+    int retval;
+    ProxyHeader header;
+    va_list ap;
+    V9fsString *path;
+    int sock_error, flags, mode, uid, gid;
+    struct iovec *iovec = NULL;
+
+    qemu_mutex_lock(&proxy->mutex);
+
+    if (proxy->sockfd == -1) {
+        goto error;
+    }
+    iovec = &proxy->iovec;
+
+    va_start(ap, fmt);
+    switch (type) {
+    case T_OPEN:
+        path = va_arg(ap, V9fsString *);
+        flags = va_arg(ap, int);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sd", path,
+                        flags);
+        header.type = T_OPEN;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
+    case T_CREATE:
+        path = va_arg(ap, V9fsString *);
+        flags = va_arg(ap, int);
+        mode = va_arg(ap, int);
+        uid = va_arg(ap, int);
+        gid = va_arg(ap, int);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sdddd", path,
+                        flags, mode, uid, gid);
+        header.type = T_CREATE;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
+    default:
+        fprintf(stderr, "Invalid type %d\n", type);
+        goto close_error;
+    }
+    va_end(ap);
+
+    retval = qemu_write_full(proxy->sockfd, iovec->iov_base, header.size);
+    if (retval != header.size) {
+        goto close_error;
+    }
+
+    /*
+     * Response for T_OPEN is a file descriptor
+     * and returns the file descriptor
+     */
+    switch (type) {
+    case T_OPEN:
+    case T_CREATE:
+        retval = v9fs_receivefd(proxy->sockfd, &sock_error);
+        if (sock_error) {
+            goto close_error;
+        }
+        break;
+    }
+    qemu_mutex_unlock(&proxy->mutex);
+    return retval;
+close_error:
+    close(proxy->sockfd);
+    proxy->sockfd = -1;
+error:
+    qemu_mutex_unlock(&proxy->mutex);
+    return -EIO;
+}
+
 static int proxy_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
 {
     errno = EOPNOTSUPP;
@@ -52,16 +191,30 @@ static int proxy_closedir(FsContext *ctx, V9fsFidOpenState *fs)
 static int proxy_open(FsContext *ctx, V9fsPath *fs_path,
                       int flags, V9fsFidOpenState *fs)
 {
-    fs->fd = -1;
+    fs->fd = v9fs_request(ctx->private, T_OPEN, NULL, "sd",
+                    fs_path, flags);
     return fs->fd;
 }
 
 static int proxy_opendir(FsContext *ctx,
                          V9fsPath *fs_path, V9fsFidOpenState *fs)
 {
-    fs->dir = NULL;
-    errno = EOPNOTSUPP;
-    return -1;
+    int serrno, fd;
+
+    fd = v9fs_request(ctx->private, T_OPEN, NULL, "sd",
+                    fs_path, O_DIRECTORY);
+    if (fd < 0) {
+        errno = -fd;
+        return -1;
+    }
+    fs->dir = fdopendir(fd);
+    if (!fs->dir) {
+        serrno = errno;
+        close(fd);
+        errno = serrno;
+        return -1;
+    }
+    return 0;
 }
 
 static void proxy_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
@@ -163,9 +316,20 @@ static int proxy_fstat(FsContext *fs_ctx,
 static int proxy_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
                        int flags, FsCred *credp, V9fsFidOpenState *fs)
 {
-    fs->fd = -1;
-    errno = EOPNOTSUPP;
-    return -1;
+    V9fsString fullname;
+
+    v9fs_string_init(&fullname);
+    v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
+
+    fs->fd = v9fs_request(fs_ctx->private, T_CREATE, NULL, "sdddd",
+                    &fullname, flags, credp->fc_mode,
+                    credp->fc_uid, credp->fc_gid);
+    v9fs_string_free(&fullname);
+    if (fs->fd < 0) {
+        errno = -fs->fd;
+        fs->fd = -1;
+    }
+    return fs->fd;
 }
 
 
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index 177c0ee..f0cb000 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -149,18 +149,6 @@ void v9fs_string_init(V9fsString *str)
     str->size = 0;
 }
 
-void v9fs_string_free(V9fsString *str)
-{
-    g_free(str->data);
-    str->data = NULL;
-    str->size = 0;
-}
-
-void v9fs_string_null(V9fsString *str)
-{
-    v9fs_string_free(str);
-}
-
 static int number_to_string(void *arg, char type)
 {
     unsigned int ret = 0;
-- 
1.7.6

^ permalink raw reply related

* Re: [git patches] libata updates, GPG signed (but see admin notes)
From: Junio C Hamano @ 2011-10-31 20:53 UTC (permalink / raw)
  To: Ted Ts'o
  Cc: Linus Torvalds, git, James Bottomley, Jeff Garzik, Andrew Morton
In-Reply-To: <20111031203059.GJ16825@thunk.org>

Ted Ts'o <tytso@mit.edu> writes:

> Suppose the project wasn't Linus, but some other project, say, a
> ...
> this, and are good (Kevin Mitnick or better) at social engineering
> attacks.
>
> In this sort of scenario, it's useful if *other* people could
> independently verify the Troll3 git tree via the crypto signatures,
> even though the central maintainer couldn't be bothered to check the
> crypto signatures.

I think we are in total agreement here ;-)

> Here's an idea.... what if the "signed push" information could be
> embedded into the merge commit's description? That is, the
> information could sent via a signed git tag, or some other mechanism,...

I think you described what the signed-commit series that is cooking in
'next' is about way better than I have done so far ;-)

The contributors sign the tips of their histories (which can independently
be validated), the integrator pulls and can choose to bother or not to
bother the tips s/he obtains, and the integrator signs his/her tip before
s/he pushes the integration result out for general consumption.

> ...
> The problem with notes and tags is that they have to be pushed
> separately, and might get lost; where as if they are stored in the
> merge commit's description, they will always be there.

Exactly.

^ permalink raw reply

* [Qemu-devel] [PATCH 05/13] hw/9pfs: Add support to use named socket for proxy FS
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
  To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
In-Reply-To: <1320094412-19091-1-git-send-email-mohan@in.ibm.com>

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

Add option to use named socket for communicating between proxy helper
and qemu proxy FS. Access to socket can be given by using command line
options -u and -g.

Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
 hw/9pfs/virtfs-proxy-helper.c |   89 ++++++++++++++++++++++++++++++++++++++--
 hw/9pfs/virtio-9p-proxy.c     |   56 ++++++++++++++++++++++---
 qemu-config.c                 |    6 +++
 vl.c                          |    6 ++-
 4 files changed, 144 insertions(+), 13 deletions(-)

diff --git a/hw/9pfs/virtfs-proxy-helper.c b/hw/9pfs/virtfs-proxy-helper.c
index 8e82ca7..9d925e0 100644
--- a/hw/9pfs/virtfs-proxy-helper.c
+++ b/hw/9pfs/virtfs-proxy-helper.c
@@ -26,6 +26,9 @@ static struct option helper_opts[] = {
     {"fd", required_argument, NULL, 'f'},
     {"path", required_argument, NULL, 'p'},
     {"nodaemon", no_argument, NULL, 'n'},
+    {"socket", required_argument, NULL, 's'},
+    {"uid", required_argument, NULL, 'u'},
+    {"gid", required_argument, NULL, 'g'},
 };
 
 int is_daemon;
@@ -153,11 +156,61 @@ static int read_request(int sockfd, struct iovec *iovec)
     } while (1);
 }
 
+/* create unix domain socket and return the descriptor */
+static int proxy_socket(const char *path, uid_t uid, gid_t gid)
+{
+    int sock, client;
+    struct sockaddr_un proxy, qemu;
+    socklen_t size;
+
+    /* requested socket already exists, refuse to start */
+    if (!access(path, F_OK)) {
+        do_log(LOG_CRIT, "socket already exists\n");
+        return -1;
+    }
+
+    sock = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (sock < 0) {
+        do_perror("socket");
+        return -1;
+    }
+
+    /* mask other part of mode bits */
+    umask(7);
+
+    proxy.sun_family = AF_UNIX;
+    strcpy(proxy.sun_path, path);
+    if (bind(sock, (struct sockaddr *)&proxy,
+            sizeof(struct sockaddr_un)) < 0) {
+        do_perror("bind");
+        return -1;
+    }
+    if (chown(proxy.sun_path, uid, gid) < 0) {
+        do_perror("chown");
+        return -1;
+    }
+    if (listen(sock, 1) < 0) {
+        do_perror("listen");
+        return -1;
+    }
+
+    client = accept(sock, (struct sockaddr *)&qemu, &size);
+    if (client < 0) {
+        do_perror("accept");
+        return -1;
+    }
+    return client;
+}
+
 static void usage(char *prog)
 {
     fprintf(stderr, "usage: %s\n"
         " -p|--path <path> 9p path to export\n"
         " {-f|--fd <socket-descriptor>} socket file descriptor to be used\n"
+        " {-s|--socket <socketname> socket file used for communication\n"
+        " \t-u|--uid <uid> -g|--gid <gid>} - uid:gid combination to give "
+        " access to this socket\n"
+        " \tNote: -s & -f can not be used together\n"
         " [-n|--nodaemon] Run as a normal program\n",
         basename(prog));
 }
@@ -184,16 +237,20 @@ error:
 int main(int argc, char **argv)
 {
     int sock;
+    char sock_name[PATH_MAX];
     char rpath[PATH_MAX];
     struct stat stbuf;
     int c, option_index;
+    uid_t own_u;
+    gid_t own_g;
 
     is_daemon = 1;
-    rpath[0] = '\0';
+    sock_name[0] = rpath[0] = '\0';
     sock = -1;
+    own_u = own_g = -1;
     while (1) {
         option_index = 0;
-        c = getopt_long(argc, argv, "p:nh?f:", helper_opts,
+        c = getopt_long(argc, argv, "p:nh?f:s:u:g:", helper_opts,
                         &option_index);
         if (c == -1) {
             break;
@@ -205,9 +262,18 @@ int main(int argc, char **argv)
         case 'n':
             is_daemon = 0;
             break;
-	case 'f':
+        case 'f':
             sock = atoi(optarg);
             break;
+        case 's':
+            strcpy(sock_name, optarg);
+            break;
+        case 'u':
+            own_u = atoi(optarg);
+            break;
+        case 'g':
+            own_g = atoi(optarg);
+            break;
         case '?':
         case 'h':
         default:
@@ -218,8 +284,15 @@ int main(int argc, char **argv)
     }
 
     /* Parameter validation */
-    if (sock == -1 || rpath[0] == '\0') {
-        fprintf(stderr, "socket descriptor or path not specified\n");
+    if ((sock_name[0] == '\0' && sock == -1) || rpath[0] == '\0') {
+        fprintf(stderr, "socket, socket descriptor or path not specified\n");
+        usage(argv[0]);
+        return -1;
+    }
+
+    if (*sock_name && (own_u == -1 || own_g == -1)) {
+        fprintf(stderr, "owner uid:gid not specified, ");
+        fprintf(stderr, "owner specifies who can access the socket file\n");
         usage(argv[0]);
         return -1;
     }
@@ -243,6 +316,12 @@ int main(int argc, char **argv)
     }
 
     do_log(LOG_INFO, "Started");
+    if (*sock_name) {
+        sock = proxy_socket(sock_name, own_u, own_g);
+        if (sock < 0) {
+            goto error;
+        }
+    }
 
     if (chroot(rpath) < 0) {
         do_perror("chroot");
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index c682e36..0ec686c 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -16,6 +16,10 @@
 #include "fsdev/qemu-fsdev.h"
 #include "proxy.h"
 
+/* FS specific flags */
+#define V9FS_PROXY_SOCK_FD          (1 << 9)
+#define V9FS_PROXY_SOCK_NAME        (1 << 10)
+
 typedef struct V9fsProxy {
     int sockfd;
     QemuMutex mutex;
@@ -301,15 +305,49 @@ static int proxy_unlinkat(FsContext *ctx, V9fsPath *dir,
     return ret;
 }
 
+static int connect_namedsocket(const char *path)
+{
+    int sockfd, size;
+    struct sockaddr_un helper;
+
+    sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (sockfd < 0) {
+        fprintf(stderr, "socket %s\n", strerror(errno));
+        return -1;
+    }
+    strcpy(helper.sun_path, path);
+    helper.sun_family = AF_UNIX;
+    size = strlen(helper.sun_path) + sizeof(helper.sun_family);
+    if (connect(sockfd, (struct sockaddr *)&helper, size) < 0) {
+        fprintf(stderr, "socket error\n");
+        return -1;
+    }
+
+    /* remove the socket for security reasons */
+    unlink(path);
+    return sockfd;
+}
+
 static int proxy_parse_opts(QemuOpts *opts, struct FsDriverEntry *fs)
 {
+    const char *socket = qemu_opt_get(opts, "socket");
     const char *sock_fd = qemu_opt_get(opts, "sock_fd");
 
-    if (sock_fd) {
-        fprintf(stderr, "sock_fd option not specified\n");
+    if (!socket && !sock_fd) {
+        fprintf(stderr, "socket and sock_fd none of the option specified\n");
+        return -1;
+    }
+    if (socket && sock_fd) {
+        fprintf(stderr, "Both socket and sock_fd options specified\n");
         return -1;
     }
-    fs->path = g_strdup(sock_fd);
+    if (socket) {
+        fs->path = g_strdup(socket);
+        fs->export_flags = V9FS_PROXY_SOCK_NAME;
+    } else {
+        fs->path = g_strdup(sock_fd);
+        fs->export_flags = V9FS_PROXY_SOCK_FD;
+    }
     return 0;
 }
 
@@ -318,10 +356,14 @@ static int proxy_init(FsContext *ctx)
     V9fsProxy *proxy = g_malloc(sizeof(V9fsProxy));
     int sock_id;
 
-    sock_id = atoi(ctx->fs_root);
-    if (sock_id < 0) {
-        fprintf(stderr, "socket descriptor not initialized\n");
-        return -1;
+    if (ctx->export_flags & V9FS_PROXY_SOCK_NAME) {
+        sock_id = connect_namedsocket(ctx->fs_root);
+    } else {
+        sock_id = atoi(ctx->fs_root);
+        if (sock_id < 0) {
+            fprintf(stderr, "socket descriptor not initialized\n");
+            return -1;
+        }
     }
     g_free(ctx->fs_root);
 
diff --git a/qemu-config.c b/qemu-config.c
index 5e63c14..6203e7b 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -187,6 +187,9 @@ QemuOptsList qemu_fsdev_opts = {
         }, {
             .name = "sock_fd",
             .type = QEMU_OPT_NUMBER,
+        }, {
+            .name = "socket",
+            .type = QEMU_OPT_STRING,
         },
 
         { /*End of list */ }
@@ -219,6 +222,9 @@ QemuOptsList qemu_virtfs_opts = {
         }, {
             .name = "sock_fd",
             .type = QEMU_OPT_NUMBER,
+        }, {
+            .name = "socket",
+            .type = QEMU_OPT_STRING,
         },
 
         { /*End of list */ }
diff --git a/vl.c b/vl.c
index 5a5ab7f..8fbf481 100644
--- a/vl.c
+++ b/vl.c
@@ -2663,7 +2663,7 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_virtfs: {
                 QemuOpts *fsdev;
                 QemuOpts *device;
-                const char *writeout, *sock_fd;
+                const char *writeout, *sock_fd, *socket;
 
                 olist = qemu_find_opts("virtfs");
                 if (!olist) {
@@ -2703,6 +2703,10 @@ int main(int argc, char **argv, char **envp)
                 qemu_opt_set(fsdev, "path", qemu_opt_get(opts, "path"));
                 qemu_opt_set(fsdev, "security_model",
                              qemu_opt_get(opts, "security_model"));
+                socket = qemu_opt_get(opts, "socket");
+                if (socket) {
+                    qemu_opt_set(fsdev, "socket", socket);
+                }
                 sock_fd = qemu_opt_get(opts, "sock_fd");
                 if (sock_fd) {
                     qemu_opt_set(fsdev, "sock_fd", sock_fd);
-- 
1.7.6

^ permalink raw reply related

* [Qemu-devel] [PATCH 07/13] hw/9pfs: Create other filesystem objects
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
  To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
In-Reply-To: <1320094412-19091-1-git-send-email-mohan@in.ibm.com>

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

Add interfaces to create filesystem objects like directory,
device nodes, symbolic links, links for proxy filesytem driver

Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
 hw/9pfs/proxy.h               |    4 ++
 hw/9pfs/virtfs-proxy-helper.c |   63 +++++++++++++++++++++-
 hw/9pfs/virtio-9p-proxy.c     |  119 +++++++++++++++++++++++++++++++++++++----
 3 files changed, 175 insertions(+), 11 deletions(-)

diff --git a/hw/9pfs/proxy.h b/hw/9pfs/proxy.h
index 69e7baa..5564eb5 100644
--- a/hw/9pfs/proxy.h
+++ b/hw/9pfs/proxy.h
@@ -17,6 +17,10 @@ typedef struct {
 enum {
     T_OPEN = 1,
     T_CREATE,
+    T_MKNOD,
+    T_MKDIR,
+    T_SYMLINK,
+    T_LINK,
 };
 
 #endif
diff --git a/hw/9pfs/virtfs-proxy-helper.c b/hw/9pfs/virtfs-proxy-helper.c
index 73609e1..82aa267 100644
--- a/hw/9pfs/virtfs-proxy-helper.c
+++ b/hw/9pfs/virtfs-proxy-helper.c
@@ -268,6 +268,48 @@ static int setfsugid(int uid, int gid)
 }
 
 /*
+ * create a other filesystem objects and send 0 on success
+ * return -errno on error
+ */
+static int do_create_others(int type, struct iovec *iovec)
+{
+    V9fsString oldpath, path;
+    int retval, mode, uid, gid, cur_uid, cur_gid;
+    dev_t rdev;
+    int offset;
+
+    cur_uid = geteuid();
+    cur_gid = getegid();
+
+    offset = v9fs_unmarshal(iovec, 1, 0, "dd", &uid, &gid);
+    if (setfsugid(uid, gid) < 0) {
+        return -EPERM;
+    }
+    switch (type) {
+    case T_MKNOD:
+        v9fs_unmarshal(iovec, 1, offset, "sdq", &path, &mode, &rdev);
+        retval = mknod(path.data, mode, rdev);
+        break;
+    case T_MKDIR:
+        v9fs_unmarshal(iovec, 1, offset, "sd", &path, &mode);
+        retval = mkdir(path.data, mode);
+        break;
+    case T_SYMLINK:
+        v9fs_unmarshal(iovec, 1, offset, "ss", &oldpath, &path);
+        retval = symlink(oldpath.data, path.data);
+        v9fs_string_free(&oldpath);
+        break;
+    }
+
+    if (retval < 0) {
+        retval = -errno;
+    }
+    v9fs_string_free(&path);
+    setfsugid(cur_uid, cur_gid);
+    return retval;
+}
+
+/*
  * create a file and send fd on success
  * return -errno on error
  */
@@ -325,6 +367,7 @@ static int process_requests(int sock)
     int type, retval;
     struct iovec iovec;
     int valid_fd;
+    V9fsString oldpath, path;
 
     iovec.iov_base = g_malloc(BUFF_SZ);
     iovec.iov_len = BUFF_SZ;
@@ -344,6 +387,20 @@ static int process_requests(int sock)
                 valid_fd = 1;
             }
             break;
+        case T_MKNOD:
+        case T_MKDIR:
+        case T_SYMLINK:
+            retval = do_create_others(type, &iovec);
+            break;
+        case T_LINK:
+            v9fs_unmarshal(&iovec, 1, 0, "ss", &oldpath, &path);
+            retval = link(oldpath.data, path.data);
+            if (retval < 0) {
+                retval = -errno;
+            }
+            v9fs_string_free(&oldpath);
+            v9fs_string_free(&path);
+            break;
         default:
             goto error;
             break;
@@ -353,7 +410,11 @@ static int process_requests(int sock)
         switch (type) {
         case T_OPEN:
         case T_CREATE:
-            sendfd(sock, retval, valid_fd);
+        case T_MKNOD:
+        case T_MKDIR:
+        case T_SYMLINK:
+        case T_LINK:
+             sendfd(sock, retval, valid_fd);
             break;
         default:
             break;
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index d686454..5f5eb35 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -97,9 +97,10 @@ static int v9fs_request(V9fsProxy *proxy, int type,
     int retval;
     ProxyHeader header;
     va_list ap;
-    V9fsString *path;
+    V9fsString *path, *oldpath;
     int sock_error, flags, mode, uid, gid;
     struct iovec *iovec = NULL;
+    dev_t rdev;
 
     qemu_mutex_lock(&proxy->mutex);
 
@@ -131,6 +132,49 @@ static int v9fs_request(V9fsProxy *proxy, int type,
         v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
         header.size += sizeof(header);
         break;
+    case T_MKNOD:
+        path = va_arg(ap, V9fsString *);
+        mode = va_arg(ap, int);
+        rdev = va_arg(ap, long int);
+        uid = va_arg(ap, int);
+        gid = va_arg(ap, int);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "ddsdq",
+                        uid, gid, path, mode, rdev);
+        header.type = T_MKNOD;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
+    case T_MKDIR:
+        path = va_arg(ap, V9fsString *);
+        mode = va_arg(ap, int);
+        uid = va_arg(ap, int);
+        gid = va_arg(ap, int);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "ddsd",
+                        uid, gid, path, mode);
+        header.type = T_MKDIR;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
+    case T_SYMLINK:
+        oldpath = va_arg(ap, V9fsString *);
+        path = va_arg(ap, V9fsString *);
+        uid = va_arg(ap, int);
+        gid = va_arg(ap, int);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "ddss",
+                        uid, gid, oldpath, path);
+        header.type = T_SYMLINK;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
+    case T_LINK:
+        oldpath = va_arg(ap, V9fsString *);
+        path = va_arg(ap, V9fsString *);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "ss",
+                        oldpath, path);
+        header.type = T_LINK;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
     default:
         fprintf(stderr, "Invalid type %d\n", type);
         goto close_error;
@@ -149,6 +193,10 @@ static int v9fs_request(V9fsProxy *proxy, int type,
     switch (type) {
     case T_OPEN:
     case T_CREATE:
+    case T_MKNOD:
+    case T_MKDIR:
+    case T_SYMLINK:
+    case T_LINK:
         retval = v9fs_receivefd(proxy->sockfd, &sock_error);
         if (sock_error) {
             goto close_error;
@@ -294,15 +342,40 @@ static int proxy_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
 static int proxy_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
                        const char *name, FsCred *credp)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    V9fsString fullname;
+    int retval;
+    v9fs_string_init(&fullname);
+    v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
+
+    retval = v9fs_request(fs_ctx->private, T_MKNOD, NULL, "sdqdd",
+                    &fullname, credp->fc_mode, credp->fc_rdev,
+                    credp->fc_uid, credp->fc_gid);
+    v9fs_string_free(&fullname);
+    if (retval < 0) {
+        errno = -retval;
+        retval = -1;
+    }
+    return retval;
 }
 
 static int proxy_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
                        const char *name, FsCred *credp)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    V9fsString fullname;
+    int retval;
+
+    v9fs_string_init(&fullname);
+    v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
+
+    retval = v9fs_request(fs_ctx->private, T_MKDIR, NULL, "sddd", &fullname,
+                    credp->fc_mode, credp->fc_uid, credp->fc_gid);
+    v9fs_string_free(&fullname);
+    if (retval < 0) {
+        errno = -retval;
+        retval = -1;
+    }
+    v9fs_string_free(&fullname);
+    return retval;
 }
 
 static int proxy_fstat(FsContext *fs_ctx,
@@ -332,19 +405,45 @@ static int proxy_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
     return fs->fd;
 }
 
-
 static int proxy_symlink(FsContext *fs_ctx, const char *oldpath,
                          V9fsPath *dir_path, const char *name, FsCred *credp)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    V9fsString fullname, target;
+    int retval;
+
+    v9fs_string_init(&fullname);
+    v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
+    v9fs_string_init(&target);
+    v9fs_string_sprintf(&target, "%s", oldpath);
+
+    retval = v9fs_request(fs_ctx->private, T_SYMLINK, NULL, "ssdd",
+                    &target, &fullname, credp->fc_uid, credp->fc_gid);
+    v9fs_string_free(&fullname);
+    if (retval < 0) {
+        errno = -retval;
+        retval = -1;
+    }
+    return retval;
 }
 
 static int proxy_link(FsContext *ctx, V9fsPath *oldpath,
                       V9fsPath *dirpath, const char *name)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    V9fsString newpath;
+
+    v9fs_string_init(&newpath);
+    v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name);
+
+    retval = v9fs_request(ctx->private, T_LINK, NULL, "ss",
+                    oldpath, &newpath);
+    v9fs_string_free(&newpath);
+    if (retval < 0) {
+        errno = -retval;
+        retval = -1;
+    }
+    v9fs_string_free(&newpath);
+    return retval;
 }
 
 static int proxy_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
-- 
1.7.6

^ permalink raw reply related

* Re: Lock in the ironlake_panel_vdd_work()
From: Daniel Vetter @ 2011-10-31 20:55 UTC (permalink / raw)
  To: Keith Packard; +Cc: intel-gfx
In-Reply-To: <yun7h3l2eq5.fsf@aiko.keithp.com>

On Mon, Oct 31, 2011 at 11:33:22AM -0700, Keith Packard wrote:
> On Mon, 31 Oct 2011 14:34:46 +0100, Daniel Vetter <daniel@ffwll.ch> wrote:
> > On Mon, Oct 31, 2011 at 03:01:33PM +0200, Konstantin Belousov wrote:
> > > I have a question about ironlake_panel_vdd_work(). Should it use
> > > the device struct_mutex, or need it to be the mode_config.mutex
> > > instead ?
> > 
> > Yeah. This was actually flagged in review by Chris and me, but seems to
> > have been lost in the merge. Keith?
> 
> I thought I fixed that; it must have gotten lost in the fairly steady
> set of rebasing/reworking of that patch sequence.

Yeah, I recall having seen a fixed version somewhere ...

> commit 241dedda2785f040da45576418686490431232d2
> Author: Keith Packard <keithp@keithp.com>
> Date:   Mon Oct 31 11:30:10 2011 -0700
> 
>     drm/i915: Use mode_config.mutex in ironlake_panel_vdd_work
>     
>     Use of the struct_mutex is not correct for locking in mode setting paths.
>     
>     Signed-off-by: Keith Packard <keithp@keithp.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply

* [Qemu-devel] [PATCH 08/13] hw/9pfs: Add stat/readlink/statfs for proxy FS
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
  To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
In-Reply-To: <1320094412-19091-1-git-send-email-mohan@in.ibm.com>

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


Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
 hw/9pfs/proxy.h               |    3 ++
 hw/9pfs/virtfs-proxy-helper.c |   81 ++++++++++++++++++++++++++++++++++++++++-
 hw/9pfs/virtio-9p-proxy.c     |   67 +++++++++++++++++++++++++++++++---
 3 files changed, 144 insertions(+), 7 deletions(-)

diff --git a/hw/9pfs/proxy.h b/hw/9pfs/proxy.h
index 5564eb5..5a13b5f 100644
--- a/hw/9pfs/proxy.h
+++ b/hw/9pfs/proxy.h
@@ -21,6 +21,9 @@ enum {
     T_MKDIR,
     T_SYMLINK,
     T_LINK,
+    T_LSTAT,
+    T_READLINK,
+    T_STATFS,
 };
 
 #endif
diff --git a/hw/9pfs/virtfs-proxy-helper.c b/hw/9pfs/virtfs-proxy-helper.c
index 82aa267..9fa4a30 100644
--- a/hw/9pfs/virtfs-proxy-helper.c
+++ b/hw/9pfs/virtfs-proxy-helper.c
@@ -17,6 +17,7 @@
 #include <stdarg.h>
 #include "bswap.h"
 #include <sys/socket.h>
+#include <sys/vfs.h>
 #include "qemu-common.h"
 #include "virtio-9p.h"
 #include "hw/9pfs/proxy.h"
@@ -268,6 +269,59 @@ static int setfsugid(int uid, int gid)
 }
 
 /*
+ * send response in two parts
+ * 1) Size of the response
+ * 2) Response
+ * If there was a error send -errno only
+ */
+static int send_response(int sock, int size, char *response)
+{
+    int retval;
+    retval = socket_write(sock, &size, sizeof(size));
+    if (retval > 0 && size > 0) {
+        retval = socket_write(sock, response, size);
+    }
+    if (size > 0) {
+        g_free(response);
+    }
+    return retval;
+}
+
+static int do_stat(int type, struct iovec *iovec, char **response)
+{
+    V9fsString path;
+    int size = 0, retval = -1;
+
+    v9fs_unmarshal(iovec, 1, 0, "s", &path);
+
+    switch (type) {
+    case T_LSTAT:
+        size = sizeof(struct stat);
+        *response = g_malloc(size);
+        retval = lstat(path.data, (struct stat *)*response);
+        break;
+    case T_STATFS:
+        size = sizeof(struct statfs);
+        *response = g_malloc(size);
+        retval = statfs(path.data, (struct statfs *)*response);
+        break;
+    default:
+        retval = -EOPNOTSUPP;
+        goto error;
+    }
+
+    if (retval < 0) {
+        retval = -errno;
+        g_free(*response);
+    } else {
+        retval = size;
+    }
+error:
+    v9fs_string_free(&path);
+    return retval;
+}
+
+/*
  * create a other filesystem objects and send 0 on success
  * return -errno on error
  */
@@ -368,6 +422,8 @@ static int process_requests(int sock)
     struct iovec iovec;
     int valid_fd;
     V9fsString oldpath, path;
+    char *response = NULL;
+    int size;
 
     iovec.iov_base = g_malloc(BUFF_SZ);
     iovec.iov_len = BUFF_SZ;
@@ -401,6 +457,22 @@ static int process_requests(int sock)
             v9fs_string_free(&oldpath);
             v9fs_string_free(&path);
             break;
+        case T_LSTAT:
+        case T_STATFS:
+            retval = do_stat(type, &iovec, &response);
+            break;
+        case T_READLINK:
+            response = g_malloc(size);
+            v9fs_unmarshal(&iovec, 1, 0, "sd", &path, &size);
+            retval = readlink(path.data, response, size);
+            if (retval > 0) {
+                response[retval++] = '\0';
+            } else {
+                retval = -errno;
+                g_free(response);
+            }
+            v9fs_string_free(&path);
+            break;
         default:
             goto error;
             break;
@@ -416,11 +488,18 @@ static int process_requests(int sock)
         case T_LINK:
              sendfd(sock, retval, valid_fd);
             break;
+        case T_LSTAT:
+        case T_READLINK:
+        case T_STATFS:
+            if (send_response(sock, retval, response) < 0) {
+                do_perror("send_response");
+                goto error;
+            }
+            break;
         default:
             break;
         }
     }
-    (void)socket_write;
 error:
     g_free(iovec.iov_base);
     return -1;
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 5f5eb35..1328e59 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -101,6 +101,7 @@ static int v9fs_request(V9fsProxy *proxy, int type,
     int sock_error, flags, mode, uid, gid;
     struct iovec *iovec = NULL;
     dev_t rdev;
+    int msg_size, size;
 
     qemu_mutex_lock(&proxy->mutex);
 
@@ -175,6 +176,29 @@ static int v9fs_request(V9fsProxy *proxy, int type,
         v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
         header.size += sizeof(header);
         break;
+    case T_LSTAT:
+        path = va_arg(ap, V9fsString *);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "s", path);
+        header.type = T_LSTAT;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
+    case T_READLINK:
+        path = va_arg(ap, V9fsString *);
+        size = va_arg(ap, int);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sd",
+                        path, size);
+        header.type = T_READLINK;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
+    case T_STATFS:
+        path = va_arg(ap, V9fsString *);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "s", path);
+        header.type = T_STATFS;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
     default:
         fprintf(stderr, "Invalid type %d\n", type);
         goto close_error;
@@ -202,6 +226,23 @@ static int v9fs_request(V9fsProxy *proxy, int type,
             goto close_error;
         }
         break;
+    case T_LSTAT:
+    case T_READLINK:
+    case T_STATFS:
+        retval = read(proxy->sockfd, &msg_size, sizeof(msg_size));
+        if (retval != sizeof(msg_size)) {
+            goto close_error;
+        }
+        if (msg_size < 0) {
+            qemu_mutex_unlock(&proxy->mutex);
+            return msg_size;
+        }
+        retval = read(proxy->sockfd, response, msg_size);
+        if (retval != msg_size) {
+            goto close_error;
+        }
+        retval = 0; /* success */
+        break;
     }
     qemu_mutex_unlock(&proxy->mutex);
     return retval;
@@ -215,15 +256,25 @@ error:
 
 static int proxy_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    retval = v9fs_request(fs_ctx->private, T_LSTAT, stbuf, "s", fs_path);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    return retval;
 }
 
 static ssize_t proxy_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
                               char *buf, size_t bufsz)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    retval = v9fs_request(fs_ctx->private, T_READLINK, buf, "sd",
+                    fs_path, bufsz);
+    if (retval < 0) {
+        errno = -retval;
+        return -1;
+    }
+    return strlen(buf);
 }
 
 static int proxy_close(FsContext *ctx, V9fsFidOpenState *fs)
@@ -489,8 +540,12 @@ static int proxy_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync)
 
 static int proxy_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    retval = v9fs_request(s->private, T_STATFS, stbuf, "s", fs_path);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    return retval;
 }
 
 static ssize_t proxy_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
-- 
1.7.6

^ permalink raw reply related

* [Qemu-devel] [PATCH 03/13] hw/9pfs: Add new proxy filesystem driver
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
  To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
In-Reply-To: <1320094412-19091-1-git-send-email-mohan@in.ibm.com>

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

Add new proxy filesystem driver to add root privilege to qemu process.
It needs a helper process to be started by root user.

Following command line can be used to utilize proxy filesystem driver
-virtfs proxy,id=<id>,mount_tag=<tag>,sock_fd=<socket-fd>

Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
 Makefile.objs             |    1 +
 fsdev/qemu-fsdev.c        |    1 +
 fsdev/qemu-fsdev.h        |    1 +
 hw/9pfs/proxy.h           |   10 ++
 hw/9pfs/virtio-9p-proxy.c |  374 +++++++++++++++++++++++++++++++++++++++++++++
 qemu-config.c             |    7 +
 vl.c                      |    6 +-
 7 files changed, 399 insertions(+), 1 deletions(-)
 create mode 100644 hw/9pfs/proxy.h
 create mode 100644 hw/9pfs/virtio-9p-proxy.c

diff --git a/Makefile.objs b/Makefile.objs
index 804bc3c..fd5f73c 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -311,6 +311,7 @@ hw-obj-$(CONFIG_SOUND) += $(sound-obj-y)
 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-coth.o cofs.o codir.o cofile.o
 9pfs-nested-$(CONFIG_VIRTFS) += coxattr.o virtio-9p-handle.o
 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-synth.o virtio-9p-marshal.o
+9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-proxy.o
 
 hw-obj-$(CONFIG_REALLY_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y))
 $(addprefix 9pfs/, $(9pfs-nested-y)): QEMU_CFLAGS+=$(GLIB_CFLAGS)
diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
index efbfea1..b31d116 100644
--- a/fsdev/qemu-fsdev.c
+++ b/fsdev/qemu-fsdev.c
@@ -25,6 +25,7 @@ static FsDriverTable FsDrivers[] = {
     { .name = "local", .ops = &local_ops},
     { .name = "handle", .ops = &handle_ops},
     { .name = "synth", .ops = &synth_ops},
+    { .name = "proxy", .ops = &proxy_ops},
 };
 
 int qemu_fsdev_add(QemuOpts *opts)
diff --git a/fsdev/qemu-fsdev.h b/fsdev/qemu-fsdev.h
index 921452d..1af1f54 100644
--- a/fsdev/qemu-fsdev.h
+++ b/fsdev/qemu-fsdev.h
@@ -44,4 +44,5 @@ FsDriverEntry *get_fsdev_fsentry(char *id);
 extern FileOperations local_ops;
 extern FileOperations handle_ops;
 extern FileOperations synth_ops;
+extern FileOperations proxy_ops;
 #endif
diff --git a/hw/9pfs/proxy.h b/hw/9pfs/proxy.h
new file mode 100644
index 0000000..1a47509
--- /dev/null
+++ b/hw/9pfs/proxy.h
@@ -0,0 +1,10 @@
+#ifndef __PROXY_HELP_H
+#define __PROXY_HELP_H
+
+#define BUFF_SZ (4 * 1024)
+
+typedef struct {
+    int type;
+    int size;
+} ProxyHeader;
+#endif
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
new file mode 100644
index 0000000..c682e36
--- /dev/null
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -0,0 +1,374 @@
+/*
+ * Virtio 9p Proxy callback
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * M. Mohan Kumar <mohan@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 <sys/socket.h>
+#include <sys/un.h>
+#include "hw/virtio.h"
+#include "virtio-9p.h"
+#include "fsdev/qemu-fsdev.h"
+#include "proxy.h"
+
+typedef struct V9fsProxy {
+    int sockfd;
+    QemuMutex mutex;
+    struct iovec iovec;
+} V9fsProxy;
+
+static int proxy_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static ssize_t proxy_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
+                              char *buf, size_t bufsz)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_close(FsContext *ctx, V9fsFidOpenState *fs)
+{
+    return close(fs->fd);
+}
+
+static int proxy_closedir(FsContext *ctx, V9fsFidOpenState *fs)
+{
+    return closedir(fs->dir);
+}
+
+static int proxy_open(FsContext *ctx, V9fsPath *fs_path,
+                      int flags, V9fsFidOpenState *fs)
+{
+    fs->fd = -1;
+    return fs->fd;
+}
+
+static int proxy_opendir(FsContext *ctx,
+                         V9fsPath *fs_path, V9fsFidOpenState *fs)
+{
+    fs->dir = NULL;
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static void proxy_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
+{
+    return rewinddir(fs->dir);
+}
+
+static off_t proxy_telldir(FsContext *ctx, V9fsFidOpenState *fs)
+{
+    return telldir(fs->dir);
+}
+
+static int proxy_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
+                           struct dirent *entry,
+                           struct dirent **result)
+{
+    return readdir_r(fs->dir, entry, result);
+}
+
+static void proxy_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
+{
+    return seekdir(fs->dir, off);
+}
+
+static ssize_t proxy_preadv(FsContext *ctx, V9fsFidOpenState *fs,
+                            const struct iovec *iov,
+                            int iovcnt, off_t offset)
+{
+#ifdef CONFIG_PREADV
+    return preadv(fs->fd, iov, iovcnt, offset);
+#else
+    int err = lseek(fs->fd, offset, SEEK_SET);
+    if (err == -1) {
+        return err;
+    } else {
+        return readv(fs->fd, iov, iovcnt);
+    }
+#endif
+}
+
+static ssize_t proxy_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
+                             const struct iovec *iov,
+                             int iovcnt, off_t offset)
+{
+    ssize_t ret
+;
+#ifdef CONFIG_PREADV
+    ret = pwritev(fs->fd, iov, iovcnt, offset);
+#else
+    int err = lseek(fs->fd, offset, SEEK_SET);
+    if (err == -1) {
+        return err;
+    } else {
+        ret = writev(fs->fd, iov, iovcnt);
+    }
+#endif
+#ifdef CONFIG_SYNC_FILE_RANGE
+    if (ret > 0 && ctx->export_flags & V9FS_IMMEDIATE_WRITEOUT) {
+        /*
+         * Initiate a writeback. This is not a data integrity sync.
+         * We want to ensure that we don't leave dirty pages in the cache
+         * after write when writeout=immediate is sepcified.
+         */
+        sync_file_range(fs->fd, offset, ret,
+                        SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE);
+    }
+#endif
+    return ret;
+}
+
+static int proxy_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
+                       const char *name, FsCred *credp)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
+                       const char *name, FsCred *credp)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_fstat(FsContext *fs_ctx,
+                       V9fsFidOpenState *fs, struct stat *stbuf)
+{
+    int err;
+    err = fstat(fs->fd, stbuf);
+    return err;
+}
+
+static int proxy_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
+                       int flags, FsCred *credp, V9fsFidOpenState *fs)
+{
+    fs->fd = -1;
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+
+static int proxy_symlink(FsContext *fs_ctx, const char *oldpath,
+                         V9fsPath *dir_path, const char *name, FsCred *credp)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_link(FsContext *ctx, V9fsPath *oldpath,
+                      V9fsPath *dirpath, const char *name)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_rename(FsContext *ctx, const char *oldpath,
+                        const char *newpath)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_utimensat(FsContext *s, V9fsPath *fs_path,
+                           const struct timespec *buf)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_remove(FsContext *ctx, const char *path)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync)
+{
+    if (datasync) {
+        return qemu_fdatasync(fs->fd);
+    } else {
+        return fsync(fs->fd);
+    }
+}
+
+static int proxy_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static ssize_t proxy_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
+                               const char *name, void *value, size_t size)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static ssize_t proxy_llistxattr(FsContext *ctx, V9fsPath *fs_path,
+                                void *value, size_t size)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
+                           void *value, size_t size, int flags)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
+                              const char *name)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_name_to_path(FsContext *ctx, V9fsPath *dir_path,
+                              const char *name, V9fsPath *target)
+{
+    if (dir_path) {
+        v9fs_string_sprintf((V9fsString *)target, "%s/%s",
+                            dir_path->data, name);
+    } else {
+        v9fs_string_sprintf((V9fsString *)target, "%s", name);
+    }
+    /* Bump the size for including terminating NULL */
+    target->size++;
+    return 0;
+}
+
+static int proxy_renameat(FsContext *ctx, V9fsPath *olddir,
+                          const char *old_name, V9fsPath *newdir,
+                          const char *new_name)
+{
+    int ret;
+    V9fsString old_full_name, new_full_name;
+
+    v9fs_string_init(&old_full_name);
+    v9fs_string_init(&new_full_name);
+
+    v9fs_string_sprintf(&old_full_name, "%s/%s", olddir->data, old_name);
+    v9fs_string_sprintf(&new_full_name, "%s/%s", newdir->data, new_name);
+
+    ret = proxy_rename(ctx, old_full_name.data, new_full_name.data);
+    v9fs_string_free(&old_full_name);
+    v9fs_string_free(&new_full_name);
+    return ret;
+}
+
+static int proxy_unlinkat(FsContext *ctx, V9fsPath *dir,
+                          const char *name, int flags)
+{
+    int ret;
+    V9fsString fullname;
+    v9fs_string_init(&fullname);
+
+    v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name);
+    ret = proxy_remove(ctx, fullname.data);
+    v9fs_string_free(&fullname);
+
+    return ret;
+}
+
+static int proxy_parse_opts(QemuOpts *opts, struct FsDriverEntry *fs)
+{
+    const char *sock_fd = qemu_opt_get(opts, "sock_fd");
+
+    if (sock_fd) {
+        fprintf(stderr, "sock_fd option not specified\n");
+        return -1;
+    }
+    fs->path = g_strdup(sock_fd);
+    return 0;
+}
+
+static int proxy_init(FsContext *ctx)
+{
+    V9fsProxy *proxy = g_malloc(sizeof(V9fsProxy));
+    int sock_id;
+
+    sock_id = atoi(ctx->fs_root);
+    if (sock_id < 0) {
+        fprintf(stderr, "socket descriptor not initialized\n");
+        return -1;
+    }
+    g_free(ctx->fs_root);
+
+    proxy->iovec.iov_base = g_malloc(BUFF_SZ);
+    proxy->iovec.iov_len = BUFF_SZ;
+    ctx->private = proxy;
+    proxy->sockfd = sock_id;
+    qemu_mutex_init(&proxy->mutex);
+
+    ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT;
+    return 0;
+}
+
+FileOperations proxy_ops = {
+    .parse_opts   = proxy_parse_opts,
+    .init         = proxy_init,
+    .lstat        = proxy_lstat,
+    .readlink     = proxy_readlink,
+    .close        = proxy_close,
+    .closedir     = proxy_closedir,
+    .open         = proxy_open,
+    .opendir      = proxy_opendir,
+    .rewinddir    = proxy_rewinddir,
+    .telldir      = proxy_telldir,
+    .readdir_r    = proxy_readdir_r,
+    .seekdir      = proxy_seekdir,
+    .preadv       = proxy_preadv,
+    .pwritev      = proxy_pwritev,
+    .chmod        = proxy_chmod,
+    .mknod        = proxy_mknod,
+    .mkdir        = proxy_mkdir,
+    .fstat        = proxy_fstat,
+    .open2        = proxy_open2,
+    .symlink      = proxy_symlink,
+    .link         = proxy_link,
+    .truncate     = proxy_truncate,
+    .rename       = proxy_rename,
+    .chown        = proxy_chown,
+    .utimensat    = proxy_utimensat,
+    .remove       = proxy_remove,
+    .fsync        = proxy_fsync,
+    .statfs       = proxy_statfs,
+    .lgetxattr    = proxy_lgetxattr,
+    .llistxattr   = proxy_llistxattr,
+    .lsetxattr    = proxy_lsetxattr,
+    .lremovexattr = proxy_lremovexattr,
+    .name_to_path = proxy_name_to_path,
+    .renameat     = proxy_renameat,
+    .unlinkat     = proxy_unlinkat,
+};
diff --git a/qemu-config.c b/qemu-config.c
index 597d7e1..5e63c14 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -183,6 +183,10 @@ QemuOptsList qemu_fsdev_opts = {
         }, {
             .name = "readonly",
             .type = QEMU_OPT_BOOL,
+
+        }, {
+            .name = "sock_fd",
+            .type = QEMU_OPT_NUMBER,
         },
 
         { /*End of list */ }
@@ -212,6 +216,9 @@ QemuOptsList qemu_virtfs_opts = {
         }, {
             .name = "readonly",
             .type = QEMU_OPT_BOOL,
+        }, {
+            .name = "sock_fd",
+            .type = QEMU_OPT_NUMBER,
         },
 
         { /*End of list */ }
diff --git a/vl.c b/vl.c
index cf538b2..5a5ab7f 100644
--- a/vl.c
+++ b/vl.c
@@ -2663,7 +2663,7 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_virtfs: {
                 QemuOpts *fsdev;
                 QemuOpts *device;
-                const char *writeout;
+                const char *writeout, *sock_fd;
 
                 olist = qemu_find_opts("virtfs");
                 if (!olist) {
@@ -2703,6 +2703,10 @@ int main(int argc, char **argv, char **envp)
                 qemu_opt_set(fsdev, "path", qemu_opt_get(opts, "path"));
                 qemu_opt_set(fsdev, "security_model",
                              qemu_opt_get(opts, "security_model"));
+                sock_fd = qemu_opt_get(opts, "sock_fd");
+                if (sock_fd) {
+                    qemu_opt_set(fsdev, "sock_fd", sock_fd);
+                }
 
                 qemu_opt_set_bool(fsdev, "readonly",
                                 qemu_opt_get_bool(opts, "readonly", 0));
-- 
1.7.6

^ permalink raw reply related

* [Qemu-devel] [PATCH 10/13] hw/9pfs: xattr interfaces in proxy filesystem driver
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
  To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
In-Reply-To: <1320094412-19091-1-git-send-email-mohan@in.ibm.com>

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

Add xattr support for proxy FS

Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
 hw/9pfs/proxy.h               |    4 ++
 hw/9pfs/virtfs-proxy-helper.c |   60 ++++++++++++++++++++
 hw/9pfs/virtio-9p-proxy.c     |  121 ++++++++++++++++++++++++++++++++++++++---
 3 files changed, 176 insertions(+), 9 deletions(-)

diff --git a/hw/9pfs/proxy.h b/hw/9pfs/proxy.h
index 557a8f4..fdfa651 100644
--- a/hw/9pfs/proxy.h
+++ b/hw/9pfs/proxy.h
@@ -30,6 +30,10 @@ enum {
     T_UTIME,
     T_RENAME,
     T_REMOVE,
+    T_LGETXATTR,
+    T_LLISTXATTR,
+    T_LSETXATTR,
+    T_LREMOVEXATTR,
 };
 
 #endif
diff --git a/hw/9pfs/virtfs-proxy-helper.c b/hw/9pfs/virtfs-proxy-helper.c
index 845e3c6..78669d0 100644
--- a/hw/9pfs/virtfs-proxy-helper.c
+++ b/hw/9pfs/virtfs-proxy-helper.c
@@ -18,6 +18,7 @@
 #include "bswap.h"
 #include <sys/socket.h>
 #include <sys/vfs.h>
+#include <attr/xattr.h>
 #include "qemu-common.h"
 #include "virtio-9p.h"
 #include "hw/9pfs/proxy.h"
@@ -426,6 +427,8 @@ static int process_requests(int sock)
     int size, mode, uid, gid;
     struct timespec spec[2];
     uint64_t offset;
+    V9fsString name, value;
+    int flags;
 
     iovec.iov_base = g_malloc(BUFF_SZ);
     iovec.iov_len = BUFF_SZ;
@@ -526,6 +529,49 @@ static int process_requests(int sock)
             }
             v9fs_string_free(&path);
             break;
+        case T_LGETXATTR:
+            if (size) {
+                response = g_malloc(size);
+            }
+            v9fs_unmarshal(&iovec, 1, 0, "ssd", &path, &name, &size);
+            retval = lgetxattr(path.data, name.data, response, size);
+            if (retval < 0) {
+                retval = -errno;
+            }
+            v9fs_string_free(&path);
+            v9fs_string_free(&name);
+            break;
+        case T_LLISTXATTR:
+            if (size) {
+                response = g_malloc(size);
+            }
+            v9fs_unmarshal(&iovec, 1, 0, "sd", &path, &size);
+            retval = llistxattr(path.data, response, size);
+            if (retval < 0) {
+                retval = -errno;
+            }
+            v9fs_string_free(&path);
+            break;
+        case T_LSETXATTR:
+            v9fs_unmarshal(&iovec, 1, 0, "sssdd", &path, &name, &value, &size,
+                            &flags);
+            retval = lsetxattr(path.data, name.data, value.data, size, flags);
+            if (retval < 0) {
+                retval = -errno;
+            }
+            v9fs_string_free(&path);
+            v9fs_string_free(&name);
+            v9fs_string_free(&value);
+            break;
+        case T_LREMOVEXATTR:
+            v9fs_unmarshal(&iovec, 1, 0, "ss", &path, &name);
+            retval = lremovexattr(path.data, name.data);
+            if (retval < 0) {
+                retval = -errno;
+            }
+            v9fs_string_free(&path);
+            v9fs_string_free(&name);
+            break;
         default:
             goto error;
             break;
@@ -545,6 +591,8 @@ static int process_requests(int sock)
         case T_UTIME:
         case T_RENAME:
         case T_REMOVE:
+        case T_LSETXATTR:
+        case T_LREMOVEXATTR:
              sendfd(sock, retval, valid_fd);
             break;
         case T_LSTAT:
@@ -555,6 +603,18 @@ static int process_requests(int sock)
                 goto error;
             }
             break;
+        case T_LGETXATTR:
+        case T_LLISTXATTR:
+            /* send only size of xattr attribute as per request */
+            if (!size) {
+                socket_write(sock, &retval, sizeof(retval));
+            } else { /* send value of xattr 'name' */
+                if (send_response(sock, retval, response) < 0) {
+                    do_perror("send_response");
+                    goto error;
+                }
+            }
+            break;
         default:
             break;
         }
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 47419dd..143a784 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -101,9 +101,10 @@ static int v9fs_request(V9fsProxy *proxy, int type,
     int sock_error, flags, mode, uid, gid;
     struct iovec *iovec = NULL;
     dev_t rdev;
-    int msg_size, size;
+    int msg_size, size = 0;
     struct timespec spec[2];
     uint64_t offset;
+    V9fsString *name, *value;
 
     qemu_mutex_lock(&proxy->mutex);
 
@@ -258,6 +259,46 @@ static int v9fs_request(V9fsProxy *proxy, int type,
         v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
         header.size += sizeof(header);
         break;
+    case T_LGETXATTR:
+        path = va_arg(ap, V9fsString *);
+        name = va_arg(ap, V9fsString *);
+        size = va_arg(ap, int);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "ssd", path,
+                        name, size);
+        header.type = T_LGETXATTR;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
+    case T_LLISTXATTR:
+        path = va_arg(ap, V9fsString *);
+        size = va_arg(ap, int);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sd",
+                        path, size);
+        header.type = T_LLISTXATTR;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
+    case T_LSETXATTR:
+        path = va_arg(ap, V9fsString *);
+        name = va_arg(ap, V9fsString *);
+        value = va_arg(ap, V9fsString *);
+        size = va_arg(ap, int);
+        flags = va_arg(ap, int);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sssdd",
+                        path, name, value, size, flags);
+        header.type = T_LSETXATTR;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
+    case T_LREMOVEXATTR:
+        path = va_arg(ap, V9fsString *);
+        name = va_arg(ap, V9fsString *);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "ss",
+                        path, name);
+        header.type = T_LREMOVEXATTR;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
     default:
         fprintf(stderr, "Invalid type %d\n", type);
         goto close_error;
@@ -286,6 +327,8 @@ static int v9fs_request(V9fsProxy *proxy, int type,
     case T_TRUNCATE:
     case T_UTIME:
     case T_REMOVE:
+    case T_LSETXATTR:
+    case T_LREMOVEXATTR:
         retval = v9fs_receivefd(proxy->sockfd, &sock_error);
         if (sock_error) {
             goto close_error;
@@ -308,6 +351,24 @@ static int v9fs_request(V9fsProxy *proxy, int type,
         }
         retval = 0; /* success */
         break;
+    case T_LGETXATTR:
+    case T_LLISTXATTR:
+        if (!size) {
+            if (read(proxy->sockfd, &retval, sizeof(int)) < 0) {
+                retval = -errno;
+            }
+        } else {
+            retval = read(proxy->sockfd, &msg_size, sizeof(msg_size));
+            if (msg_size < 0) {
+                qemu_mutex_unlock(&proxy->mutex);
+                return msg_size;
+            }
+            retval = read(proxy->sockfd, response, msg_size);
+            if (retval != msg_size) {
+                goto close_error;
+            }
+        }
+        break;
     }
     qemu_mutex_unlock(&proxy->mutex);
     return retval;
@@ -661,29 +722,71 @@ static int proxy_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
 static ssize_t proxy_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
                                const char *name, void *value, size_t size)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    V9fsString xname;
+
+    v9fs_string_init(&xname);
+    v9fs_string_sprintf(&xname, "%s", name);
+    retval = v9fs_request(ctx->private, T_LGETXATTR, value, "ssd",
+                    fs_path, &xname, size);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    v9fs_string_free(&xname);
+    return retval;
 }
 
 static ssize_t proxy_llistxattr(FsContext *ctx, V9fsPath *fs_path,
                                 void *value, size_t size)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    retval = v9fs_request(ctx->private, T_LLISTXATTR, value, "sd",
+                    fs_path, size);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    return retval;
 }
 
 static int proxy_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
                            void *value, size_t size, int flags)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    V9fsString xname, xvalue;
+
+    v9fs_string_init(&xname);
+    v9fs_string_sprintf(&xname, "%s", name);
+
+    v9fs_string_init(&xvalue);
+    xvalue.size = size;
+    xvalue.data = g_malloc(size);
+    memcpy(xvalue.data, value, size);
+
+    retval = v9fs_request(ctx->private, T_LSETXATTR, value, "sssdd",
+                    fs_path, xname, xvalue, size, flags);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    v9fs_string_free(&xname);
+    v9fs_string_free(&xvalue);
+    return retval;
 }
 
 static int proxy_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
                               const char *name)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    V9fsString xname;
+
+    v9fs_string_init(&xname);
+    v9fs_string_sprintf(&xname, "%s", name);
+    retval = v9fs_request(ctx->private, T_LREMOVEXATTR, NULL, "ss",
+                    fs_path, &xname);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    v9fs_string_free(&xname);
+    return retval;
 }
 
 static int proxy_name_to_path(FsContext *ctx, V9fsPath *dir_path,
-- 
1.7.6

^ permalink raw reply related

* [Qemu-devel] [PATCH 12/13] hw/9pfs: Documentation changes related to proxy fs
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
  To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
In-Reply-To: <1320094412-19091-1-git-send-email-mohan@in.ibm.com>

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


Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
 qemu-options.hx |   30 ++++++++++++++++++++++--------
 1 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/qemu-options.hx b/qemu-options.hx
index 8df6165..eef98c5 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -527,19 +527,19 @@ DEFHEADING()
 DEFHEADING(File system options:)
 
 DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev,
-    "-fsdev fsdriver,id=id,path=path,[security_model={mapped|passthrough|none}]\n"
-    "       [,writeout=immediate][,readonly]\n",
+    "-fsdev fsdriver,id=id[,path=path,][security_model={mapped|passthrough|none}]\n"
+    " [,writeout=immediate][,readonly][,socket=socket|sock_fd=sock_fd]\n",
     QEMU_ARCH_ALL)
 
 STEXI
 
-@item -fsdev @var{fsdriver},id=@var{id},path=@var{path},[security_model=@var{security_model}][,writeout=@var{writeout}][,readonly]
+@item -fsdev @var{fsdriver},id=@var{id},path=@var{path},[security_model=@var{security_model}][,writeout=@var{writeout}][,readonly][,socket=@var{socket}|sock_fd=@var{sock_fd}]
 @findex -fsdev
 Define a new file system device. Valid options are:
 @table @option
 @item @var{fsdriver}
 This option specifies the fs driver backend to use.
-Currently "local" and "handle" file system drivers are supported.
+Currently "local", "handle" and "proxy" file system drivers are supported.
 @item id=@var{id}
 Specifies identifier for this device
 @item path=@var{path}
@@ -556,7 +556,7 @@ file attributes. Directories exported by this security model cannot
 interact with other unix tools. "none" security model is same as
 passthrough except the sever won't report failures if it fails to
 set file attributes like ownership. Security model is mandatory
-only for local fsdriver. Other fsdrivers (like handle) don't take
+only for local fsdriver. Other fsdrivers (like handle, proxy) don't take
 security model as a parameter.
 @item writeout=@var{writeout}
 This is an optional argument. The only supported value is "immediate".
@@ -566,6 +566,13 @@ reported as written by the storage subsystem.
 @item readonly
 Enables exporting 9p share as a readonly mount for guests. By default
 read-write access is given.
+@item socket=@var{socket}
+Enables proxy filesystem driver to use passed socket file for communicating
+with virtfs-proxy-helper
+@item sock_fd=@var{sock_fd}
+Enables proxy filesystem driver to use passed socket descriptor for
+communicating with virtfs-proxy-helper. Usually a helper like libvirt
+will create socketpair and pass one of the fds as sock_fd
 @end table
 
 -fsdev option is used along with -device driver "virtio-9p-pci".
@@ -591,14 +598,14 @@ DEF("virtfs", HAS_ARG, QEMU_OPTION_virtfs,
 
 STEXI
 
-@item -virtfs @var{fsdriver},path=@var{path},mount_tag=@var{mount_tag},security_model=@var{security_model}[,writeout=@var{writeout}][,readonly]
+@item -virtfs @var{fsdriver}[,path=@var{path}],mount_tag=@var{mount_tag}[,security_model=@var{security_model}][,writeout=@var{writeout}][,readonly][,socket=@var{socket}|sock_fd=@var{sock_fd}]
 @findex -virtfs
 
 The general form of a Virtual File system pass-through options are:
 @table @option
 @item @var{fsdriver}
 This option specifies the fs driver backend to use.
-Currently "local" and "handle" file system drivers are supported.
+Currently "local", "handle" and "proxy" file system drivers are supported.
 @item id=@var{id}
 Specifies identifier for this device
 @item path=@var{path}
@@ -615,7 +622,7 @@ file attributes. Directories exported by this security model cannot
 interact with other unix tools. "none" security model is same as
 passthrough except the sever won't report failures if it fails to
 set file attributes like ownership. Security model is mandatory only
-for local fsdriver. Other fsdrivers (like handle) don't take security
+for local fsdriver. Other fsdrivers (like handle, proxy) don't take security
 model as a parameter.
 @item writeout=@var{writeout}
 This is an optional argument. The only supported value is "immediate".
@@ -625,6 +632,13 @@ reported as written by the storage subsystem.
 @item readonly
 Enables exporting 9p share as a readonly mount for guests. By default
 read-write access is given.
+@item socket=@var{socket}
+Enables proxy filesystem driver to use passed socket file for
+communicating with virtfs-proxy-helper. Usually a helper like libvirt
+will create socketpair and pass one of the fds as sock_fd
+@item sock_fd
+Enables proxy filesystem driver to use passed 'sock_fd' as the socket
+descriptor for interfacing with virtfs-proxy-helper
 @end table
 ETEXI
 
-- 
1.7.6

^ permalink raw reply related

* [Qemu-devel] [PATCH 09/13] hw/9pfs: File ownership and others
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
  To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
In-Reply-To: <1320094412-19091-1-git-send-email-mohan@in.ibm.com>

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

Add file ownership interfaces like chmod/chown, utime update, rename,
remove and truncating files for proxy FS

Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
 hw/9pfs/proxy.h               |    6 ++
 hw/9pfs/virtfs-proxy-helper.c |   61 ++++++++++++++++++-
 hw/9pfs/virtio-9p-proxy.c     |  134 +++++++++++++++++++++++++++++++++++++----
 3 files changed, 188 insertions(+), 13 deletions(-)

diff --git a/hw/9pfs/proxy.h b/hw/9pfs/proxy.h
index 5a13b5f..557a8f4 100644
--- a/hw/9pfs/proxy.h
+++ b/hw/9pfs/proxy.h
@@ -24,6 +24,12 @@ enum {
     T_LSTAT,
     T_READLINK,
     T_STATFS,
+    T_CHMOD,
+    T_CHOWN,
+    T_TRUNCATE,
+    T_UTIME,
+    T_RENAME,
+    T_REMOVE,
 };
 
 #endif
diff --git a/hw/9pfs/virtfs-proxy-helper.c b/hw/9pfs/virtfs-proxy-helper.c
index 9fa4a30..845e3c6 100644
--- a/hw/9pfs/virtfs-proxy-helper.c
+++ b/hw/9pfs/virtfs-proxy-helper.c
@@ -423,7 +423,9 @@ static int process_requests(int sock)
     int valid_fd;
     V9fsString oldpath, path;
     char *response = NULL;
-    int size;
+    int size, mode, uid, gid;
+    struct timespec spec[2];
+    uint64_t offset;
 
     iovec.iov_base = g_malloc(BUFF_SZ);
     iovec.iov_len = BUFF_SZ;
@@ -473,6 +475,57 @@ static int process_requests(int sock)
             }
             v9fs_string_free(&path);
             break;
+        case T_CHMOD:
+            v9fs_unmarshal(&iovec, 1, 0, "sd", &path, &mode);
+            retval = chmod(path.data, mode);
+            if (retval < 0) {
+                retval = -errno;
+            }
+            v9fs_string_free(&path);
+            break;
+        case T_CHOWN:
+            v9fs_unmarshal(&iovec, 1, 0, "sdd", &path, &uid, &gid);
+            retval = lchown(path.data, uid, gid);
+            if (retval < 0) {
+                retval = -errno;
+            }
+            v9fs_string_free(&path);
+            break;
+        case T_TRUNCATE:
+            v9fs_unmarshal(&iovec, 1, 0, "sq", &path, &offset);
+            retval = truncate(path.data, offset);
+            if (retval < 0) {
+                retval = -errno;
+            }
+            v9fs_string_free(&path);
+            break;
+        case T_UTIME:
+            v9fs_unmarshal(&iovec, 1, 0, "sqqqq", &path,
+                            &spec[0].tv_sec, &spec[0].tv_nsec,
+                            &spec[1].tv_sec, &spec[1].tv_nsec);
+            retval = utimensat(AT_FDCWD, path.data, spec, AT_SYMLINK_NOFOLLOW);
+            if (retval < 0) {
+                retval = -errno;
+            }
+            v9fs_string_free(&path);
+            break;
+        case T_RENAME:
+            v9fs_unmarshal(&iovec, 1, 0, "ss", &oldpath, &path);
+            retval = rename(oldpath.data, path.data);
+            if (retval < 0) {
+                retval = -errno;
+            }
+            v9fs_string_free(&oldpath);
+            v9fs_string_free(&path);
+            break;
+        case T_REMOVE:
+            v9fs_unmarshal(&iovec, 1, 0, "s", &path);
+            retval = remove(path.data);
+            if (retval < 0) {
+                retval = -errno;
+            }
+            v9fs_string_free(&path);
+            break;
         default:
             goto error;
             break;
@@ -486,6 +539,12 @@ static int process_requests(int sock)
         case T_MKDIR:
         case T_SYMLINK:
         case T_LINK:
+        case T_CHMOD:
+        case T_CHOWN:
+        case T_TRUNCATE:
+        case T_UTIME:
+        case T_RENAME:
+        case T_REMOVE:
              sendfd(sock, retval, valid_fd);
             break;
         case T_LSTAT:
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 1328e59..47419dd 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -102,6 +102,8 @@ static int v9fs_request(V9fsProxy *proxy, int type,
     struct iovec *iovec = NULL;
     dev_t rdev;
     int msg_size, size;
+    struct timespec spec[2];
+    uint64_t offset;
 
     qemu_mutex_lock(&proxy->mutex);
 
@@ -199,6 +201,63 @@ static int v9fs_request(V9fsProxy *proxy, int type,
         v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
         header.size += sizeof(header);
         break;
+    case T_CHMOD:
+        path = va_arg(ap, V9fsString *);
+        mode = va_arg(ap, int);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sd",
+                        path, mode);
+        header.type = T_CHMOD;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
+    case T_CHOWN:
+        path = va_arg(ap, V9fsString *);
+        uid = va_arg(ap, int);
+        gid = va_arg(ap, int);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sdd",
+                        path, uid, gid);
+        header.type = T_CHOWN;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
+    case T_TRUNCATE:
+        path = va_arg(ap, V9fsString *);
+        offset = va_arg(ap, uint64_t);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sq",
+                        path, offset);
+        header.type = T_TRUNCATE;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
+    case T_UTIME:
+        path = va_arg(ap, V9fsString *);
+        spec[0].tv_sec = va_arg(ap, long);
+        spec[0].tv_nsec = va_arg(ap, long);
+        spec[1].tv_sec = va_arg(ap, long);
+        spec[1].tv_nsec = va_arg(ap, long);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sqqqq",
+                        path, spec[0].tv_sec, spec[1].tv_nsec,
+                        spec[1].tv_sec, spec[1].tv_nsec);
+        header.type = T_UTIME;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
+    case T_RENAME:
+        oldpath = va_arg(ap, V9fsString *);
+        path = va_arg(ap, V9fsString *);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "ss",
+                        oldpath, path);
+        header.type = T_RENAME;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
+    case T_REMOVE:
+        path = va_arg(ap, V9fsString *);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "s", path);
+        header.type = T_REMOVE;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
     default:
         fprintf(stderr, "Invalid type %d\n", type);
         goto close_error;
@@ -221,6 +280,12 @@ static int v9fs_request(V9fsProxy *proxy, int type,
     case T_MKDIR:
     case T_SYMLINK:
     case T_LINK:
+    case T_CHMOD:
+    case T_CHOWN:
+    case T_RENAME:
+    case T_TRUNCATE:
+    case T_UTIME:
+    case T_REMOVE:
         retval = v9fs_receivefd(proxy->sockfd, &sock_error);
         if (sock_error) {
             goto close_error;
@@ -386,8 +451,13 @@ static ssize_t proxy_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
 
 static int proxy_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    retval = v9fs_request(fs_ctx->private, T_CHMOD, NULL, "sd",
+                    fs_path, credp->fc_mode);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    return retval;
 }
 
 static int proxy_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
@@ -499,34 +569,74 @@ static int proxy_link(FsContext *ctx, V9fsPath *oldpath,
 
 static int proxy_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+
+    retval = v9fs_request(ctx->private, T_TRUNCATE, NULL, "sq", fs_path, size);
+    if (retval < 0) {
+        errno = -retval;
+        return -1;
+    }
+    return 0;
 }
 
 static int proxy_rename(FsContext *ctx, const char *oldpath,
                         const char *newpath)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    V9fsString oldname, newname;
+
+    v9fs_string_init(&oldname);
+    v9fs_string_init(&newname);
+
+    v9fs_string_sprintf(&oldname, "%s", oldpath);
+    v9fs_string_sprintf(&newname, "%s", newpath);
+    retval = v9fs_request(ctx->private, T_RENAME, NULL, "ss",
+                    &oldname, &newname);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    v9fs_string_free(&oldname);
+    v9fs_string_free(&newname);
+    return retval;
 }
 
 static int proxy_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    retval = v9fs_request(fs_ctx->private, T_CHOWN, NULL, "sdd",
+                    fs_path, credp->fc_uid, credp->fc_gid);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    return retval;
 }
 
 static int proxy_utimensat(FsContext *s, V9fsPath *fs_path,
                            const struct timespec *buf)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    retval = v9fs_request(s->private, T_UTIME, NULL, "sqqqq",
+                    fs_path,
+                    buf[0].tv_sec, buf[0].tv_nsec,
+                    buf[1].tv_sec, buf[1].tv_nsec);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    return retval;
 }
 
 static int proxy_remove(FsContext *ctx, const char *path)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    V9fsString name;
+    v9fs_string_init(&name);
+    v9fs_string_sprintf(&name, "%s", path);
+    retval = v9fs_request(ctx->private, T_REMOVE, NULL, "s", &name);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    v9fs_string_free(&name);
+    return retval;
 }
 
 static int proxy_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync)
-- 
1.7.6

^ permalink raw reply related

* [Qemu-devel] [PATCH 13/13] hw/9pfs: man page for proxy helper
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
  To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
In-Reply-To: <1320094412-19091-1-git-send-email-mohan@in.ibm.com>

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


Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
 Makefile                         |   12 ++++++-
 hw/9pfs/virtfs-proxy-helper.texi |   63 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 74 insertions(+), 1 deletions(-)
 create mode 100644 hw/9pfs/virtfs-proxy-helper.texi

diff --git a/Makefile b/Makefile
index d13b167..cff1170 100644
--- a/Makefile
+++ b/Makefile
@@ -37,6 +37,7 @@ LIBS+=-lz $(LIBS_TOOLS)
 
 ifdef BUILD_DOCS
 DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8 QMP/qmp-commands.txt
+DOCS+=hw/9pfs/virtfs-proxy-helper.1
 else
 DOCS=
 endif
@@ -283,7 +284,10 @@ ifdef CONFIG_POSIX
 	$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man8"
 	$(INSTALL_DATA) qemu-nbd.8 "$(DESTDIR)$(mandir)/man8"
 endif
-
+ifdef CONFIG_VIRTFS
+	$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1"
+	$(INSTALL_DATA) hw/9pfs/virtfs-proxy-helper.1 "$(DESTDIR)$(mandir)/man1"
+endif
 install-sysconfig:
 	$(INSTALL_DIR) "$(DESTDIR)$(sysconfdir)/qemu"
 	$(INSTALL_DATA) $(SRC_PATH)/sysconfigs/target/target-x86_64.conf "$(DESTDIR)$(sysconfdir)/qemu"
@@ -361,6 +365,12 @@ qemu-img.1: qemu-img.texi qemu-img-cmds.texi
 	  pod2man --section=1 --center=" " --release=" " qemu-img.pod > $@, \
 	  "  GEN   $@")
 
+hw/9pfs/virtfs-proxy-helper.1: hw/9pfs/virtfs-proxy-helper.texi
+	$(call quiet-command, \
+	  perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< hw/9pfs/virtfs-proxy-helper.pod && \
+	  pod2man --section=1 --center=" " --release=" " hw/9pfs/virtfs-proxy-helper.pod > $@, \
+	  "  GEN   $@")
+
 qemu-nbd.8: qemu-nbd.texi
 	$(call quiet-command, \
 	  perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu-nbd.pod && \
diff --git a/hw/9pfs/virtfs-proxy-helper.texi b/hw/9pfs/virtfs-proxy-helper.texi
new file mode 100644
index 0000000..faa0434
--- /dev/null
+++ b/hw/9pfs/virtfs-proxy-helper.texi
@@ -0,0 +1,63 @@
+@example
+@c man begin SYNOPSIS
+usage: virtfs-proxy-helper options
+@c man end
+@end example
+
+@c man begin DESCRIPTION
+@table @description
+Pass-through security model in QEMU 9p server needs root privilege to do
+few file operations (like chown, chmod to any mode/uid:gid).  There are two
+issues in pass-through security model
+
+1) TOCTTOU vulnerability: Following symbolic links in the server could
+provide access to files beyond 9p export path.
+
+2) Running QEMU with root privilege could be a security issue.
+
+To overcome above issues, following approach is used: A new filesytem
+type 'proxy' is introduced. Proxy FS uses chroot + socket combination
+for securing the vulnerability known with following symbolic links.
+Intention of adding a new filesystem type is to allow qemu to run
+in non-root mode, but doing privileged operations using socket IO.
+
+Proxy helper(a stand alone binary part of qemu) is invoked with
+root privileges. Proxy helper chroots into 9p export path and creates
+a socket pair or a named socket based on the command line parameter.
+Qemu and proxy helper communicate using this socket. QEMU proxy fs
+driver sends filesystem request to proxy helper and receives the
+response from it.
+
+Proxy helper is designed so that it can drop the root privilege with
+retaining capbilities needed for doing filesystem operations only.
+
+@end table
+@c man end
+
+@c man begin OPTIONS
+The following options are supported:
+@table @option
+@item -h
+@findex -h
+Display help and exit
+@item -p|--path path
+Path to export for proxy filesystem driver
+@item -f|--fd socket-id
+Use given file descriptor as socket descriptor for communicating with
+qemu proxy fs drier. Usually a helper like libvirt will create
+socketpair and pass one of the fds as parameter to -f|--fd
+@item -s|--socket socket-file
+Creates named socket file for communicating with qemu proxy fs driver
+@item -u|--uid uid -g|--gid gid
+uid:gid combination to give access to named socket file
+@item -n|--nodaemon
+Run as a normal program. By default program will run in daemon mode
+@end table
+@c man end
+
+@setfilename virtfs-proxy-helper
+@settitle QEMU 9p virtfs proxy filesystem helper
+
+@c man begin AUTHOR
+M. Mohan Kumar
+@c man end
-- 
1.7.6

^ permalink raw reply related

* RE: [GIT PULL] mm: frontswap (for 3.2 window)
From: Dan Magenheimer @ 2011-10-31 20:58 UTC (permalink / raw)
  To: Andrea Arcangeli
  Cc: Pekka Enberg, Cyclonus J, Sasha Levin, Christoph Hellwig,
	David Rientjes, Linus Torvalds, linux-mm, LKML, Andrew Morton,
	Konrad Wilk, Jeremy Fitzhardinge, Seth Jennings, ngupta,
	Chris Mason, JBeulich, Dave Hansen, Jonathan Corbet
In-Reply-To: <20111031181651.GF3466@redhat.com>

> From: Andrea Arcangeli [mailto:aarcange@redhat.com]
> Subject: Re: [GIT PULL] mm: frontswap (for 3.2 window)

Hi Andrea --

Thanks for your input. It's good to have some real technical
discussion about the core of tmem.  I hope you will
take the time to read and consider my reply,
and comment on any disagreements.

OK, let's go over your concerns about the "flawed API."

> 1) 4k page limit (no way to handle hugepages)

FALSE.  The API/ABI was designed from the beginning to handle
different pagesizes.  It can even dynamically handle more than
one page size, though a different "pool" must be created on
the kernel side for each different pagesize.  (At the risk
of derision, remember I used to code for IA64 so I am
very familiar with different pagesizes.)

It is true that the current tmem _backends_ (Xen and
zcache) reject pagesizes other than 4K, but if there are
"frontends" that have a different pagesize, the API/ABI
supports it.

For hugepages, I agree copying 2M seems odd.  But talking
about hugepages in the swap subsystem, I think we are
talking about a very remote future.  (Remember cleancache
is _already_ merged so I'm limiting this to swap.)  Perhaps
in that far future, Intel will have an optimized "copy2M"
instruction that can circumvent cache pollution?

> 2) synchronous

TRUE.  (Well, mostly.... RAMster is exploiting some asynchrony
but that's all still experimental.)

Remember the whole point of tmem/cleancache/frontswap is in
environments where memory is scarce and CPU is plentiful,
which is increasingly common (especially in virtualization).
We all cut our teeth on kernel work in an environment where
saving every CPU cycle was important, but in these new
memory-constrained many-core environments, the majority of
CPU cycles are idle.  So does it really matter if the CPU is
idle because it is waiting on the disk vs being used for
synchronous copying/compression/dedup?  See the published
Xen benchmarks:  CPU utilization goes up, but throughput
goes up too.  Why?  Because physical memory is being used
more efficiently.

Also IMHO the reason the frontswap hooks and the cleancache
hooks can be so simple and elegant and can support many
different users is because the API/ABI is synchronous.
If you change that, I think you will introduce all sorts
of special cases and races and bugs on both sides of the
ABI/API.  And (IMHO) the end result is that most CPUs
are still mostly sitting idle waiting for work to do.

> 3) not zerocopy, requires one bounce buffer for every get and one
>    bounce buffer again for every put (like highmem I/O with 32bit pci)

Hmmm... not sure I understand this one.  It IS copy-based
so is not zerocopy; the page of data is actually moving out
of memory controlled/directly-addressable by the kernel into
memory that is not controlled/directly-addressable by the kernel.
But neither the Xen implementation nor the zcache implementation
uses any bounce buffers, even when compressing or dedup'ing.

So unless I misunderstand, this one is FALSE.

> 4) can't handle batched requests

TRUE.  Tell me again why a vmexit/vmenter per 4K page is
"impossible"?  Again you are assuming (1) the CPU had some
real work to do instead and (2) that vmexit/vmenter is horribly
slow.  Even if vmexit/vmenter is thousands of cycles, it is still
orders of magnitude faster than a disk access.  And vmexit/vmenter
is about the same order of magnitude as page copy, and much
faster than compression/decompression, both of which still
result in a nice win.

You are also assuming that frontswap puts/gets are highly
frequent.  By definition they are not, because they are
replacing single-page disk reads/writes due to swapping.

That said, the API/ABI is very extensible, so if it were
proven that batching was sufficiently valuable, it could
be added later... but I don't see it as a showstopper.
Really do you?

> worse than HIGHMEM 32bit... Obviously you must be mlocking all Oracle
> db memory so you won't hit that bounce buffering ever with
> Oracle. Also note, historically there's nobody that hated bounce
> buffers more than Oracle (at least I remember the highmem issues with
> pci32 cards :). Also Oracle was the biggest user of hugetlbfs.

I already noted that there's no bounce buffers, but Oracle is
not pursuing this because of the Oracle _database_ (though
it does work on single node databases).  While "Oracle" is
often used to equate to its eponymous database, tmem works
on lots of workloads and Oracle (even pre-Sun-merger) sells
tons of non-DB software.  In fact I personally take some heat
for putting more emphasis on getting tmem into Linux than in
using it to proprietarily improve other Oracle products.

> If I'm wrong please correct me, I hadn't lots of time to check
> code. But we already raised these points before without much answer.

OK, so you're wrong on two of the points and I've corrected
you.  On two of the points, synchrony and non-batchability,
you make claims that (1) these are bad and (2) that there
is a better way to achieve the same results with asynchrony
and batchability.

I do agree you've raised the points before, but I am pretty
sure I've always given the same answers, so you shouldn't
say that you haven't gotten "much answer" but that you disagree
with the answer you got.

I've got working code, it's going in real distros and products and
has growing usage by (non-Oracle) kernel developers as well as
real users clamoring for it or already using it.  You claim
that by making it asynchronous it would be better, while I claim
that it would make it impossibly complicated.  (We'd essentially
be rewriting, or creating a parallel, blkio subsystem.)  You claim
that a batch interface is necessary, while I claim that if it is
proven that it is needed, it could be added later.

We've been talking about this since July 2009, right?
If you can do it better, where's your code?  I have the
highest degree of respect for your abilities and I have no
doubt that you could do something similar for KVM over a
long weekend... but can you also make it work for Xen, for
in-kernel compression, and for cross-kernel clustering
(not to mention for other "users" in my queue)?  The foundation
tmem code in the core kernel (frontswap and cleancache)
is elegant in its simplicity and _it works_.

REALLY no disrespect intended and I'm sorry if I am flaming,
so let me calm down by quoting Linus from the LWN KS2011
article:

  "[Linus] stated that, simply, code that actually is used is
   code that is actually worth something... code aimed at
   solving the same problem is just a vague idea that is
   worthless by comparison...  Even if it truly is crap,
   we've had crap in the kernel before.  The code does not
   get better out of tree."

So, please, all the other parts necessary for tmem are
already in-tree, why all the resistance about frontswap?

Thanks,
Dan

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* RE: [GIT PULL] mm: frontswap (for 3.2 window)
From: Dan Magenheimer @ 2011-10-31 20:58 UTC (permalink / raw)
  To: Andrea Arcangeli
  Cc: Pekka Enberg, Cyclonus J, Sasha Levin, Christoph Hellwig,
	David Rientjes, Linus Torvalds, linux-mm, LKML, Andrew Morton,
	Konrad Wilk, Jeremy Fitzhardinge, Seth Jennings, ngupta,
	Chris Mason, JBeulich, Dave Hansen, Jonathan Corbet
In-Reply-To: <20111031181651.GF3466@redhat.com>

> From: Andrea Arcangeli [mailto:aarcange@redhat.com]
> Subject: Re: [GIT PULL] mm: frontswap (for 3.2 window)

Hi Andrea --

Thanks for your input. It's good to have some real technical
discussion about the core of tmem.  I hope you will
take the time to read and consider my reply,
and comment on any disagreements.

OK, let's go over your concerns about the "flawed API."

> 1) 4k page limit (no way to handle hugepages)

FALSE.  The API/ABI was designed from the beginning to handle
different pagesizes.  It can even dynamically handle more than
one page size, though a different "pool" must be created on
the kernel side for each different pagesize.  (At the risk
of derision, remember I used to code for IA64 so I am
very familiar with different pagesizes.)

It is true that the current tmem _backends_ (Xen and
zcache) reject pagesizes other than 4K, but if there are
"frontends" that have a different pagesize, the API/ABI
supports it.

For hugepages, I agree copying 2M seems odd.  But talking
about hugepages in the swap subsystem, I think we are
talking about a very remote future.  (Remember cleancache
is _already_ merged so I'm limiting this to swap.)  Perhaps
in that far future, Intel will have an optimized "copy2M"
instruction that can circumvent cache pollution?

> 2) synchronous

TRUE.  (Well, mostly.... RAMster is exploiting some asynchrony
but that's all still experimental.)

Remember the whole point of tmem/cleancache/frontswap is in
environments where memory is scarce and CPU is plentiful,
which is increasingly common (especially in virtualization).
We all cut our teeth on kernel work in an environment where
saving every CPU cycle was important, but in these new
memory-constrained many-core environments, the majority of
CPU cycles are idle.  So does it really matter if the CPU is
idle because it is waiting on the disk vs being used for
synchronous copying/compression/dedup?  See the published
Xen benchmarks:  CPU utilization goes up, but throughput
goes up too.  Why?  Because physical memory is being used
more efficiently.

Also IMHO the reason the frontswap hooks and the cleancache
hooks can be so simple and elegant and can support many
different users is because the API/ABI is synchronous.
If you change that, I think you will introduce all sorts
of special cases and races and bugs on both sides of the
ABI/API.  And (IMHO) the end result is that most CPUs
are still mostly sitting idle waiting for work to do.

> 3) not zerocopy, requires one bounce buffer for every get and one
>    bounce buffer again for every put (like highmem I/O with 32bit pci)

Hmmm... not sure I understand this one.  It IS copy-based
so is not zerocopy; the page of data is actually moving out
of memory controlled/directly-addressable by the kernel into
memory that is not controlled/directly-addressable by the kernel.
But neither the Xen implementation nor the zcache implementation
uses any bounce buffers, even when compressing or dedup'ing.

So unless I misunderstand, this one is FALSE.

> 4) can't handle batched requests

TRUE.  Tell me again why a vmexit/vmenter per 4K page is
"impossible"?  Again you are assuming (1) the CPU had some
real work to do instead and (2) that vmexit/vmenter is horribly
slow.  Even if vmexit/vmenter is thousands of cycles, it is still
orders of magnitude faster than a disk access.  And vmexit/vmenter
is about the same order of magnitude as page copy, and much
faster than compression/decompression, both of which still
result in a nice win.

You are also assuming that frontswap puts/gets are highly
frequent.  By definition they are not, because they are
replacing single-page disk reads/writes due to swapping.

That said, the API/ABI is very extensible, so if it were
proven that batching was sufficiently valuable, it could
be added later... but I don't see it as a showstopper.
Really do you?

> worse than HIGHMEM 32bit... Obviously you must be mlocking all Oracle
> db memory so you won't hit that bounce buffering ever with
> Oracle. Also note, historically there's nobody that hated bounce
> buffers more than Oracle (at least I remember the highmem issues with
> pci32 cards :). Also Oracle was the biggest user of hugetlbfs.

I already noted that there's no bounce buffers, but Oracle is
not pursuing this because of the Oracle _database_ (though
it does work on single node databases).  While "Oracle" is
often used to equate to its eponymous database, tmem works
on lots of workloads and Oracle (even pre-Sun-merger) sells
tons of non-DB software.  In fact I personally take some heat
for putting more emphasis on getting tmem into Linux than in
using it to proprietarily improve other Oracle products.

> If I'm wrong please correct me, I hadn't lots of time to check
> code. But we already raised these points before without much answer.

OK, so you're wrong on two of the points and I've corrected
you.  On two of the points, synchrony and non-batchability,
you make claims that (1) these are bad and (2) that there
is a better way to achieve the same results with asynchrony
and batchability.

I do agree you've raised the points before, but I am pretty
sure I've always given the same answers, so you shouldn't
say that you haven't gotten "much answer" but that you disagree
with the answer you got.

I've got working code, it's going in real distros and products and
has growing usage by (non-Oracle) kernel developers as well as
real users clamoring for it or already using it.  You claim
that by making it asynchronous it would be better, while I claim
that it would make it impossibly complicated.  (We'd essentially
be rewriting, or creating a parallel, blkio subsystem.)  You claim
that a batch interface is necessary, while I claim that if it is
proven that it is needed, it could be added later.

We've been talking about this since July 2009, right?
If you can do it better, where's your code?  I have the
highest degree of respect for your abilities and I have no
doubt that you could do something similar for KVM over a
long weekend... but can you also make it work for Xen, for
in-kernel compression, and for cross-kernel clustering
(not to mention for other "users" in my queue)?  The foundation
tmem code in the core kernel (frontswap and cleancache)
is elegant in its simplicity and _it works_.

REALLY no disrespect intended and I'm sorry if I am flaming,
so let me calm down by quoting Linus from the LWN KS2011
article:

  "[Linus] stated that, simply, code that actually is used is
   code that is actually worth something... code aimed at
   solving the same problem is just a vague idea that is
   worthless by comparison...  Even if it truly is crap,
   we've had crap in the kernel before.  The code does not
   get better out of tree."

So, please, all the other parts necessary for tmem are
already in-tree, why all the resistance about frontswap?

Thanks,
Dan

^ permalink raw reply

* Re: [PATCH] drm: serialize access to list of debugfs files
From: Daniel Vetter @ 2011-10-31 21:00 UTC (permalink / raw)
  To: Marcin Slusarz; +Cc: nouveau, dri-devel
In-Reply-To: <20111031173357.GA28581@joi.lan>

On Mon, Oct 31, 2011 at 06:33:57PM +0100, Marcin Slusarz wrote:
> Nouveau, when configured with debugfs, creates debugfs files for every
> channel, so structure holding list of files needs to be protected from
> simultaneous changes by multiple threads.
> 
> Without this patch it's possible to hit kernel oops in
> drm_debugfs_remove_files just by running a couple of xterms with
> looped glxinfo.
> 
> Signed-off-by: Marcin Slusarz <marcin.slusarz@gmail.com>

And v2 also includes a nice comment in the header explaining the locking.
Awesome!
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply

* Re: [Fedora-xen] [Xen-devel] Xen 4.1.2 PVHVM guest with Linux 3.1.0 network problem, empty MAC address (all zeroes)
From: Pasi Kärkkäinen @ 2011-10-31 21:00 UTC (permalink / raw)
  To: xen-devel; +Cc: xen
In-Reply-To: <20111031205134.GE12984@reaktio.net>

On Mon, Oct 31, 2011 at 10:51:34PM +0200, Pasi Kärkkäinen wrote:
> On Mon, Oct 31, 2011 at 10:13:36PM +0200, Pasi Kärkkäinen wrote:
> > Hello,
> > 
> > While testing Fedora 16 Xen PVHVM guests I noticed the following problem:
> > 
> > When starting F16 PVHVM guest I can see the vifX.0 and tapX.0 interfaces appear on dom0, 
> > but after the guest kernel (Linux 3.1.0) starts and loads PVHVM drivers the 
> > vif/tap interfaces disappear from dom0.. 
> > so the bridge in dom0 doesn't have any vifs/taps connected to it anymore.
> > 
> > Has anyone seen that behaviour? 
> > 
> > I bet that's also the reason why eth0 inside the PVHVM guest 
> > has a MAC address with only zeroes in it: 00:00:00:00:00:00.
> > 
> > If I disable PVHVM with "xen_platform_pci=0" in the domain cfgfile
> > then network for the guest works OK using the qemu-dm emulated nic.
> > 
> > PVHVM guest cfgfile:
> > 
> 
> <snip>
> 
> > 
> > Some output from inside the PVHVM guest:
> > 
> > # ifconfig eth0
> > eth0      Link encap:Ethernet  HWaddr 00:00:00:00:00:00
> >           BROADCAST MULTICAST  MTU:1500  Metric:1
> >           RX packets:0 errors:0 dropped:0 overruns:0 frame:0
> >           TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
> >           collisions:0 txqueuelen:1000
> >           RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)
> > 
> 
> <snip>
> 
> > 
> > Full PVHVM guest kernel (Linux 3.1.0) dmesg attached to this email.
> > Some parts of the guest dmesg here:
> > 
> > $ egrep -i 'xen|vif' xen-4.1.2-f16pvhvm-linux-3.1.0-dmesg.txt
> > 
> 
> <snip>
> 
> > 
> > dom0 kernel (Linux 3.1.0 aswell) messages:
> > 
> 
> <snip>
> 
> > 
> > 
> > "xm log" doesn't have any errors.
> > Any ideas how to fix this? Why do the vif/tap devices disappear from dom0?
> > 
> 
> Well.. it was actually as simple as removing "type=ioemu" from the vif line.
> Working vif-example for Xen PVHVM Linux guest VM:
> 
> vif = [ 'mac=00:16:5f:03:01:15, bridge=virbr0, model=e1000' ]
> 
> So uhm.. when enabling PVHVM there's no need to modify the disk line, 
> but you need to modify the vif-line.. is that like it should be ?
> 

It seems "type=ioemu" is not required for anything.. 
not even for normal HVM emulated nics.

So this works for both normal HVM and PVHVM:
vif = [ 'mac=00:16:5f:03:01:15, bridge=virbr0, model=e1000' ]

And control the HVM/PVHVM mode with:
	xen_platform_pci=1
or
	xen_platform_pci=0



-- Pasi

--
xen mailing list
xen@lists.fedoraproject.org
https://admin.fedoraproject.org/mailman/listinfo/xen

^ permalink raw reply

* Re: [PATCH v2] drm: add some comments to drm_wait_vblank and drm_queue_vblank_event
From: Daniel Vetter @ 2011-10-31 21:02 UTC (permalink / raw)
  To: Ilija Hadzic; +Cc: dri-devel
In-Reply-To: <1320081117-15020-1-git-send-email-ihadzic@research.bell-labs.com>

On Mon, Oct 31, 2011 at 01:11:57PM -0400, Ilija Hadzic wrote:
> during the review of the fix for locks problems in drm_wait_vblank,
> a couple of false concerns were raised about how the drm_vblank_get
> and drm_vblank_put are used in this function; it turned out that the
> code is correct and that it cannot be simplified
> 
> add a few comments to explain non-obvious flows in the code,
> to prevent "false alarms" in the future
> 
> v2: incorporate comments received from Daniel Vetter
> 
> Signed-off-by: Ilija Hadzic <ihadzic@research.bell-labs.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply

* [PATCHv2] Make mce_chrdev_ops "static const"
From: Luck, Tony @ 2011-10-31 21:02 UTC (permalink / raw)
  To: linux-kernel; +Cc: Arjan van de Ven
In-Reply-To: <4eaeea2d17118d40b4@agluck-desktop.sc.intel.com>

Arjan would like to make struct file_operations const, but mce-inject
directly writes to the mce_chrdev_ops to install its write handler.
In an ideal world mce-inject would have its own character device, but
we have a sizable legacy of test scripts that hardwire "/dev/mcelog",
so it would be painful to switch to a separate device now. Instead,
this patch switches to a stub function in the mce code, with a
registration helper that mce-inject can call when it is loaded.

Note that this would also allow for a sane process to allow mce-inject
to be unloaded again (with an unregister function, and appropriate
module_{get,put}() calls), but that is left for potential future patches.

Reported-by: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>

---

v2 - fixes some checkpatch complaints about tabs/spaces/long-lines, and
     more importantly fixes the problems that Arjan wants fixed (rather
     than enabling him to apply the 2-liner to fix it).

diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index c9321f3..22cc0eb 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -201,7 +201,10 @@ int mce_notify_irq(void);
 void mce_notify_process(void);
 
 DECLARE_PER_CPU(struct mce, injectm);
-extern struct file_operations mce_chrdev_ops;
+
+extern void register_mce_write_hook(ssize_t (*)(struct file *filp,
+				    const char __user *ubuf,
+				    size_t usize, loff_t *off));
 
 /*
  * Exception handler
diff --git a/arch/x86/kernel/cpu/mcheck/mce-inject.c b/arch/x86/kernel/cpu/mcheck/mce-inject.c
index 0ed633c..a18c2c8 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-inject.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-inject.c
@@ -215,7 +215,7 @@ static int inject_init(void)
 	if (!alloc_cpumask_var(&mce_inject_cpumask, GFP_KERNEL))
 		return -ENOMEM;
 	printk(KERN_INFO "Machine check injector initialized\n");
-	mce_chrdev_ops.write = mce_write;
+	register_mce_write_hook(mce_write);
 	register_die_notifier(&mce_raise_nb);
 	return 0;
 }
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 08363b0..7010901 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -1628,16 +1628,35 @@ static long mce_chrdev_ioctl(struct file *f, unsigned int cmd,
 	}
 }
 
-/* Modified in mce-inject.c, so not static or const */
-struct file_operations mce_chrdev_ops = {
+static ssize_t (*mce_write)(struct file *filp, const char __user *ubuf,
+			    size_t usize, loff_t *off);
+
+void register_mce_write_hook(ssize_t (*fn)(struct file *filp,
+			     const char __user *ubuf,
+			     size_t usize, loff_t *off))
+{
+	mce_write = fn;
+}
+EXPORT_SYMBOL_GPL(register_mce_write_hook);
+
+ssize_t mce_chrdev_write(struct file *filp, const char __user *ubuf,
+			 size_t usize, loff_t *off)
+{
+	if (mce_write)
+		return mce_write(filp, ubuf, usize, off);
+	else
+		return -ENODEV;
+}
+
+static const struct file_operations mce_chrdev_ops = {
 	.open			= mce_chrdev_open,
 	.release		= mce_chrdev_release,
 	.read			= mce_chrdev_read,
+	.write			= mce_chrdev_write,
 	.poll			= mce_chrdev_poll,
 	.unlocked_ioctl		= mce_chrdev_ioctl,
 	.llseek			= no_llseek,
 };
-EXPORT_SYMBOL_GPL(mce_chrdev_ops);
 
 static struct miscdevice mce_chrdev_device = {
 	MISC_MCELOG_MINOR,

^ permalink raw reply related

* Re: [lm-sensors] [PATCH 3/3] hwmon: (w83627ehf) Add support for the
From: Jean Delvare @ 2011-10-31 21:03 UTC (permalink / raw)
  To: lm-sensors
In-Reply-To: <20111031152342.15f99729@endymion.delvare>

On Mon, 31 Oct 2011 08:45:52 -0700, Guenter Roeck wrote:
> Not sure if moving NCT677[56] to a separate driver would make much of a
> difference in the complexity of this one.

The W83627UHG is clearly on the side of the W83627DHG. The decision of
splitting NCT677[56] support to a separate driver is unrelated IMHO.
The rationale is that the w83627ehf driver code has become quite
complex (it's the 3rd hwmon driver by size out of 117!) and a lot of the
code recently added only applies to the NCT677[56]. If future devices
are almost compatible with the NCT677[56] but not quite, things will
only become worse.

With separate drivers, the code would become easier to read IMHO.
Obviously this implies some code duplication but I believe we reached
the point where this should be considered. Another benefit is that we
could then have separate maintainers for the two drivers, so better
load balancing.

-- 
Jean Delvare

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply

* Re: In regard of commit "gudev: Use strtoul to parse unsigned 64-bit
From: Rafał Mużyło @ 2011-10-31 21:04 UTC (permalink / raw)
  To: linux-hotplug
In-Reply-To: <20111031201318.GA2447@blackspire>

On Mon, Oct 31, 2011 at 04:32:07PM -0400, David Zeuthen wrote:
> On Mon, Oct 31, 2011 at 4:13 PM, Rafał Mużyło <galtgendo@gmail.com> wrote:
> > Perhaps I'm simply misreading something, but won't going from strtoll to
> > strtoul break things for 32bit case ?
> 
> What do you think it would break? Or are you perhaps suggesting we
> should be using strtoull() instead? Please be specific.
>
Well, given on what happens on strtoul overflow according to the
manpage...

But, as you're the main author of udisks, would you mind looking at the
bug I've mentioned ?
Perhaps it doesn't matter there, but it would be good to do something
about the warnings.


^ permalink raw reply


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.