From 46c417d959e9b599aa8c46de27b4ef2fee523cb1 Mon Sep 17 00:00:00 2001 From: Erez Zadok Date: Tue, 6 Sep 2011 01:02:42 -0400 Subject: [PATCH] Wrapfs: use d_alloc_root Signed-off-by: Erez Zadok --- fs/unionfs/lookup.c | 2 +- fs/unionfs/main.c | 59 ++++++++++++++++++--------------------------- 2 files changed, 25 insertions(+), 36 deletions(-) diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c index 35bccc81897..041d674279a 100644 --- a/fs/unionfs/lookup.c +++ b/fs/unionfs/lookup.c @@ -30,7 +30,7 @@ struct dentry *__lookup_one(struct dentry *base, struct vfsmount *mnt, const char *name, struct vfsmount **new_mnt) { struct dentry *dentry = NULL; - struct path lower_path; + struct path lower_path = {NULL, NULL}; int err; /* we use flags=0 to get basic lookup */ diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c index f4bcd894986..87cd1fcdfe1 100644 --- a/fs/unionfs/main.c +++ b/fs/unionfs/main.c @@ -525,32 +525,6 @@ out: return lower_root_info; } -/* - * 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 *unionfs_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 (likely(ret)) { - d_set_d_op(ret, &unionfs_dops); - ret->d_sb = sb; - ret->d_parent = ret; - } - } - return ret; -} - /* * There is no need to lock the unionfs_super_info's rwsem as there is no * way anyone can have a reference to the superblock at this point in time. @@ -561,6 +535,7 @@ static int unionfs_read_super(struct super_block *sb, void *raw_data, int err = 0; struct unionfs_dentry_info *lower_root_info = NULL; int bindex, bstart, bend; + struct inode *inode = NULL; if (!raw_data) { printk(KERN_ERR @@ -618,12 +593,18 @@ static int unionfs_read_super(struct super_block *sb, void *raw_data, sb->s_op = &unionfs_sops; - /* See comment next to the definition of unionfs_d_alloc_root */ - sb->s_root = unionfs_d_alloc_root(sb); + /* get a new inode and allocate our root dentry */ + inode = unionfs_iget(sb, iunique(sb, UNIONFS_ROOT_INO)); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto out_dput; + } + sb->s_root = d_alloc_root(inode); if (unlikely(!sb->s_root)) { err = -ENOMEM; - goto out_dput; + goto out_iput; } + d_set_d_op(sb->s_root, &unionfs_dops); /* link the upper and lower dentries */ sb->s_root->d_fsdata = NULL; @@ -631,6 +612,8 @@ static int unionfs_read_super(struct super_block *sb, void *raw_data, if (unlikely(err)) goto out_freedpd; + /* if get here: cannot have error */ + /* Set the lower dentries for s_root */ for (bindex = bstart; bindex <= bend; bindex++) { struct dentry *d; @@ -648,15 +631,18 @@ static int unionfs_read_super(struct super_block *sb, void *raw_data, /* Set the generation number to one, since this is for the mount. */ atomic_set(&UNIONFS_D(sb->s_root)->generation, 1); + if (atomic_read(&inode->i_count) <= 1) + unionfs_fill_inode(sb->s_root, inode); + /* - * Call interpose to create the upper level inode. Only - * INTERPOSE_LOOKUP can return a value other than 0 on err. + * 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. */ - err = PTR_ERR(unionfs_interpose(sb->s_root, sb, 0)); + d_rehash(sb->s_root); + unionfs_unlock_dentry(sb->s_root); - if (!err) - goto out; - /* else fall through */ + goto out; /* all is well */ out_freedpd: if (UNIONFS_D(sb->s_root)) { @@ -665,6 +651,9 @@ out_freedpd: } dput(sb->s_root); +out_iput: + iput(inode); + out_dput: if (lower_root_info && !IS_ERR(lower_root_info)) { for (bindex = lower_root_info->bstart; -- 2.34.1