Commit 9850c056 authored by Al Viro's avatar Al Viro

Fix the -ESTALE handling in do_filp_open()

Instead of playing sick games with path saving, cleanups, just retry
the entire thing once with LOOKUP_REVAL added.  Post-.34 we'll convert
all -ESTALE handling in there to that style, rather than playing with
many retry loops deep in the call chain.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 806892e9
...@@ -1604,11 +1604,12 @@ struct file *do_filp_open(int dfd, const char *pathname, ...@@ -1604,11 +1604,12 @@ 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, save; struct path path;
struct dentry *dir; struct dentry *dir;
int count = 0; int count = 0;
int will_truncate; int will_truncate;
int flag = open_to_namei_flags(open_flag); int flag = open_to_namei_flags(open_flag);
int force_reval = 0;
/* /*
* O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only * O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only
...@@ -1660,9 +1661,12 @@ struct file *do_filp_open(int dfd, const char *pathname, ...@@ -1660,9 +1661,12 @@ struct file *do_filp_open(int dfd, const char *pathname,
/* /*
* Create - we need to know the parent. * Create - we need to know the parent.
*/ */
reval:
error = path_init(dfd, pathname, LOOKUP_PARENT, &nd); error = path_init(dfd, pathname, LOOKUP_PARENT, &nd);
if (error) if (error)
return ERR_PTR(error); return ERR_PTR(error);
if (force_reval)
nd.flags |= LOOKUP_REVAL;
error = path_walk(pathname, &nd); error = path_walk(pathname, &nd);
if (error) { if (error) {
if (nd.root.mnt) if (nd.root.mnt)
...@@ -1854,17 +1858,7 @@ struct file *do_filp_open(int dfd, const char *pathname, ...@@ -1854,17 +1858,7 @@ struct file *do_filp_open(int dfd, const char *pathname,
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
...@@ -1874,6 +1868,10 @@ struct file *do_filp_open(int dfd, const char *pathname, ...@@ -1874,6 +1868,10 @@ struct file *do_filp_open(int dfd, const char *pathname,
release_open_intent(&nd); release_open_intent(&nd);
if (nd.root.mnt) if (nd.root.mnt)
path_put(&nd.root); path_put(&nd.root);
if (error == -ESTALE && !force_reval) {
force_reval = 1;
goto reval;
}
return ERR_PTR(error); return ERR_PTR(error);
} }
nd.flags &= ~LOOKUP_PARENT; nd.flags &= ~LOOKUP_PARENT;
......
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