mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-13 14:24:11 +08:00
namei: untanlge lookup_fast()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
6c51e513a3
commit
5d0f49c136
83
fs/namei.c
83
fs/namei.c
@ -1512,32 +1512,29 @@ static struct dentry *__lookup_hash(struct qstr *name,
|
|||||||
return lookup_real(base->d_inode, dentry, flags);
|
return lookup_real(base->d_inode, dentry, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* It's more convoluted than I'd like it to be, but... it's still fairly
|
|
||||||
* small and for now I'd prefer to have fast path as straight as possible.
|
|
||||||
* It _is_ time-critical.
|
|
||||||
*/
|
|
||||||
static int lookup_fast(struct nameidata *nd,
|
static int lookup_fast(struct nameidata *nd,
|
||||||
struct path *path, struct inode **inode,
|
struct path *path, struct inode **inode,
|
||||||
unsigned *seqp)
|
unsigned *seqp)
|
||||||
{
|
{
|
||||||
struct vfsmount *mnt = nd->path.mnt;
|
struct vfsmount *mnt = nd->path.mnt;
|
||||||
struct dentry *dentry, *parent = nd->path.dentry;
|
struct dentry *dentry, *parent = nd->path.dentry;
|
||||||
int need_reval = 1;
|
|
||||||
int status = 1;
|
int status = 1;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Rename seqlock is not required here because in the off chance
|
* Rename seqlock is not required here because in the off chance
|
||||||
* of a false negative due to a concurrent rename, we're going to
|
* of a false negative due to a concurrent rename, the caller is
|
||||||
* do the non-racy lookup, below.
|
* going to fall back to non-racy lookup.
|
||||||
*/
|
*/
|
||||||
if (nd->flags & LOOKUP_RCU) {
|
if (nd->flags & LOOKUP_RCU) {
|
||||||
unsigned seq;
|
unsigned seq;
|
||||||
bool negative;
|
bool negative;
|
||||||
dentry = __d_lookup_rcu(parent, &nd->last, &seq);
|
dentry = __d_lookup_rcu(parent, &nd->last, &seq);
|
||||||
if (!dentry)
|
if (unlikely(!dentry)) {
|
||||||
goto unlazy;
|
if (unlazy_walk(nd, NULL, 0))
|
||||||
|
return -ECHILD;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This sequence count validates that the inode matches
|
* This sequence count validates that the inode matches
|
||||||
@ -1545,7 +1542,7 @@ static int lookup_fast(struct nameidata *nd,
|
|||||||
*/
|
*/
|
||||||
*inode = d_backing_inode(dentry);
|
*inode = d_backing_inode(dentry);
|
||||||
negative = d_is_negative(dentry);
|
negative = d_is_negative(dentry);
|
||||||
if (read_seqcount_retry(&dentry->d_seq, seq))
|
if (unlikely(read_seqcount_retry(&dentry->d_seq, seq)))
|
||||||
return -ECHILD;
|
return -ECHILD;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1555,63 +1552,57 @@ static int lookup_fast(struct nameidata *nd,
|
|||||||
* The memory barrier in read_seqcount_begin of child is
|
* The memory barrier in read_seqcount_begin of child is
|
||||||
* enough, we can use __read_seqcount_retry here.
|
* enough, we can use __read_seqcount_retry here.
|
||||||
*/
|
*/
|
||||||
if (__read_seqcount_retry(&parent->d_seq, nd->seq))
|
if (unlikely(__read_seqcount_retry(&parent->d_seq, nd->seq)))
|
||||||
return -ECHILD;
|
return -ECHILD;
|
||||||
|
|
||||||
*seqp = seq;
|
*seqp = seq;
|
||||||
if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) {
|
if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE))
|
||||||
status = d_revalidate(dentry, nd->flags);
|
status = d_revalidate(dentry, nd->flags);
|
||||||
if (unlikely(status <= 0)) {
|
if (unlikely(status <= 0)) {
|
||||||
if (status != -ECHILD)
|
if (unlazy_walk(nd, dentry, seq))
|
||||||
need_reval = 0;
|
return -ECHILD;
|
||||||
goto unlazy;
|
if (status == -ECHILD)
|
||||||
}
|
status = d_revalidate(dentry, nd->flags);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Note: do negative dentry check after revalidation in
|
||||||
|
* case that drops it.
|
||||||
|
*/
|
||||||
|
if (unlikely(negative))
|
||||||
|
return -ENOENT;
|
||||||
|
path->mnt = mnt;
|
||||||
|
path->dentry = dentry;
|
||||||
|
if (likely(__follow_mount_rcu(nd, path, inode, seqp)))
|
||||||
|
return 0;
|
||||||
|
if (unlazy_walk(nd, dentry, seq))
|
||||||
|
return -ECHILD;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* Note: do negative dentry check after revalidation in
|
|
||||||
* case that drops it.
|
|
||||||
*/
|
|
||||||
if (negative)
|
|
||||||
return -ENOENT;
|
|
||||||
path->mnt = mnt;
|
|
||||||
path->dentry = dentry;
|
|
||||||
if (likely(__follow_mount_rcu(nd, path, inode, seqp)))
|
|
||||||
return 0;
|
|
||||||
unlazy:
|
|
||||||
if (unlazy_walk(nd, dentry, seq))
|
|
||||||
return -ECHILD;
|
|
||||||
} else {
|
} else {
|
||||||
dentry = __d_lookup(parent, &nd->last);
|
dentry = __d_lookup(parent, &nd->last);
|
||||||
|
if (unlikely(!dentry))
|
||||||
|
return 1;
|
||||||
|
if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE))
|
||||||
|
status = d_revalidate(dentry, nd->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(!dentry))
|
|
||||||
goto need_lookup;
|
|
||||||
|
|
||||||
if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE) && need_reval)
|
|
||||||
status = d_revalidate(dentry, nd->flags);
|
|
||||||
if (unlikely(status <= 0)) {
|
if (unlikely(status <= 0)) {
|
||||||
if (status < 0) {
|
if (!status) {
|
||||||
dput(dentry);
|
d_invalidate(dentry);
|
||||||
return status;
|
status = 1;
|
||||||
}
|
}
|
||||||
d_invalidate(dentry);
|
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
goto need_lookup;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(d_is_negative(dentry))) {
|
if (unlikely(d_is_negative(dentry))) {
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
path->mnt = mnt;
|
path->mnt = mnt;
|
||||||
path->dentry = dentry;
|
path->dentry = dentry;
|
||||||
err = follow_managed(path, nd);
|
err = follow_managed(path, nd);
|
||||||
if (likely(!err))
|
if (likely(!err))
|
||||||
*inode = d_backing_inode(path->dentry);
|
*inode = d_backing_inode(path->dentry);
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
need_lookup:
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fast lookup failed, do it the slow way */
|
/* Fast lookup failed, do it the slow way */
|
||||||
|
Loading…
Reference in New Issue
Block a user