Push to branch refs/heads/master:
0d060dcf813a277c0ac92abad83f266bc8706a4e -->
  6beb78b5ab0e2994438c04442d8a3a7ebc0ddf72

 fs/wrapfs/lookup.c | 55 +++++++++++++++++++++++++++++++++++++-----------------
 fs/wrapfs/main.c   |  2 ++
 fs/wrapfs/super.c  | 40 +++++++++++++++++++++++++++++++++++++++
 fs/wrapfs/wrapfs.h |  2 ++
 4 files changed, 82 insertions(+), 17 deletions(-)

commit 6beb78b5ab0e2994438c04442d8a3a7ebc0ddf72
Author: Erez Zadok <e...@cs.sunysb.edu>
Date:   Sun May 22 00:48:35 2016 -0400

    Wrapfs: support NFS exports
    
    Based on patch from Sandeep Joshi <sanjos...@gmail.com>.
    
    Signed-off-by: Erez Zadok <e...@cs.sunysb.edu>

commit f26939a6ed9f1d12e59d2909a5c1084eefe09df3
Author: Erez Zadok <e...@cs.sunysb.edu>
Date:   Sun May 22 00:48:35 2016 -0400

    Wrapfs: use d_splice_alias
    
    Refactor interpose code to allow lookup to use d_splice_alias.
    
    Signed-off-by: Erez Zadok <e...@cs.sunysb.edu>

diff --git a/fs/wrapfs/lookup.c b/fs/wrapfs/lookup.c
index 32824e7..95d2dba 100644
--- a/fs/wrapfs/lookup.c
+++ b/fs/wrapfs/lookup.c
@@ -172,27 +172,24 @@ struct inode *wrapfs_iget(struct super_block *sb, struct 
inode *lower_inode)
 }
 
 /*
- * Connect a wrapfs inode dentry/inode with several lower ones.  This is
- * the classic stackable file system "vnode interposition" action.
- *
- * @dentry: wrapfs's dentry which interposes on lower one
- * @sb: wrapfs's super_block
- * @lower_path: the lower path (caller does path_get/put)
+ * Helper interpose routine, called directly by ->lookup to handle
+ * spliced dentries.
  */
-int wrapfs_interpose(struct dentry *dentry, struct super_block *sb,
-                    struct path *lower_path)
+static struct dentry *__wrapfs_interpose(struct dentry *dentry,
+                                        struct super_block *sb,
+                                        struct path *lower_path)
 {
-       int err = 0;
        struct inode *inode;
        struct inode *lower_inode;
        struct super_block *lower_sb;
+       struct dentry *ret_dentry;
 
        lower_inode = lower_path->dentry->d_inode;
        lower_sb = wrapfs_lower_super(sb);
 
        /* check that the lower file system didn't cross a mount point */
        if (lower_inode->i_sb != lower_sb) {
-               err = -EXDEV;
+               ret_dentry = ERR_PTR(-EXDEV);
                goto out;
        }
 
@@ -204,14 +201,31 @@ int wrapfs_interpose(struct dentry *dentry, struct 
super_block *sb,
        /* inherit lower inode number for wrapfs's inode */
        inode = wrapfs_iget(sb, lower_inode);
        if (IS_ERR(inode)) {
-               err = PTR_ERR(inode);
+               ret_dentry = ERR_PTR(PTR_ERR(inode));
                goto out;
        }
 
-       d_add(dentry, inode);
+       ret_dentry = d_splice_alias(inode, dentry);
 
 out:
-       return err;
+       return ret_dentry;
+}
+
+/*
+ * Connect a wrapfs inode dentry/inode with several lower ones.  This is
+ * the classic stackable file system "vnode interposition" action.
+ *
+ * @dentry: wrapfs's dentry which interposes on lower one
+ * @sb: wrapfs's super_block
+ * @lower_path: the lower path (caller does path_get/put)
+ */
+int wrapfs_interpose(struct dentry *dentry, struct super_block *sb,
+                    struct path *lower_path)
+{
+       struct dentry *ret_dentry;
+
+       ret_dentry = __wrapfs_interpose(dentry, sb, lower_path);
+       return PTR_ERR(ret_dentry);
 }
 
 /*
@@ -231,6 +245,7 @@ static struct dentry *__wrapfs_lookup(struct dentry *dentry,
        const char *name;
        struct path lower_path;
        struct qstr this;
+       struct dentry *ret_dentry = NULL;
 
        /* must initialize dentry operations */
        d_set_d_op(dentry, &wrapfs_dops);
@@ -251,9 +266,13 @@ static struct dentry *__wrapfs_lookup(struct dentry 
*dentry,
        /* no error: handle positive dentries */
        if (!err) {
                wrapfs_set_lower_path(dentry, &lower_path);
-               err = wrapfs_interpose(dentry, dentry->d_sb, &lower_path);
-               if (err) /* path_put underlying path on error */
+               ret_dentry =
+                       __wrapfs_interpose(dentry, dentry->d_sb, &lower_path);
+               if (IS_ERR(ret_dentry)) {
+                       err = PTR_ERR(ret_dentry);
+                        /* path_put underlying path on error */
                        wrapfs_put_reset_lower_path(dentry);
+               }
                goto out;
        }
 
@@ -289,11 +308,13 @@ setup_lower:
         * the VFS will continue the process of making this negative dentry
         * into a positive one.
         */
-       if (flags & (LOOKUP_CREATE|LOOKUP_RENAME_TARGET))
+       if (err == -ENOENT || (flags & (LOOKUP_CREATE|LOOKUP_RENAME_TARGET)))
                err = 0;
 
 out:
-       return ERR_PTR(err);
+       if (err)
+               return ERR_PTR(err);
+       return ret_dentry;
 }
 
 struct dentry *wrapfs_lookup(struct inode *dir, struct dentry *dentry,
diff --git a/fs/wrapfs/main.c b/fs/wrapfs/main.c
index 80cd181..b70ee82 100644
--- a/fs/wrapfs/main.c
+++ b/fs/wrapfs/main.c
@@ -64,6 +64,8 @@ static int wrapfs_read_super(struct super_block *sb, void 
*raw_data, int silent)
 
        sb->s_op = &wrapfs_sops;
 
+       sb->s_export_op = &wrapfs_export_ops; /* adding NFS support */
+
        /* get a new inode and allocate our root dentry */
        inode = wrapfs_iget(sb, lower_path.dentry->d_inode);
        if (IS_ERR(inode)) {
diff --git a/fs/wrapfs/super.c b/fs/wrapfs/super.c
index 9f90f57..5c99c47 100644
--- a/fs/wrapfs/super.c
+++ b/fs/wrapfs/super.c
@@ -166,3 +166,43 @@ const struct super_operations wrapfs_sops = {
        .destroy_inode  = wrapfs_destroy_inode,
        .drop_inode     = generic_delete_inode,
 };
+
+/* NFS support */
+
+static struct inode *wrapfs_nfs_get_inode(struct super_block *sb, u64 ino,
+                                         u32 generation)
+{
+       struct super_block *lower_sb;
+       struct inode *inode;
+       struct inode *lower_inode;
+
+       lower_sb = wrapfs_lower_super(sb);
+       lower_inode = ilookup(lower_sb, ino);
+       inode = wrapfs_iget(sb, lower_inode);
+       return inode;
+}
+
+static struct dentry *wrapfs_fh_to_dentry(struct super_block *sb,
+                                         struct fid *fid, int fh_len,
+                                         int fh_type)
+{
+       return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
+                                   wrapfs_nfs_get_inode);
+}
+
+static struct dentry *wrapfs_fh_to_parent(struct super_block *sb,
+                                         struct fid *fid, int fh_len,
+                                         int fh_type)
+{
+       return generic_fh_to_parent(sb, fid, fh_len, fh_type,
+                                   wrapfs_nfs_get_inode);
+}
+
+/*
+ * all other funcs are default as defined in exportfs/expfs.c
+ */
+
+const struct export_operations wrapfs_export_ops = {
+       .fh_to_dentry      = wrapfs_fh_to_dentry,
+       .fh_to_parent      = wrapfs_fh_to_parent
+};
diff --git a/fs/wrapfs/wrapfs.h b/fs/wrapfs/wrapfs.h
index cb8c0ab..0e5e34e 100644
--- a/fs/wrapfs/wrapfs.h
+++ b/fs/wrapfs/wrapfs.h
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/xattr.h>
+#include <linux/exportfs.h>
 
 /* the file system name */
 #define WRAPFS_NAME "wrapfs"
@@ -47,6 +48,7 @@ extern const struct super_operations wrapfs_sops;
 extern const struct dentry_operations wrapfs_dops;
 extern const struct address_space_operations wrapfs_aops, wrapfs_dummy_aops;
 extern const struct vm_operations_struct wrapfs_vm_ops;
+extern const struct export_operations wrapfs_export_ops;
 
 extern int wrapfs_init_inode_cache(void);
 extern void wrapfs_destroy_inode_cache(void);

_______________________________________________
unionfs-cvs mailing list: http://unionfs.filesystems.org/
unionfs-cvs@fsl.cs.sunysb.edu
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs

Reply via email to