OSDN Git Service

follow_automount() doesn't need the entire nameidata
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 17 Jan 2020 03:05:18 +0000 (22:05 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 27 Feb 2020 19:43:55 +0000 (14:43 -0500)
Only the address of ->total_link_count and the flags.
And fix an off-by-one is ELOOP detection - make it
consistent with symlink following, where we check if
the pre-increment value has reached 40, rather than
check the post-increment one.

[kudos to Christian Brauner for spotted braino]

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

index 39dd56f..6721c5f 100644 (file)
@@ -1208,7 +1208,7 @@ EXPORT_SYMBOL(follow_up);
  * - return -EISDIR to tell follow_managed() to stop and return the path we
  *   were called with.
  */
-static int follow_automount(struct path *path, struct nameidata *nd)
+static int follow_automount(struct path *path, int *count, unsigned lookup_flags)
 {
        struct dentry *dentry = path->dentry;
 
@@ -1223,13 +1223,12 @@ static int follow_automount(struct path *path, struct nameidata *nd)
         * as being automount points.  These will need the attentions
         * of the daemon to instantiate them before they can be used.
         */
-       if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY |
+       if (!(lookup_flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY |
                           LOOKUP_OPEN | LOOKUP_CREATE | LOOKUP_AUTOMOUNT)) &&
            dentry->d_inode)
                return -EISDIR;
 
-       nd->total_link_count++;
-       if (nd->total_link_count >= 40)
+       if (count && (*count)++ >= MAXSYMLINKS)
                return -ELOOP;
 
        return finish_automount(dentry->d_op->d_automount(path), path);
@@ -1290,7 +1289,8 @@ static int follow_managed(struct path *path, struct nameidata *nd)
 
                /* Handle an automount point */
                if (flags & DCACHE_NEED_AUTOMOUNT) {
-                       ret = follow_automount(path, nd);
+                       ret = follow_automount(path, &nd->total_link_count,
+                                               nd->flags);
                        if (ret < 0)
                                break;
                        continue;