step_into(): lose inode argument
make handle_mounts() always fetch it. This is just the first step - the callers of step_into() will stop trying to calculate the sucker, etc. The passed value should be equal to dentry->d_inode in all cases; in RCU mode - fetched after we'd sampled ->d_seq. Might as well fetch it here. We do need to validate ->d_seq, which duplicates the check currently done in lookup_fast(); that duplication will go away shortly. After that change handle_mounts() always ignores the initial value of *inode and always sets it on success. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
03fa86e9f7
commit
a4f5b52167
15
fs/namei.c
15
fs/namei.c
|
@ -1536,6 +1536,9 @@ static inline int handle_mounts(struct nameidata *nd, struct dentry *dentry,
|
|||
path->dentry = dentry;
|
||||
if (nd->flags & LOOKUP_RCU) {
|
||||
unsigned int seq = nd->next_seq;
|
||||
*inode = dentry->d_inode;
|
||||
if (read_seqcount_retry(&dentry->d_seq, seq))
|
||||
return -ECHILD;
|
||||
if (unlikely(!*inode))
|
||||
return -ENOENT;
|
||||
if (likely(__follow_mount_rcu(nd, path, inode)))
|
||||
|
@ -1848,9 +1851,10 @@ all_done: // pure jump
|
|||
* NOTE: dentry must be what nd->next_seq had been sampled from.
|
||||
*/
|
||||
static const char *step_into(struct nameidata *nd, int flags,
|
||||
struct dentry *dentry, struct inode *inode)
|
||||
struct dentry *dentry)
|
||||
{
|
||||
struct path path;
|
||||
struct inode *inode;
|
||||
int err = handle_mounts(nd, dentry, &path, &inode);
|
||||
|
||||
if (err < 0)
|
||||
|
@ -1976,7 +1980,7 @@ static const char *handle_dots(struct nameidata *nd, int type)
|
|||
parent = follow_dotdot(nd, &inode);
|
||||
if (IS_ERR(parent))
|
||||
return ERR_CAST(parent);
|
||||
error = step_into(nd, WALK_NOFOLLOW, parent, inode);
|
||||
error = step_into(nd, WALK_NOFOLLOW, parent);
|
||||
if (unlikely(error))
|
||||
return error;
|
||||
|
||||
|
@ -2021,7 +2025,7 @@ static const char *walk_component(struct nameidata *nd, int flags)
|
|||
}
|
||||
if (!(flags & WALK_MORE) && nd->depth)
|
||||
put_link(nd);
|
||||
return step_into(nd, flags, dentry, inode);
|
||||
return step_into(nd, flags, dentry);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2480,8 +2484,7 @@ static int handle_lookup_down(struct nameidata *nd)
|
|||
if (!(nd->flags & LOOKUP_RCU))
|
||||
dget(nd->path.dentry);
|
||||
nd->next_seq = nd->seq;
|
||||
return PTR_ERR(step_into(nd, WALK_NOFOLLOW,
|
||||
nd->path.dentry, nd->inode));
|
||||
return PTR_ERR(step_into(nd, WALK_NOFOLLOW, nd->path.dentry));
|
||||
}
|
||||
|
||||
/* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
|
||||
|
@ -3470,7 +3473,7 @@ static const char *open_last_lookups(struct nameidata *nd,
|
|||
finish_lookup:
|
||||
if (nd->depth)
|
||||
put_link(nd);
|
||||
res = step_into(nd, WALK_TRAILING, dentry, inode);
|
||||
res = step_into(nd, WALK_TRAILING, dentry);
|
||||
if (unlikely(res))
|
||||
nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
|
||||
return res;
|
||||
|
|
Loading…
Reference in New Issue