From: Miklos Szeredi <mszeredi@xxxxxxx> Split do_lookup() into two functions: lookup_fast() - does cached lookup without i_mutex lookup_slow() - does lookup with i_mutex Both follow managed dentries. The new functions are needed by atomic_open. Signed-off-by: Miklos Szeredi <mszeredi@xxxxxxx> --- fs/namei.c | 56 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 42 insertions(+), 14 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 29a00e3..f9639bf 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1147,8 +1147,8 @@ static struct dentry *__lookup_hash(struct qstr *name, struct dentry *base, * small and for now I'd prefer to have fast path as straight as possible. * It _is_ time-critical. */ -static int do_lookup(struct nameidata *nd, struct qstr *name, - struct path *path, struct inode **inode) +static int lookup_fast(struct nameidata *nd, struct qstr *name, + struct path *path, struct inode **inode) { struct vfsmount *mnt = nd->path.mnt; struct dentry *dentry, *parent = nd->path.dentry; @@ -1217,7 +1217,6 @@ unlazy: } } -success: path->mnt = mnt; path->dentry = dentry; err = follow_managed(path, nd); @@ -1229,6 +1228,17 @@ success: return 0; need_lookup: + return 1; +} + +/* Fast lookup failed, do it the slow way */ +static int lookup_slow(struct nameidata *nd, struct qstr *name, + struct path *path) +{ + struct dentry *dentry, *parent; + int err; + + parent = nd->path.dentry; BUG_ON(nd->inode != parent->d_inode); mutex_lock(&parent->d_inode->i_mutex); @@ -1237,7 +1247,14 @@ need_lookup: if (IS_ERR(dentry)) return PTR_ERR(dentry); - goto success; + path->mnt = nd->path.mnt; + path->dentry = dentry; + err = follow_managed(path, nd); + if (unlikely(err)) { + path_put_conditional(path, nd); + return err; + } + return 0; } static inline int may_lookup(struct nameidata *nd) @@ -1309,21 +1326,26 @@ static inline int walk_component(struct nameidata *nd, struct path *path, */ if (unlikely(type != LAST_NORM)) return handle_dots(nd, type); - err = do_lookup(nd, name, path, &inode); + err = lookup_fast(nd, name, path, &inode); if (unlikely(err)) { - terminate_walk(nd); - return err; - } - if (!inode) { - path_to_nameidata(path, nd); - terminate_walk(nd); - return -ENOENT; + if (err < 0) + goto out_err; + + err = lookup_slow(nd, name, path); + if (err < 0) + goto out_err; + + inode = path->dentry->d_inode; } + err = -ENOENT; + if (!inode) + goto out_path_put; + if (should_follow_link(inode, follow)) { if (nd->flags & LOOKUP_RCU) { if (unlikely(unlazy_walk(nd, path->dentry))) { - terminate_walk(nd); - return -ECHILD; + err = -ECHILD; + goto out_err; } } BUG_ON(inode != path->dentry->d_inode); @@ -1332,6 +1354,12 @@ static inline int walk_component(struct nameidata *nd, struct path *path, path_to_nameidata(path, nd); nd->inode = inode; return 0; + +out_path_put: + path_to_nameidata(path, nd); +out_err: + terminate_walk(nd); + return err; } /* -- 1.7.7 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html