Unionfs: unlock lower parent inode correctly on error path
authorErez Zadok <ezk@cs.sunysb.edu>
Sun, 8 Nov 2009 23:18:56 +0000 (18:18 -0500)
committerErez Zadok <ezk@cs.sunysb.edu>
Fri, 24 Jun 2011 18:08:13 +0000 (14:08 -0400)
Bug fix: on some errors, lower directory inode may remain locked and hold a
reference.  This was in ->create, ->symlink, and ->mknod.

Signed-off-by: Erez Zadok <ezk@cs.sunysb.edu>
fs/unionfs/inode.c

index bd5a3b3369451a9126825ef4e370b48948af522d..0855cdb24b3f732031c53f0838de672779761f01 100644 (file)
@@ -125,12 +125,12 @@ static int unionfs_create(struct inode *dir, struct dentry *dentry,
        lower_parent_dentry = lock_parent(lower_dentry);
        if (IS_ERR(lower_parent_dentry)) {
                err = PTR_ERR(lower_parent_dentry);
-               goto out;
+               goto out_unlock;
        }
 
        err = init_lower_nd(&lower_nd, LOOKUP_CREATE);
        if (unlikely(err < 0))
-               goto out;
+               goto out_unlock;
        err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode,
                         &lower_nd);
        release_lower_nd(&lower_nd, err);
@@ -146,8 +146,8 @@ static int unionfs_create(struct inode *dir, struct dentry *dentry,
                }
        }
 
+out_unlock:
        unlock_dir(lower_parent_dentry);
-
 out:
        if (!err) {
                unionfs_postcopyup_setmnt(dentry);
@@ -390,7 +390,7 @@ static int unionfs_symlink(struct inode *dir, struct dentry *dentry,
        lower_parent_dentry = lock_parent(lower_dentry);
        if (IS_ERR(lower_parent_dentry)) {
                err = PTR_ERR(lower_parent_dentry);
-               goto out;
+               goto out_unlock;
        }
 
        mode = S_IALLUGO;
@@ -406,8 +406,8 @@ static int unionfs_symlink(struct inode *dir, struct dentry *dentry,
                }
        }
 
+out_unlock:
        unlock_dir(lower_parent_dentry);
-
 out:
        dput(wh_dentry);
        kfree(name);
@@ -583,7 +583,7 @@ static int unionfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
        lower_parent_dentry = lock_parent(lower_dentry);
        if (IS_ERR(lower_parent_dentry)) {
                err = PTR_ERR(lower_parent_dentry);
-               goto out;
+               goto out_unlock;
        }
 
        err = vfs_mknod(lower_parent_dentry->d_inode, lower_dentry, mode, dev);
@@ -598,8 +598,8 @@ static int unionfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
                }
        }
 
+out_unlock:
        unlock_dir(lower_parent_dentry);
-
 out:
        dput(wh_dentry);
        kfree(name);