Commit 806b681c authored by Al Viro's avatar Al Viro

Turn do_link spaghetty into a normal loop

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 10fa8e62
...@@ -1844,39 +1844,20 @@ struct file *do_filp_open(int dfd, const char *pathname, ...@@ -1844,39 +1844,20 @@ struct file *do_filp_open(int dfd, const char *pathname,
if (open_flag & O_EXCL) if (open_flag & O_EXCL)
nd.flags |= LOOKUP_EXCL; nd.flags |= LOOKUP_EXCL;
filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname); filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname);
if (!filp) while (unlikely(!filp)) { /* trailing symlink */
goto do_link;
goto out;
exit_dput:
path_put_conditional(&path, &nd);
if (!IS_ERR(nd.intent.open.file))
release_open_intent(&nd);
exit_parent:
path_put(&nd.path);
filp = ERR_PTR(error);
out:
if (nd.root.mnt)
path_put(&nd.root);
if (filp == ERR_PTR(-ESTALE) && !force_reval) {
force_reval = 1;
goto reval;
}
return filp;
do_link:
error = -ELOOP; error = -ELOOP;
if ((open_flag & O_NOFOLLOW) || count++ == 32) if ((open_flag & O_NOFOLLOW) || count++ == 32)
goto exit_dput; goto exit_dput;
/* /*
* This is subtle. Instead of calling do_follow_link() we do the * This is subtle. Instead of calling do_follow_link() we do
* thing by hands. The reason is that this way we have zero link_count * the thing by hands. The reason is that this way we have zero
* and path_walk() (called from ->follow_link) honoring LOOKUP_PARENT. * link_count and path_walk() (called from ->follow_link)
* After that we have the parent and last component, i.e. * honoring LOOKUP_PARENT. After that we have the parent and
* we are in the same situation as after the first path_walk(). * last component, i.e. we are in the same situation as after
* Well, almost - if the last component is normal we get its copy * the first path_walk(). Well, almost - if the last component
* stored in nd->last.name and we will have to putname() it when we * is normal we get its copy stored in nd->last.name and we will
* are done. Procfs-like symlinks just set LAST_BIND. * have to putname() it when we are done. Procfs-like symlinks
* just set LAST_BIND.
*/ */
nd.flags |= LOOKUP_PARENT; nd.flags |= LOOKUP_PARENT;
error = security_inode_follow_link(path.dentry, &nd); error = security_inode_follow_link(path.dentry, &nd);
...@@ -1885,10 +1866,7 @@ struct file *do_filp_open(int dfd, const char *pathname, ...@@ -1885,10 +1866,7 @@ struct file *do_filp_open(int dfd, const char *pathname,
error = __do_follow_link(&path, &nd); error = __do_follow_link(&path, &nd);
path_put(&path); path_put(&path);
if (error) { if (error) {
/* Does someone understand code flow here? Or it is only /* nd.path had been dropped */
* me so stupid? Anathema to whoever designed this non-sense
* with "intent.open".
*/
release_open_intent(&nd); release_open_intent(&nd);
filp = ERR_PTR(error); filp = ERR_PTR(error);
goto out; goto out;
...@@ -1897,8 +1875,23 @@ struct file *do_filp_open(int dfd, const char *pathname, ...@@ -1897,8 +1875,23 @@ struct file *do_filp_open(int dfd, const char *pathname,
filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname); filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname);
if (nd.last_type == LAST_NORM) if (nd.last_type == LAST_NORM)
__putname(nd.last.name); __putname(nd.last.name);
if (!filp) }
goto do_link; out:
if (nd.root.mnt)
path_put(&nd.root);
if (filp == ERR_PTR(-ESTALE) && !force_reval) {
force_reval = 1;
goto reval;
}
return filp;
exit_dput:
path_put_conditional(&path, &nd);
if (!IS_ERR(nd.intent.open.file))
release_open_intent(&nd);
exit_parent:
path_put(&nd.path);
filp = ERR_PTR(error);
goto out; goto out;
} }
......
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