namei: fold put_link() into the failure case of complete_walk()
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 8 May 2015 20:28:42 +0000 (16:28 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 11 May 2015 02:20:17 +0000 (22:20 -0400)
... and don't open-code unlazy_walk() in there - the only reason
for that is to avoid verfication of cached nd->root, which is
trivially avoided by discarding said cached nd->root first.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/namei.c

index c6ff9da69cec5da2c85f17ca71f3760dd60fdc8d..55283fe952457a23c3fa02ea5131be048c42e05f 100644 (file)
@@ -567,6 +567,8 @@ static inline int nd_alloc_stack(struct nameidata *nd)
  * to restart the path walk from the beginning in ref-walk mode.
  */
 
+static void terminate_walk(struct nameidata *nd);
+
 /**
  * unlazy_walk - try to switch to ref-walk mode.
  * @nd: nameidata pathwalk data
@@ -673,26 +675,12 @@ static int complete_walk(struct nameidata *nd)
        int status;
 
        if (nd->flags & LOOKUP_RCU) {
-               nd->flags &= ~LOOKUP_RCU;
                if (!(nd->flags & LOOKUP_ROOT))
                        nd->root.mnt = NULL;
-
-               if (!legitimize_mnt(nd->path.mnt, nd->m_seq)) {
-                       rcu_read_unlock();
-                       return -ECHILD;
-               }
-               if (unlikely(!lockref_get_not_dead(&dentry->d_lockref))) {
-                       rcu_read_unlock();
-                       mntput(nd->path.mnt);
-                       return -ECHILD;
-               }
-               if (read_seqcount_retry(&dentry->d_seq, nd->seq)) {
-                       rcu_read_unlock();
-                       dput(dentry);
-                       mntput(nd->path.mnt);
+               if (unlikely(unlazy_walk(nd, NULL))) {
+                       terminate_walk(nd);
                        return -ECHILD;
                }
-               rcu_read_unlock();
        }
 
        if (likely(!(nd->flags & LOOKUP_JUMPED)))
@@ -708,7 +696,7 @@ static int complete_walk(struct nameidata *nd)
        if (!status)
                status = -ESTALE;
 
-       path_put(&nd->path);
+       terminate_walk(nd);
        return status;
 }
 
@@ -3008,11 +2996,8 @@ static int do_last(struct nameidata *nd,
                 * about to look up
                 */
                error = complete_walk(nd);
-               if (error) {
-                       if (nd->depth)
-                               put_link(nd);
+               if (error)
                        return error;
-               }
 
                audit_inode(name, dir, LOOKUP_PARENT);
                error = -EISDIR;
@@ -3117,8 +3102,6 @@ finish_lookup:
 finish_open:
        error = complete_walk(nd);
        if (error) {
-               if (nd->depth)
-                       put_link(nd);
                path_put(&save_parent);
                return error;
        }