提交 ba8f4613 编写于 作者: A Al Viro

namei: saner calling conventions for mountpoint_last()

leave the result in nd->path, have caller do follow_mount() and
copy it to the final destination.
Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
上级 c1d4dd27
...@@ -2561,7 +2561,6 @@ EXPORT_SYMBOL(user_path_at_empty); ...@@ -2561,7 +2561,6 @@ EXPORT_SYMBOL(user_path_at_empty);
/** /**
* mountpoint_last - look up last component for umount * mountpoint_last - look up last component for umount
* @nd: pathwalk nameidata - currently pointing at parent directory of "last" * @nd: pathwalk nameidata - currently pointing at parent directory of "last"
* @path: pointer to container for result
* *
* This is a special lookup_last function just for umount. In this case, we * This is a special lookup_last function just for umount. In this case, we
* need to resolve the path without doing any revalidation. * need to resolve the path without doing any revalidation.
...@@ -2574,23 +2573,20 @@ EXPORT_SYMBOL(user_path_at_empty); ...@@ -2574,23 +2573,20 @@ EXPORT_SYMBOL(user_path_at_empty);
* *
* Returns: * Returns:
* -error: if there was an error during lookup. This includes -ENOENT if the * -error: if there was an error during lookup. This includes -ENOENT if the
* lookup found a negative dentry. The nd->path reference will also be * lookup found a negative dentry.
* put in this case.
* *
* 0: if we successfully resolved nd->path and found it to not to be a * 0: if we successfully resolved nd->last and found it to not to be a
* symlink that needs to be followed. "path" will also be populated. * symlink that needs to be followed.
* The nd->path reference will also be put.
* *
* 1: if we successfully resolved nd->last and found it to be a symlink * 1: if we successfully resolved nd->last and found it to be a symlink
* that needs to be followed. "path" will be populated with the path * that needs to be followed.
* to the link, and nd->path will *not* be put.
*/ */
static int static int
mountpoint_last(struct nameidata *nd, struct path *path) mountpoint_last(struct nameidata *nd)
{ {
int error = 0; int error = 0;
struct dentry *dentry;
struct dentry *dir = nd->path.dentry; struct dentry *dir = nd->path.dentry;
struct path path;
/* If we're in rcuwalk, drop out of it to handle last component */ /* If we're in rcuwalk, drop out of it to handle last component */
if (nd->flags & LOOKUP_RCU) { if (nd->flags & LOOKUP_RCU) {
...@@ -2604,36 +2600,34 @@ mountpoint_last(struct nameidata *nd, struct path *path) ...@@ -2604,36 +2600,34 @@ mountpoint_last(struct nameidata *nd, struct path *path)
error = handle_dots(nd, nd->last_type); error = handle_dots(nd, nd->last_type);
if (error) if (error)
return error; return error;
dentry = dget(nd->path.dentry); path.dentry = dget(nd->path.dentry);
} else { } else {
dentry = d_lookup(dir, &nd->last); path.dentry = d_lookup(dir, &nd->last);
if (!dentry) { if (!path.dentry) {
/* /*
* No cached dentry. Mounted dentries are pinned in the * No cached dentry. Mounted dentries are pinned in the
* cache, so that means that this dentry is probably * cache, so that means that this dentry is probably
* a symlink or the path doesn't actually point * a symlink or the path doesn't actually point
* to a mounted dentry. * to a mounted dentry.
*/ */
dentry = lookup_slow(&nd->last, dir, path.dentry = lookup_slow(&nd->last, dir,
nd->flags | LOOKUP_NO_REVAL); nd->flags | LOOKUP_NO_REVAL);
if (IS_ERR(dentry)) if (IS_ERR(path.dentry))
return PTR_ERR(dentry); return PTR_ERR(path.dentry);
} }
} }
if (d_is_negative(dentry)) { if (d_is_negative(path.dentry)) {
dput(dentry); dput(path.dentry);
return -ENOENT; return -ENOENT;
} }
if (nd->depth) if (nd->depth)
put_link(nd); put_link(nd);
path->dentry = dentry; path.mnt = nd->path.mnt;
path->mnt = nd->path.mnt; error = should_follow_link(nd, &path, nd->flags & LOOKUP_FOLLOW,
error = should_follow_link(nd, path, nd->flags & LOOKUP_FOLLOW, d_backing_inode(path.dentry), 0);
d_backing_inode(dentry), 0);
if (unlikely(error)) if (unlikely(error))
return error; return error;
mntget(path->mnt); path_to_nameidata(&path, nd);
follow_mount(path);
return 0; return 0;
} }
...@@ -2654,13 +2648,19 @@ path_mountpoint(struct nameidata *nd, unsigned flags, struct path *path) ...@@ -2654,13 +2648,19 @@ path_mountpoint(struct nameidata *nd, unsigned flags, struct path *path)
if (IS_ERR(s)) if (IS_ERR(s))
return PTR_ERR(s); return PTR_ERR(s);
while (!(err = link_path_walk(s, nd)) && while (!(err = link_path_walk(s, nd)) &&
(err = mountpoint_last(nd, path)) > 0) { (err = mountpoint_last(nd)) > 0) {
s = trailing_symlink(nd); s = trailing_symlink(nd);
if (IS_ERR(s)) { if (IS_ERR(s)) {
err = PTR_ERR(s); err = PTR_ERR(s);
break; break;
} }
} }
if (!err) {
*path = nd->path;
nd->path.mnt = NULL;
nd->path.dentry = NULL;
follow_mount(path);
}
terminate_walk(nd); terminate_walk(nd);
return err; return err;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册