This patch changes real_lookup() into returning a struct path. Signed-off-by: Jan Blunck --- fs/namei.c | 77 ++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 29 deletions(-) --- a/fs/namei.c +++ b/fs/namei.c @@ -462,10 +462,11 @@ ok: * make sure that nobody added the entry to the dcache in the meantime.. * SMP-safe */ -static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, struct nameidata *nd) +static int real_lookup(struct nameidata *nd, struct qstr *name, + struct path *path) { - struct dentry * result; - struct inode *dir = parent->d_inode; + struct inode *dir = nd->dentry->d_inode; + int res = 0; mutex_lock(&dir->i_mutex); /* @@ -482,19 +483,27 @@ static struct dentry * real_lookup(struc * * so doing d_lookup() (with seqlock), instead of lockfree __d_lookup */ - result = d_lookup(parent, name); - if (!result) { - struct dentry * dentry = d_alloc(parent, name); - result = ERR_PTR(-ENOMEM); + path->dentry = d_lookup(nd->dentry, name); + path->mnt = nd->mnt; + if (!path->dentry) { + struct dentry *dentry = d_alloc(nd->dentry, name); if (dentry) { - result = dir->i_op->lookup(dir, dentry, nd); - if (result) + path->dentry = dir->i_op->lookup(dir, dentry, nd); + if (path->dentry) { dput(dentry); - else - result = dentry; + if (IS_ERR(path->dentry)) { + res = PTR_ERR(path->dentry); + path->dentry = NULL; + path->mnt = NULL; + } + } else + path->dentry = dentry; + } else { + res = -ENOMEM; + path->mnt = NULL; } mutex_unlock(&dir->i_mutex); - return result; + return res; } /* @@ -502,12 +511,20 @@ static struct dentry * real_lookup(struc * we waited on the semaphore. Need to revalidate. */ mutex_unlock(&dir->i_mutex); - if (result->d_op && result->d_op->d_revalidate) { - result = do_revalidate(result, nd); - if (!result) - result = ERR_PTR(-ENOENT); + if (path->dentry->d_op && path->dentry->d_op->d_revalidate) { + path->dentry = do_revalidate(path->dentry, nd); + if (!path->dentry) { + res = -ENOENT; + path->mnt = NULL; + } + if (IS_ERR(path->dentry)) { + res = PTR_ERR(path->dentry); + path->dentry = NULL; + path->mnt = NULL; + } } - return result; + + return res; } static int __emul_lookup_dentry(const char *, struct nameidata *); @@ -748,35 +765,37 @@ static __always_inline void follow_dotdo static int do_lookup(struct nameidata *nd, struct qstr *name, struct path *path) { - struct vfsmount *mnt = nd->mnt; - struct dentry *dentry = __d_lookup(nd->dentry, name); + int err; - if (!dentry) + path->dentry = __d_lookup(nd->dentry, name); + path->mnt = nd->mnt; + if (!path->dentry) goto need_lookup; - if (dentry->d_op && dentry->d_op->d_revalidate) + if (path->dentry->d_op && path->dentry->d_op->d_revalidate) goto need_revalidate; + done: - path->mnt = mnt; - path->dentry = dentry; __follow_mount(path); return 0; need_lookup: - dentry = real_lookup(nd->dentry, name, nd); - if (IS_ERR(dentry)) + err = real_lookup(nd, name, path); + if (err) goto fail; goto done; need_revalidate: - dentry = do_revalidate(dentry, nd); - if (!dentry) + path->dentry = do_revalidate(path->dentry, nd); + if (!path->dentry) goto need_lookup; - if (IS_ERR(dentry)) + if (IS_ERR(path->dentry)) { + err = PTR_ERR(path->dentry); goto fail; + } goto done; fail: - return PTR_ERR(dentry); + return err; } /* --