diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 1e96c8b..956fda0 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -56,11 +56,15 @@ typedef struct extended_ops {
  * On failure ignore the error.
  */
 #define V9FS_SM_NONE                0x00000010
-#define V9FS_RDONLY                 0x00000020
-#define V9FS_PROXY_SOCK_FD          0x00000040
-#define V9FS_PROXY_SOCK_NAME        0x00000080
+/*
+ * uid/gid part of .virtfs_meatadata namespace
+ */
+#define V9FS_SM_MAPPED_FILE         0x00000020
+#define V9FS_RDONLY                 0x00000040
+#define V9FS_PROXY_SOCK_FD          0x00000080
+#define V9FS_PROXY_SOCK_NAME        0x00000100
 
-#define V9FS_SEC_MASK               0x0000001C
+#define V9FS_SEC_MASK               0x0000003C
 
 
 typedef struct FileOperations FileOperations;
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 642d5e2..41a1a82 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -91,15 +91,6 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
         s->ctx.fs_root = NULL;
     }
     s->ctx.exops.get_st_gen = NULL;
-
-    if (fse->export_flags & V9FS_SM_PASSTHROUGH) {
-        s->ctx.xops = passthrough_xattr_ops;
-    } else if (fse->export_flags & V9FS_SM_MAPPED) {
-        s->ctx.xops = mapped_xattr_ops;
-    } else if (fse->export_flags & V9FS_SM_NONE) {
-        s->ctx.xops = none_xattr_ops;
-    }
-
     len = strlen(conf->tag);
     if (len > MAX_TAG_LEN - 1) {
         fprintf(stderr, "mount tag '%s' (%d bytes) is longer than "
diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index 3ae6ef2..6862018 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -20,6 +20,7 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 #include "qemu-xattr.h"
+#include <libgen.h>
 #include <linux/fs.h>
 #ifdef CONFIG_LINUX_MAGIC_H
 #include <linux/magic.h>
@@ -39,6 +40,51 @@
 #define BTRFS_SUPER_MAGIC 0x9123683E
 #endif
 
+#define VIRTFS_META_DIR ".virtfs_metadata"
+
+static const char *local_mapped_attr_path(FsContext *ctx,
+                                          const char *path, char *buffer)
+{
+    char *dir_name;
+    char *tmp_path = strdup(path);
+    char *base_name = basename(tmp_path);
+
+    /* NULL terminate the directory */
+    dir_name = tmp_path;
+    *(base_name - 1) = '\0';
+
+    snprintf(buffer, PATH_MAX, "%s/%s/%s/%s",
+             ctx->fs_root, dir_name, VIRTFS_META_DIR, base_name);
+    free(tmp_path);
+    return buffer;
+}
+
+#define ATTR_MAX 100
+static void local_mapped_file_attr(const char *attr_path, struct stat *stbuf)
+{
+    FILE *fp;
+    char buf[ATTR_MAX];
+
+    fp = fopen(attr_path, "r");
+    if (!fp) {
+        return;
+    }
+    memset(buf, 0, ATTR_MAX);
+    while (fgets(buf, ATTR_MAX, fp)) {
+        if (!strncmp(buf, "virtfs.uid", 10)) {
+            stbuf->st_uid = atoi(buf+11);
+        } else if (!strncmp(buf, "virtfs.gid", 10)) {
+            stbuf->st_gid = atoi(buf+11);
+        } else if (!strncmp(buf, "virtfs.mode", 11)) {
+            stbuf->st_mode = atoi(buf+12);
+        } else if (!strncmp(buf, "virtfs.rdev", 11)) {
+            stbuf->st_rdev = atoi(buf+12);
+        }
+        memset(buf, 0, ATTR_MAX);
+    }
+    fclose(fp);
+}
+
 static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
 {
     int err;
@@ -71,10 +117,101 @@ static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
                         sizeof(dev_t)) > 0) {
                 stbuf->st_rdev = tmp_dev;
         }
+    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        local_mapped_attr_path(fs_ctx, path, buffer);
+        local_mapped_file_attr(buffer, stbuf);
     }
     return err;
 }
 
+static int local_set_mapped_file_attr(FsContext *ctx,
+                                      const char *path, FsCred *credp)
+{
+    FILE *fp;
+    int ret = 0;
+    char *dir_name;
+    char buf[ATTR_MAX];
+    char attr_path[PATH_MAX];
+    int uid, gid, mode, rdev;
+    char *tmp_path = strdup(path);
+    char *base_name = basename(tmp_path);
+
+    /* NULL terminate the directory */
+    dir_name = tmp_path;
+    *(base_name - 1) = '\0';
+
+    snprintf(attr_path, PATH_MAX, "%s/%s/%s/%s",
+             ctx->fs_root, dir_name, VIRTFS_META_DIR, base_name);
+
+    fp = fopen(attr_path, "r");
+    if (!fp) {
+        goto create_map_file;
+    }
+    memset(buf, 0, ATTR_MAX);
+    while (fgets(buf, ATTR_MAX, fp)) {
+        if (!strncmp(buf, "virtfs.uid", 10)) {
+            uid = atoi(buf+11);
+        } else if (!strncmp(buf, "virtfs.gid", 10)) {
+            gid = atoi(buf+11);
+        } else if (!strncmp(buf, "virtfs.mode", 11)) {
+            mode = atoi(buf+12);
+        } else if (!strncmp(buf, "virtfs.rdev", 11)) {
+            rdev = atoi(buf+12);
+        }
+        memset(buf, 0, ATTR_MAX);
+    }
+    fclose(fp);
+    goto update_map_file;
+
+create_map_file:
+    /*
+     * if attr file is not present create one
+     */
+    snprintf(attr_path, PATH_MAX, "%s/%s/%s",
+             ctx->fs_root, dir_name, VIRTFS_META_DIR);
+
+    ret = mkdir(attr_path, 0700);
+    if (ret < 0) {
+        if (errno != EEXIST) {
+            goto err_out;
+        } else {
+            ret = 0;
+        }
+    }
+    snprintf(attr_path, PATH_MAX, "%s/%s/%s/%s",
+             ctx->fs_root, dir_name, VIRTFS_META_DIR, base_name);
+
+update_map_file:
+    fp = fopen(attr_path, "w");
+    if (!fp) {
+        ret = -1;
+        goto err_out;
+    }
+
+    if (credp->fc_uid != -1) {
+        uid = credp->fc_uid;
+    }
+    if (credp->fc_gid != -1) {
+        gid = credp->fc_gid;
+    }
+    if (credp->fc_mode != -1) {
+        mode = credp->fc_mode;
+    }
+    if (credp->fc_rdev != -1) {
+        rdev = credp->fc_rdev;
+    }
+    fprintf(fp, "virtfs.uid=%d\n", uid);
+    fprintf(fp, "virtfs.gid=%d\n", gid);
+    fprintf(fp, "virtfs.mode=%d\n", mode);
+    fprintf(fp, "virtfs.rdev=%d\n", rdev);
+
+    fclose(fp);
+
+err_out:
+    free(tmp_path);
+    return ret;
+}
+
 static int local_set_xattr(const char *path, FsCred *credp)
 {
     int err;
@@ -138,7 +275,8 @@ static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
     char buffer[PATH_MAX];
     char *path = fs_path->data;
 
-    if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
+    if ((fs_ctx->export_flags & V9FS_SM_MAPPED) ||
+        (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
         int fd;
         fd = open(rpath(fs_ctx, path, buffer), O_RDONLY);
         if (fd == -1) {
@@ -203,7 +341,18 @@ static int local_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
                            struct dirent *entry,
                            struct dirent **result)
 {
-    return readdir_r(fs->dir, entry, result);
+    int ret;
+
+again:
+    ret = readdir_r(fs->dir, entry, result);
+    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;
+        }
+    }
+    return ret;
 }
 
 static void local_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
@@ -264,6 +413,8 @@ static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
 
     if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
         return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
+    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        return local_set_mapped_file_attr(fs_ctx, path, credp);
     } 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);
@@ -296,6 +447,18 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
             serrno = errno;
             goto err_end;
         }
+    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+
+        err = mknod(rpath(fs_ctx, path, buffer),
+                    SM_LOCAL_MODE_BITS|S_IFREG, 0);
+        if (err == -1) {
+            goto out;
+        }
+        err = local_set_mapped_file_attr(fs_ctx, path, credp);
+        if (err == -1) {
+            serrno = errno;
+            goto err_end;
+        }
     } 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,
@@ -344,6 +507,17 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
             serrno = errno;
             goto err_end;
         }
+    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS);
+        if (err == -1) {
+            goto out;
+        }
+        credp->fc_mode = credp->fc_mode|S_IFDIR;
+        err = local_set_mapped_file_attr(fs_ctx, path, credp);
+        if (err == -1) {
+            serrno = errno;
+            goto err_end;
+        }
     } 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);
@@ -404,6 +578,10 @@ static int local_fstat(FsContext *fs_ctx, int fid_type,
                       &tmp_dev, sizeof(dev_t)) > 0) {
                 stbuf->st_rdev = tmp_dev;
         }
+#if 0
+    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        /* FIXME!! how to implement that for MAPPED_FILE */
+#endif
     }
     return err;
 }
@@ -436,6 +614,19 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
             serrno = errno;
             goto err_end;
         }
+    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS);
+        if (fd == -1) {
+            err = fd;
+            goto out;
+        }
+        credp->fc_mode = credp->fc_mode|S_IFREG;
+        /* Set client credentials in .virtfs_metadata directory files */
+        err = local_set_mapped_file_attr(fs_ctx, path, credp);
+        if (err == -1) {
+            serrno = errno;
+            goto err_end;
+        }
     } 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);
@@ -506,6 +697,35 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
             serrno = errno;
             goto err_end;
         }
+    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        int fd;
+        ssize_t oldpath_size, write_size;
+        fd = open(rpath(fs_ctx, newpath, buffer), O_CREAT|O_EXCL|O_RDWR,
+                  SM_LOCAL_MODE_BITS);
+        if (fd == -1) {
+            err = fd;
+            goto out;
+        }
+        /* Write the oldpath (target) to the file. */
+        oldpath_size = strlen(oldpath);
+        do {
+            write_size = write(fd, (void *)oldpath, oldpath_size);
+        } while (write_size == -1 && errno == EINTR);
+
+        if (write_size != oldpath_size) {
+            serrno = errno;
+            close(fd);
+            err = -1;
+            goto err_end;
+        }
+        close(fd);
+        /* Set cleint credentials in symlink's xattr */
+        credp->fc_mode = credp->fc_mode|S_IFLNK;
+        err = local_set_mapped_file_attr(fs_ctx, newpath, credp);
+        if (err == -1) {
+            serrno = errno;
+            goto err_end;
+        }
     } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
                (fs_ctx->export_flags & V9FS_SM_NONE)) {
         err = symlink(oldpath, rpath(fs_ctx, newpath, buffer));
@@ -548,6 +768,17 @@ static int local_link(FsContext *ctx, V9fsPath *oldpath,
 
     ret = link(rpath(ctx, oldpath->data, buffer),
                rpath(ctx, newpath.data, buffer1));
+
+    /* now link the virtfs_metadata files */
+    if (!ret && (ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
+        /* rename the .virtfs_metadata files */
+        ret = link(local_mapped_attr_path(ctx, oldpath->data, buffer),
+                   local_mapped_attr_path(ctx, newpath.data, buffer1));
+        if (ret < 0 && errno != ENOENT) {
+            goto err_out;
+        }
+    }
+err_out:
     v9fs_string_free(&newpath);
     return ret;
 }
@@ -563,8 +794,17 @@ static int local_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
 static int local_rename(FsContext *ctx, const char *oldpath,
                         const char *newpath)
 {
+    int err;
     char buffer[PATH_MAX], buffer1[PATH_MAX];
 
+    if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        /* rename the .virtfs_metadata files */
+        err = rename(local_mapped_attr_path(ctx, oldpath, buffer),
+                     local_mapped_attr_path(ctx, newpath, buffer1));
+        if (err < 0 && errno != ENOENT) {
+            return err;
+        }
+    }
     return rename(rpath(ctx, oldpath, buffer), rpath(ctx, newpath, buffer1));
 }
 
@@ -580,6 +820,8 @@ static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
                       credp->fc_uid, credp->fc_gid);
     } else if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
         return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
+    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        return local_set_mapped_file_attr(fs_ctx, path, credp);
     }
     return -1;
 }
@@ -595,8 +837,46 @@ static int local_utimensat(FsContext *s, V9fsPath *fs_path,
 
 static int local_remove(FsContext *ctx, const char *path)
 {
+    int err;
+    struct stat stbuf;
     char buffer[PATH_MAX];
+
+    if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        err =  lstat(rpath(ctx, path, buffer), &stbuf);
+        if (err) {
+            goto err_out;
+        }
+        /*
+         *If directory remove .virtfs_metadata contained in the
+         * directory
+         */
+        if (S_ISDIR(stbuf.st_mode)) {
+            sprintf(buffer, "%s/%s/%s", ctx->fs_root, path, VIRTFS_META_DIR);
+            err = remove(buffer);
+            if (err < 0 && errno != ENOENT) {
+                /*
+                 * We didn't had the .virtfs_metadata file. May be file created
+                 * in non-mapped mode ?. Ignore ENOENT.
+                 */
+                goto err_out;
+            }
+        }
+        /*
+         * Now remove the name from parent directory
+         *.virtfs_metadata directory
+         */
+        err = remove(local_mapped_attr_path(ctx, path, buffer));;
+        if (err < 0 && errno != ENOENT) {
+            /*
+             * We didn't had the .virtfs_metadata file. May be file created
+             * in non-mapped mode ?. Ignore ENOENT.
+             */
+            goto err_out;
+        }
+    }
     return remove(rpath(ctx, path, buffer));
+err_out:
+    return err;
 }
 
 static int local_fsync(FsContext *ctx, int fid_type,
@@ -696,12 +976,45 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
     int ret;
     V9fsString fullname;
     char buffer[PATH_MAX];
+
     v9fs_string_init(&fullname);
 
     v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name);
+    if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        if (flags == AT_REMOVEDIR) {
+            /*
+             *If directory remove .virtfs_metadata contained in the
+             * directory
+             */
+            sprintf(buffer, "%s/%s/%s", ctx->fs_root,
+                    fullname.data, VIRTFS_META_DIR);
+            ret = remove(buffer);
+            if (ret < 0 && errno != ENOENT) {
+                /*
+                 * We didn't had the .virtfs_metadata file. May be file created
+                 * in non-mapped mode ?. Ignore ENOENT.
+                 */
+                goto err_out;
+            }
+        }
+        /*
+         * Now remove the name from parent directory
+         * .virtfs_metadata directory. Igno
+         */
+        ret = remove(local_mapped_attr_path(ctx, fullname.data, buffer));
+        if (ret < 0 && errno != ENOENT) {
+            /*
+             * We didn't had the .virtfs_metadata file. May be file created
+             * in non-mapped mode ?. Ignore ENOENT.
+             */
+            goto err_out;
+        }
+    }
+    /* Remove the name finally */
     ret = remove(rpath(ctx, fullname.data, buffer));
     v9fs_string_free(&fullname);
 
+err_out:
     return ret;
 }
 
@@ -736,6 +1049,19 @@ static int local_init(FsContext *ctx)
     int err = 0;
     struct statfs stbuf;
 
+    if (ctx->export_flags & V9FS_SM_PASSTHROUGH) {
+        ctx->xops = passthrough_xattr_ops;
+    } else if (ctx->export_flags & V9FS_SM_MAPPED) {
+        ctx->xops = mapped_xattr_ops;
+    } else if (ctx->export_flags & V9FS_SM_NONE) {
+        ctx->xops = none_xattr_ops;
+    } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        /*
+         * xattr operation for mapped-file and passthrough
+         * remain same.
+         */
+        ctx->xops = passthrough_xattr_ops;
+    }
     ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT;
 #ifdef FS_IOC_GETVERSION
     /*
@@ -770,13 +1096,17 @@ static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
 
     if (!strcmp(sec_model, "passthrough")) {
         fse->export_flags |= V9FS_SM_PASSTHROUGH;
-    } else if (!strcmp(sec_model, "mapped")) {
+    } else if (!strcmp(sec_model, "mapped") ||
+               !strcmp(sec_model, "mapped-xattr")) {
         fse->export_flags |= V9FS_SM_MAPPED;
     } else if (!strcmp(sec_model, "none")) {
         fse->export_flags |= V9FS_SM_NONE;
+    } else if (!strcmp(sec_model, "mapped-file")) {
+        fse->export_flags |= V9FS_SM_MAPPED_FILE;
     } else {
         fprintf(stderr, "Invalid security model %s specified, valid options are"
-                "\n\t [passthrough|mapped|none]\n", sec_model);
+                "\n\t [passthrough|mapped-xattr|mapped-file|none]\n",
+                sec_model);
         return -1;
     }
 
