handle_dots(), follow_dotdot{,_rcu}(): preparation to switch to step_into()
Right now the tail ends of follow_dotdot{,_rcu}() are pretty much the open-coded analogues of step_into(). The differences: * the lack of proper LOOKUP_NO_XDEV handling in non-RCU case (arguably a bug) * the lack of ->d_manage() handling (again, arguably a bug) Adjust the calling conventions so that on the next step with could just switch those functions to returning step_into(). Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
957dd41d88
commit
7521f22b3c
52
fs/namei.c
52
fs/namei.c
@ -1687,7 +1687,7 @@ 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 int follow_dotdot_rcu(struct nameidata *nd)
|
static const char *follow_dotdot_rcu(struct nameidata *nd)
|
||||||
{
|
{
|
||||||
struct dentry *parent = NULL;
|
struct dentry *parent = NULL;
|
||||||
struct inode *inode = nd->inode;
|
struct inode *inode = nd->inode;
|
||||||
@ -1703,9 +1703,9 @@ static int follow_dotdot_rcu(struct nameidata *nd)
|
|||||||
inode = parent->d_inode;
|
inode = parent->d_inode;
|
||||||
seq = 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 -ECHILD;
|
return ERR_PTR(-ECHILD);
|
||||||
if (unlikely(!path_connected(nd->path.mnt, parent)))
|
if (unlikely(!path_connected(nd->path.mnt, parent)))
|
||||||
return -ECHILD;
|
return ERR_PTR(-ECHILD);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
struct mount *mnt = real_mount(nd->path.mnt);
|
struct mount *mnt = real_mount(nd->path.mnt);
|
||||||
@ -1714,11 +1714,11 @@ static int follow_dotdot_rcu(struct nameidata *nd)
|
|||||||
struct inode *inode2 = mountpoint->d_inode;
|
struct inode *inode2 = 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 -ECHILD;
|
return ERR_PTR(-ECHILD);
|
||||||
if (&mparent->mnt == nd->path.mnt)
|
if (&mparent->mnt == nd->path.mnt)
|
||||||
break;
|
break;
|
||||||
if (unlikely(nd->flags & LOOKUP_NO_XDEV))
|
if (unlikely(nd->flags & LOOKUP_NO_XDEV))
|
||||||
return -ECHILD;
|
return ERR_PTR(-ECHILD);
|
||||||
/* 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;
|
||||||
@ -1728,7 +1728,7 @@ static int follow_dotdot_rcu(struct nameidata *nd)
|
|||||||
}
|
}
|
||||||
if (unlikely(!parent)) {
|
if (unlikely(!parent)) {
|
||||||
if (unlikely(nd->flags & LOOKUP_BENEATH))
|
if (unlikely(nd->flags & LOOKUP_BENEATH))
|
||||||
return -ECHILD;
|
return ERR_PTR(-ECHILD);
|
||||||
} else {
|
} else {
|
||||||
nd->path.dentry = parent;
|
nd->path.dentry = parent;
|
||||||
nd->seq = seq;
|
nd->seq = seq;
|
||||||
@ -1737,21 +1737,21 @@ static int follow_dotdot_rcu(struct nameidata *nd)
|
|||||||
struct mount *mounted;
|
struct mount *mounted;
|
||||||
mounted = __lookup_mnt(nd->path.mnt, nd->path.dentry);
|
mounted = __lookup_mnt(nd->path.mnt, nd->path.dentry);
|
||||||
if (unlikely(read_seqretry(&mount_lock, nd->m_seq)))
|
if (unlikely(read_seqretry(&mount_lock, nd->m_seq)))
|
||||||
return -ECHILD;
|
return ERR_PTR(-ECHILD);
|
||||||
if (!mounted)
|
if (!mounted)
|
||||||
break;
|
break;
|
||||||
if (unlikely(nd->flags & LOOKUP_NO_XDEV))
|
if (unlikely(nd->flags & LOOKUP_NO_XDEV))
|
||||||
return -ECHILD;
|
return ERR_PTR(-ECHILD);
|
||||||
nd->path.mnt = &mounted->mnt;
|
nd->path.mnt = &mounted->mnt;
|
||||||
nd->path.dentry = mounted->mnt.mnt_root;
|
nd->path.dentry = mounted->mnt.mnt_root;
|
||||||
inode = nd->path.dentry->d_inode;
|
inode = nd->path.dentry->d_inode;
|
||||||
nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
|
nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
|
||||||
}
|
}
|
||||||
nd->inode = inode;
|
nd->inode = inode;
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int follow_dotdot(struct nameidata *nd)
|
static const char *follow_dotdot(struct nameidata *nd)
|
||||||
{
|
{
|
||||||
struct dentry *parent = NULL;
|
struct dentry *parent = NULL;
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -1762,34 +1762,34 @@ static int follow_dotdot(struct nameidata *nd)
|
|||||||
parent = dget_parent(nd->path.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 -ENOENT;
|
return ERR_PTR(-ENOENT);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
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 -EXDEV;
|
return ERR_PTR(-EXDEV);
|
||||||
}
|
}
|
||||||
if (unlikely(!parent)) {
|
if (unlikely(!parent)) {
|
||||||
if (unlikely(nd->flags & LOOKUP_BENEATH))
|
if (unlikely(nd->flags & LOOKUP_BENEATH))
|
||||||
return -EXDEV;
|
return ERR_PTR(-EXDEV);
|
||||||
} else {
|
} else {
|
||||||
dput(nd->path.dentry);
|
dput(nd->path.dentry);
|
||||||
nd->path.dentry = parent;
|
nd->path.dentry = parent;
|
||||||
}
|
}
|
||||||
follow_mount(&nd->path);
|
follow_mount(&nd->path);
|
||||||
nd->inode = nd->path.dentry->d_inode;
|
nd->inode = nd->path.dentry->d_inode;
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int 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) {
|
||||||
int error = 0;
|
const char *error = NULL;
|
||||||
|
|
||||||
if (!nd->root.mnt) {
|
if (!nd->root.mnt) {
|
||||||
error = set_root(nd);
|
error = ERR_PTR(set_root(nd));
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -1809,12 +1809,12 @@ static inline int handle_dots(struct nameidata *nd, int type)
|
|||||||
*/
|
*/
|
||||||
smp_rmb();
|
smp_rmb();
|
||||||
if (unlikely(__read_seqcount_retry(&mount_lock.seqcount, nd->m_seq)))
|
if (unlikely(__read_seqcount_retry(&mount_lock.seqcount, nd->m_seq)))
|
||||||
return -EAGAIN;
|
return ERR_PTR(-EAGAIN);
|
||||||
if (unlikely(__read_seqcount_retry(&rename_lock.seqcount, nd->r_seq)))
|
if (unlikely(__read_seqcount_retry(&rename_lock.seqcount, nd->r_seq)))
|
||||||
return -EAGAIN;
|
return ERR_PTR(-EAGAIN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *walk_component(struct nameidata *nd, int flags)
|
static const char *walk_component(struct nameidata *nd, int flags)
|
||||||
@ -1822,7 +1822,6 @@ static const char *walk_component(struct nameidata *nd, int flags)
|
|||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
unsigned seq;
|
unsigned seq;
|
||||||
int err;
|
|
||||||
/*
|
/*
|
||||||
* "." and ".." are special - ".." especially so because it has
|
* "." and ".." are special - ".." especially so because it has
|
||||||
* to be able to know about the current root directory and
|
* to be able to know about the current root directory and
|
||||||
@ -1831,8 +1830,7 @@ static const char *walk_component(struct nameidata *nd, int flags)
|
|||||||
if (unlikely(nd->last_type != LAST_NORM)) {
|
if (unlikely(nd->last_type != LAST_NORM)) {
|
||||||
if (!(flags & WALK_MORE) && nd->depth)
|
if (!(flags & WALK_MORE) && nd->depth)
|
||||||
put_link(nd);
|
put_link(nd);
|
||||||
err = handle_dots(nd, nd->last_type);
|
return handle_dots(nd, nd->last_type);
|
||||||
return ERR_PTR(err);
|
|
||||||
}
|
}
|
||||||
dentry = lookup_fast(nd, &inode, &seq);
|
dentry = lookup_fast(nd, &inode, &seq);
|
||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
@ -3128,10 +3126,10 @@ static const char *open_last_lookups(struct nameidata *nd,
|
|||||||
if (nd->last_type != LAST_NORM) {
|
if (nd->last_type != LAST_NORM) {
|
||||||
if (nd->depth)
|
if (nd->depth)
|
||||||
put_link(nd);
|
put_link(nd);
|
||||||
error = handle_dots(nd, nd->last_type);
|
res = handle_dots(nd, nd->last_type);
|
||||||
if (likely(!error))
|
if (likely(!res))
|
||||||
error = complete_walk(nd);
|
res = ERR_PTR(complete_walk(nd));
|
||||||
return ERR_PTR(error);
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(open_flag & O_CREAT)) {
|
if (!(open_flag & O_CREAT)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user