Unionfs: unlock lower parent inode correctly on error path
authorErez Zadok <ezk@cs.sunysb.edu>
Fri, 4 Dec 2009 00:06:00 +0000 (19:06 -0500)
committerErez Zadok <ezk@cs.sunysb.edu>
Fri, 4 Dec 2009 00:06:00 +0000 (19:06 -0500)
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 26ec0e00b708d7c34af70b7375e53e8c55af2e23..40e4a722b5d357e44f3edc12c4110c65482e7214 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;
@@ -407,8 +407,8 @@ static int unionfs_symlink(struct inode *dir, struct dentry *dentry,
                }
        }
 
+out_unlock:
        unlock_dir(lower_parent_dentry);
-
 out:
        dput(wh_dentry);
        kfree(name);
@@ -584,7 +584,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);
@@ -599,8 +599,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);