All of lore.kernel.org
 help / color / mirror / Atom feed
From: Greg Kurz <gkurz@linux.vnet.ibm.com>
To: Michael Fritscher <michael@fritscher.net>
Cc: sw@weilnetz.de, aneesh.kumar@linux.vnet.ibm.com, mst@redhat.com,
	qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v2] [WIP] [RFC ]Add initial 9pfs support for Windows hosts v2
Date: Mon, 9 May 2016 10:38:28 +0200	[thread overview]
Message-ID: <20160509103828.6bfc5b96@bahia.huguette.org> (raw)
In-Reply-To: <1460447520-12499-1-git-send-email-michael@fritscher.net>

More comments.

On Tue, 12 Apr 2016 09:52:00 +0200
Michael Fritscher <michael@fritscher.net> wrote:

> It was tested on Windows & Linux hosts, on the later no obvious regressions could be found. The guest was a Knoppix 7.6.0 live cd.
> 
> This is WIP and a RFC - it isn't meant to be upstreamed yet. The error_printf are only for debugging and will be deleted in the final patch.
> 
> There are some comments with "mifritscher" - I'm not quite sure how to handle these problems (e.g. on mingw, this in 32 bit, while on Linux this is 16 bit and so on). Additionally, some places from which I suspect problems are marked with a #warning.
> 
> Changes against v1:
>   * fixed open (added binary flag) -> read/write is fine now, file
> creation was fixed as well
>   * added inode calculation using own crude hash algorithm
>   * fixed xattr returning -1  + EOPNOTSUP -> fixes e.g. executing files
>   * fixed unlinkat / remove für directories by trying rmdir as well
>   * prepend 777 mode on files (for executing)
> 
> What does work:
>   * reading/writing "big" files (5MB, verified with md5sum)
>   * creating files
>   * executing files
>   * mkdir
>   * rm / rmdir
>   * cp files
>   * running gcc
>   * cp first 250 files & directories from /etc
>   * tar it from and to the 9p mount
>   * create a 100 MB swap file and do a mkswap on it
> 
> What does not work:
>   * swapon - no real surprise (doesn't work on Linux as well - with the same error message) ;-) (swapon returns -1 EINVAL)
>   * link / symlink (there is no real aequivalent for this on windows)
>   * mknod (dito)
>   * chown (dito - prepend success for compatibility)
> 
> State of v1:
> What works:
>    * mount
>    * stat
>    * chdir
>    * readdir (aka ls)
>    * read of small files (<10k)
>    * overwrite
> 
> What does not work:
>    * create new files (in 90% problems with path handling (old path occurs)
>    * read / probably write big files
> 
> 
> Signed-off-by: Michael Fritscher <michael@fritscher.net>
> ---
> On https://github.com/mifritscher/qemu/tree/9pfs_windows is a git tree with the patch.
> 
> I gave a shot at xattr (try to include xattr stuff) but it ended up even more #ifdefs. So I gave up at this.
> Now I'm waiting on comments etc. If there are no big objections, I'll remove the debug output and make a patch which is meant for upstreaming.
> 
> Thanks to everybody which helped me!
> 
>  Makefile.objs              |   1 +
>  configure                  |  15 ++-
>  fsdev/9p-iov-marshal.c     |   2 +
>  fsdev/9p-marshal.c         |   4 +-
>  fsdev/file-op-9p.h         |  35 ++++-
>  fsdev/qemu-fsdev.c         |   2 +
>  hw/9pfs/9p-local.c         | 326 +++++++++++++++++++++++++++++++++++++++++----
>  hw/9pfs/9p-synth.c         |  10 +-
>  hw/9pfs/9p.c               | 102 +++++++++++++-
>  hw/9pfs/9p.h               |  70 +++++++++-
>  hw/9pfs/Makefile.objs      |   7 +-
>  hw/9pfs/codir.c            |  31 +++++
>  hw/9pfs/cofile.c           |  15 +++
>  hw/9pfs/cofs.c             |  15 +++
>  hw/9pfs/coxattr.c          |   6 +
>  hw/9pfs/virtio-9p-device.c |   4 +-
>  16 files changed, 600 insertions(+), 45 deletions(-)
> 
> diff --git a/Makefile.objs b/Makefile.objs
> index 8f705f6..6fd02bc 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -48,6 +48,7 @@ common-obj-$(CONFIG_WIN32) += os-win32.o
>  common-obj-$(CONFIG_POSIX) += os-posix.o
> 
>  common-obj-$(CONFIG_LINUX) += fsdev/
> +common-obj-$(CONFIG_WIN32) += fsdev/
> 
>  common-obj-y += migration/
>  common-obj-y += qemu-char.o #aio.o
> diff --git a/configure b/configure
> index 5db29f0..a4797c3 100755
> --- a/configure
> +++ b/configure
> @@ -4566,12 +4566,21 @@ if test "$want_tools" = "yes" ; then
>  fi
>  if test "$softmmu" = yes ; then
>    if test "$virtfs" != no ; then
> -    if test "$cap" = yes && test "$linux" = yes && test "$attr" = yes ; then
> +    if test "$linux" = yes ; then
> +      if test "$cap" = yes  && test "$attr" = yes ; then
> +        virtfs=yes
> +        tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)"
> +      else
> +        if test "$virtfs" = yes; then
> +          error_exit "VirtFS requires libcap-devel and libattr-devel on Linux"
> +        fi
> +        virtfs=no
> +      fi
> +    elif test "$mingw32" = yes; then
>        virtfs=yes
> -      tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)"
>      else
>        if test "$virtfs" = yes; then
> -        error_exit "VirtFS is supported only on Linux and requires libcap-devel and libattr-devel"
> +        error_exit "VirtFS is only supported on Linux or Windows"
>        fi
>        virtfs=no
>      fi
> diff --git a/fsdev/9p-iov-marshal.c b/fsdev/9p-iov-marshal.c
> index fb40bdf..1a292c6 100644
> --- a/fsdev/9p-iov-marshal.c
> +++ b/fsdev/9p-iov-marshal.c
> @@ -15,7 +15,9 @@
>  #include <glib.h>
>  #include <glib/gprintf.h>
>  #include <utime.h>
> +#ifndef _WIN32
>  #include <sys/uio.h>
> +#endif
> 
>  #include "9p-iov-marshal.h"
>  #include "qemu/bswap.h"
> diff --git a/fsdev/9p-marshal.c b/fsdev/9p-marshal.c
> index 183d366..081cb88 100644
> --- a/fsdev/9p-marshal.c
> +++ b/fsdev/9p-marshal.c
> @@ -16,7 +16,9 @@
>  #include <glib/gprintf.h>
>  #include <dirent.h>
>  #include <utime.h>
> -#include <sys/uio.h>
> +#ifndef WIN32
> +    #include <sys/uio.h>
> +#endif
> 
>  #include "9p-marshal.h"
> 
> diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
> index b8c2602..446c6a5 100644
> --- a/fsdev/file-op-9p.h
> +++ b/fsdev/file-op-9p.h
> @@ -14,12 +14,43 @@
>  #define _FILEOP_H
>  #include <dirent.h>
>  #include <utime.h>
> -#include <sys/uio.h>
> -#include <sys/vfs.h>
> +#ifndef _WIN32
> +    #include <sys/uio.h>
> +    #include <sys/vfs.h>
> +#endif
> 
>  #define SM_LOCAL_MODE_BITS    0600
>  #define SM_LOCAL_DIR_MODE_BITS    0700
> 
> +#ifdef _WIN32
> +typedef uint32_t uid_t;
> +typedef uint32_t gid_t;
> +
> +/* from http://man7.org/linux/man-pages/man2/statfs.2.html */
> +typedef uint32_t __fsword_t;
> +typedef uint32_t fsblkcnt_t;
> +typedef uint32_t fsfilcnt_t;
> +
> +/* from linux/include/uapi/asm-generic/posix_types.h */
> +typedef struct {
> +        long    __val[2];
> +} fsid_t;
> +
> +struct statfs {
> +    __fsword_t f_type;
> +    __fsword_t f_bsize;
> +    fsblkcnt_t f_blocks;
> +    fsblkcnt_t f_bfree;
> +    fsblkcnt_t f_bavail;
> +    fsfilcnt_t f_files;
> +    fsfilcnt_t f_ffree;
> +    fsid_t f_fsid;
> +    __fsword_t f_namelen;
> +    __fsword_t f_frsize;
> +    __fsword_t f_flags;
> +};
> +#endif
> +
>  typedef struct FsCred
>  {
>      uid_t   fc_uid;
> diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
> index bf7f0b0..384d72e 100644
> --- a/fsdev/qemu-fsdev.c
> +++ b/fsdev/qemu-fsdev.c
> @@ -26,7 +26,9 @@ static FsDriverTable FsDrivers[] = {
>      { .name = "handle", .ops = &handle_ops},
>  #endif
>      { .name = "synth", .ops = &synth_ops},
> +#ifndef WIN32
>      { .name = "proxy", .ops = &proxy_ops},
> +#endif
>  };
> 
>  int qemu_fsdev_add(QemuOpts *opts)
> diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
> index 16f45f4..710ab5f 100644
> --- a/hw/9pfs/9p-local.c
> +++ b/hw/9pfs/9p-local.c
> @@ -12,23 +12,174 @@
>   */
> 
>  #include "qemu/osdep.h"
> +/* mifritscher: after killing the debug printf, kill this as well! */
> +#include "qemu/error-report.h"
>  #include "9p.h"
> -#include "9p-xattr.h"
> +#ifdef _WIN32
> +/* idea from http://mingw-users.1079350.n2.nabble.com/Undefined-reference-to-quot-lstat-quot-and-quot-S-ISLNK-quot-td5450984.html */
> +# define lstat(path, buffer) stat(path, buffer)
> +
> +# define mkdir(path, mode) mkdir(path)

Maybe these definitions can go to include/sysemu/os-win32.h ?

> +# define getxattr(buffer, name, pointer, length) 0
> +
> +/* pretend success */
> +static int setxattr(const char *path, const char *name,
> +                    const void *value, size_t size, int flags)
> +{
> +    return 0;
> +}
> +
> +static ssize_t fgetxattr(int fd, const char *name,
> +                         void *value, size_t size)
> +{
> +    return 0;
> +}
> +

and these xattr definitions to include/qemu/xattr.h ?

> +# define lchown(buffer, uid, gid) 0
> +# define readlink(buffer, buf, bufsz) 0
> +# define mknod(buffer, mode, u) 0
> +# define link(buffer, buffer1) 0
> +# define symlink(buffer, buffer1) 0
> +
> +static ssize_t v9fs_get_xattr(FsContext *ctx, const char *path,
> +                              const char *name, void *value, size_t size)
> +{
> +    errno = 95; /* EOPNOTSUP - wrong definition in mingw(130); */

This is ENOTSUP actually.

> +    return -1;
> +}
> +
> +static ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
> +                               void *value, size_t vsize)
> +{
> +    errno = 95; /* EOPNOTSUP - wrong definition in mingw(130); */
> +    return -1;
> +}
> +
> +static int v9fs_set_xattr(FsContext *ctx, const char *path,
> +                          const char *name, void *value, size_t size,
> +                          int flags)
> +{
> +    errno = 95; /* EOPNOTSUP - wrong definition in mingw(130); */
> +    return -1;
> +}
> +
> +static int v9fs_remove_xattr(FsContext *ctx, const char *path,
> +                             const char *name)
> +{
> +    errno = 95; /* EOPNOTSUP - wrong definition in mingw(130); */
> +    return -1;
> +}
> +
> +static int readdir_r(DIR *dirp, struct dirent *entry,
> +                     struct dirent **result)
> +{
> +    struct dirent *temp;
> +    errno = 0;
> +    temp = readdir(dirp);

readdir() isn't expected to be thread safe... I believe we need some locking here.

Also this function should probably be in os-win32.c.

> +    if (temp == 0) {
> +        error_printf("readdir_r: End of directory reached -> returning NULL\n");
> +        *result = 0;
> +    } else {
> +        /* Copy it from the stack to the buffer got from the caller */
> +        memcpy(entry, temp, sizeof(struct dirent));
> +        error_printf("readdir_r: Name: %hu %s\n",
> +                     temp->d_namlen, temp->d_name);
> +        error_printf("readdir_r: Name: %hu %s\n",
> +                     entry->d_namlen, entry->d_name);
> +        *result = entry;
> +    }
> +    return errno;
> +}
> +
> +/* Can be done better... */
> +static int statfs(const char *file, struct statfs *buf)
> +{
> +    memset(buf, 0, sizeof(struct statfs));
> +    buf->f_type = 0x01021997; /* V9FS_MAGIC */
> +    buf->f_bsize = 4096;
> +    buf->f_blocks = 4000000;
> +    buf->f_bfree = 3000000;
> +    buf->f_bavail = 2999000;
> +    buf->f_files = 1000000;
> +    buf->f_ffree = 800000;
> +    buf->f_namelen = NAME_MAX;
> +    return 0;
> +}
> +
> +/* a crude hash function (needed for fake inodes) */
> +static ino_t hash(const char *path)
> +{
> +    ino_t result = (ino_t)41021998;
> +    int len = strlen(path);
> +    if (!len) {
> +        return result;
> +    }
> +
> +    /* Q&D canolizement of the path */
> +    if (path[len - 1]  == '\\' || path[len - 1] == '/') {
> +        len--;
> +    }
> +    if (!len) {
> +        return result;
> +    }
> +
> +    if (path[len - 1]  == '.') {
> +        if (len == 1) {
> +            return result;
> +        }
> +        len--;
> +        if (path[len - 1] == '\\' || path[len - 1] == '/') {
> +            len--;
> +        /* .. -> kill last part */
> +        } else if (path[len - 1] == '.') {
> +            len--;
> +            while (len) {
> +                if (path[len - 1] == '\\' || path[len - 1] == '/') {
> +                    len--;
> +                    break;
> +                }
> +                len--;
> +            }
> +        }
> +    }
> +
> +    if (!len) {
> +        return result;
> +    }
> +
> +    for (int i = 0; i < len; i++) {
> +        result += path[i] << (i % 7);
> +        result += path[i] << ((i + 11) % 17);
> +        result += path[i] << ((i + 19) % 23);
> +    }
> +
> +    return result;
> +}
> +
> +#else
> +# include "9p-xattr.h"
> +#endif

I'd prefer the missing xattr bits to be added to win32... and
if we really need different implementations, then maybe add
9p-xattr-posix.c and 9p-xattr-win32.c...

>  #include "fsdev/qemu-fsdev.h"   /* local_ops */
> +#ifndef _WIN32
>  #include <arpa/inet.h>
>  #include <pwd.h>
>  #include <grp.h>
>  #include <sys/socket.h>
>  #include <sys/un.h>
>  #include "qemu/xattr.h"
> +#endif
>  #include "qemu/cutils.h"
>  #include "qemu/error-report.h"
>  #include <libgen.h>
> -#include <linux/fs.h>
> +#ifndef _WIN32
> +    #include <linux/fs.h>
> +#endif
>  #ifdef CONFIG_LINUX_MAGIC_H
>  #include <linux/magic.h>
>  #endif
> +#ifndef _WIN32
>  #include <sys/ioctl.h>
> +#endif
> 
>  #ifndef XFS_SUPER_MAGIC
>  #define XFS_SUPER_MAGIC  0x58465342
> @@ -76,7 +227,7 @@ static FILE *local_fopen(const char *path, const char *mode)
>      } else {
>          return NULL;
>      }
> -    fd = open(path, flags, o_mode);
> +    fd = open(path, flags | O_BINARY, o_mode);

Why is this needed ?

>      if (fd == -1) {
>          return NULL;
>      }
> @@ -124,10 +275,20 @@ static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
>      char *path = fs_path->data;
> 
>      buffer = rpath(fs_ctx, path);
> -    err =  lstat(buffer, stbuf);
> +    error_printf("\nrpath %s + %s -> %s\n\n", fs_ctx->fs_root, path, buffer);
> +    err = lstat(buffer, stbuf);
>      if (err) {
>          goto err_out;
>      }
> +#ifdef _WIN32
> +    /* This way, all files are executable
> +       (MingW seems to do 777 on dirs, but 666 on files) */
> +    stbuf->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH;
> +
> +    /* Under WIN32 (MingW), st_ino seems to be always 2,
> +       which leads to confusion */
> +    stbuf->st_ino = hash(path);
> +#endif
>      if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
>          /* Actual credentials are part of extended attrs */
>          uid_t tmp_uid;
> @@ -162,7 +323,7 @@ static int local_create_mapped_attr_dir(FsContext *ctx, const char *path)
>      char *attr_dir;
>      char *tmp_path = g_strdup(path);
> 
> -    attr_dir = g_strdup_printf("%s/%s/%s",
> +    attr_dir = g_strdup_printf(DELIMITER_IN_PATH2,
>               ctx->fs_root, dirname(tmp_path), VIRTFS_META_DIR);
> 
>      err = mkdir(attr_dir, 0700);
> @@ -223,7 +384,8 @@ update_map_file:
>      if (credp->fc_gid != -1) {
>          gid = credp->fc_gid;
>      }
> -    if (credp->fc_mode != -1) {
> +    /* mifritscher: is normally unsigned... */
> +    if ((int16_t)(credp->fc_mode) != -1) {
>          mode = credp->fc_mode;
>      }
>      if (credp->fc_rdev != -1) {
> @@ -268,7 +430,8 @@ static int local_set_xattr(const char *path, FsCred *credp)
>              return err;
>          }
>      }
> -    if (credp->fc_mode != -1) {
> +    /* mifritscher: is normally unsigned... */
> +    if ((int16_t)(credp->fc_mode) != -1) {
>          uint32_t tmp_mode = cpu_to_le32(credp->fc_mode);
>          err = setxattr(path, "user.virtfs.mode", &tmp_mode, sizeof(mode_t), 0);
>          if (err) {
> @@ -323,7 +486,7 @@ static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
>          (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
>          int fd;
>          buffer = rpath(fs_ctx, path);
> -        fd = open(buffer, O_RDONLY | O_NOFOLLOW);
> +        fd = open(buffer, O_RDONLY | O_NOFOLLOW | O_BINARY);
>          g_free(buffer);
>          if (fd == -1) {
>              return -1;
> @@ -358,7 +521,8 @@ static int local_open(FsContext *ctx, V9fsPath *fs_path,
>      char *path = fs_path->data;
> 
>      buffer = rpath(ctx, path);
> -    fs->fd = open(buffer, flags | O_NOFOLLOW);
> +    error_printf("File which should be opened: %s\n", buffer);
> +    fs->fd = open(buffer, flags | O_NOFOLLOW | O_BINARY);

I see you add O_BINARY on all open() call sites ? Does this mean we
need a helper ?

>      g_free(buffer);
>      return fs->fd;
>  }
> @@ -370,6 +534,7 @@ static int local_opendir(FsContext *ctx,
>      char *path = fs_path->data;
> 
>      buffer = rpath(ctx, path);
> +    error_printf("Directory (opendir) which should be opened: %s\n", buffer);
>      fs->dir = opendir(buffer);
>      g_free(buffer);
>      if (!fs->dir) {
> @@ -395,17 +560,36 @@ static int local_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
>      int ret;
> 
>  again:
> +#ifdef _WIN32
> +    error_printf("local_readdir_r: Directory which should be read:%s\n",
> +                 fs->dir->dd_name);
> +#endif
>      ret = readdir_r(fs->dir, entry, result);
>      if (ctx->export_flags & V9FS_SM_MAPPED) {
> +#ifndef _WIN32
>          entry->d_type = DT_UNKNOWN;
> +#endif
>      } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
>          if (!ret && *result != NULL &&
>              !strcmp(entry->d_name, VIRTFS_META_DIR)) {
>              /* skp the meta data directory */
>              goto again;
>          }
> +#ifndef _WIN32
>          entry->d_type = DT_UNKNOWN;
> +#endif
>      }
> +    if (*result == NULL) {
> +        error_printf("local_readdir_r: End of directory -> returning NULL\n");
> +    } else {
> +#ifdef _WIN32
> +        error_printf("local_readdir_r: Name: %hu %s\n",
> +                     entry->d_namlen, entry->d_name);
> +#else
> +        error_printf("local_readdir_r: Name: %s\n", entry->d_name);
> +#endif
> +    }
> +    error_printf("local_readdir_r: return %d\n", ret);
>      return ret;
>  }
> 
> @@ -418,10 +602,15 @@ static ssize_t local_preadv(FsContext *ctx, V9fsFidOpenState *fs,
>                              const struct iovec *iov,
>                              int iovcnt, off_t offset)
>  {
> +   error_printf("local_preadv: #iov: %u, addr: %p, #bytes: %u, offset: %llu\n",
> +                iovcnt, iov->iov_base, iov->iov_len, offset);
>  #ifdef CONFIG_PREADV
> +    error_printf("local_preadv: using preadv\n");
>      return preadv(fs->fd, iov, iovcnt, offset);
>  #else
> +    error_printf("local_preadv: not using preadv\n");
>      int err = lseek(fs->fd, offset, SEEK_SET);
> +    error_printf("local_preadv: lseek returned %d\n", err);
>      if (err == -1) {
>          return err;
>      } else {
> @@ -491,7 +680,7 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
>      char *buffer = NULL;
> 
>      v9fs_string_init(&fullname);
> -    v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
> +    v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, name);
>      path = fullname.data;
> 
>      /* Determine the security model */
> @@ -552,7 +741,7 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
>      char *buffer = NULL;
> 
>      v9fs_string_init(&fullname);
> -    v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
> +    v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, name);
>      path = fullname.data;
> 
>      /* Determine the security model */
> @@ -610,7 +799,14 @@ static int local_fstat(FsContext *fs_ctx, int fid_type,
>      int err, fd;
> 
>      if (fid_type == P9_FID_DIR) {
> +        /* Don't know if that's right...
> +           (on WIN32/mingw, DIR has no fd entry) */
> +#ifdef _WIN32
> +        #warning "Could cause problems!"
> +        fd = fs->fd;
> +#else
>          fd = dirfd(fs->dir);
> +#endif
>      } else {
>          fd = fs->fd;
>      }
> @@ -619,6 +815,13 @@ static int local_fstat(FsContext *fs_ctx, int fid_type,
>      if (err) {
>          return err;
>      }
> +#ifdef _WIN32
> +    /* This way, all files are executable
> +       (MingW seems to do 777 on dirs, but 666 on files) */
> +    stbuf->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH;
> +
> +    /* mifritscher: TODO: fake inode? */
> +#endif
>      if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
>          /* Actual credentials are part of extended attrs */
>          uid_t tmp_uid;
> @@ -661,13 +864,16 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
>      flags |= O_NOFOLLOW;
> 
>      v9fs_string_init(&fullname);
> -    v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
> +    v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, name);
>      path = fullname.data;
> 
> +    error_printf("local_open2: got %s %s\n", dir_path->data, name);
> +    error_printf("local_open2: full path: %s\n", path);
> +
>      /* Determine the security model */
>      if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
>          buffer = rpath(fs_ctx, path);
> -        fd = open(buffer, flags, SM_LOCAL_MODE_BITS);
> +        fd = open(buffer, flags | O_BINARY, SM_LOCAL_MODE_BITS);
>          if (fd == -1) {
>              err = fd;
>              goto out;
> @@ -681,7 +887,7 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
>          }
>      } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
>          buffer = rpath(fs_ctx, path);
> -        fd = open(buffer, flags, SM_LOCAL_MODE_BITS);
> +        fd = open(buffer, flags | O_BINARY, SM_LOCAL_MODE_BITS);
>          if (fd == -1) {
>              err = fd;
>              goto out;
> @@ -696,12 +902,17 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
>      } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
>                 (fs_ctx->export_flags & V9FS_SM_NONE)) {
>          buffer = rpath(fs_ctx, path);
> -        fd = open(buffer, flags, credp->fc_mode);
> +        error_printf("local_open2: File which should be opened (open2): %s\n",
> +                     buffer);
> +        fd = open(buffer, flags | O_BINARY, credp->fc_mode);
> +        error_printf("local_open2: open returned %d\n", fd);
>          if (fd == -1) {
>              err = fd;
>              goto out;
>          }
>          err = local_post_create_passthrough(fs_ctx, path, credp);
> +        error_printf("local_open2: local_post_create_passthrough returned %u\n",
> +                     err);
>          if (err == -1) {
>              serrno = errno;
>              goto err_end;
> @@ -732,7 +943,7 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
>      char *buffer = NULL;
> 
>      v9fs_string_init(&fullname);
> -    v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
> +    v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, name);
>      newpath = fullname.data;
> 
>      /* Determine the security model */
> @@ -740,7 +951,9 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
>          int fd;
>          ssize_t oldpath_size, write_size;
>          buffer = rpath(fs_ctx, newpath);
> -        fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS);
> +        fd = open(buffer,
> +                  O_CREAT | O_EXCL | O_RDWR | O_NOFOLLOW | O_BINARY,
> +                  SM_LOCAL_MODE_BITS);
>          if (fd == -1) {
>              err = fd;
>              goto out;
> @@ -758,8 +971,10 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
>              goto err_end;
>          }
>          close(fd);
> -        /* Set cleint credentials in symlink's xattr */
> +        /* Set client credentials in symlink's xattr */
> +#ifndef _WIN32
>          credp->fc_mode = credp->fc_mode|S_IFLNK;
> +#endif
>          err = local_set_xattr(buffer, credp);
>          if (err == -1) {
>              serrno = errno;
> @@ -769,7 +984,9 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
>          int fd;
>          ssize_t oldpath_size, write_size;
>          buffer = rpath(fs_ctx, newpath);
> -        fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS);
> +        fd = open(buffer,
> +                  O_CREAT | O_EXCL | O_RDWR | O_NOFOLLOW | O_BINARY,
> +                  SM_LOCAL_MODE_BITS);
>          if (fd == -1) {
>              err = fd;
>              goto out;
> @@ -788,7 +1005,9 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
>          }
>          close(fd);
>          /* Set cleint credentials in symlink's xattr */
> +#ifndef _WIN32
>          credp->fc_mode = credp->fc_mode|S_IFLNK;
> +#endif
>          err = local_set_mapped_file_attr(fs_ctx, newpath, credp);
>          if (err == -1) {
>              serrno = errno;
> @@ -833,7 +1052,7 @@ static int local_link(FsContext *ctx, V9fsPath *oldpath,
>      char *buffer, *buffer1;
> 
>      v9fs_string_init(&newpath);
> -    v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name);
> +    v9fs_string_sprintf(&newpath, DELIMITER_IN_PATH, dirpath->data, name);
> 
>      buffer = rpath(ctx, oldpath->data);
>      buffer1 = rpath(ctx, newpath.data);
> @@ -934,7 +1153,12 @@ static int local_utimensat(FsContext *s, V9fsPath *fs_path,
>      char *path = fs_path->data;
> 
>      buffer = rpath(s, path);
> +#ifdef _WIN32
> +    #warning "Could cause problems!"
> +    ret = 0;
> +#else
>      ret = qemu_utimens(buffer, buf);
> +#endif
>      g_free(buffer);
>      return ret;
>  }
> @@ -949,6 +1173,7 @@ static int local_remove(FsContext *ctx, const char *path)
>          buffer = rpath(ctx, path);
>          err =  lstat(buffer, &stbuf);
>          g_free(buffer);
> +        error_printf("local_remove: stat %d %d\n", err, errno);
>          if (err) {
>              goto err_out;
>          }
> @@ -957,10 +1182,12 @@ static int local_remove(FsContext *ctx, const char *path)
>           * directory
>           */
>          if (S_ISDIR(stbuf.st_mode)) {
> -            buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root,
> +            buffer = g_strdup_printf(DELIMITER_IN_PATH2, ctx->fs_root,
>                                       path, VIRTFS_META_DIR);
>              err = remove(buffer);
>              g_free(buffer);
> +            error_printf("local_remove: .virtfs_metdata remove %d %d\n",
> +                         err, errno);
>              if (err < 0 && errno != ENOENT) {
>                  /*
>                   * We didn't had the .virtfs_metadata file. May be file created
> @@ -976,6 +1203,8 @@ static int local_remove(FsContext *ctx, const char *path)
>          buffer = local_mapped_attr_path(ctx, path);
>          err = remove(buffer);
>          g_free(buffer);
> +        error_printf("local_remove: local_mapped_attr_path remove %d %d\n",
> +                     err, errno);
>          if (err < 0 && errno != ENOENT) {
>              /*
>               * We didn't had the .virtfs_metadata file. May be file created
> @@ -986,7 +1215,14 @@ static int local_remove(FsContext *ctx, const char *path)
>      }
> 
>      buffer = rpath(ctx, path);
> -    err = remove(buffer);
> +    /* mifritscher: posix remove can delete directories as well, windows not */
> +    if (S_ISDIR(stbuf.st_mode)) {
> +        err = rmdir(buffer);
> +    } else {
> +        err = remove(buffer);
> +    }
> +    error_printf("local_remove: final remove %d %d\n",
> +                 err, errno);
>      g_free(buffer);
>  err_out:
>      return err;
> @@ -998,7 +1234,12 @@ static int local_fsync(FsContext *ctx, int fid_type,
>      int fd;
> 
>      if (fid_type == P9_FID_DIR) {
> +#ifdef _WIN32
> +        #warning "Could cause problems!"
> +        fd = fs->fd;
> +#else
>          fd = dirfd(fs->dir);
> +#endif
>      } else {
>          fd = fs->fd;
>      }
> @@ -1058,10 +1299,14 @@ static int local_name_to_path(FsContext *ctx, V9fsPath *dir_path,
>                                const char *name, V9fsPath *target)
>  {
>      if (dir_path) {
> -        v9fs_string_sprintf((V9fsString *)target, "%s/%s",
> +        v9fs_string_sprintf((V9fsString *)target, DELIMITER_IN_PATH,
>                              dir_path->data, name);
> +        error_printf("local_name_to_path: ");
> +        error_printf(DELIMITER_IN_PATH, dir_path->data, name);
> +        error_printf("\n");
>      } else {
>          v9fs_string_sprintf((V9fsString *)target, "%s", name);
> +        error_printf("local_name_to_path: %s\n", name);
>      }
>      /* Bump the size for including terminating NULL */
>      target->size++;
> @@ -1078,8 +1323,10 @@ static int local_renameat(FsContext *ctx, V9fsPath *olddir,
>      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);
> +    v9fs_string_sprintf(&old_full_name,
> +                        DELIMITER_IN_PATH, olddir->data, old_name);
> +    v9fs_string_sprintf(&new_full_name,
> +                        DELIMITER_IN_PATH, newdir->data, new_name);
> 
>      ret = local_rename(ctx, old_full_name.data, new_full_name.data);
>      v9fs_string_free(&old_full_name);
> @@ -1096,17 +1343,19 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
> 
>      v9fs_string_init(&fullname);
> 
> -    v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name);
> +    v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir->data, name);
>      if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
>          if (flags == AT_REMOVEDIR) {
>              /*
>               * If directory remove .virtfs_metadata contained in the
>               * directory
>               */
> -            buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root,
> +            buffer = g_strdup_printf(DELIMITER_IN_PATH2, ctx->fs_root,
>                                       fullname.data, VIRTFS_META_DIR);
>              ret = remove(buffer);
>              g_free(buffer);
> +            error_printf("local_unlinkat: .virtfs_metadata %d %d\n",
> +                         ret, errno);
>              if (ret < 0 && errno != ENOENT) {
>                  /*
>                   * We didn't had the .virtfs_metadata file. May be file created
> @@ -1121,6 +1370,8 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
>           */
>          buffer = local_mapped_attr_path(ctx, fullname.data);
>          ret = remove(buffer);
> +        error_printf("local_unlinkat: local_mapped_attr_path %d %d\n",
> +                     ret, errno);
>          g_free(buffer);
>          if (ret < 0 && errno != ENOENT) {
>              /*
> @@ -1133,6 +1384,19 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
>      /* Remove the name finally */
>      buffer = rpath(ctx, fullname.data);
>      ret = remove(buffer);
> +    error_printf("local_unlinkat: final |%s| %d %d\n", buffer, ret, errno);
> +    /* extension for MingW: remove or Windows can't handle directories... */
> +#ifdef _WIN32
> +    /* mifritscher: Try to delete it as directory
> +       (AT_REMOVEDIR doesn't seem to be set in this case
> +       (testcase: rmdir from Linux)) */
> +    if (ret < 0) {
> +        ret = rmdir(buffer);
> +            error_printf("local_unlinkat: final rmdir |%s| %d %d\n",
> +                         buffer, ret, errno);
> +
> +    }
> +#endif
>      g_free(buffer);
> 
>  err_out:
> @@ -1140,6 +1404,7 @@ err_out:
>      return ret;
>  }
> 
> +#ifndef _WIN32
>  static int local_ioc_getversion(FsContext *ctx, V9fsPath *path,
>                                  mode_t st_mode, uint64_t *st_gen)
>  {
> @@ -1167,12 +1432,18 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path,
>      return -1;
>  #endif
>  }
> +#endif
> 
>  static int local_init(FsContext *ctx)
>  {
>      int err = 0;
> +#ifdef FS_IOC_GETVERSION
>      struct statfs stbuf;
> +#endif
> 
> +#ifdef _WIN32
> +    ctx->xops = 0;
> +#else
>      if (ctx->export_flags & V9FS_SM_PASSTHROUGH) {
>          ctx->xops = passthrough_xattr_ops;
>      } else if (ctx->export_flags & V9FS_SM_MAPPED) {
> @@ -1186,6 +1457,7 @@ static int local_init(FsContext *ctx)
>           */
>          ctx->xops = passthrough_xattr_ops;
>      }
> +#endif
>      ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT;
>  #ifdef FS_IOC_GETVERSION
>      /*
> diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c
> index f1475df..8355722 100644
> --- a/hw/9pfs/9p-synth.c
> +++ b/hw/9pfs/9p-synth.c
> @@ -15,7 +15,9 @@
>  #include "qemu/osdep.h"
>  #include "hw/virtio/virtio.h"
>  #include "9p.h"
> -#include "9p-xattr.h"
> +#ifndef _WIN32
> +    #include "9p-xattr.h"
> +#endif
>  #include "fsdev/qemu-fsdev.h"
>  #include "9p-synth.h"
>  #include "qemu/rcu.h"
> @@ -152,8 +154,10 @@ static void v9fs_synth_fill_statbuf(V9fsSynthNode *node, struct stat *stbuf)
>      stbuf->st_gid = 0;
>      stbuf->st_rdev = 0;
>      stbuf->st_size = 0;
> +#ifndef _WIN32
>      stbuf->st_blksize = 0;
>      stbuf->st_blocks = 0;
> +#endif
>      stbuf->st_atime = 0;
>      stbuf->st_mtime = 0;
>      stbuf->st_ctime = 0;
> @@ -222,7 +226,11 @@ static void v9fs_synth_direntry(V9fsSynthNode *node,
>  {
>      strcpy(entry->d_name, node->name);
>      entry->d_ino = node->attr->inode;
> +#ifdef _WIN32
> +    #warning "Can cause problems!"
> +#else
>      entry->d_off = off + 1;
> +#endif
>  }
> 
>  static int v9fs_synth_get_dentry(V9fsSynthNode *dir, struct dirent *entry,
> diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
> index f5e3012..7980f33 100644
> --- a/hw/9pfs/9p.c
> +++ b/hw/9pfs/9p.c
> @@ -20,7 +20,21 @@
>  #include "qemu/sockets.h"
>  #include "virtio-9p.h"
>  #include "fsdev/qemu-fsdev.h"
> -#include "9p-xattr.h"
> +#ifdef _WIN32
> +/* taken from linux/kdev_t.h */
> +# define MINORBITS       20
> +# define MINORMASK       ((1U << MINORBITS) - 1)
> +
> +# define major(dev)      ((unsigned int) ((dev) >> MINORBITS))
> +# define minor(dev)      ((unsigned int) ((dev) & MINORMASK))
> +# define makedev(ma, mi)    (((ma) << MINORBITS) | (mi))
> +
> +/* taken from linux/include/linux/stat.h */
> +# define UTIME_NOW ((1l << 30) - 1l)
> +# define UTIME_OMIT ((1l << 30) - 2l)
> +#else
> +# include "9p-xattr.h"
> +#endif
>  #include "coth.h"
>  #include "trace.h"
>  #include "migration/migration.h"
> @@ -576,9 +590,11 @@ static void stat_to_qid(const struct stat *stbuf, V9fsQID *qidp)
>      if (S_ISDIR(stbuf->st_mode)) {
>          qidp->type |= P9_QID_TYPE_DIR;
>      }
> -    if (S_ISLNK(stbuf->st_mode)) {
> -        qidp->type |= P9_QID_TYPE_SYMLINK;
> -    }
> +    #ifndef _WIN32
> +        if (S_ISLNK(stbuf->st_mode)) {
> +            qidp->type |= P9_QID_TYPE_SYMLINK;
> +        }
> +    #endif
>  }
> 
>  static int fid_to_qid(V9fsPDU *pdu, V9fsFidState *fidp, V9fsQID *qidp)
> @@ -677,12 +693,15 @@ static mode_t v9mode_to_mode(uint32_t mode, V9fsString *extension)
>          ret |= S_IFDIR;
>      }
> 
> +#ifndef _WIN32
>      if (mode & P9_STAT_MODE_SYMLINK) {
>          ret |= S_IFLNK;
>      }
>      if (mode & P9_STAT_MODE_SOCKET) {
>          ret |= S_IFSOCK;
>      }
> +#endif
> +
>      if (mode & P9_STAT_MODE_NAMED_PIPE) {
>          ret |= S_IFIFO;
>      }
> @@ -698,6 +717,7 @@ static mode_t v9mode_to_mode(uint32_t mode, V9fsString *extension)
>          ret |= S_IFREG;
>      }
> 
> +#ifndef _WIN32
>      if (mode & P9_STAT_MODE_SETUID) {
>          ret |= S_ISUID;
>      }
> @@ -707,6 +727,7 @@ static mode_t v9mode_to_mode(uint32_t mode, V9fsString *extension)
>      if (mode & P9_STAT_MODE_SETVTX) {
>          ret |= S_ISVTX;
>      }
> +#endif
> 
>      return ret;
>  }
> @@ -762,6 +783,7 @@ static uint32_t stat_to_v9mode(const struct stat *stbuf)
>          mode |= P9_STAT_MODE_DIR;
>      }
> 
> +#ifndef _WIN32
>      if (S_ISLNK(stbuf->st_mode)) {
>          mode |= P9_STAT_MODE_SYMLINK;
>      }
> @@ -769,6 +791,7 @@ static uint32_t stat_to_v9mode(const struct stat *stbuf)
>      if (S_ISSOCK(stbuf->st_mode)) {
>          mode |= P9_STAT_MODE_SOCKET;
>      }
> +#endif
> 
>      if (S_ISFIFO(stbuf->st_mode)) {
>          mode |= P9_STAT_MODE_NAMED_PIPE;
> @@ -778,6 +801,7 @@ static uint32_t stat_to_v9mode(const struct stat *stbuf)
>          mode |= P9_STAT_MODE_DEVICE;
>      }
> 
> +#ifndef _WIN32
>      if (stbuf->st_mode & S_ISUID) {
>          mode |= P9_STAT_MODE_SETUID;
>      }
> @@ -789,6 +813,7 @@ static uint32_t stat_to_v9mode(const struct stat *stbuf)
>      if (stbuf->st_mode & S_ISVTX) {
>          mode |= P9_STAT_MODE_SETVTX;
>      }
> +#endif
> 
>      return mode;
>  }
> @@ -881,14 +906,34 @@ static void stat_to_v9stat_dotl(V9fsState *s, const struct stat *stbuf,
>      v9lstat->st_gid = stbuf->st_gid;
>      v9lstat->st_rdev = stbuf->st_rdev;
>      v9lstat->st_size = stbuf->st_size;
> +#ifdef _WIN32
> +    /* Blksize is the optimal EA-block,
> +       while blocks always refers to 512 blocks
> +    */
> +    v9lstat->st_blksize = 4096;
> +    v9lstat->st_blocks = ((stbuf->st_size + 1) / 512) + 1;
> +#else
>      v9lstat->st_blksize = stbuf->st_blksize;
>      v9lstat->st_blocks = stbuf->st_blocks;
> +#endif
>      v9lstat->st_atime_sec = stbuf->st_atime;
> +#ifdef _WIN32
> +    v9lstat->st_atime_nsec = 0;
> +#else
>      v9lstat->st_atime_nsec = stbuf->st_atim.tv_nsec;
> +#endif
>      v9lstat->st_mtime_sec = stbuf->st_mtime;
> +#ifdef _WIN32
> +    v9lstat->st_mtime_nsec = 0;
> +#else
>      v9lstat->st_mtime_nsec = stbuf->st_mtim.tv_nsec;
> +#endif
>      v9lstat->st_ctime_sec = stbuf->st_ctime;
> +#ifdef _WIN32
> +    v9lstat->st_ctime_nsec = 0;
> +#else
>      v9lstat->st_ctime_nsec = stbuf->st_ctim.tv_nsec;
> +#endif
>      /* Currently we only support BASIC fields in stat */
>      v9lstat->st_result_mask = P9_STATS_BASIC;
> 
> @@ -1639,7 +1684,10 @@ static int v9fs_do_readdir_with_stat(V9fsPDU *pdu,
>          v9fs_path_init(&path);
>          err = v9fs_co_readdir_r(pdu, fidp, dent, &result);
>          if (err || !result) {
> +            error_printf("v9fs_do_readdir_with_stat: exiting...\n");
>              break;
> +        } else {
> +            error_printf("v9fs_do_readdir_with_stat: continue\n");
>          }
>          err = v9fs_co_name_to_path(pdu, &fidp->path, dent->d_name, &path);
>          if (err < 0) {
> @@ -1666,7 +1714,12 @@ static int v9fs_do_readdir_with_stat(V9fsPDU *pdu,
>          count += len;
>          v9fs_stat_free(&v9stat);
>          v9fs_path_free(&path);
> +#ifdef _WIN32
> +        #warning "Probably right, but could make problems!"
> +        saved_dir_pos = v9fs_co_telldir(pdu, fidp);
> +#else
>          saved_dir_pos = dent->d_off;
> +#endif
>      }
>  out:
>      g_free(dent);
> @@ -1806,6 +1859,9 @@ static int v9fs_do_readdir(V9fsPDU *pdu,
>      int32_t count = 0;
>      off_t saved_dir_pos;
>      struct dirent *dent, *result;
> +#ifdef _WIN32
> +    uint8_t type = 0; /* DT_UNKNOWN */
> +#endif
> 
>      /* save the directory position */
>      saved_dir_pos = v9fs_co_telldir(pdu, fidp);
> @@ -1818,15 +1874,27 @@ static int v9fs_do_readdir(V9fsPDU *pdu,
>      while (1) {
>          err = v9fs_co_readdir_r(pdu, fidp, dent, &result);
>          if (err || !result) {
> +            error_printf("v9fs_do_readdir: exiting...\n");
>              break;
> +        } else {
> +            error_printf("v9fs_do_readdir: continue\n");
>          }
>          v9fs_string_init(&name);
> +        if (!dent->d_name) {
> +            error_printf("\ndent->d_name is NULL!\n");
> +            break;
> +        } else {
> +            error_printf("v9fs_do_readdir: entry is named %s, strlen %u\n",
> +                         dent->d_name, strlen(dent->d_name));
> +        }
>          v9fs_string_sprintf(&name, "%s", dent->d_name);
>          if ((count + v9fs_readdir_data_size(&name)) > max_count) {
>              /* Ran out of buffer. Set dir back to old position and return */
>              v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
>              v9fs_string_free(&name);
>              g_free(dent);
> +            error_printf("v9fs_do_readdir: RAN OUT OF BUFFER return %d\n\n",
> +                         count);
>              return count;
>          }
>          /*
> @@ -1841,9 +1909,16 @@ static int v9fs_do_readdir(V9fsPDU *pdu,
>          qid.version = 0;
> 
>          /* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */
> +#ifdef _WIN32
> +        #warning "Probably right, but could make problems!"
> +        len = pdu_marshal(pdu, 11 + count, "Qqbs",
> +                          &qid, v9fs_co_telldir(pdu, fidp),
> +                          type, &name);
> +#else
>          len = pdu_marshal(pdu, 11 + count, "Qqbs",
>                            &qid, dent->d_off,
>                            dent->d_type, &name);
> +#endif
>          if (len < 0) {
>              v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
>              v9fs_string_free(&name);
> @@ -1852,12 +1927,18 @@ static int v9fs_do_readdir(V9fsPDU *pdu,
>          }
>          count += len;
>          v9fs_string_free(&name);
> +#ifdef _WIN32
> +        #warning "Probably right, but could make problems!"
> +        saved_dir_pos = v9fs_co_telldir(pdu, fidp);
> +#else
>          saved_dir_pos = dent->d_off;
> +#endif
>      }
>      g_free(dent);
>      if (err < 0) {
>          return err;
>      }
> +    error_printf("v9fs_do_readdir: return %d\n\n", count);
>      return count;
>  }
> 
> @@ -1878,6 +1959,8 @@ static void v9fs_readdir(void *opaque)
>          goto out_nofid;
>      }
>      trace_v9fs_readdir(pdu->tag, pdu->id, fid, initial_offset, max_count);
> +    error_printf("v9fs_readdir initial: %llu max count: %u\n",
> +                 initial_offset, max_count);
> 
>      fidp = get_fid(pdu, fid);
>      if (fidp == NULL) {
> @@ -1904,10 +1987,13 @@ static void v9fs_readdir(void *opaque)
>      }
>      retval += count + offset;
>      trace_v9fs_readdir_return(pdu->tag, pdu->id, count, retval);
> +    error_printf("v9fs_readdir: count: %d retval: %d\n\n", count, retval);
>  out:
>      put_fid(pdu, fidp);
>  out_nofid:
>      pdu_complete(pdu, retval);
> +
> +    error_printf("v9fs_readdir: return\n");
>  }
> 
>  static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
> @@ -2166,8 +2252,12 @@ static void v9fs_create(void *opaque)
>          }
>          v9fs_path_copy(&fidp->path, &path);
>      } else if (perm & P9_STAT_MODE_SOCKET) {
> +#ifdef _WIN32
> +        err = -1;
> +#else
>          err = v9fs_co_mknod(pdu, fidp, &name, fidp->uid, -1,
>                              0, S_IFSOCK | (perm & 0777), &stbuf);
> +#endif
>          if (err < 0) {
>              goto out;
>          }
> @@ -3338,7 +3428,7 @@ int v9fs_device_realize_common(V9fsState *s, Error **errp)
>       * call back to do that. Since we are in the init path, we don't
>       * use co-routines here.
>       */
> -    if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) {
> +    if (s->ops->name_to_path(&s->ctx, NULL, DELIMITER_STRING, &path) < 0) {
>          error_setg(errp,
>                     "error in converting name to path %s", strerror(errno));
>          goto out;
> @@ -3370,6 +3460,7 @@ void v9fs_device_unrealize_common(V9fsState *s, Error **errp)
> 
>  static void __attribute__((__constructor__)) v9fs_set_fd_limit(void)
>  {
> +#ifndef _WIN32
>      struct rlimit rlim;
>      if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
>          error_report("Failed to get the resource limit");
> @@ -3377,4 +3468,5 @@ static void __attribute__((__constructor__)) v9fs_set_fd_limit(void)
>      }
>      open_fd_hw = rlim.rlim_cur - MIN(400, rlim.rlim_cur/3);
>      open_fd_rc = rlim.rlim_cur/2;
> +#endif
>  }
> diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
> index 1a19418..7bc8863 100644
> --- a/hw/9pfs/9p.h
> +++ b/hw/9pfs/9p.h
> @@ -3,7 +3,29 @@
> 
>  #include <dirent.h>
>  #include <utime.h>
> -#include <sys/resource.h>
> +#ifdef _WIN32
> +/* Bad workaround, from http://octave.org/doxygen/3.4/fcntl_8h.html */
> +# define O_NOCTTY 0
> +# define O_NDELAY 0
> +# define O_NONBLOCK O_NDELAY
> +# define O_DSYNC 0
> +# define O_DIRECT 0
> +# define O_DIRECTORY 0
> +# define O_NOFOLLOW 0
> +# define O_NOATIME 0
> +# define O_SYNC 0
> +# define O_ASYNC 0
> +
> +# define FASYNC 0
> +
> +# define AT_REMOVEDIR 1
> +
> +# define NAME_MAX 260
> +
> +#else
> +# include <sys/resource.h>
> +#endif
> +
>  #include <glib.h>
>  #include "standard-headers/linux/virtio_9p.h"
>  #include "hw/virtio/virtio.h"
> @@ -12,6 +34,10 @@
>  #include "qemu/thread.h"
>  #include "qemu/coroutine.h"
> 
> +#define DELIMITER_STRING "/"
> +#define DELIMITER_IN_PATH "%s/%s"
> +#define DELIMITER_IN_PATH2 "%s/%s/%s"
> +

Is this really needed (will there be different values for
win32) ? If yes, I guess DELEMITER_STRING should be defined
in a host arch specific header ? And anyway, this should be
pushed to a separate patch.

>  enum {
>      P9_TLERROR = 6,
>      P9_RLERROR,
> @@ -108,9 +134,49 @@ enum p9_proto_version {
> 
>  #define FID_REFERENCED          0x1
>  #define FID_NON_RECLAIMABLE     0x2
> +
> +/* combines the host's root dir and the path to a complete host path */
>  static inline char *rpath(FsContext *ctx, const char *path)
>  {
> -    return g_strdup_printf("%s/%s", ctx->fs_root, path);
> +    char *result;
> +    result = g_strdup_printf(DELIMITER_IN_PATH, ctx->fs_root, path);
> +#ifdef _WIN32
> +    int input = 0;
> +    int output = 0;
> +    while (result[input]) {
> +        /* error_printf("<-%d %c\n", input, result[input]); */
> +        if (result[input] == '/') {
> +            result[output] = '\\';
> +            /* remove duplicate \... */

Why do we need to remove duplicate \ ?

> +            if (output > 0 && result[output - 1] == '\\') {
> +                /* error_printf("remove duplicate \\\n"); */
> +                output--;
> +            } else {
> +                result[output] = '\\';
> +            }
> +            /* error_printf("    %c\n", result[output]); */
> +        } else {
> +            result[output] = result[input];
> +        }
> +        /* error_printf("->%d %c\n\n", output, result[output]); */
> +        input++;
> +        output++;
> +    }
> +    /* Kill last \ (but leave it if the char before is a : ...)

Why kill last \ ?

> +    So:
> +    C:\ -> C:\
> +    C:\blah\ -> C:\blah
> +    b\ -> b
> +    blah\ -> blah */
> +    if (output > 1 && result[output - 1] == '\\'
> +        && (output == 1 || result[output - 2] != ':')) {
> +        /* error_printf("Killed last \\\n"); */
> +        result[output - 1] = '\0';
> +    } else {
> +        result[output] = '\0';
> +    }
> +#endif

I understand we need to convert / to \, but I don't see why
we should remove duplicates... and anyway, this should be
moved to a fixup helper.

> +    return result;
>  }
> 
>  /*
> diff --git a/hw/9pfs/Makefile.objs b/hw/9pfs/Makefile.objs
> index da0ae0c..6f6ed19 100644
> --- a/hw/9pfs/Makefile.objs
> +++ b/hw/9pfs/Makefile.objs
> @@ -1,9 +1,10 @@
>  common-obj-y  = 9p.o
> -common-obj-y += 9p-local.o 9p-xattr.o
> -common-obj-y += 9p-xattr-user.o 9p-posix-acl.o
> +common-obj-$(CONFIG_LINUX) += 9p-local.o 9p-xattr.o
> +common-obj-$(CONFIG_LINUX) += 9p-xattr-user.o 9p-posix-acl.o
> +common-obj-$(CONFIG_WIN32) += 9p-local.o
>  common-obj-y += coth.o cofs.o codir.o cofile.o
>  common-obj-y += coxattr.o 9p-synth.o
>  common-obj-$(CONFIG_OPEN_BY_HANDLE) +=  9p-handle.o
> -common-obj-y += 9p-proxy.o
> +common-obj-$(CONFIG_POSIX) += 9p-proxy.o
> 
>  obj-y += virtio-9p-device.o
> diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c
> index 91df7f7..399bd8a 100644
> --- a/hw/9pfs/codir.c
> +++ b/hw/9pfs/codir.c
> @@ -17,6 +17,8 @@
>  #include "qemu/thread.h"
>  #include "qemu/coroutine.h"
>  #include "coth.h"
> +/* mifritscher: after killing the debug printf, kill this as well! */
> +#include "qemu/error-report.h"
> 
>  int v9fs_co_readdir_r(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent *dent,
>                        struct dirent **result)
> @@ -37,6 +39,12 @@ int v9fs_co_readdir_r(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent *dent,
>                  err = 0;
>              }
>          });
> +#ifdef _WIN32
> +    error_printf("v9fs_co_readdir_r: %s %d %p\n",
> +                 (&fidp->fs)->dir->dd_name, err, *result);
> +#else
> +    error_printf("v9fs_co_readdir_r: %d %p\n", err, *result);
> +#endif
>      return err;
>  }
> 
> @@ -55,6 +63,12 @@ off_t v9fs_co_telldir(V9fsPDU *pdu, V9fsFidState *fidp)
>                  err = -errno;
>              }
>          });
> +#ifdef _WIN32
> +    error_printf("v9fs_co_telldir_r: %s %lld\n",
> +                 (&fidp->fs)->dir->dd_name, err);
> +#else
> +    error_printf("v9fs_co_telldir_r: %ld\n", err);
> +#endif
>      return err;
>  }
> 
> @@ -68,6 +82,11 @@ void v9fs_co_seekdir(V9fsPDU *pdu, V9fsFidState *fidp, off_t offset)
>          {
>              s->ops->seekdir(&s->ctx, &fidp->fs, offset);
>          });
> +#ifdef _WIN32
> +    error_printf("v9fs_co_seekdir: %s\n", (&fidp->fs)->dir->dd_name);
> +#else
> +    error_printf("v9fs_co_seekdir\n");
> +#endif
>  }
> 
>  void v9fs_co_rewinddir(V9fsPDU *pdu, V9fsFidState *fidp)
> @@ -80,6 +99,11 @@ void v9fs_co_rewinddir(V9fsPDU *pdu, V9fsFidState *fidp)
>          {
>              s->ops->rewinddir(&s->ctx, &fidp->fs);
>          });
> +#ifdef _WIN32
> +    error_printf("v9fs_co_rewinddir: %s\n", (&fidp->fs)->dir->dd_name);
> +#else
> +    error_printf("v9fs_co_rewinddir\n");
> +#endif
>  }
> 
>  int v9fs_co_mkdir(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name,
> @@ -116,6 +140,7 @@ int v9fs_co_mkdir(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name,
>              }
>          });
>      v9fs_path_unlock(s);
> +    error_printf("v9fs_co_mkdir: %d\n", err);
>      return err;
>  }
> 
> @@ -144,6 +169,11 @@ int v9fs_co_opendir(V9fsPDU *pdu, V9fsFidState *fidp)
>              v9fs_reclaim_fd(pdu);
>          }
>      }
> +#ifdef _WIN32
> +    error_printf("v9fs_co_opendir: %s %d\n", (&fidp->fs)->dir->dd_name, err);
> +#else
> +    error_printf("v9fs_co_opendir: %d\n", err);
> +#endif
>      return err;
>  }
> 
> @@ -165,5 +195,6 @@ int v9fs_co_closedir(V9fsPDU *pdu, V9fsFidOpenState *fs)
>      if (!err) {
>          total_open_fd--;
>      }
> +    error_printf("v9fs_co_closedir: %d\n", err);
>      return err;
>  }
> diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c
> index 293483e..a9c1a10 100644
> --- a/hw/9pfs/cofile.c
> +++ b/hw/9pfs/cofile.c
> @@ -17,6 +17,8 @@
>  #include "qemu/thread.h"
>  #include "qemu/coroutine.h"
>  #include "coth.h"
> +/* mifritscher: after killing the debug printf, kill this as well! */
> +#include "qemu/error-report.h"
> 
>  int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode,
>                     V9fsStatDotl *v9stat)
> @@ -39,6 +41,7 @@ int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode,
>              });
>          v9fs_path_unlock(s);
>      }
> +    error_printf("v9fs_co_st_gen: %d\n", err);
>      return err;
>  }
> 
> @@ -59,6 +62,7 @@ int v9fs_co_lstat(V9fsPDU *pdu, V9fsPath *path, struct stat *stbuf)
>              }
>          });
>      v9fs_path_unlock(s);
> +    error_printf("v9fs_co_lstat: %d\n", err);
>      return err;
>  }
> 
> @@ -91,6 +95,7 @@ int v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp, struct stat *stbuf)
>              err = 0;
>          }
>      }
> +    error_printf("v9fs_co_fstat: %s %d\n", (&fidp->path)->data, err);
>      return err;
>  }
> 
> @@ -119,6 +124,7 @@ int v9fs_co_open(V9fsPDU *pdu, V9fsFidState *fidp, int flags)
>              v9fs_reclaim_fd(pdu);
>          }
>      }
> +    error_printf("v9fs_co_open: %s %d\n", (&fidp->path)->data, err);
>      return err;
>  }
> 
> @@ -147,13 +153,17 @@ int v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, gid_t gid,
>          {
>              err = s->ops->open2(&s->ctx, &fidp->path,
>                                  name->data, flags, &cred, &fidp->fs);
> +            error_printf("v9fs_co_open2: open returned %d\n", err);
>              if (err < 0) {
>                  err = -errno;
>              } else {
>                  v9fs_path_init(&path);
>                  err = v9fs_name_to_path(s, &fidp->path, name->data, &path);
> +                error_printf("v9fs_co_open2: v9fs_name_to_path returned %d\n",
> +                             err);
>                  if (!err) {
>                      err = s->ops->lstat(&s->ctx, &path, stbuf);
> +                    error_printf("v9fs_co_open2: lstat returned %d\n", err);
>                      if (err < 0) {
>                          err = -errno;
>                          s->ops->close(&s->ctx, &fidp->fs);
> @@ -173,6 +183,7 @@ int v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, gid_t gid,
>              v9fs_reclaim_fd(pdu);
>          }
>      }
> +    error_printf("v9fs_co_open2: %s %d\n", (&fidp->path)->data, err);
>      return err;
>  }
> 
> @@ -194,6 +205,7 @@ int v9fs_co_close(V9fsPDU *pdu, V9fsFidOpenState *fs)
>      if (!err) {
>          total_open_fd--;
>      }
> +    error_printf("v9fs_co_close: %d\n", err);
>      return err;
>  }
> 
> @@ -234,6 +246,7 @@ int v9fs_co_link(V9fsPDU *pdu, V9fsFidState *oldfid,
>              }
>          });
>      v9fs_path_unlock(s);
> +    error_printf("v9fs_co_link: %d\n", err);
>      return err;
>  }
> 
> @@ -253,6 +266,7 @@ int v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState *fidp,
>                  err = -errno;
>              }
>          });
> +    error_printf("v9fs_co_pwritev: %s %d\n", (&fidp->path)->data, err);
>      return err;
>  }
> 
> @@ -272,5 +286,6 @@ int v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp,
>                  err = -errno;
>              }
>          });
> +    error_printf("v9fs_co_preadv: %s %d\n", (&fidp->path)->data, err);
>      return err;
>  }
> diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c
> index 18c81cb..a3a42bf 100644
> --- a/hw/9pfs/cofs.c
> +++ b/hw/9pfs/cofs.c
> @@ -17,6 +17,8 @@
>  #include "qemu/thread.h"
>  #include "qemu/coroutine.h"
>  #include "coth.h"
> +/* mifritscher: after killing the debug printf, kill this as well! */
> +#include "qemu/error-report.h"
> 
>  static ssize_t __readlink(V9fsState *s, V9fsPath *path, V9fsString *buf)
>  {
> @@ -67,6 +69,7 @@ int v9fs_co_readlink(V9fsPDU *pdu, V9fsPath *path, V9fsString *buf)
>              }
>          });
>      v9fs_path_unlock(s);
> +    error_printf("v9fs_co_readlink: %d\n", err);
>      return err;
>  }
> 
> @@ -87,6 +90,7 @@ int v9fs_co_statfs(V9fsPDU *pdu, V9fsPath *path, struct statfs *stbuf)
>              }
>          });
>      v9fs_path_unlock(s);
> +    error_printf("v9fs_co_statfs: %d\n", err);
>      return err;
>  }
> 
> @@ -110,6 +114,7 @@ int v9fs_co_chmod(V9fsPDU *pdu, V9fsPath *path, mode_t mode)
>              }
>          });
>      v9fs_path_unlock(s);
> +    error_printf("v9fs_co_chmod: %d\n", err);
>      return err;
>  }
> 
> @@ -131,6 +136,7 @@ int v9fs_co_utimensat(V9fsPDU *pdu, V9fsPath *path,
>              }
>          });
>      v9fs_path_unlock(s);
> +    error_printf("v9fs_co_utimensat: %d\n", err);
>      return err;
>  }
> 
> @@ -155,6 +161,7 @@ int v9fs_co_chown(V9fsPDU *pdu, V9fsPath *path, uid_t uid, gid_t gid)
>              }
>          });
>      v9fs_path_unlock(s);
> +    error_printf("v9fs_co_chown: %d\n", err);
>      return err;
>  }
> 
> @@ -175,6 +182,7 @@ int v9fs_co_truncate(V9fsPDU *pdu, V9fsPath *path, off_t size)
>              }
>          });
>      v9fs_path_unlock(s);
> +    error_printf("v9fs_co_truncate: %d\n", err);
>      return err;
>  }
> 
> @@ -213,6 +221,7 @@ int v9fs_co_mknod(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, uid_t uid,
>              }
>          });
>      v9fs_path_unlock(s);
> +    error_printf("v9fs_co_mknod: %d\n", err);
>      return err;
>  }
> 
> @@ -234,6 +243,7 @@ int v9fs_co_remove(V9fsPDU *pdu, V9fsPath *path)
>              }
>          });
>      v9fs_path_unlock(s);
> +    error_printf("v9fs_co_remove: %d\n", err);
>      return err;
>  }
> 
> @@ -254,6 +264,7 @@ int v9fs_co_unlinkat(V9fsPDU *pdu, V9fsPath *path, V9fsString *name, int flags)
>              }
>          });
>      v9fs_path_unlock(s);
> +    error_printf("v9fs_co_unlinkat: %d\n", err);
>      return err;
>  }
> 
> @@ -273,6 +284,7 @@ int v9fs_co_rename(V9fsPDU *pdu, V9fsPath *oldpath, V9fsPath *newpath)
>                  err = -errno;
>              }
>          });
> +    error_printf("v9fs_co_rename: %d\n", err);
>      return err;
>  }
> 
> @@ -293,6 +305,7 @@ int v9fs_co_renameat(V9fsPDU *pdu, V9fsPath *olddirpath, V9fsString *oldname,
>                  err = -errno;
>              }
>          });
> +    error_printf("v9fs_co_renameat: %d\n", err);
>      return err;
>  }
> 
> @@ -331,6 +344,7 @@ int v9fs_co_symlink(V9fsPDU *pdu, V9fsFidState *dfidp, V9fsString *name,
>              }
>          });
>      v9fs_path_unlock(s);
> +    error_printf("v9fs_co_symlink: %d\n", err);
>      return err;
>  }
> 
> @@ -361,5 +375,6 @@ int v9fs_co_name_to_path(V9fsPDU *pdu, V9fsPath *dirpath,
>                  }
>              });
>      }
> +    error_printf("v9fs_co_name_to_path: %d\n", err);
>      return err;
>  }
> diff --git a/hw/9pfs/coxattr.c b/hw/9pfs/coxattr.c
> index 6ad96ea..49fbd5e 100644
> --- a/hw/9pfs/coxattr.c
> +++ b/hw/9pfs/coxattr.c
> @@ -17,6 +17,8 @@
>  #include "qemu/thread.h"
>  #include "qemu/coroutine.h"
>  #include "coth.h"
> +/* mifritscher: after killing the debug printf, kill this as well! */
> +#include "qemu/error-report.h"
> 
>  int v9fs_co_llistxattr(V9fsPDU *pdu, V9fsPath *path, void *value, size_t size)
>  {
> @@ -35,6 +37,7 @@ int v9fs_co_llistxattr(V9fsPDU *pdu, V9fsPath *path, void *value, size_t size)
>              }
>          });
>      v9fs_path_unlock(s);
> +    error_printf("v9fs_co_llistxattr: %d\n", err);
>      return err;
>  }
> 
> @@ -59,6 +62,7 @@ int v9fs_co_lgetxattr(V9fsPDU *pdu, V9fsPath *path,
>              }
>          });
>      v9fs_path_unlock(s);
> +    error_printf("v9fs_co_lgetxattr: %d\n", err);
>      return err;
>  }
> 
> @@ -83,6 +87,7 @@ int v9fs_co_lsetxattr(V9fsPDU *pdu, V9fsPath *path,
>              }
>          });
>      v9fs_path_unlock(s);
> +    error_printf("v9fs_co_lsetxattr: %d\n", err);
>      return err;
>  }
> 
> @@ -104,5 +109,6 @@ int v9fs_co_lremovexattr(V9fsPDU *pdu, V9fsPath *path,
>              }
>          });
>      v9fs_path_unlock(s);
> +    error_printf("v9fs_co_lremovexattr: %d\n", err);
>      return err;
>  }
> diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
> index a38850e..59d0a50 100644
> --- a/hw/9pfs/virtio-9p-device.c
> +++ b/hw/9pfs/virtio-9p-device.c
> @@ -17,7 +17,9 @@
>  #include "qemu/sockets.h"
>  #include "virtio-9p.h"
>  #include "fsdev/qemu-fsdev.h"
> -#include "9p-xattr.h"
> +#ifndef WIN32
> +    #include "9p-xattr.h"
> +#endif
>  #include "coth.h"
>  #include "hw/virtio/virtio-access.h"
>  #include "qemu/iov.h"

  parent reply	other threads:[~2016-05-09  8:39 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-12  7:52 [Qemu-devel] [PATCH v2] [WIP] [RFC ]Add initial 9pfs support for Windows hosts v2 Michael Fritscher
2016-04-13 12:30 ` Greg Kurz
2016-04-14 19:17 ` Greg Kurz
2016-05-09  8:38 ` Greg Kurz [this message]
2016-05-09  9:12   ` Michael Fritscher
2016-05-10 11:26     ` Greg Kurz
2017-08-28  7:35     ` Michael Fritscher
2017-09-04  8:35       ` Greg Kurz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160509103828.6bfc5b96@bahia.huguette.org \
    --to=gkurz@linux.vnet.ibm.com \
    --cc=aneesh.kumar@linux.vnet.ibm.com \
    --cc=michael@fritscher.net \
    --cc=mst@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=sw@weilnetz.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.