Commit 949a852e authored by Al Viro's avatar Al Viro

namei: teach lookup_slow() to skip revalidate

... and make mountpoint_last() use it.  That makes all
candidates for lookup with parent locked shared go
through lookup_slow().
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent e3c13928
...@@ -1605,7 +1605,29 @@ static struct dentry *lookup_slow(const struct qstr *name, ...@@ -1605,7 +1605,29 @@ static struct dentry *lookup_slow(const struct qstr *name,
{ {
struct dentry *dentry; struct dentry *dentry;
inode_lock(dir->d_inode); inode_lock(dir->d_inode);
dentry = __lookup_hash(name, dir, flags); dentry = d_lookup(dir, name);
if (unlikely(dentry)) {
if ((dentry->d_flags & DCACHE_OP_REVALIDATE) &&
!(flags & LOOKUP_NO_REVAL)) {
int error = d_revalidate(dentry, flags);
if (unlikely(error <= 0)) {
if (!error)
d_invalidate(dentry);
dput(dentry);
dentry = ERR_PTR(error);
}
}
if (dentry) {
inode_unlock(dir->d_inode);
return dentry;
}
}
dentry = d_alloc(dir, name);
if (unlikely(!dentry)) {
inode_unlock(dir->d_inode);
return ERR_PTR(-ENOMEM);
}
dentry = lookup_real(dir->d_inode, dentry, flags);
inode_unlock(dir->d_inode); inode_unlock(dir->d_inode);
return dentry; return dentry;
} }
...@@ -2425,31 +2447,21 @@ mountpoint_last(struct nameidata *nd, struct path *path) ...@@ -2425,31 +2447,21 @@ mountpoint_last(struct nameidata *nd, struct path *path)
if (error) if (error)
return error; return error;
dentry = dget(nd->path.dentry); dentry = dget(nd->path.dentry);
goto done; } else {
} dentry = d_lookup(dir, &nd->last);
inode_lock(dir->d_inode);
dentry = d_lookup(dir, &nd->last);
if (!dentry) {
/*
* No cached dentry. Mounted dentries are pinned in the cache,
* so that means that this dentry is probably a symlink or the
* path doesn't actually point to a mounted dentry.
*/
dentry = d_alloc(dir, &nd->last);
if (!dentry) { if (!dentry) {
inode_unlock(dir->d_inode); /*
return -ENOMEM; * No cached dentry. Mounted dentries are pinned in the
} * cache, so that means that this dentry is probably
dentry = lookup_real(dir->d_inode, dentry, nd->flags); * a symlink or the path doesn't actually point
if (IS_ERR(dentry)) { * to a mounted dentry.
inode_unlock(dir->d_inode); */
return PTR_ERR(dentry); dentry = lookup_slow(&nd->last, dir,
nd->flags | LOOKUP_NO_REVAL);
if (IS_ERR(dentry))
return PTR_ERR(dentry);
} }
} }
inode_unlock(dir->d_inode);
done:
if (d_is_negative(dentry)) { if (d_is_negative(dentry)) {
dput(dentry); dput(dentry);
return -ENOENT; return -ENOENT;
......
...@@ -31,6 +31,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; ...@@ -31,6 +31,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
#define LOOKUP_PARENT 0x0010 #define LOOKUP_PARENT 0x0010
#define LOOKUP_REVAL 0x0020 #define LOOKUP_REVAL 0x0020
#define LOOKUP_RCU 0x0040 #define LOOKUP_RCU 0x0040
#define LOOKUP_NO_REVAL 0x0080
/* /*
* Intent data * Intent data
......
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