summaryrefslogtreecommitdiff
path: root/fs/namei.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2016-03-06 22:03:27 +0300
committerAl Viro <viro@zeniv.linux.org.uk>2016-03-14 07:15:40 +0300
commite3c13928086f1ed3620329b9fff678df2294d327 (patch)
tree9992da992122a64ca15fa2bb5222f4bc8952ba95 /fs/namei.c
parentd6d95ded914eb321b0a2c8c26cdf0a225a0d9917 (diff)
downloadlinux-e3c13928086f1ed3620329b9fff678df2294d327.tar.xz
namei: massage lookup_slow() to be usable by lookup_one_len_unlocked()
Return dentry and don't pass nameidata or path; lift crossing mountpoints into the caller. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c56
1 files changed, 24 insertions, 32 deletions
diff --git a/fs/namei.c b/fs/namei.c
index ae673355c386..cb70a817d439 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1445,7 +1445,8 @@ static int follow_dotdot(struct nameidata *nd)
* allocates a new one if not found or not valid. In the need_lookup argument
* returns whether i_op->lookup is necessary.
*/
-static struct dentry *lookup_dcache(struct qstr *name, struct dentry *dir,
+static struct dentry *lookup_dcache(const struct qstr *name,
+ struct dentry *dir,
unsigned int flags)
{
struct dentry *dentry;
@@ -1491,7 +1492,7 @@ static struct dentry *lookup_real(struct inode *dir, struct dentry *dentry,
return dentry;
}
-static struct dentry *__lookup_hash(struct qstr *name,
+static struct dentry *__lookup_hash(const struct qstr *name,
struct dentry *base, unsigned int flags)
{
struct dentry *dentry = lookup_dcache(name, base, flags);
@@ -1598,21 +1599,15 @@ static int lookup_fast(struct nameidata *nd,
}
/* Fast lookup failed, do it the slow way */
-static int lookup_slow(struct nameidata *nd, struct path *path)
+static struct dentry *lookup_slow(const struct qstr *name,
+ struct dentry *dir,
+ unsigned int flags)
{
- struct dentry *dentry, *parent;
-
- parent = nd->path.dentry;
- BUG_ON(nd->inode != parent->d_inode);
-
- inode_lock(parent->d_inode);
- dentry = __lookup_hash(&nd->last, parent, nd->flags);
- inode_unlock(parent->d_inode);
- if (IS_ERR(dentry))
- return PTR_ERR(dentry);
- path->mnt = nd->path.mnt;
- path->dentry = dentry;
- return follow_managed(path, nd);
+ struct dentry *dentry;
+ inode_lock(dir->d_inode);
+ dentry = __lookup_hash(name, dir, flags);
+ inode_unlock(dir->d_inode);
+ return dentry;
}
static inline int may_lookup(struct nameidata *nd)
@@ -1719,15 +1714,20 @@ static int walk_component(struct nameidata *nd, int flags)
if (unlikely(err <= 0)) {
if (err < 0)
return err;
-
- err = lookup_slow(nd, &path);
- if (err < 0)
+ path.dentry = lookup_slow(&nd->last, nd->path.dentry,
+ nd->flags);
+ if (IS_ERR(path.dentry))
+ return PTR_ERR(path.dentry);
+ if (unlikely(d_is_negative(path.dentry))) {
+ dput(path.dentry);
+ return -ENOENT;
+ }
+ path.mnt = nd->path.mnt;
+ err = follow_managed(&path, nd);
+ if (unlikely(err < 0))
return err;
seq = 0; /* we are already out of RCU mode */
- err = -ENOENT;
- if (d_is_negative(path.dentry))
- goto out_path_put;
inode = d_backing_inode(path.dentry);
}
@@ -1740,10 +1740,6 @@ static int walk_component(struct nameidata *nd, int flags)
nd->inode = inode;
nd->seq = seq;
return 0;
-
-out_path_put:
- path_to_nameidata(&path, nd);
- return err;
}
/*
@@ -2350,12 +2346,8 @@ struct dentry *lookup_one_len_unlocked(const char *name,
return ERR_PTR(err);
ret = lookup_dcache(&this, base, 0);
- if (ret)
- return ret;
-
- inode_lock(base->d_inode);
- ret = __lookup_hash(&this, base, 0);
- inode_unlock(base->d_inode);
+ if (!ret)
+ ret = lookup_slow(&this, base, 0);
return ret;
}
EXPORT_SYMBOL(lookup_one_len_unlocked);