From: Erez Zadok <ezk@xxxxxxxxxxxxx> Signed-off-by: Erez Zadok <ezk@xxxxxxxxxxxxx> Signed-off-by: Josef 'Jeff' Sipek <jsipek@xxxxxxxxxxxxx> --- fs/unionfs/lookup.c | 11 +++++++++-- 1 files changed, 9 insertions(+), 2 deletions(-) diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c index df929e9..967bb5b 100644 --- a/fs/unionfs/lookup.c +++ b/fs/unionfs/lookup.c @@ -84,6 +84,7 @@ struct dentry *unionfs_lookup_backend(struct dentry *dentry, struct nameidata *n struct vfsmount *first_hidden_mnt = NULL; int locked_parent = 0; int locked_child = 0; + int allocated_new_info = 0; int opaque; char *whname = NULL; @@ -101,9 +102,11 @@ struct dentry *unionfs_lookup_backend(struct dentry *dentry, struct nameidata *n BUG_ON(UNIONFS_D(dentry) != NULL); locked_child = 1; } - if (lookupmode != INTERPOSE_PARTIAL) + if (lookupmode != INTERPOSE_PARTIAL) { if ((err = new_dentry_private_data(dentry))) goto out; + allocated_new_info = 1; + } /* must initialize dentry operations */ dentry->d_op = &unionfs_dops; @@ -380,7 +383,7 @@ out: if (locked_parent) unionfs_unlock_dentry(parent_dentry); dput(parent_dentry); - if (locked_child) + if (locked_child || (err && allocated_new_info)) unionfs_unlock_dentry(dentry); return ERR_PTR(err); } @@ -431,6 +434,7 @@ int new_dentry_private_data(struct dentry *dentry) int newsize; int oldsize = 0; struct unionfs_dentry_info *info = UNIONFS_D(dentry); + int unlock_on_err = 0; spin_lock(&dentry->d_lock); if (!info) { @@ -443,6 +447,7 @@ int new_dentry_private_data(struct dentry *dentry) mutex_init(&info->lock); mutex_lock(&info->lock); + unlock_on_err = 1; info->lower_paths = NULL; } else @@ -482,6 +487,8 @@ int new_dentry_private_data(struct dentry *dentry) out_free: kfree(info->lower_paths); + if (unlock_on_err) + mutex_unlock(&info->lock); out: free_dentry_private_data(info); -- 1.5.0.2.260.g2eb065 - To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html