diff mbox

[WIP,RFC] Add initial 9pfs support for Windows hosts

Message ID 1460293457-24200-1-git-send-email-michael@fritscher.net (mailing list archive)
State New, archived
Headers show

Commit Message

Michael Fritscher April 10, 2016, 1:04 p.m. UTC
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.

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

TODO:
   * fix broken functionality
   * test & fix mapped permission style
   * prepend a 777 on all files if security modell "NONE"
   * test everything - on Windows and Linux

Signed-off-by: Michael Fritscher <michael@fritscher.net>
---
Many thanks to Stefan Weil for supporting 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         | 200 +++++++++++++++++++++++++++++++++++++++++----
 hw/9pfs/9p-synth.c         |  10 ++-
 hw/9pfs/9p.c               |  99 ++++++++++++++++++++--
 hw/9pfs/9p.h               |  70 +++++++++++++++-
 hw/9pfs/Makefile.objs      |   7 +-
 hw/9pfs/codir.c            |  35 ++++++++
 hw/9pfs/cofile.c           |  15 ++++
 hw/9pfs/cofs.c             |  15 ++++
 hw/9pfs/virtio-9p-device.c |   4 +-
 15 files changed, 478 insertions(+), 36 deletions(-)
diff mbox

Patch

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..4f5d927 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -12,23 +12,120 @@ 
  */
 
 #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)
+# 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;
+}
+
+# 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)
+{
+    return 0;
+}
+
+static ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
+                               void *value, size_t vsize)
+{
+    return 0;
+}
+
+static int v9fs_set_xattr(FsContext *ctx, const char *path,
+                          const char *name, void *value, size_t size,
+                          int flags)
+{
+    return 0;
+}
+
+static int v9fs_remove_xattr(FsContext *ctx, const char *path,
+                             const char *name)
+{
+    return 0;
+}
+
+static int readdir_r(DIR *dirp, struct dirent *entry,
+                     struct dirent **result)
+{
+    struct dirent *temp;
+    errno = 0;
+    temp = readdir(dirp);
+    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;
+}
+
+#else
+# include "9p-xattr.h"
+#endif
 #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
@@ -124,7 +221,8 @@  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;
     }
@@ -162,7 +260,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 +321,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 +367,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) {
@@ -358,6 +458,7 @@  static int local_open(FsContext *ctx, V9fsPath *fs_path,
     char *path = fs_path->data;
 
     buffer = rpath(ctx, path);
+    error_printf("File which should be opened: %s\n", buffer);
     fs->fd = open(buffer, flags | O_NOFOLLOW);
     g_free(buffer);
     return fs->fd;
@@ -370,6 +471,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 +497,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 (entry == 0) {
+        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;
 }
 
@@ -491,7 +612,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 +673,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 +731,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;
     }
@@ -661,9 +789,12 @@  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);
@@ -696,12 +827,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);
+        error_printf("local_open2: File which should be opened (open2): %s\n",
+                     buffer);
         fd = open(buffer, flags, 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 +868,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 */
@@ -758,8 +894,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;
@@ -788,7 +926,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 +973,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 +1074,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;
 }
@@ -957,7 +1102,7 @@  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);
@@ -998,7 +1143,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 +1208,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 +1232,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,14 +1252,14 @@  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);
@@ -1140,6 +1296,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 +1324,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 +1349,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..e14d7b0 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,31 @@  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
+    v9lstat->st_blksize = 4096;
+    v9lstat->st_blocks = ((stbuf->st_size + 1) / v9lstat->st_blksize) + 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 +1681,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 +1711,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 +1856,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 +1871,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 +1906,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 +1924,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 +1956,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 +1984,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 +2249,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 +3425,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 +3457,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 +3465,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"
+
 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 \... */
+            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 : ...)
+    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
+    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..46754c8 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,11 @@  int v9fs_co_mkdir(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name,
             }
         });
     v9fs_path_unlock(s);
+#ifdef _WIN32
+    error_printf("v9fs_co_mkdir: %s %d\n", (&fidp->fs)->dir->dd_name, err);
+#else
+    error_printf("v9fs_co_mkdir: %d\n", err);
+#endif
     return err;
 }
 
@@ -144,6 +173,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 +199,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/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"