enable passing fast relative symlinks without dropping out of RCU mode
authorAl Viro <viro@zeniv.linux.org.uk>
Sat, 9 May 2015 22:15:21 +0000 (18:15 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Fri, 15 May 2015 05:06:28 +0000 (01:06 -0400)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/namei.c

index d9f77ff60b557de0edb575b760781bf1418fc20c..bf46e1010a744aaa50e686f46a3c913246de1b31 100644 (file)
@@ -975,11 +975,6 @@ const char *get_link(struct nameidata *nd)
                touch_atime(&last->link);
        }
 
-       if (nd->flags & LOOKUP_RCU) {
-               if (unlikely(unlazy_walk(nd, NULL, 0)))
-                       return ERR_PTR(-ECHILD);
-       }
-
        error = security_inode_follow_link(dentry, inode,
                                           nd->flags & LOOKUP_RCU);
        if (unlikely(error))
@@ -988,6 +983,10 @@ const char *get_link(struct nameidata *nd)
        nd->last_type = LAST_BIND;
        res = inode->i_link;
        if (!res) {
+               if (nd->flags & LOOKUP_RCU) {
+                       if (unlikely(unlazy_walk(nd, NULL, 0)))
+                               return ERR_PTR(-ECHILD);
+               }
                res = inode->i_op->follow_link(dentry, &last->cookie);
                if (IS_ERR_OR_NULL(res)) {
                        last->cookie = NULL;
@@ -995,6 +994,10 @@ const char *get_link(struct nameidata *nd)
                }
        }
        if (*res == '/') {
+               if (nd->flags & LOOKUP_RCU) {
+                       if (unlikely(unlazy_walk(nd, NULL, 0)))
+                               return ERR_PTR(-ECHILD);
+               }
                if (!nd->root.mnt)
                        set_root(nd);
                path_put(&nd->path);