Unionfs: lock base inode mutex around lookup_one_len
authorErez Zadok <ezk@cs.sunysb.edu>
Fri, 22 May 2009 01:02:31 +0000 (21:02 -0400)
committerErez Zadok <ezk@cs.sunysb.edu>
Fri, 12 Aug 2011 02:39:07 +0000 (22:39 -0400)
Signed-off-by: Erez Zadok <ezk@cs.sunysb.edu>
fs/unionfs/commonfops.c
fs/unionfs/copyup.c
fs/unionfs/lookup.c
fs/unionfs/union.h
fs/unionfs/whiteout.c

index e9dc23c5478d38c6f55a9ca139b9196305bda272..f1d66b3ca5522df2d23ff02f1ae6129678cc4daa 100644 (file)
@@ -62,7 +62,7 @@ retry:
                pr_debug("unionfs: trying to rename %s to %s\n",
                         dentry->d_name.name, name);
 
-               tmp_dentry = lookup_one_len(name, lower_dentry->d_parent,
+               tmp_dentry = lookup_lck_len(name, lower_dentry->d_parent,
                                            nlen);
                if (IS_ERR(tmp_dentry)) {
                        err = PTR_ERR(tmp_dentry);
index 3d0c0ca0beca2b31b64f259ec4e91a2e9d4f1b3b..c43cc7f133c28ba4d36d23e679407748b2f6ad8b 100644 (file)
@@ -778,7 +778,7 @@ begin:
 
        if (child_dentry != dentry) {
                /* lookup child in the underlying file system */
-               lower_dentry = lookup_one_len(childname, lower_parent_dentry,
+               lower_dentry = lookup_lck_len(childname, lower_parent_dentry,
                                              childnamelen);
                if (IS_ERR(lower_dentry))
                        goto out;
@@ -787,7 +787,7 @@ begin:
                 * Is the name a whiteout of the child name ?  lookup the
                 * whiteout child in the underlying file system
                 */
-               lower_dentry = lookup_one_len(name, lower_parent_dentry,
+               lower_dentry = lookup_lck_len(name, lower_parent_dentry,
                                              strlen(name));
                if (IS_ERR(lower_dentry))
                        goto out;
index 9d887ac5ff993adb96e769c7c7a8f5d7418f454c..6361541a5ce5a03237063378983419896bfdf322 100644 (file)
@@ -50,7 +50,7 @@ struct dentry *__lookup_one(struct dentry *base, struct vfsmount *mnt,
                  * it's safe to call lookup_one_len (which doesn't take a
                  * vfsmount).
                  */
-               dentry = lookup_one_len(name, base, strlen(name));
+               dentry = lookup_lck_len(name, base, strlen(name));
                if (new_mnt)
                        *new_mnt = mntget(lower_nd.path.mnt);
                break;
@@ -469,7 +469,7 @@ struct dentry *unionfs_lookup_full(struct dentry *dentry,
                if (!S_ISDIR(lower_dir_dentry->d_inode->i_mode))
                        goto out; /* XXX: should be BUG_ON */
                /* XXX: do we need to cross bind mounts here? */
-               lower_dentry = lookup_one_len(name, lower_dir_dentry, namelen);
+               lower_dentry = lookup_lck_len(name, lower_dir_dentry, namelen);
                if (IS_ERR(lower_dentry)) {
                        err = PTR_ERR(lower_dentry);
                        goto out;
index 1b2b86f4acf12b5826c90de46446e03439faecf0..1a05f63c5f9c9330a3ba206b8019421c95429438 100644 (file)
@@ -553,6 +553,17 @@ static inline void unlock_dir(struct dentry *dir)
        dput(dir);
 }
 
+/* lock base inode mutex before calling lookup_one_len */
+static inline struct dentry *lookup_lck_len(const char *name,
+                                           struct dentry *base, int len)
+{
+       struct dentry *d;
+       mutex_lock(&base->d_inode->i_mutex);
+       d = lookup_one_len(name, base, len);
+       mutex_unlock(&base->d_inode->i_mutex);
+       return d;
+}
+
 static inline struct vfsmount *unionfs_mntget(struct dentry *dentry,
                                              int bindex)
 {
index a55684d98aeddef05bd333e0ee91ae81818986e7..626006a3735d9e3860b7dccaff42206c4373d6fe 100644 (file)
@@ -101,7 +101,7 @@ struct dentry *lookup_whiteout(const char *name, struct dentry *lower_parent)
        }
 
        /* check if whiteout exists in this branch: lookup .wh.foo */
-       wh_dentry = lookup_one_len(whname, lower_parent, strlen(whname));
+       wh_dentry = lookup_lck_len(whname, lower_parent, strlen(whname));
        if (IS_ERR(wh_dentry)) {
                err = PTR_ERR(wh_dentry);
                goto out;
@@ -311,7 +311,7 @@ int create_whiteout(struct dentry *dentry, int start)
                }
 
                lower_wh_dentry =
-                       lookup_one_len(name, lower_dentry->d_parent,
+                       lookup_lck_len(name, lower_dentry->d_parent,
                                       dentry->d_name.len + UNIONFS_WHLEN);
                if (IS_ERR(lower_wh_dentry))
                        continue;
@@ -334,7 +334,7 @@ int create_whiteout(struct dentry *dentry, int start)
                if (!err)
                        err = vfs_create(lower_dir_dentry->d_inode,
                                         lower_wh_dentry,
-                                        ~current->fs->umask & S_IRUGO,
+                                        current_umask() & S_IRUGO,
                                         &nd);
                unlock_dir(lower_dir_dentry);
                dput(lower_wh_dentry);
@@ -397,7 +397,7 @@ static int do_delete_whiteouts(struct dentry *dentry, int bindex,
 
                        strlcpy(p, cursor->name, PATH_MAX - UNIONFS_WHLEN);
                        lower_dentry =
-                               lookup_one_len(name, lower_dir_dentry,
+                               lookup_lck_len(name, lower_dir_dentry,
                                               cursor->namelen +
                                               UNIONFS_WHLEN);
                        if (IS_ERR(lower_dentry)) {