Commit 6de88d72 authored by Al Viro's avatar Al Viro

kill __link_path_walk()/link_path_walk() distinction

put retry logics into path_walk() and do_filp_open()
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 258fa999
...@@ -108,8 +108,6 @@ ...@@ -108,8 +108,6 @@
* any extra contention... * 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 /* In order to reduce some races, while at the same time doing additional
* checking and hopefully speeding things up, we copy filenames to the * checking and hopefully speeding things up, we copy filenames to the
* kernel data space before using them.. * kernel data space before using them..
...@@ -529,35 +527,6 @@ out_unlock: ...@@ -529,35 +527,6 @@ out_unlock:
return result; 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) static __always_inline void set_root(struct nameidata *nd)
{ {
if (!nd->root.mnt) { if (!nd->root.mnt) {
...@@ -569,6 +538,8 @@ static __always_inline void set_root(struct nameidata *nd) ...@@ -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) static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link)
{ {
int res = 0; int res = 0;
...@@ -834,7 +805,7 @@ fail: ...@@ -834,7 +805,7 @@ fail:
* Returns 0 and nd will have valid dentry and mnt on success. * Returns 0 and nd will have valid dentry and mnt on success.
* Returns error and drops reference to input namei data on failure. * 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 path next;
struct inode *inode; struct inode *inode;
...@@ -1016,8 +987,27 @@ return_err: ...@@ -1016,8 +987,27 @@ return_err:
static int path_walk(const char *name, struct nameidata *nd) static int path_walk(const char *name, struct nameidata *nd)
{ {
struct path save = nd->path;
int result;
current->total_link_count = 0; 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) 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, ...@@ -1649,7 +1639,7 @@ struct file *do_filp_open(int dfd, const char *pathname,
struct file *filp; struct file *filp;
struct nameidata nd; struct nameidata nd;
int error; int error;
struct path path; struct path path, save;
struct dentry *dir; struct dentry *dir;
int count = 0; int count = 0;
int will_write; int will_write;
...@@ -1862,7 +1852,17 @@ do_link: ...@@ -1862,7 +1852,17 @@ do_link:
error = security_inode_follow_link(path.dentry, &nd); error = security_inode_follow_link(path.dentry, &nd);
if (error) if (error)
goto exit_dput; goto exit_dput;
save = nd.path;
path_get(&save);
error = __do_follow_link(&path, &nd); 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); path_put(&path);
if (error) { if (error) {
/* Does someone understand code flow here? Or it is only /* Does someone understand code flow here? Or it is only
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment