kill __link_path_walk()/link_path_walk() distinction
authorAl Viro <viro@zeniv.linux.org.uk>
Sat, 8 Aug 2009 21:41:57 +0000 (01:41 +0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Wed, 16 Dec 2009 17:16:43 +0000 (12:16 -0500)
put retry logics into path_walk() and do_filp_open()

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

index 30c61c2..89e3805 100644 (file)
  * any extra contention...
  */
 
-static int __link_path_walk(const char *name, struct nameidata *nd);
-
 /* In order to reduce some races, while at the same time doing additional
  * checking and hopefully speeding things up, we copy filenames to the
  * kernel data space before using them..
@@ -529,35 +527,6 @@ out_unlock:
        return result;
 }
 
-/*
- * Wrapper to retry pathname resolution whenever the underlying
- * file system returns an ESTALE.
- *
- * Retry the whole path once, forcing real lookup requests
- * instead of relying on the dcache.
- */
-static __always_inline int link_path_walk(const char *name, struct nameidata *nd)
-{
-       struct path save = nd->path;
-       int result;
-
-       /* make sure the stuff we saved doesn't go away */
-       path_get(&save);
-
-       result = __link_path_walk(name, nd);
-       if (result == -ESTALE) {
-               /* nd->path had been dropped */
-               nd->path = save;
-               path_get(&nd->path);
-               nd->flags |= LOOKUP_REVAL;
-               result = __link_path_walk(name, nd);
-       }
-
-       path_put(&save);
-
-       return result;
-}
-
 static __always_inline void set_root(struct nameidata *nd)
 {
        if (!nd->root.mnt) {
@@ -569,6 +538,8 @@ static __always_inline void set_root(struct nameidata *nd)
        }
 }
 
+static int link_path_walk(const char *, struct nameidata *);
+
 static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link)
 {
        int res = 0;
@@ -834,7 +805,7 @@ fail:
  * Returns 0 and nd will have valid dentry and mnt on success.
  * Returns error and drops reference to input namei data on failure.
  */
-static int __link_path_walk(const char *name, struct nameidata *nd)
+static int link_path_walk(const char *name, struct nameidata *nd)
 {
        struct path next;
        struct inode *inode;
@@ -1016,8 +987,27 @@ return_err:
 
 static int path_walk(const char *name, struct nameidata *nd)
 {
+       struct path save = nd->path;
+       int result;
+
        current->total_link_count = 0;
-       return link_path_walk(name, nd);
+
+       /* make sure the stuff we saved doesn't go away */
+       path_get(&save);
+
+       result = link_path_walk(name, nd);
+       if (result == -ESTALE) {
+               /* nd->path had been dropped */
+               current->total_link_count = 0;
+               nd->path = save;
+               path_get(&nd->path);
+               nd->flags |= LOOKUP_REVAL;
+               result = link_path_walk(name, nd);
+       }
+
+       path_put(&save);
+
+       return result;
 }
 
 static int path_init(int dfd, const char *name, unsigned int flags, struct nameidata *nd)
@@ -1649,7 +1639,7 @@ struct file *do_filp_open(int dfd, const char *pathname,
        struct file *filp;
        struct nameidata nd;
        int error;
-       struct path path;
+       struct path path, save;
        struct dentry *dir;
        int count = 0;
        int will_write;
@@ -1862,7 +1852,17 @@ do_link:
        error = security_inode_follow_link(path.dentry, &nd);
        if (error)
                goto exit_dput;
+       save = nd.path;
+       path_get(&save);
        error = __do_follow_link(&path, &nd);
+       if (error == -ESTALE) {
+               /* nd.path had been dropped */
+               nd.path = save;
+               path_get(&nd.path);
+               nd.flags |= LOOKUP_REVAL;
+               error = __do_follow_link(&path, &nd);
+       }
+       path_put(&save);
        path_put(&path);
        if (error) {
                /* Does someone understand code flow here? Or it is only