summary refs log tree commit diff stats
path: root/hw/9pfs
diff options
context:
space:
mode:
Diffstat (limited to 'hw/9pfs')
-rw-r--r--hw/9pfs/cofile.c24
-rw-r--r--hw/9pfs/cofs.c2
-rw-r--r--hw/9pfs/virtio-9p-coth.h3
-rw-r--r--hw/9pfs/virtio-9p-debug.c646
-rw-r--r--hw/9pfs/virtio-9p-debug.h6
-rw-r--r--hw/9pfs/virtio-9p-device.c70
-rw-r--r--hw/9pfs/virtio-9p-handle.c120
-rw-r--r--hw/9pfs/virtio-9p-local.c126
-rw-r--r--hw/9pfs/virtio-9p.c170
-rw-r--r--hw/9pfs/virtio-9p.h35
10 files changed, 434 insertions, 768 deletions
diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c
index 7ad4bec005..692811e5ab 100644
--- a/hw/9pfs/cofile.c
+++ b/hw/9pfs/cofile.c
@@ -17,6 +17,30 @@
 #include "qemu-coroutine.h"
 #include "virtio-9p-coth.h"
 
+int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode,
+                   V9fsStatDotl *v9stat)
+{
+    int err = 0;
+    V9fsState *s = pdu->s;
+
+    if (v9fs_request_cancelled(pdu)) {
+        return -EINTR;
+    }
+    if (s->ctx.exops.get_st_gen) {
+        v9fs_path_read_lock(s);
+        v9fs_co_run_in_worker(
+            {
+                err = s->ctx.exops.get_st_gen(&s->ctx, path, st_mode,
+                                              &v9stat->st_gen);
+                if (err < 0) {
+                    err = -errno;
+                }
+            });
+        v9fs_path_unlock(s);
+    }
+    return err;
+}
+
 int v9fs_co_lstat(V9fsPDU *pdu, V9fsPath *path, struct stat *stbuf)
 {
     int err;
diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c
index 68745add1e..83f125bd47 100644
--- a/hw/9pfs/cofs.c
+++ b/hw/9pfs/cofs.c
@@ -323,7 +323,7 @@ int v9fs_co_name_to_path(V9fsPDU *pdu, V9fsPath *dirpath,
     int err;
     V9fsState *s = pdu->s;
 
-    if (s->ctx.flags & PATHNAME_FSCONTEXT) {
+    if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
         err = s->ops->name_to_path(&s->ctx, dirpath, name, path);
         if (err < 0) {
             err = -errno;
diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h
index 4630080e53..ca96b9cf2f 100644
--- a/hw/9pfs/virtio-9p-coth.h
+++ b/hw/9pfs/virtio-9p-coth.h
@@ -101,4 +101,7 @@ extern int v9fs_co_preadv(V9fsPDU *, V9fsFidState *,
                           struct iovec *, int, int64_t);
 extern int v9fs_co_name_to_path(V9fsPDU *, V9fsPath *,
                                 const char *, V9fsPath *);
+extern int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t,
+                          V9fsStatDotl *v9stat);
+
 #endif
diff --git a/hw/9pfs/virtio-9p-debug.c b/hw/9pfs/virtio-9p-debug.c
deleted file mode 100644
index 96925f04a4..0000000000
--- a/hw/9pfs/virtio-9p-debug.c
+++ /dev/null
@@ -1,646 +0,0 @@
-/*
- * Virtio 9p PDU debug
- *
- * Copyright IBM, Corp. 2010
- *
- * Authors:
- *  Anthony Liguori   <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2.  See
- * the COPYING file in the top-level directory.
- *
- */
-
-#include "hw/virtio.h"
-#include "hw/pc.h"
-#include "virtio-9p.h"
-#include "virtio-9p-debug.h"
-
-#define BUG_ON(cond) assert(!(cond))
-
-static FILE *llogfile;
-
-static struct iovec *get_sg(V9fsPDU *pdu, int rx)
-{
-    if (rx) {
-        return pdu->elem.in_sg;
-    }
-    return pdu->elem.out_sg;
-}
-
-static int get_sg_count(V9fsPDU *pdu, int rx)
-{
-    if (rx) {
-        return pdu->elem.in_num;
-    }
-    return pdu->elem.out_num;
-
-}
-
-static void pprint_int8(V9fsPDU *pdu, int rx, size_t *offsetp,
-                        const char *name)
-{
-    size_t copied;
-    int count = get_sg_count(pdu, rx);
-    size_t offset = *offsetp;
-    struct iovec *sg = get_sg(pdu, rx);
-    int8_t value;
-
-    copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
-
-    BUG_ON(copied != sizeof(value));
-    offset += sizeof(value);
-    fprintf(llogfile, "%s=0x%x", name, value);
-    *offsetp = offset;
-}
-
-static void pprint_int16(V9fsPDU *pdu, int rx, size_t *offsetp,
-                        const char *name)
-{
-    size_t copied;
-    int count = get_sg_count(pdu, rx);
-    struct iovec *sg = get_sg(pdu, rx);
-    size_t offset = *offsetp;
-    int16_t value;
-
-
-    copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
-
-    BUG_ON(copied != sizeof(value));
-    offset += sizeof(value);
-    fprintf(llogfile, "%s=0x%x", name, value);
-    *offsetp = offset;
-}
-
-static void pprint_int32(V9fsPDU *pdu, int rx, size_t *offsetp,
-                        const char *name)
-{
-    size_t copied;
-    int count = get_sg_count(pdu, rx);
-    struct iovec *sg = get_sg(pdu, rx);
-    size_t offset = *offsetp;
-    int32_t value;
-
-
-    copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
-
-    BUG_ON(copied != sizeof(value));
-    offset += sizeof(value);
-    fprintf(llogfile, "%s=0x%x", name, value);
-    *offsetp = offset;
-}
-
-static void pprint_int64(V9fsPDU *pdu, int rx, size_t *offsetp,
-                        const char *name)
-{
-    size_t copied;
-    int count = get_sg_count(pdu, rx);
-    struct iovec *sg = get_sg(pdu, rx);
-    size_t offset = *offsetp;
-    int64_t value;
-
-
-    copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
-
-    BUG_ON(copied != sizeof(value));
-    offset += sizeof(value);
-    fprintf(llogfile, "%s=0x%" PRIx64, name, value);
-    *offsetp = offset;
-}
-
-static void pprint_str(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
-{
-    int sg_count = get_sg_count(pdu, rx);
-    struct iovec *sg = get_sg(pdu, rx);
-    size_t offset = *offsetp;
-    uint16_t tmp_size, size;
-    size_t result;
-    size_t copied = 0;
-    int i = 0;
-
-    /* get the size */
-    copied = do_pdu_unpack(&tmp_size, sg, sg_count, offset, sizeof(tmp_size));
-    BUG_ON(copied != sizeof(tmp_size));
-    size = le16_to_cpupu(&tmp_size);
-    offset += copied;
-
-    fprintf(llogfile, "%s=", name);
-    for (i = 0; size && i < sg_count; i++) {
-        size_t len;
-        if (offset >= sg[i].iov_len) {
-            /* skip this sg */
-            offset -= sg[i].iov_len;
-            continue;
-        } else {
-            len = MIN(sg[i].iov_len - offset, size);
-            result = fwrite(sg[i].iov_base + offset, 1, len, llogfile);
-            BUG_ON(result != len);
-            size -= len;
-            copied += len;
-            if (size) {
-                offset = 0;
-                continue;
-            }
-        }
-    }
-    *offsetp += copied;
-}
-
-static void pprint_qid(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
-{
-    fprintf(llogfile, "%s={", name);
-    pprint_int8(pdu, rx, offsetp, "type");
-    pprint_int32(pdu, rx, offsetp, ", version");
-    pprint_int64(pdu, rx, offsetp, ", path");
-    fprintf(llogfile, "}");
-}
-
-static void pprint_stat(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
-{
-    fprintf(llogfile, "%s={", name);
-    pprint_int16(pdu, rx, offsetp, "size");
-    pprint_int16(pdu, rx, offsetp, ", type");
-    pprint_int32(pdu, rx, offsetp, ", dev");
-    pprint_qid(pdu, rx, offsetp, ", qid");
-    pprint_int32(pdu, rx, offsetp, ", mode");
-    pprint_int32(pdu, rx, offsetp, ", atime");
-    pprint_int32(pdu, rx, offsetp, ", mtime");
-    pprint_int64(pdu, rx, offsetp, ", length");
-    pprint_str(pdu, rx, offsetp, ", name");
-    pprint_str(pdu, rx, offsetp, ", uid");
-    pprint_str(pdu, rx, offsetp, ", gid");
-    pprint_str(pdu, rx, offsetp, ", muid");
-    pprint_str(pdu, rx, offsetp, ", extension");
-    pprint_int32(pdu, rx, offsetp, ", uid");
-    pprint_int32(pdu, rx, offsetp, ", gid");
-    pprint_int32(pdu, rx, offsetp, ", muid");
-    fprintf(llogfile, "}");
-}
-
-static void pprint_stat_dotl(V9fsPDU *pdu, int rx, size_t *offsetp,
-                                                  const char *name)
-{
-    fprintf(llogfile, "%s={", name);
-    pprint_qid(pdu, rx, offsetp, "qid");
-    pprint_int32(pdu, rx, offsetp, ", st_mode");
-    pprint_int64(pdu, rx, offsetp, ", st_nlink");
-    pprint_int32(pdu, rx, offsetp, ", st_uid");
-    pprint_int32(pdu, rx, offsetp, ", st_gid");
-    pprint_int64(pdu, rx, offsetp, ", st_rdev");
-    pprint_int64(pdu, rx, offsetp, ", st_size");
-    pprint_int64(pdu, rx, offsetp, ", st_blksize");
-    pprint_int64(pdu, rx, offsetp, ", st_blocks");
-    pprint_int64(pdu, rx, offsetp, ", atime");
-    pprint_int64(pdu, rx, offsetp, ", atime_nsec");
-    pprint_int64(pdu, rx, offsetp, ", mtime");
-    pprint_int64(pdu, rx, offsetp, ", mtime_nsec");
-    pprint_int64(pdu, rx, offsetp, ", ctime");
-    pprint_int64(pdu, rx, offsetp, ", ctime_nsec");
-    fprintf(llogfile, "}");
-}
-
-
-
-static void pprint_strs(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
-{
-    int sg_count = get_sg_count(pdu, rx);
-    struct iovec *sg = get_sg(pdu, rx);
-    size_t offset = *offsetp;
-    uint16_t tmp_count, count, i;
-    size_t copied = 0;
-
-    fprintf(llogfile, "%s={", name);
-
-    /* Get the count */
-    copied = do_pdu_unpack(&tmp_count, sg, sg_count, offset, sizeof(tmp_count));
-    BUG_ON(copied != sizeof(tmp_count));
-    count = le16_to_cpupu(&tmp_count);
-    offset += copied;
-
-    for (i = 0; i < count; i++) {
-        char str[512];
-        if (i) {
-            fprintf(llogfile, ", ");
-        }
-        snprintf(str, sizeof(str), "[%d]", i);
-        pprint_str(pdu, rx, &offset, str);
-    }
-
-    fprintf(llogfile, "}");
-
-    *offsetp = offset;
-}
-
-static void pprint_qids(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
-{
-    int sg_count = get_sg_count(pdu, rx);
-    struct iovec *sg = get_sg(pdu, rx);
-    size_t offset = *offsetp;
-    uint16_t tmp_count, count, i;
-    size_t copied = 0;
-
-    fprintf(llogfile, "%s={", name);
-
-    copied = do_pdu_unpack(&tmp_count, sg, sg_count, offset, sizeof(tmp_count));
-    BUG_ON(copied != sizeof(tmp_count));
-    count = le16_to_cpupu(&tmp_count);
-    offset += copied;
-
-    for (i = 0; i < count; i++) {
-        char str[512];
-        if (i) {
-            fprintf(llogfile, ", ");
-        }
-        snprintf(str, sizeof(str), "[%d]", i);
-        pprint_qid(pdu, rx, &offset, str);
-    }
-
-    fprintf(llogfile, "}");
-
-    *offsetp = offset;
-}
-
-static void pprint_sg(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
-{
-    struct iovec *sg = get_sg(pdu, rx);
-    unsigned int count;
-    int i;
-
-    if (rx) {
-        count = pdu->elem.in_num;
-    } else {
-        count = pdu->elem.out_num;
-    }
-
-    fprintf(llogfile, "%s={", name);
-    for (i = 0; i < count; i++) {
-        if (i) {
-            fprintf(llogfile, ", ");
-        }
-        fprintf(llogfile, "(%p, 0x%zx)", sg[i].iov_base, sg[i].iov_len);
-    }
-    fprintf(llogfile, "}");
-}
-
-/* FIXME: read from a directory fid returns serialized stat_t's */
-#ifdef DEBUG_DATA
-static void pprint_data(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
-{
-    struct iovec *sg = get_sg(pdu, rx);
-    size_t offset = *offsetp;
-    unsigned int count;
-    int32_t size;
-    int total, i, j;
-    ssize_t len;
-
-    if (rx) {
-        count = pdu->elem.in_num;
-    } else {
-        count = pdu->elem.out_num;
-    }
-
-    BUG_ON((offset + sizeof(size)) > sg[0].iov_len);
-
-    memcpy(&size, sg[0].iov_base + offset, sizeof(size));
-    offset += sizeof(size);
-
-    fprintf(llogfile, "size: %x\n", size);
-
-    sg[0].iov_base += 11; /* skip header */
-    sg[0].iov_len -= 11;
-
-    total = 0;
-    for (i = 0; i < count; i++) {
-        total += sg[i].iov_len;
-        if (total >= size) {
-            /* trim sg list so writev does the right thing */
-            sg[i].iov_len -= (total - size);
-            i++;
-            break;
-        }
-    }
-
-    fprintf(llogfile, "%s={\"", name);
-    fflush(llogfile);
-    for (j = 0; j < i; j++) {
-        if (j) {
-            fprintf(llogfile, "\", \"");
-            fflush(llogfile);
-        }
-
-        do {
-            len = writev(fileno(llogfile), &sg[j], 1);
-        } while (len == -1 && errno == EINTR);
-        fprintf(llogfile, "len == %ld: %m\n", len);
-        BUG_ON(len != sg[j].iov_len);
-    }
-    fprintf(llogfile, "\"}");
-
-    sg[0].iov_base -= 11;
-    sg[0].iov_len += 11;
-
-}
-#endif
-
-void pprint_pdu(V9fsPDU *pdu)
-{
-    size_t offset = 7;
-
-    if (llogfile == NULL) {
-        llogfile = fopen("/tmp/pdu.log", "w");
-    }
-
-    BUG_ON(!llogfile);
-
-    switch (pdu->id) {
-    case P9_TREADDIR:
-        fprintf(llogfile, "TREADDIR: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        pprint_int64(pdu, 0, &offset, ", initial offset");
-        pprint_int32(pdu, 0, &offset, ", max count");
-        break;
-    case P9_RREADDIR:
-        fprintf(llogfile, "RREADDIR: (");
-        pprint_int32(pdu, 1, &offset, "count");
-#ifdef DEBUG_DATA
-        pprint_data(pdu, 1, &offset, ", data");
-#endif
-        break;
-    case P9_TMKDIR:
-        fprintf(llogfile, "TMKDIR: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        pprint_str(pdu, 0, &offset, "name");
-        pprint_int32(pdu, 0, &offset, "mode");
-        pprint_int32(pdu, 0, &offset, "gid");
-        break;
-    case P9_RMKDIR:
-        fprintf(llogfile, "RMKDIR: (");
-        pprint_qid(pdu, 0, &offset, "qid");
-        break;
-    case P9_TVERSION:
-        fprintf(llogfile, "TVERSION: (");
-        pprint_int32(pdu, 0, &offset, "msize");
-        pprint_str(pdu, 0, &offset, ", version");
-        break;
-    case P9_RVERSION:
-        fprintf(llogfile, "RVERSION: (");
-        pprint_int32(pdu, 1, &offset, "msize");
-        pprint_str(pdu, 1, &offset, ", version");
-        break;
-    case P9_TGETATTR:
-        fprintf(llogfile, "TGETATTR: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        break;
-    case P9_RGETATTR:
-        fprintf(llogfile, "RGETATTR: (");
-        pprint_stat_dotl(pdu, 1, &offset, "getattr");
-        break;
-    case P9_TAUTH:
-        fprintf(llogfile, "TAUTH: (");
-        pprint_int32(pdu, 0, &offset, "afid");
-        pprint_str(pdu, 0, &offset, ", uname");
-        pprint_str(pdu, 0, &offset, ", aname");
-        pprint_int32(pdu, 0, &offset, ", n_uname");
-        break;
-    case P9_RAUTH:
-        fprintf(llogfile, "RAUTH: (");
-        pprint_qid(pdu, 1, &offset, "qid");
-        break;
-    case P9_TATTACH:
-        fprintf(llogfile, "TATTACH: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        pprint_int32(pdu, 0, &offset, ", afid");
-        pprint_str(pdu, 0, &offset, ", uname");
-        pprint_str(pdu, 0, &offset, ", aname");
-        pprint_int32(pdu, 0, &offset, ", n_uname");
-        break;
-    case P9_RATTACH:
-        fprintf(llogfile, "RATTACH: (");
-        pprint_qid(pdu, 1, &offset, "qid");
-        break;
-    case P9_TERROR:
-        fprintf(llogfile, "TERROR: (");
-        break;
-    case P9_RERROR:
-        fprintf(llogfile, "RERROR: (");
-        pprint_str(pdu, 1, &offset, "ename");
-        pprint_int32(pdu, 1, &offset, ", ecode");
-        break;
-    case P9_TFLUSH:
-        fprintf(llogfile, "TFLUSH: (");
-        pprint_int16(pdu, 0, &offset, "oldtag");
-        break;
-    case P9_RFLUSH:
-        fprintf(llogfile, "RFLUSH: (");
-        break;
-    case P9_TWALK:
-        fprintf(llogfile, "TWALK: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        pprint_int32(pdu, 0, &offset, ", newfid");
-        pprint_strs(pdu, 0, &offset, ", wnames");
-        break;
-    case P9_RWALK:
-        fprintf(llogfile, "RWALK: (");
-        pprint_qids(pdu, 1, &offset, "wqids");
-        break;
-    case P9_TOPEN:
-        fprintf(llogfile, "TOPEN: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        pprint_int8(pdu, 0, &offset, ", mode");
-        break;
-    case P9_ROPEN:
-        fprintf(llogfile, "ROPEN: (");
-        pprint_qid(pdu, 1, &offset, "qid");
-        pprint_int32(pdu, 1, &offset, ", iounit");
-        break;
-    case P9_TCREATE:
-        fprintf(llogfile, "TCREATE: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        pprint_str(pdu, 0, &offset, ", name");
-        pprint_int32(pdu, 0, &offset, ", perm");
-        pprint_int8(pdu, 0, &offset, ", mode");
-        pprint_str(pdu, 0, &offset, ", extension");
-        break;
-    case P9_RCREATE:
-        fprintf(llogfile, "RCREATE: (");
-        pprint_qid(pdu, 1, &offset, "qid");
-        pprint_int32(pdu, 1, &offset, ", iounit");
-        break;
-    case P9_TSYMLINK:
-        fprintf(llogfile, "TSYMLINK: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        pprint_str(pdu, 0, &offset, ", name");
-        pprint_str(pdu, 0, &offset, ", symname");
-        pprint_int32(pdu, 0, &offset, ", gid");
-        break;
-    case P9_RSYMLINK:
-        fprintf(llogfile, "RSYMLINK: (");
-        pprint_qid(pdu, 1, &offset, "qid");
-        break;
-    case P9_TLCREATE:
-        fprintf(llogfile, "TLCREATE: (");
-        pprint_int32(pdu, 0, &offset, "dfid");
-        pprint_str(pdu, 0, &offset, ", name");
-        pprint_int32(pdu, 0, &offset, ", flags");
-        pprint_int32(pdu, 0, &offset, ", mode");
-        pprint_int32(pdu, 0, &offset, ", gid");
-        break;
-    case P9_RLCREATE:
-        fprintf(llogfile, "RLCREATE: (");
-        pprint_qid(pdu, 1, &offset, "qid");
-        pprint_int32(pdu, 1, &offset, ", iounit");
-        break;
-    case P9_TMKNOD:
-	fprintf(llogfile, "TMKNOD: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        pprint_str(pdu, 0, &offset, "name");
-        pprint_int32(pdu, 0, &offset, "mode");
-        pprint_int32(pdu, 0, &offset, "major");
-        pprint_int32(pdu, 0, &offset, "minor");
-        pprint_int32(pdu, 0, &offset, "gid");
-        break;
-    case P9_RMKNOD:
-        fprintf(llogfile, "RMKNOD: )");
-        pprint_qid(pdu, 0, &offset, "qid");
-        break;
-    case P9_TREADLINK:
-	fprintf(llogfile, "TREADLINK: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        break;
-    case P9_RREADLINK:
-	fprintf(llogfile, "RREADLINK: (");
-        pprint_str(pdu, 0, &offset, "target");
-        break;
-    case P9_TREAD:
-        fprintf(llogfile, "TREAD: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        pprint_int64(pdu, 0, &offset, ", offset");
-        pprint_int32(pdu, 0, &offset, ", count");
-        pprint_sg(pdu, 0, &offset, ", sg");
-        break;
-    case P9_RREAD:
-        fprintf(llogfile, "RREAD: (");
-        pprint_int32(pdu, 1, &offset, "count");
-        pprint_sg(pdu, 1, &offset, ", sg");
-        offset = 7;
-#ifdef DEBUG_DATA
-        pprint_data(pdu, 1, &offset, ", data");
-#endif
-        break;
-    case P9_TWRITE:
-        fprintf(llogfile, "TWRITE: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        pprint_int64(pdu, 0, &offset, ", offset");
-        pprint_int32(pdu, 0, &offset, ", count");
-        break;
-    case P9_RWRITE:
-        fprintf(llogfile, "RWRITE: (");
-        pprint_int32(pdu, 1, &offset, "count");
-        break;
-    case P9_TCLUNK:
-        fprintf(llogfile, "TCLUNK: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        break;
-    case P9_RCLUNK:
-        fprintf(llogfile, "RCLUNK: (");
-        break;
-    case P9_TFSYNC:
-        fprintf(llogfile, "TFSYNC: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        break;
-    case P9_RFSYNC:
-        fprintf(llogfile, "RFSYNC: (");
-        break;
-    case P9_TLINK:
-        fprintf(llogfile, "TLINK: (");
-        pprint_int32(pdu, 0, &offset, "dfid");
-        pprint_int32(pdu, 0, &offset, ", fid");
-        pprint_str(pdu, 0, &offset, ", newpath");
-        break;
-    case P9_RLINK:
-        fprintf(llogfile, "RLINK: (");
-        break;
-    case P9_TREMOVE:
-        fprintf(llogfile, "TREMOVE: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        break;
-    case P9_RREMOVE:
-        fprintf(llogfile, "RREMOVE: (");
-        break;
-    case P9_TSTAT:
-        fprintf(llogfile, "TSTAT: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        break;
-    case P9_RSTAT:
-        fprintf(llogfile, "RSTAT: (");
-        offset += 2; /* ignored */
-        pprint_stat(pdu, 1, &offset, "stat");
-        break;
-    case P9_TWSTAT:
-        fprintf(llogfile, "TWSTAT: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        offset += 2; /* ignored */
-        pprint_stat(pdu, 0, &offset, ", stat");
-        break;
-    case P9_RWSTAT:
-        fprintf(llogfile, "RWSTAT: (");
-        break;
-    case P9_TXATTRWALK:
-        fprintf(llogfile, "TXATTRWALK: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        pprint_int32(pdu, 0, &offset, ", newfid");
-        pprint_str(pdu, 0, &offset, ", xattr name");
-        break;
-    case P9_RXATTRWALK:
-        fprintf(llogfile, "RXATTRWALK: (");
-        pprint_int64(pdu, 1, &offset, "xattrsize");
-    case P9_TXATTRCREATE:
-        fprintf(llogfile, "TXATTRCREATE: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        pprint_str(pdu, 0, &offset, ", name");
-        pprint_int64(pdu, 0, &offset, ", xattrsize");
-        pprint_int32(pdu, 0, &offset, ", flags");
-        break;
-    case P9_RXATTRCREATE:
-        fprintf(llogfile, "RXATTRCREATE: (");
-        break;
-    case P9_TLOCK:
-        fprintf(llogfile, "TLOCK: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        pprint_int8(pdu, 0, &offset, ", type");
-        pprint_int32(pdu, 0, &offset, ", flags");
-        pprint_int64(pdu, 0, &offset, ", start");
-        pprint_int64(pdu, 0, &offset, ", length");
-        pprint_int32(pdu, 0, &offset, ", proc_id");
-        pprint_str(pdu, 0, &offset, ", client_id");
-        break;
-    case P9_RLOCK:
-        fprintf(llogfile, "RLOCK: (");
-        pprint_int8(pdu, 0, &offset, "status");
-        break;
-    case P9_TGETLOCK:
-        fprintf(llogfile, "TGETLOCK: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        pprint_int8(pdu, 0, &offset, ", type");
-        pprint_int64(pdu, 0, &offset, ", start");
-        pprint_int64(pdu, 0, &offset, ", length");
-        pprint_int32(pdu, 0, &offset, ", proc_id");
-        pprint_str(pdu, 0, &offset, ", client_id");
-        break;
-    case P9_RGETLOCK:
-        fprintf(llogfile, "RGETLOCK: (");
-        pprint_int8(pdu, 0, &offset, "type");
-        pprint_int64(pdu, 0, &offset, ", start");
-        pprint_int64(pdu, 0, &offset, ", length");
-        pprint_int32(pdu, 0, &offset, ", proc_id");
-        pprint_str(pdu, 0, &offset, ", client_id");
-        break;
-    default:
-        fprintf(llogfile, "unknown(%d): (", pdu->id);
-        break;
-    }
-
-    fprintf(llogfile, ")\n");
-    /* Flush the log message out */
-    fflush(llogfile);
-}
diff --git a/hw/9pfs/virtio-9p-debug.h b/hw/9pfs/virtio-9p-debug.h
deleted file mode 100644
index d9a249118d..0000000000
--- a/hw/9pfs/virtio-9p-debug.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _QEMU_VIRTIO_9P_DEBUG_H
-#define _QEMU_VIRTIO_9P_DEBUG_H
-
-void pprint_pdu(V9fsPDU *pdu);
-
-#endif
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 513e181c82..bba4c54762 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -49,7 +49,8 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
     V9fsState *s;
     int i, len;
     struct stat stat;
-    FsTypeEntry *fse;
+    FsDriverEntry *fse;
+    V9fsPath path;
 
     s = (V9fsState *)virtio_common_init("virtio-9p",
                                     VIRTIO_ID_9P,
@@ -82,55 +83,33 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
         exit(1);
     }
 
-    if (!strcmp(fse->security_model, "passthrough")) {
-        /* Files on the Fileserver set to client user credentials */
-        s->ctx.fs_sm = SM_PASSTHROUGH;
+    s->ctx.export_flags = fse->export_flags;
+    s->ctx.fs_root = g_strdup(fse->path);
+    s->ctx.exops.get_st_gen = NULL;
+
+    if (fse->export_flags & V9FS_SM_PASSTHROUGH) {
         s->ctx.xops = passthrough_xattr_ops;
-    } else if (!strcmp(fse->security_model, "mapped")) {
-        /* Files on the fileserver are set to QEMU credentials.
-         * Client user credentials are saved in extended attributes.
-         */
-        s->ctx.fs_sm = SM_MAPPED;
+    } else if (fse->export_flags & V9FS_SM_MAPPED) {
         s->ctx.xops = mapped_xattr_ops;
-    } else if (!strcmp(fse->security_model, "none")) {
-        /*
-         * Files on the fileserver are set to QEMU credentials.
-         */
-        s->ctx.fs_sm = SM_NONE;
-        s->ctx.xops = none_xattr_ops;
-    } else {
-        fprintf(stderr, "Default to security_model=none. You may want"
-                " enable advanced security model using "
-                "security option:\n\t security_model=passthrough\n\t "
-                "security_model=mapped\n");
-        s->ctx.fs_sm = SM_NONE;
+    } else if (fse->export_flags & V9FS_SM_NONE) {
         s->ctx.xops = none_xattr_ops;
     }
 
-    if (lstat(fse->path, &stat)) {
-        fprintf(stderr, "share path %s does not exist\n", fse->path);
-        exit(1);
-    } else if (!S_ISDIR(stat.st_mode)) {
-        fprintf(stderr, "share path %s is not a directory\n", fse->path);
-        exit(1);
-    }
-
-    s->ctx.fs_root = g_strdup(fse->path);
     len = strlen(conf->tag);
     if (len > MAX_TAG_LEN) {
-        len = MAX_TAG_LEN;
+        fprintf(stderr, "mount tag '%s' (%d bytes) is longer than "
+                "maximum (%d bytes)", conf->tag, len, MAX_TAG_LEN);
+        exit(1);
     }
     /* s->tag is non-NULL terminated string */
     s->tag = g_malloc(len);
     memcpy(s->tag, conf->tag, len);
     s->tag_len = len;
     s->ctx.uid = -1;
-    s->ctx.flags = 0;
 
     s->ops = fse->ops;
     s->vdev.get_features = virtio_9p_get_features;
-    s->config_size = sizeof(struct virtio_9p_config) +
-                        s->tag_len;
+    s->config_size = sizeof(struct virtio_9p_config) + s->tag_len;
     s->vdev.get_config = virtio_9p_get_config;
     s->fid_list = NULL;
     qemu_co_rwlock_init(&s->rename_lock);
@@ -144,6 +123,27 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
         fprintf(stderr, "worker thread initialization failed\n");
         exit(1);
     }
+
+    /*
+     * Check details of export path, We need to use fs driver
+     * call back to do that. Since we are in the init path, we don't
+     * use co-routines here.
+     */
+    v9fs_path_init(&path);
+    if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) {
+        fprintf(stderr,
+                "error in converting name to path %s", strerror(errno));
+        exit(1);
+    }
+    if (s->ops->lstat(&s->ctx, &path, &stat)) {
+        fprintf(stderr, "share path %s does not exist\n", fse->path);
+        exit(1);
+    } else if (!S_ISDIR(stat.st_mode)) {
+        fprintf(stderr, "share path %s is not a directory\n", fse->path);
+        exit(1);
+    }
+    v9fs_path_free(&path);
+
     return &s->vdev;
 }
 
@@ -169,6 +169,8 @@ static PCIDeviceInfo virtio_9p_info = {
     .revision  = VIRTIO_PCI_ABI_VERSION,
     .class_id  = 0x2,
     .qdev.props = (Property[]) {
+        DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
+                        VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
         DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
         DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
         DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c
index 5c8b5ed471..98809f1642 100644
--- a/hw/9pfs/virtio-9p-handle.c
+++ b/hw/9pfs/virtio-9p-handle.c
@@ -21,49 +21,56 @@
 #include <sys/un.h>
 #include <attr/xattr.h>
 #include <unistd.h>
-
-struct handle_data {
-    int mountfd;
-    int handle_bytes;
-};
-
-#if __GLIBC__ <= 2 && __GLIBC_MINOR__ < 14
-struct file_handle {
-        unsigned int handle_bytes;
-        int handle_type;
-        unsigned char handle[0];
-};
+#include <linux/fs.h>
+#ifdef CONFIG_LINUX_MAGIC_H
+#include <linux/magic.h>
 #endif
+#include <sys/ioctl.h>
 
-#ifndef AT_EMPTY_PATH
-#define AT_EMPTY_PATH   0x1000  /* Allow empty relative pathname */
+#ifndef XFS_SUPER_MAGIC
+#define XFS_SUPER_MAGIC  0x58465342
 #endif
-#ifndef O_PATH
-#define O_PATH    010000000
+#ifndef EXT2_SUPER_MAGIC
+#define EXT2_SUPER_MAGIC 0xEF53
 #endif
-
-#ifndef __NR_name_to_handle_at
-#if defined(__i386__)
-#define __NR_name_to_handle_at  341
-#define __NR_open_by_handle_at  342
-#elif defined(__x86_64__)
-#define __NR_name_to_handle_at  303
-#define __NR_open_by_handle_at  304
+#ifndef REISERFS_SUPER_MAGIC
+#define REISERFS_SUPER_MAGIC 0x52654973
 #endif
+#ifndef BTRFS_SUPER_MAGIC
+#define BTRFS_SUPER_MAGIC 0x9123683E
 #endif
 
-#ifdef __NR_name_to_handle_at
+struct handle_data {
+    int mountfd;
+    int handle_bytes;
+};
+
+#ifdef CONFIG_OPEN_BY_HANDLE
 static inline int name_to_handle(int dirfd, const char *name,
                                  struct file_handle *fh, int *mnt_id, int flags)
 {
-    return syscall(__NR_name_to_handle_at, dirfd, name, fh, mnt_id, flags);
+    return name_to_handle_at(dirfd, name, fh, mnt_id, flags);
 }
 
 static inline int open_by_handle(int mountfd, const char *fh, int flags)
 {
-    return syscall(__NR_open_by_handle_at, mountfd, fh, flags);
+    return open_by_handle_at(mountfd, (struct file_handle *)fh, flags);
 }
 #else
+
+struct file_handle {
+    unsigned int handle_bytes;
+    int handle_type;
+    unsigned char handle[0];
+};
+
+#ifndef AT_EMPTY_PATH
+#define AT_EMPTY_PATH   0x1000  /* Allow empty relative pathname */
+#endif
+#ifndef O_PATH
+#define O_PATH    010000000
+#endif
+
 static inline int name_to_handle(int dirfd, const char *name,
                                  struct file_handle *fh, int *mnt_id, int flags)
 {
@@ -192,16 +199,29 @@ static ssize_t handle_preadv(FsContext *ctx, int fd, const struct iovec *iov,
 static ssize_t handle_pwritev(FsContext *ctx, int fd, const struct iovec *iov,
                               int iovcnt, off_t offset)
 {
+    ssize_t ret;
 #ifdef CONFIG_PREADV
-    return pwritev(fd, iov, iovcnt, offset);
+    ret = pwritev(fd, iov, iovcnt, offset);
 #else
     int err = lseek(fd, offset, SEEK_SET);
     if (err == -1) {
         return err;
     } else {
-        return writev(fd, iov, iovcnt);
+        ret = writev(fd, iov, iovcnt);
     }
 #endif
+#ifdef CONFIG_SYNC_FILE_RANGE
+    if (ret > 0 && ctx->export_flags & V9FS_IMMEDIATE_WRITEOUT) {
+        /*
+         * Initiate a writeback. This is not a data integrity sync.
+         * We want to ensure that we don't leave dirty pages in the cache
+         * after write when writeout=immediate is sepcified.
+         */
+        sync_file_range(fd, offset, ret,
+                        SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE);
+    }
+#endif
+    return ret;
 }
 
 static int handle_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
@@ -367,7 +387,9 @@ static int handle_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
 static int handle_utimensat(FsContext *ctx, V9fsPath *fs_path,
                             const struct timespec *buf)
 {
-    int fd, ret;
+    int ret;
+#ifdef CONFIG_UTIMENSAT
+    int fd;
     struct handle_data *data = (struct handle_data *)ctx->private;
 
     fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
@@ -376,6 +398,10 @@ static int handle_utimensat(FsContext *ctx, V9fsPath *fs_path,
     }
     ret = futimens(fd, buf);
     close(fd);
+#else
+    ret = -1;
+    errno = ENOSYS;
+#endif
     return ret;
 }
 
@@ -546,16 +572,50 @@ static int handle_unlinkat(FsContext *ctx, V9fsPath *dir,
     return ret;
 }
 
+static int handle_ioc_getversion(FsContext *ctx, V9fsPath *path,
+                                 mode_t st_mode, uint64_t *st_gen)
+{
+    int err, fd;
+
+    /*
+     * Do not try to open special files like device nodes, fifos etc
+     * We can get fd for regular files and directories only
+     */
+    if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) {
+            return 0;
+    }
+    fd = handle_open(ctx, path, O_RDONLY);
+    if (fd < 0) {
+        return fd;
+    }
+    err = ioctl(fd, FS_IOC_GETVERSION, st_gen);
+    handle_close(ctx, fd);
+    return err;
+}
+
 static int handle_init(FsContext *ctx)
 {
     int ret, mnt_id;
+    struct statfs stbuf;
     struct file_handle fh;
     struct handle_data *data = g_malloc(sizeof(struct handle_data));
+
     data->mountfd = open(ctx->fs_root, O_DIRECTORY);
     if (data->mountfd < 0) {
         ret = data->mountfd;
         goto err_out;
     }
+    ret = statfs(ctx->fs_root, &stbuf);
+    if (!ret) {
+        switch (stbuf.f_type) {
+        case EXT2_SUPER_MAGIC:
+        case BTRFS_SUPER_MAGIC:
+        case REISERFS_SUPER_MAGIC:
+        case XFS_SUPER_MAGIC:
+            ctx->exops.get_st_gen = handle_ioc_getversion;
+            break;
+        }
+    }
     memset(&fh, 0, sizeof(struct file_handle));
     ret = name_to_handle(data->mountfd, ".", &fh, &mnt_id, 0);
     if (ret && errno == EOVERFLOW) {
diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index 9559ff6550..d561de88f0 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -20,6 +20,24 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <attr/xattr.h>
+#include <linux/fs.h>
+#ifdef CONFIG_LINUX_MAGIC_H
+#include <linux/magic.h>
+#endif
+#include <sys/ioctl.h>
+
+#ifndef XFS_SUPER_MAGIC
+#define XFS_SUPER_MAGIC  0x58465342
+#endif
+#ifndef EXT2_SUPER_MAGIC
+#define EXT2_SUPER_MAGIC 0xEF53
+#endif
+#ifndef REISERFS_SUPER_MAGIC
+#define REISERFS_SUPER_MAGIC 0x52654973
+#endif
+#ifndef BTRFS_SUPER_MAGIC
+#define BTRFS_SUPER_MAGIC 0x9123683E
+#endif
 
 static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
 {
@@ -31,7 +49,7 @@ static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
     if (err) {
         return err;
     }
-    if (fs_ctx->fs_sm == SM_MAPPED) {
+    if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
         /* Actual credentials are part of extended attrs */
         uid_t tmp_uid;
         gid_t tmp_gid;
@@ -106,7 +124,7 @@ static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
          * If we fail to change ownership and if we are
          * using security model none. Ignore the error
          */
-        if (fs_ctx->fs_sm != SM_NONE) {
+        if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) {
             return -1;
         }
     }
@@ -120,7 +138,7 @@ static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
     char buffer[PATH_MAX];
     char *path = fs_path->data;
 
-    if (fs_ctx->fs_sm == SM_MAPPED) {
+    if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
         int fd;
         fd = open(rpath(fs_ctx, path, buffer), O_RDONLY);
         if (fd == -1) {
@@ -131,8 +149,8 @@ static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
         } while (tsize == -1 && errno == EINTR);
         close(fd);
         return tsize;
-    } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
-               (fs_ctx->fs_sm == SM_NONE)) {
+    } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
+               (fs_ctx->export_flags & V9FS_SM_NONE)) {
         tsize = readlink(rpath(fs_ctx, path, buffer), buf, bufsz);
     }
     return tsize;
@@ -203,16 +221,30 @@ static ssize_t local_preadv(FsContext *ctx, int fd, const struct iovec *iov,
 static ssize_t local_pwritev(FsContext *ctx, int fd, const struct iovec *iov,
                              int iovcnt, off_t offset)
 {
+    ssize_t ret
+;
 #ifdef CONFIG_PREADV
-    return pwritev(fd, iov, iovcnt, offset);
+    ret = pwritev(fd, iov, iovcnt, offset);
 #else
     int err = lseek(fd, offset, SEEK_SET);
     if (err == -1) {
         return err;
     } else {
-        return writev(fd, iov, iovcnt);
+        ret = writev(fd, iov, iovcnt);
     }
 #endif
+#ifdef CONFIG_SYNC_FILE_RANGE
+    if (ret > 0 && ctx->export_flags & V9FS_IMMEDIATE_WRITEOUT) {
+        /*
+         * Initiate a writeback. This is not a data integrity sync.
+         * We want to ensure that we don't leave dirty pages in the cache
+         * after write when writeout=immediate is sepcified.
+         */
+        sync_file_range(fd, offset, ret,
+                        SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE);
+    }
+#endif
+    return ret;
 }
 
 static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
@@ -220,10 +252,10 @@ static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
     char buffer[PATH_MAX];
     char *path = fs_path->data;
 
-    if (fs_ctx->fs_sm == SM_MAPPED) {
+    if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
         return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
-    } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
-               (fs_ctx->fs_sm == SM_NONE)) {
+    } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
+               (fs_ctx->export_flags & V9FS_SM_NONE)) {
         return chmod(rpath(fs_ctx, path, buffer), credp->fc_mode);
     }
     return -1;
@@ -243,7 +275,7 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
     path = fullname.data;
 
     /* Determine the security model */
-    if (fs_ctx->fs_sm == SM_MAPPED) {
+    if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
         err = mknod(rpath(fs_ctx, path, buffer),
                 SM_LOCAL_MODE_BITS|S_IFREG, 0);
         if (err == -1) {
@@ -254,8 +286,8 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
             serrno = errno;
             goto err_end;
         }
-    } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
-               (fs_ctx->fs_sm == SM_NONE)) {
+    } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
+               (fs_ctx->export_flags & V9FS_SM_NONE)) {
         err = mknod(rpath(fs_ctx, path, buffer), credp->fc_mode,
                 credp->fc_rdev);
         if (err == -1) {
@@ -291,7 +323,7 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
     path = fullname.data;
 
     /* Determine the security model */
-    if (fs_ctx->fs_sm == SM_MAPPED) {
+    if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
         err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS);
         if (err == -1) {
             goto out;
@@ -302,8 +334,8 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
             serrno = errno;
             goto err_end;
         }
-    } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
-               (fs_ctx->fs_sm == SM_NONE)) {
+    } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
+               (fs_ctx->export_flags & V9FS_SM_NONE)) {
         err = mkdir(rpath(fs_ctx, path, buffer), credp->fc_mode);
         if (err == -1) {
             goto out;
@@ -331,7 +363,7 @@ static int local_fstat(FsContext *fs_ctx, int fd, struct stat *stbuf)
     if (err) {
         return err;
     }
-    if (fs_ctx->fs_sm == SM_MAPPED) {
+    if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
         /* Actual credentials are part of extended attrs */
         uid_t tmp_uid;
         gid_t tmp_gid;
@@ -369,7 +401,7 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
     path = fullname.data;
 
     /* Determine the security model */
-    if (fs_ctx->fs_sm == SM_MAPPED) {
+    if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
         fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS);
         if (fd == -1) {
             err = fd;
@@ -382,8 +414,8 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
             serrno = errno;
             goto err_end;
         }
-    } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
-               (fs_ctx->fs_sm == SM_NONE)) {
+    } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
+               (fs_ctx->export_flags & V9FS_SM_NONE)) {
         fd = open(rpath(fs_ctx, path, buffer), flags, credp->fc_mode);
         if (fd == -1) {
             err = fd;
@@ -422,7 +454,7 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
     newpath = fullname.data;
 
     /* Determine the security model */
-    if (fs_ctx->fs_sm == SM_MAPPED) {
+    if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
         int fd;
         ssize_t oldpath_size, write_size;
         fd = open(rpath(fs_ctx, newpath, buffer), O_CREAT|O_EXCL|O_RDWR,
@@ -451,8 +483,8 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
             serrno = errno;
             goto err_end;
         }
-    } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
-               (fs_ctx->fs_sm == SM_NONE)) {
+    } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
+               (fs_ctx->export_flags & V9FS_SM_NONE)) {
         err = symlink(oldpath, rpath(fs_ctx, newpath, buffer));
         if (err) {
             goto out;
@@ -464,7 +496,7 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
              * If we fail to change ownership and if we are
              * using security model none. Ignore the error
              */
-            if (fs_ctx->fs_sm != SM_NONE) {
+            if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) {
                 serrno = errno;
                 goto err_end;
             } else
@@ -519,13 +551,13 @@ static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
     char *path = fs_path->data;
 
     if ((credp->fc_uid == -1 && credp->fc_gid == -1) ||
-            (fs_ctx->fs_sm == SM_PASSTHROUGH)) {
+            (fs_ctx->export_flags & V9FS_SM_PASSTHROUGH)) {
         return lchown(rpath(fs_ctx, path, buffer), credp->fc_uid,
                 credp->fc_gid);
-    } else if (fs_ctx->fs_sm == SM_MAPPED) {
+    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
         return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
-    } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
-               (fs_ctx->fs_sm == SM_NONE)) {
+    } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
+               (fs_ctx->export_flags & V9FS_SM_NONE)) {
         return lchown(rpath(fs_ctx, path, buffer), credp->fc_uid,
                 credp->fc_gid);
     }
@@ -645,10 +677,44 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
     return ret;
 }
 
+static int local_ioc_getversion(FsContext *ctx, V9fsPath *path,
+                                mode_t st_mode, uint64_t *st_gen)
+{
+    int err, fd;
+    /*
+     * Do not try to open special files like device nodes, fifos etc
+     * We can get fd for regular files and directories only
+     */
+    if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) {
+            return 0;
+    }
+    fd = local_open(ctx, path, O_RDONLY);
+    if (fd < 0) {
+        return fd;
+    }
+    err = ioctl(fd, FS_IOC_GETVERSION, st_gen);
+    local_close(ctx, fd);
+    return err;
+}
+
 static int local_init(FsContext *ctx)
 {
-    ctx->flags |= PATHNAME_FSCONTEXT;
-    return 0;
+    int err;
+    struct statfs stbuf;
+
+    ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT;
+    err = statfs(ctx->fs_root, &stbuf);
+    if (!err) {
+        switch (stbuf.f_type) {
+        case EXT2_SUPER_MAGIC:
+        case BTRFS_SUPER_MAGIC:
+        case REISERFS_SUPER_MAGIC:
+        case XFS_SUPER_MAGIC:
+            ctx->exops.get_st_gen = local_ioc_getversion;
+            break;
+        }
+    }
+    return err;
 }
 
 FileOperations local_ops = {
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index c01c31aa25..aab3bebcc7 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -17,11 +17,10 @@
 #include "hw/virtio-pci.h"
 #include "virtio-9p.h"
 #include "fsdev/qemu-fsdev.h"
-#include "virtio-9p-debug.h"
 #include "virtio-9p-xattr.h"
 #include "virtio-9p-coth.h"
+#include "trace.h"
 
-int debug_9p_pdu;
 int open_fd_hw;
 int total_open_fd;
 static int open_fd_rc;
@@ -72,6 +71,55 @@ static int omode_to_uflags(int8_t mode)
     return ret;
 }
 
+static int dotl_to_at_flags(int flags)
+{
+    int rflags = 0;
+    if (flags & P9_DOTL_AT_REMOVEDIR) {
+        rflags |= AT_REMOVEDIR;
+    }
+    return rflags;
+}
+
+struct dotl_openflag_map {
+    int dotl_flag;
+    int open_flag;
+};
+
+static int dotl_to_open_flags(int flags)
+{
+    int i;
+    /*
+     * We have same bits for P9_DOTL_READONLY, P9_DOTL_WRONLY
+     * and P9_DOTL_NOACCESS
+     */
+    int oflags = flags & O_ACCMODE;
+
+    struct dotl_openflag_map dotl_oflag_map[] = {
+        { P9_DOTL_CREATE, O_CREAT },
+        { P9_DOTL_EXCL, O_EXCL },
+        { P9_DOTL_NOCTTY , O_NOCTTY },
+        { P9_DOTL_TRUNC, O_TRUNC },
+        { P9_DOTL_APPEND, O_APPEND },
+        { P9_DOTL_NONBLOCK, O_NONBLOCK } ,
+        { P9_DOTL_DSYNC, O_DSYNC },
+        { P9_DOTL_FASYNC, FASYNC },
+        { P9_DOTL_DIRECT, O_DIRECT },
+        { P9_DOTL_LARGEFILE, O_LARGEFILE },
+        { P9_DOTL_DIRECTORY, O_DIRECTORY },
+        { P9_DOTL_NOFOLLOW, O_NOFOLLOW },
+        { P9_DOTL_NOATIME, O_NOATIME },
+        { P9_DOTL_SYNC, O_SYNC },
+    };
+
+    for (i = 0; i < ARRAY_SIZE(dotl_oflag_map); i++) {
+        if (flags & dotl_oflag_map[i].dotl_flag) {
+            oflags |= dotl_oflag_map[i].open_flag;
+        }
+    }
+
+    return oflags;
+}
+
 void cred_init(FsCred *credp)
 {
     credp->fc_uid = -1;
@@ -80,6 +128,21 @@ void cred_init(FsCred *credp)
     credp->fc_rdev = -1;
 }
 
+static int get_dotl_openflags(V9fsState *s, int oflags)
+{
+    int flags;
+    /*
+     * Filter the client open flags
+     */
+    flags = dotl_to_open_flags(oflags);
+    flags &= ~(O_NOCTTY | O_ASYNC | O_CREAT);
+    /*
+     * Ignore direct disk access hint until the server supports it.
+     */
+    flags &= ~O_DIRECT;
+    return flags;
+}
+
 void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -621,9 +684,6 @@ static V9fsPDU *alloc_pdu(V9fsState *s)
 static void free_pdu(V9fsState *s, V9fsPDU *pdu)
 {
     if (pdu) {
-        if (debug_9p_pdu) {
-            pprint_pdu(pdu);
-        }
         /*
          * Cancelled pdu are added back to the freelist
          * by flush request .
@@ -909,6 +969,7 @@ static void complete_pdu(V9fsState *s, V9fsPDU *pdu, ssize_t len)
         if (s->proto_version == V9FS_PROTO_2000L) {
             id = P9_RLERROR;
         }
+        trace_complete_pdu(pdu->tag, pdu->id, err); /* Trace ERROR */
     }
 
     /* fill out the header */
@@ -1218,6 +1279,7 @@ static void v9fs_version(void *opaque)
     size_t offset = 7;
 
     pdu_unmarshal(pdu, offset, "ds", &s->msize, &version);
+    trace_v9fs_version(pdu->tag, pdu->id, s->msize, version.data);
 
     if (!strcmp(version.data, "9P2000.u")) {
         s->proto_version = V9FS_PROTO_2000U;
@@ -1228,6 +1290,8 @@ static void v9fs_version(void *opaque)
     }
 
     offset += pdu_marshal(pdu, offset, "ds", s->msize, &version);
+    trace_v9fs_version_return(pdu->tag, pdu->id, s->msize, version.data);
+
     complete_pdu(s, pdu, offset);
 
     v9fs_string_free(&version);
@@ -1246,6 +1310,7 @@ static void v9fs_attach(void *opaque)
     ssize_t err;
 
     pdu_unmarshal(pdu, offset, "ddssd", &fid, &afid, &uname, &aname, &n_uname);
+    trace_v9fs_attach(pdu->tag, pdu->id, fid, afid, uname.data, aname.data);
 
     fidp = alloc_fid(s, fid);
     if (fidp == NULL) {
@@ -1270,6 +1335,8 @@ static void v9fs_attach(void *opaque)
 out:
     put_fid(pdu, fidp);
 out_nofid:
+    trace_v9fs_attach_return(pdu->tag, pdu->id,
+                             qid.type, qid.version, qid.path);
     complete_pdu(s, pdu, err);
     v9fs_string_free(&uname);
     v9fs_string_free(&aname);
@@ -1287,6 +1354,7 @@ static void v9fs_stat(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "d", &fid);
+    trace_v9fs_stat(pdu->tag, pdu->id, fid);
 
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
@@ -1307,6 +1375,9 @@ static void v9fs_stat(void *opaque)
 out:
     put_fid(pdu, fidp);
 out_nofid:
+    trace_v9fs_stat_return(pdu->tag, pdu->id, v9stat.mode,
+                           v9stat.atime, v9stat.mtime, v9stat.length);
+
     complete_pdu(s, pdu, err);
 }
 
@@ -1323,6 +1394,7 @@ static void v9fs_getattr(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "dq", &fid, &request_mask);
+    trace_v9fs_getattr(pdu->tag, pdu->id, fid, request_mask);
 
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
@@ -1338,11 +1410,24 @@ static void v9fs_getattr(void *opaque)
         goto out;
     }
     stat_to_v9stat_dotl(s, &stbuf, &v9stat_dotl);
+
+    /*  fill st_gen if requested and supported by underlying fs */
+    if (request_mask & P9_STATS_GEN) {
+        retval = v9fs_co_st_gen(pdu, &fidp->path, stbuf.st_mode, &v9stat_dotl);
+        if (retval < 0) {
+            goto out;
+        }
+        v9stat_dotl.st_result_mask |= P9_STATS_GEN;
+    }
     retval = offset;
     retval += pdu_marshal(pdu, offset, "A", &v9stat_dotl);
 out:
     put_fid(pdu, fidp);
 out_nofid:
+    trace_v9fs_getattr_return(pdu->tag, pdu->id, v9stat_dotl.st_result_mask,
+                              v9stat_dotl.st_mode, v9stat_dotl.st_uid,
+                              v9stat_dotl.st_gid);
+
     complete_pdu(s, pdu, retval);
 }
 
@@ -1470,6 +1555,8 @@ static void v9fs_walk(void *opaque)
     offset += pdu_unmarshal(pdu, offset, "ddw", &fid,
                             &newfid, &nwnames);
 
+    trace_v9fs_walk(pdu->tag, pdu->id, fid, newfid, nwnames);
+
     if (nwnames && nwnames <= P9_MAXWELEM) {
         wnames = g_malloc0(sizeof(wnames[0]) * nwnames);
         qids   = g_malloc0(sizeof(qids[0]) * nwnames);
@@ -1526,6 +1613,7 @@ out:
     v9fs_path_free(&dpath);
     v9fs_path_free(&path);
 out_nofid:
+    trace_v9fs_walk_return(pdu->tag, pdu->id, nwnames, qids);
     complete_pdu(s, pdu, err);
     if (nwnames && nwnames <= P9_MAXWELEM) {
         for (name_idx = 0; name_idx < nwnames; name_idx++) {
@@ -1576,6 +1664,8 @@ static void v9fs_open(void *opaque)
     } else {
         pdu_unmarshal(pdu, offset, "db", &fid, &mode);
     }
+    trace_v9fs_open(pdu->tag, pdu->id, fid, mode);
+
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
         err = -ENOENT;
@@ -1598,10 +1688,7 @@ static void v9fs_open(void *opaque)
         err = offset;
     } else {
         if (s->proto_version == V9FS_PROTO_2000L) {
-            flags = mode;
-            flags &= ~(O_NOCTTY | O_ASYNC | O_CREAT);
-            /* Ignore direct disk access hint until the server supports it. */
-            flags &= ~O_DIRECT;
+            flags = get_dotl_openflags(s, mode);
         } else {
             flags = omode_to_uflags(mode);
         }
@@ -1625,6 +1712,8 @@ static void v9fs_open(void *opaque)
 out:
     put_fid(pdu, fidp);
 out_nofid:
+    trace_v9fs_open_return(pdu->tag, pdu->id,
+                           qid.type, qid.version, qid.path, iounit);
     complete_pdu(s, pdu, err);
 }
 
@@ -1643,6 +1732,7 @@ static void v9fs_lcreate(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dsddd", &dfid, &name, &flags,
                   &mode, &gid);
+    trace_v9fs_lcreate(pdu->tag, pdu->id, dfid, flags, mode, gid);
 
     fidp = get_fid(pdu, dfid);
     if (fidp == NULL) {
@@ -1650,8 +1740,7 @@ static void v9fs_lcreate(void *opaque)
         goto out_nofid;
     }
 
-    /* Ignore direct disk access hint until the server supports it. */
-    flags &= ~O_DIRECT;
+    flags = get_dotl_openflags(pdu->s, flags);
     err = v9fs_co_open2(pdu, fidp, &name, gid,
                         flags | O_CREAT, mode, &stbuf);
     if (err < 0) {
@@ -1673,6 +1762,8 @@ static void v9fs_lcreate(void *opaque)
 out:
     put_fid(pdu, fidp);
 out_nofid:
+    trace_v9fs_lcreate_return(pdu->tag, pdu->id,
+                              qid.type, qid.version, qid.path, iounit);
     complete_pdu(pdu->s, pdu, err);
     v9fs_string_free(&name);
 }
@@ -1688,6 +1779,8 @@ static void v9fs_fsync(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "dd", &fid, &datasync);
+    trace_v9fs_fsync(pdu->tag, pdu->id, fid, datasync);
+
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
         err = -ENOENT;
@@ -1712,6 +1805,7 @@ static void v9fs_clunk(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "d", &fid);
+    trace_v9fs_clunk(pdu->tag, pdu->id, fid);
 
     fidp = clunk_fid(s, fid);
     if (fidp == NULL) {
@@ -1828,6 +1922,7 @@ static void v9fs_read(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &max_count);
+    trace_v9fs_read(pdu->tag, pdu->id, fid, off, max_count);
 
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
@@ -1886,6 +1981,7 @@ static void v9fs_read(void *opaque)
 out:
     put_fid(pdu, fidp);
 out_nofid:
+    trace_v9fs_read_return(pdu->tag, pdu->id, count, err);
     complete_pdu(s, pdu, err);
 }
 
@@ -1970,6 +2066,8 @@ static void v9fs_readdir(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dqd", &fid, &initial_offset, &max_count);
 
+    trace_v9fs_readdir(pdu->tag, pdu->id, fid, initial_offset, max_count);
+
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
         retval = -EINVAL;
@@ -1995,6 +2093,7 @@ static void v9fs_readdir(void *opaque)
 out:
     put_fid(pdu, fidp);
 out_nofid:
+    trace_v9fs_readdir_return(pdu->tag, pdu->id, count, retval);
     complete_pdu(s, pdu, retval);
 }
 
@@ -2059,6 +2158,7 @@ static void v9fs_write(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "dqdv", &fid, &off, &count, sg, &cnt);
+    trace_v9fs_write(pdu->tag, pdu->id, fid, off, count, cnt);
 
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
@@ -2105,6 +2205,7 @@ static void v9fs_write(void *opaque)
 out:
     put_fid(pdu, fidp);
 out_nofid:
+    trace_v9fs_write_return(pdu->tag, pdu->id, total, err);
     complete_pdu(s, pdu, err);
 }
 
@@ -2129,6 +2230,8 @@ static void v9fs_create(void *opaque)
     pdu_unmarshal(pdu, offset, "dsdbs", &fid, &name,
                   &perm, &mode, &extension);
 
+    trace_v9fs_create(pdu->tag, pdu->id, fid, name.data, perm, mode);
+
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
         err = -EINVAL;
@@ -2262,6 +2365,8 @@ static void v9fs_create(void *opaque)
 out:
     put_fid(pdu, fidp);
 out_nofid:
+   trace_v9fs_create_return(pdu->tag, pdu->id,
+                            qid.type, qid.version, qid.path, iounit);
    complete_pdu(pdu->s, pdu, err);
    v9fs_string_free(&name);
    v9fs_string_free(&extension);
@@ -2282,6 +2387,7 @@ static void v9fs_symlink(void *opaque)
     size_t offset = 7;
 
     pdu_unmarshal(pdu, offset, "dssd", &dfid, &name, &symname, &gid);
+    trace_v9fs_symlink(pdu->tag, pdu->id, dfid, name.data, symname.data, gid);
 
     dfidp = get_fid(pdu, dfid);
     if (dfidp == NULL) {
@@ -2298,6 +2404,8 @@ static void v9fs_symlink(void *opaque)
 out:
     put_fid(pdu, dfidp);
 out_nofid:
+    trace_v9fs_symlink_return(pdu->tag, pdu->id,
+                              qid.type, qid.version, qid.path);
     complete_pdu(pdu->s, pdu, err);
     v9fs_string_free(&name);
     v9fs_string_free(&symname);
@@ -2312,6 +2420,7 @@ static void v9fs_flush(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "w", &tag);
+    trace_v9fs_flush(pdu->tag, pdu->id, tag);
 
     QLIST_FOREACH(cancel_pdu, &s->active_list, next) {
         if (cancel_pdu->tag == tag) {
@@ -2342,6 +2451,7 @@ static void v9fs_link(void *opaque)
     int err = 0;
 
     pdu_unmarshal(pdu, offset, "dds", &dfid, &oldfid, &name);
+    trace_v9fs_link(pdu->tag, pdu->id, dfid, oldfid, name.data);
 
     dfidp = get_fid(pdu, dfid);
     if (dfidp == NULL) {
@@ -2375,6 +2485,7 @@ static void v9fs_remove(void *opaque)
     V9fsPDU *pdu = opaque;
 
     pdu_unmarshal(pdu, offset, "d", &fid);
+    trace_v9fs_remove(pdu->tag, pdu->id, fid);
 
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
@@ -2382,7 +2493,7 @@ static void v9fs_remove(void *opaque)
         goto out_nofid;
     }
     /* if fs driver is not path based, return EOPNOTSUPP */
-    if (!pdu->s->ctx.flags & PATHNAME_FSCONTEXT) {
+    if (!(pdu->s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT)) {
         err = -EOPNOTSUPP;
         goto out_err;
     }
@@ -2417,6 +2528,7 @@ static void v9fs_unlinkat(void *opaque)
     V9fsPDU *pdu = opaque;
 
     pdu_unmarshal(pdu, offset, "dsd", &dfid, &name, &flags);
+    flags = dotl_to_at_flags(flags);
 
     dfidp = get_fid(pdu, dfid);
     if (dfidp == NULL) {
@@ -2528,7 +2640,7 @@ static void v9fs_rename(void *opaque)
     }
     BUG_ON(fidp->fid_type != P9_FID_NONE);
     /* if fs driver is not path based, return EOPNOTSUPP */
-    if (!pdu->s->ctx.flags & PATHNAME_FSCONTEXT) {
+    if (!(pdu->s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT)) {
         err = -EOPNOTSUPP;
         goto out;
     }
@@ -2601,7 +2713,7 @@ static int v9fs_complete_renameat(V9fsPDU *pdu, int32_t olddirfid,
     if (err < 0) {
         goto out;
     }
-    if (s->ctx.flags & PATHNAME_FSCONTEXT) {
+    if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
         /* Only for path based fid  we need to do the below fixup */
         v9fs_fix_fid_paths(pdu, &olddirfidp->path, old_name,
                            &newdirfidp->path, new_name);
@@ -2653,6 +2765,8 @@ static void v9fs_wstat(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "dwS", &fid, &unused, &v9stat);
+    trace_v9fs_wstat(pdu->tag, pdu->id, fid,
+                     v9stat.mode, v9stat.atime, v9stat.mtime);
 
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
@@ -2821,6 +2935,7 @@ static void v9fs_mknod(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dsdddd", &fid, &name, &mode,
                   &major, &minor, &gid);
+    trace_v9fs_mknod(pdu->tag, pdu->id, fid, mode, major, minor);
 
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
@@ -2838,6 +2953,7 @@ static void v9fs_mknod(void *opaque)
 out:
     put_fid(pdu, fidp);
 out_nofid:
+    trace_v9fs_mknod_return(pdu->tag, pdu->id, qid.type, qid.version, qid.path);
     complete_pdu(s, pdu, err);
     v9fs_string_free(&name);
 }
@@ -2865,6 +2981,10 @@ static void v9fs_lock(void *opaque)
     pdu_unmarshal(pdu, offset, "dbdqqds", &fid, &flock->type,
                   &flock->flags, &flock->start, &flock->length,
                   &flock->proc_id, &flock->client_id);
+
+    trace_v9fs_lock(pdu->tag, pdu->id, fid,
+                    flock->type, flock->start, flock->length);
+
     status = P9_LOCK_ERROR;
 
     /* We support only block flag now (that too ignored currently) */
@@ -2887,6 +3007,7 @@ out:
 out_nofid:
     err = offset;
     err += pdu_marshal(pdu, offset, "b", status);
+    trace_v9fs_lock_return(pdu->tag, pdu->id, status);
     complete_pdu(s, pdu, err);
     v9fs_string_free(&flock->client_id);
     g_free(flock);
@@ -2911,6 +3032,9 @@ static void v9fs_getlock(void *opaque)
                   &glock->start, &glock->length, &glock->proc_id,
                   &glock->client_id);
 
+    trace_v9fs_getlock(pdu->tag, pdu->id, fid,
+                       glock->type, glock->start, glock->length);
+
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
         err = -ENOENT;
@@ -2920,7 +3044,7 @@ static void v9fs_getlock(void *opaque)
     if (err < 0) {
         goto out;
     }
-    glock->type = F_UNLCK;
+    glock->type = P9_LOCK_TYPE_UNLCK;
     offset += pdu_marshal(pdu, offset, "bqqds", glock->type,
                           glock->start, glock->length, glock->proc_id,
                           &glock->client_id);
@@ -2928,6 +3052,9 @@ static void v9fs_getlock(void *opaque)
 out:
     put_fid(pdu, fidp);
 out_nofid:
+    trace_v9fs_getlock_return(pdu->tag, pdu->id, glock->type, glock->start,
+                              glock->length, glock->proc_id);
+
     complete_pdu(s, pdu, err);
     v9fs_string_free(&glock->client_id);
     g_free(glock);
@@ -2948,6 +3075,8 @@ static void v9fs_mkdir(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dsdd", &fid, &name, &mode, &gid);
 
+    trace_v9fs_mkdir(pdu->tag, pdu->id, fid, name.data, mode, gid);
+
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
         err = -ENOENT;
@@ -2963,6 +3092,8 @@ static void v9fs_mkdir(void *opaque)
 out:
     put_fid(pdu, fidp);
 out_nofid:
+    trace_v9fs_mkdir_return(pdu->tag, pdu->id,
+                            qid.type, qid.version, qid.path, err);
     complete_pdu(pdu->s, pdu, err);
     v9fs_string_free(&name);
 }
@@ -2980,6 +3111,8 @@ static void v9fs_xattrwalk(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "dds", &fid, &newfid, &name);
+    trace_v9fs_xattrwalk(pdu->tag, pdu->id, fid, newfid, name.data);
+
     file_fidp = get_fid(pdu, fid);
     if (file_fidp == NULL) {
         err = -ENOENT;
@@ -3056,6 +3189,7 @@ out:
         put_fid(pdu, xattr_fidp);
     }
 out_nofid:
+    trace_v9fs_xattrwalk_return(pdu->tag, pdu->id, size);
     complete_pdu(s, pdu, err);
     v9fs_string_free(&name);
 }
@@ -3075,6 +3209,7 @@ static void v9fs_xattrcreate(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dsqd",
                   &fid, &name, &size, &flags);
+    trace_v9fs_xattrcreate(pdu->tag, pdu->id, fid, name.data, size, flags);
 
     file_fidp = get_fid(pdu, fid);
     if (file_fidp == NULL) {
@@ -3111,6 +3246,7 @@ static void v9fs_readlink(void *opaque)
     V9fsFidState *fidp;
 
     pdu_unmarshal(pdu, offset, "d", &fid);
+    trace_v9fs_readlink(pdu->tag, pdu->id, fid);
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
         err = -ENOENT;
@@ -3128,6 +3264,7 @@ static void v9fs_readlink(void *opaque)
 out:
     put_fid(pdu, fidp);
 out_nofid:
+    trace_v9fs_readlink_return(pdu->tag, pdu->id, target.data);
     complete_pdu(pdu->s, pdu, err);
 }
 
@@ -3179,9 +3316,6 @@ static void submit_pdu(V9fsState *s, V9fsPDU *pdu)
     Coroutine *co;
     CoroutineEntry *handler;
 
-    if (debug_9p_pdu) {
-        pprint_pdu(pdu);
-    }
     if (pdu->id >= ARRAY_SIZE(pdu_co_handlers) ||
         (pdu_co_handlers[pdu->id] == NULL)) {
         handler = v9fs_op_not_supp;
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index 60b8a56e57..802f5809d1 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -352,6 +352,35 @@ typedef struct V9fsMkState {
     V9fsString fullname;
 } V9fsMkState;
 
+/* 9p2000.L open flags */
+#define P9_DOTL_RDONLY        00000000
+#define P9_DOTL_WRONLY        00000001
+#define P9_DOTL_RDWR          00000002
+#define P9_DOTL_NOACCESS      00000003
+#define P9_DOTL_CREATE        00000100
+#define P9_DOTL_EXCL          00000200
+#define P9_DOTL_NOCTTY        00000400
+#define P9_DOTL_TRUNC         00001000
+#define P9_DOTL_APPEND        00002000
+#define P9_DOTL_NONBLOCK      00004000
+#define P9_DOTL_DSYNC         00010000
+#define P9_DOTL_FASYNC        00020000
+#define P9_DOTL_DIRECT        00040000
+#define P9_DOTL_LARGEFILE     00100000
+#define P9_DOTL_DIRECTORY     00200000
+#define P9_DOTL_NOFOLLOW      00400000
+#define P9_DOTL_NOATIME       01000000
+#define P9_DOTL_CLOEXEC       02000000
+#define P9_DOTL_SYNC          04000000
+
+/* 9p2000.L at flags */
+#define P9_DOTL_AT_REMOVEDIR         0x200
+
+/* 9P2000.L lock type */
+#define P9_LOCK_TYPE_RDLCK 0
+#define P9_LOCK_TYPE_WRLCK 1
+#define P9_LOCK_TYPE_UNLCK 2
+
 #define P9_LOCK_SUCCESS 0
 #define P9_LOCK_BLOCKED 1
 #define P9_LOCK_ERROR 2
@@ -393,21 +422,21 @@ static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count,
 
 static inline void v9fs_path_write_lock(V9fsState *s)
 {
-    if (s->ctx.flags & PATHNAME_FSCONTEXT) {
+    if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
         qemu_co_rwlock_wrlock(&s->rename_lock);
     }
 }
 
 static inline void v9fs_path_read_lock(V9fsState *s)
 {
-    if (s->ctx.flags & PATHNAME_FSCONTEXT) {
+    if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
         qemu_co_rwlock_rdlock(&s->rename_lock);
     }
 }
 
 static inline void v9fs_path_unlock(V9fsState *s)
 {
-    if (s->ctx.flags & PATHNAME_FSCONTEXT) {
+    if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
         qemu_co_rwlock_unlock(&s->rename_lock);
     }
 }