mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-04-01 12:04:08 +00:00
lift all calls of step_into() out of follow_dotdot/follow_dotdot_rcu
lift step_into() into handle_dots() (where they merge with each other); have follow_... return dentry and pass inode/seq to the caller. [braino fix folded; kudos to Qian Cai <cai@lca.pw> for reporting it] Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
6dfd9fe54d
commit
c2df196876
1 changed files with 37 additions and 34 deletions
63
fs/namei.c
63
fs/namei.c
|
@ -1687,31 +1687,29 @@ static const char *step_into(struct nameidata *nd, int flags,
|
||||||
return pick_link(nd, &path, inode, seq, flags);
|
return pick_link(nd, &path, inode, seq, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *follow_dotdot_rcu(struct nameidata *nd)
|
static struct dentry *follow_dotdot_rcu(struct nameidata *nd,
|
||||||
|
struct inode **inodep,
|
||||||
|
unsigned *seqp)
|
||||||
{
|
{
|
||||||
struct dentry *parent = NULL;
|
|
||||||
struct inode *inode = nd->inode;
|
|
||||||
unsigned seq;
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (path_equal(&nd->path, &nd->root))
|
if (path_equal(&nd->path, &nd->root))
|
||||||
break;
|
break;
|
||||||
if (nd->path.dentry != nd->path.mnt->mnt_root) {
|
if (nd->path.dentry != nd->path.mnt->mnt_root) {
|
||||||
struct dentry *old = nd->path.dentry;
|
struct dentry *old = nd->path.dentry;
|
||||||
|
struct dentry *parent = old->d_parent;
|
||||||
|
|
||||||
parent = old->d_parent;
|
*inodep = parent->d_inode;
|
||||||
inode = parent->d_inode;
|
*seqp = read_seqcount_begin(&parent->d_seq);
|
||||||
seq = read_seqcount_begin(&parent->d_seq);
|
|
||||||
if (unlikely(read_seqcount_retry(&old->d_seq, nd->seq)))
|
if (unlikely(read_seqcount_retry(&old->d_seq, nd->seq)))
|
||||||
return ERR_PTR(-ECHILD);
|
return ERR_PTR(-ECHILD);
|
||||||
if (unlikely(!path_connected(nd->path.mnt, parent)))
|
if (unlikely(!path_connected(nd->path.mnt, parent)))
|
||||||
return ERR_PTR(-ECHILD);
|
return ERR_PTR(-ECHILD);
|
||||||
break;
|
return parent;
|
||||||
} else {
|
} else {
|
||||||
struct mount *mnt = real_mount(nd->path.mnt);
|
struct mount *mnt = real_mount(nd->path.mnt);
|
||||||
struct mount *mparent = mnt->mnt_parent;
|
struct mount *mparent = mnt->mnt_parent;
|
||||||
struct dentry *mountpoint = mnt->mnt_mountpoint;
|
struct dentry *mountpoint = mnt->mnt_mountpoint;
|
||||||
struct inode *inode2 = mountpoint->d_inode;
|
struct inode *inode = mountpoint->d_inode;
|
||||||
unsigned seq = read_seqcount_begin(&mountpoint->d_seq);
|
unsigned seq = read_seqcount_begin(&mountpoint->d_seq);
|
||||||
if (unlikely(read_seqretry(&mount_lock, nd->m_seq)))
|
if (unlikely(read_seqretry(&mount_lock, nd->m_seq)))
|
||||||
return ERR_PTR(-ECHILD);
|
return ERR_PTR(-ECHILD);
|
||||||
|
@ -1722,54 +1720,51 @@ static const char *follow_dotdot_rcu(struct nameidata *nd)
|
||||||
/* we know that mountpoint was pinned */
|
/* we know that mountpoint was pinned */
|
||||||
nd->path.dentry = mountpoint;
|
nd->path.dentry = mountpoint;
|
||||||
nd->path.mnt = &mparent->mnt;
|
nd->path.mnt = &mparent->mnt;
|
||||||
inode = nd->inode = inode2;
|
nd->inode = inode;
|
||||||
nd->seq = seq;
|
nd->seq = seq;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (unlikely(!parent)) {
|
|
||||||
if (unlikely(nd->flags & LOOKUP_BENEATH))
|
if (unlikely(nd->flags & LOOKUP_BENEATH))
|
||||||
return ERR_PTR(-ECHILD);
|
return ERR_PTR(-ECHILD);
|
||||||
return step_into(nd, WALK_NOFOLLOW,
|
return NULL;
|
||||||
nd->path.dentry, nd->inode, nd->seq);
|
|
||||||
} else {
|
|
||||||
return step_into(nd, WALK_NOFOLLOW, parent, inode, seq);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *follow_dotdot(struct nameidata *nd)
|
static struct dentry *follow_dotdot(struct nameidata *nd,
|
||||||
|
struct inode **inodep,
|
||||||
|
unsigned *seqp)
|
||||||
{
|
{
|
||||||
struct dentry *parent = NULL;
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (path_equal(&nd->path, &nd->root))
|
if (path_equal(&nd->path, &nd->root))
|
||||||
break;
|
break;
|
||||||
if (nd->path.dentry != nd->path.mnt->mnt_root) {
|
if (nd->path.dentry != nd->path.mnt->mnt_root) {
|
||||||
/* rare case of legitimate dget_parent()... */
|
/* rare case of legitimate dget_parent()... */
|
||||||
parent = dget_parent(nd->path.dentry);
|
struct dentry *parent = dget_parent(nd->path.dentry);
|
||||||
if (unlikely(!path_connected(nd->path.mnt, parent))) {
|
if (unlikely(!path_connected(nd->path.mnt, parent))) {
|
||||||
dput(parent);
|
dput(parent);
|
||||||
return ERR_PTR(-ENOENT);
|
return ERR_PTR(-ENOENT);
|
||||||
}
|
}
|
||||||
break;
|
*seqp = 0;
|
||||||
|
*inodep = parent->d_inode;
|
||||||
|
return parent;
|
||||||
}
|
}
|
||||||
if (!follow_up(&nd->path))
|
if (!follow_up(&nd->path))
|
||||||
break;
|
break;
|
||||||
if (unlikely(nd->flags & LOOKUP_NO_XDEV))
|
if (unlikely(nd->flags & LOOKUP_NO_XDEV))
|
||||||
return ERR_PTR(-EXDEV);
|
return ERR_PTR(-EXDEV);
|
||||||
}
|
}
|
||||||
if (unlikely(!parent)) {
|
|
||||||
if (unlikely(nd->flags & LOOKUP_BENEATH))
|
if (unlikely(nd->flags & LOOKUP_BENEATH))
|
||||||
return ERR_PTR(-EXDEV);
|
return ERR_PTR(-EXDEV);
|
||||||
return step_into(nd, WALK_NOFOLLOW,
|
dget(nd->path.dentry);
|
||||||
dget(nd->path.dentry), nd->inode, nd->seq);
|
return NULL;
|
||||||
} else {
|
|
||||||
return step_into(nd, WALK_NOFOLLOW, parent, parent->d_inode, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *handle_dots(struct nameidata *nd, int type)
|
static const char *handle_dots(struct nameidata *nd, int type)
|
||||||
{
|
{
|
||||||
if (type == LAST_DOTDOT) {
|
if (type == LAST_DOTDOT) {
|
||||||
const char *error = NULL;
|
const char *error = NULL;
|
||||||
|
struct dentry *parent;
|
||||||
|
struct inode *inode;
|
||||||
|
unsigned seq;
|
||||||
|
|
||||||
if (!nd->root.mnt) {
|
if (!nd->root.mnt) {
|
||||||
error = ERR_PTR(set_root(nd));
|
error = ERR_PTR(set_root(nd));
|
||||||
|
@ -1777,10 +1772,18 @@ static const char *handle_dots(struct nameidata *nd, int type)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
if (nd->flags & LOOKUP_RCU)
|
if (nd->flags & LOOKUP_RCU)
|
||||||
error = follow_dotdot_rcu(nd);
|
parent = follow_dotdot_rcu(nd, &inode, &seq);
|
||||||
else
|
else
|
||||||
error = follow_dotdot(nd);
|
parent = follow_dotdot(nd, &inode, &seq);
|
||||||
if (error)
|
if (IS_ERR(parent))
|
||||||
|
return ERR_CAST(parent);
|
||||||
|
if (unlikely(!parent))
|
||||||
|
error = step_into(nd, WALK_NOFOLLOW,
|
||||||
|
nd->path.dentry, nd->inode, nd->seq);
|
||||||
|
else
|
||||||
|
error = step_into(nd, WALK_NOFOLLOW,
|
||||||
|
parent, inode, seq);
|
||||||
|
if (unlikely(error))
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
if (unlikely(nd->flags & LOOKUP_IS_SCOPED)) {
|
if (unlikely(nd->flags & LOOKUP_IS_SCOPED)) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue