From 07c8da008a80a561d0229b857af37aa56307c32e Mon Sep 17 00:00:00 2001 From: Erez Zadok Date: Tue, 6 Sep 2011 00:10:32 -0400 Subject: [PATCH] Wrapfs: use d_alloc_root Signed-off-by: Erez Zadok --- fs/wrapfs/lookup.c | 3 +- fs/wrapfs/main.c | 68 ++++++++++++++++++---------------------------- fs/wrapfs/wrapfs.h | 2 ++ 3 files changed, 30 insertions(+), 43 deletions(-) diff --git a/fs/wrapfs/lookup.c b/fs/wrapfs/lookup.c index 21820d9aaf8a..92ccd37499ed 100644 --- a/fs/wrapfs/lookup.c +++ b/fs/wrapfs/lookup.c @@ -136,8 +136,7 @@ static int wrapfs_inode_set(struct inode *inode, void *lower_inode) return 0; } -static struct inode *wrapfs_iget(struct super_block *sb, - struct inode *lower_inode) +struct inode *wrapfs_iget(struct super_block *sb, struct inode *lower_inode) { struct wrapfs_inode_info *info; struct inode *inode; /* the new inode to return */ diff --git a/fs/wrapfs/main.c b/fs/wrapfs/main.c index 19fc07444925..130aca66a6d4 100644 --- a/fs/wrapfs/main.c +++ b/fs/wrapfs/main.c @@ -12,32 +12,6 @@ #include "wrapfs.h" #include -/* - * our custom d_alloc_root work-alike - * - * we can't use d_alloc_root if we want to use our own interpose function - * unchanged, so we simply call our own "fake" d_alloc_root - */ -static struct dentry *wrapfs_d_alloc_root(struct super_block *sb) -{ - struct dentry *ret = NULL; - - if (sb) { - static const struct qstr name = { - .name = "/", - .len = 1 - }; - - ret = d_alloc(NULL, &name); - if (ret) { - d_set_d_op(ret, &wrapfs_dops); - ret->d_sb = sb; - ret->d_parent = ret; - } - } - return ret; -} - /* * There is no need to lock the wrapfs_super_info's rwsem as there is no * way anyone can have a reference to the superblock at this point in time. @@ -48,6 +22,7 @@ static int wrapfs_read_super(struct super_block *sb, void *raw_data, int silent) struct super_block *lower_sb; struct path lower_path; char *dev_name = (char *) raw_data; + struct inode *inode; if (!dev_name) { printk(KERN_ERR @@ -89,12 +64,18 @@ static int wrapfs_read_super(struct super_block *sb, void *raw_data, int silent) sb->s_op = &wrapfs_sops; - /* see comment next to the definition of wrapfs_d_alloc_root */ - sb->s_root = wrapfs_d_alloc_root(sb); + /* get a new inode and allocate our root dentry */ + inode = wrapfs_iget(sb, lower_path.dentry->d_inode); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto out_sput; + } + sb->s_root = d_alloc_root(inode); if (!sb->s_root) { err = -ENOMEM; - goto out_sput; + goto out_iput; } + d_set_d_op(sb->s_root, &wrapfs_dops); /* link the upper and lower dentries */ sb->s_root->d_fsdata = NULL; @@ -102,23 +83,28 @@ static int wrapfs_read_super(struct super_block *sb, void *raw_data, int silent) if (err) goto out_freeroot; + /* if get here: cannot have error */ + /* set the lower dentries for s_root */ wrapfs_set_lower_path(sb->s_root, &lower_path); - /* call interpose to create the upper level inode */ - err = wrapfs_interpose(sb->s_root, sb, &lower_path); - if (!err) { - if (!silent) - printk(KERN_INFO - "wrapfs: mounted on top of %s type %s\n", - dev_name, lower_sb->s_type->name); - goto out; - } - /* else error: fall through */ - - free_dentry_private_data(sb->s_root); + /* + * No need to call interpose because we already have a positive + * dentry, which was instantiated by d_alloc_root. Just need to + * d_rehash it. + */ + d_rehash(sb->s_root); + if (!silent) + printk(KERN_INFO + "wrapfs: mounted on top of %s type %s\n", + dev_name, lower_sb->s_type->name); + goto out; /* all is well */ + + /* no longer needed: free_dentry_private_data(sb->s_root); */ out_freeroot: dput(sb->s_root); +out_iput: + iput(inode); out_sput: /* drop refs we took earlier */ atomic_dec(&lower_sb->s_active); diff --git a/fs/wrapfs/wrapfs.h b/fs/wrapfs/wrapfs.h index 5c7a4685f0cf..5762c3543324 100644 --- a/fs/wrapfs/wrapfs.h +++ b/fs/wrapfs/wrapfs.h @@ -56,6 +56,8 @@ extern int init_lower_nd(struct nameidata *nd, unsigned int flags); extern void release_lower_nd(struct nameidata *nd, int err); extern struct dentry *wrapfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd); +extern struct inode *wrapfs_iget(struct super_block *sb, + struct inode *lower_inode); extern int wrapfs_interpose(struct dentry *dentry, struct super_block *sb, struct path *lower_path); -- 2.43.0