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