]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/namei.c
Merge branch 'work.autofs' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[linux.git] / fs / namei.c
index 2af485ddc507a2f0166f5363ea864b056762ce29..671c3c1a3425bab83d07a6b1091360dc7d03b9f0 100644 (file)
@@ -596,14 +596,12 @@ static void terminate_walk(struct nameidata *nd)
                path_put(&nd->path);
                for (i = 0; i < nd->depth; i++)
                        path_put(&nd->stack[i].link);
-               if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT)) {
+               if (nd->flags & LOOKUP_ROOT_GRABBED) {
                        path_put(&nd->root);
-                       nd->root.mnt = NULL;
+                       nd->flags &= ~LOOKUP_ROOT_GRABBED;
                }
        } else {
                nd->flags &= ~LOOKUP_RCU;
-               if (!(nd->flags & LOOKUP_ROOT))
-                       nd->root.mnt = NULL;
                rcu_read_unlock();
        }
        nd->depth = 0;
@@ -645,6 +643,7 @@ static bool legitimize_root(struct nameidata *nd)
 {
        if (!nd->root.mnt || (nd->flags & LOOKUP_ROOT))
                return true;
+       nd->flags |= LOOKUP_ROOT_GRABBED;
        return legitimize_path(nd, &nd->root, nd->root_seq);
 }
 
@@ -678,21 +677,18 @@ static int unlazy_walk(struct nameidata *nd)
 
        nd->flags &= ~LOOKUP_RCU;
        if (unlikely(!legitimize_links(nd)))
-               goto out2;
-       if (unlikely(!legitimize_path(nd, &nd->path, nd->seq)))
                goto out1;
+       if (unlikely(!legitimize_path(nd, &nd->path, nd->seq)))
+               goto out;
        if (unlikely(!legitimize_root(nd)))
                goto out;
        rcu_read_unlock();
        BUG_ON(nd->inode != parent->d_inode);
        return 0;
 
-out2:
+out1:
        nd->path.mnt = NULL;
        nd->path.dentry = NULL;
-out1:
-       if (!(nd->flags & LOOKUP_ROOT))
-               nd->root.mnt = NULL;
 out:
        rcu_read_unlock();
        return -ECHILD;
@@ -732,21 +728,14 @@ static int unlazy_child(struct nameidata *nd, struct dentry *dentry, unsigned se
         */
        if (unlikely(!lockref_get_not_dead(&dentry->d_lockref)))
                goto out;
-       if (unlikely(read_seqcount_retry(&dentry->d_seq, seq))) {
-               rcu_read_unlock();
-               dput(dentry);
-               goto drop_root_mnt;
-       }
+       if (unlikely(read_seqcount_retry(&dentry->d_seq, seq)))
+               goto out_dput;
        /*
         * Sequence counts matched. Now make sure that the root is
         * still valid and get it if required.
         */
-       if (unlikely(!legitimize_root(nd))) {
-               rcu_read_unlock();
-               dput(dentry);
-               return -ECHILD;
-       }
-
+       if (unlikely(!legitimize_root(nd)))
+               goto out_dput;
        rcu_read_unlock();
        return 0;
 
@@ -756,9 +745,10 @@ static int unlazy_child(struct nameidata *nd, struct dentry *dentry, unsigned se
        nd->path.dentry = NULL;
 out:
        rcu_read_unlock();
-drop_root_mnt:
-       if (!(nd->flags & LOOKUP_ROOT))
-               nd->root.mnt = NULL;
+       return -ECHILD;
+out_dput:
+       rcu_read_unlock();
+       dput(dentry);
        return -ECHILD;
 }
 
@@ -822,6 +812,7 @@ static void set_root(struct nameidata *nd)
                } while (read_seqcount_retry(&fs->seq, seq));
        } else {
                get_fs_root(fs, &nd->root);
+               nd->flags |= LOOKUP_ROOT_GRABBED;
        }
 }
 
@@ -1738,8 +1729,6 @@ static int pick_link(struct nameidata *nd, struct path *link,
                                nd->flags &= ~LOOKUP_RCU;
                                nd->path.mnt = NULL;
                                nd->path.dentry = NULL;
-                               if (!(nd->flags & LOOKUP_ROOT))
-                                       nd->root.mnt = NULL;
                                rcu_read_unlock();
                        } else if (likely(unlazy_walk(nd)) == 0)
                                error = nd_alloc_stack(nd);