Commit 7521f22b authored by Al Viro's avatar Al Viro

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 957dd41d
...@@ -1687,7 +1687,7 @@ static const char *step_into(struct nameidata *nd, int flags, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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)) {
......
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