new helper: __lookup_slow()
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 6 Apr 2018 20:43:47 +0000 (16:43 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Fri, 6 Apr 2018 20:43:47 +0000 (16:43 -0400)
lookup_slow() sans locking/unlocking the directory

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/namei.c

index b803c6c..ba48e15 100644 (file)
@@ -1593,22 +1593,21 @@ static int lookup_fast(struct nameidata *nd,
 }
 
 /* Fast lookup failed, do it the slow way */
-static struct dentry *lookup_slow(const struct qstr *name,
-                                 struct dentry *dir,
-                                 unsigned int flags)
+static struct dentry *__lookup_slow(const struct qstr *name,
+                                   struct dentry *dir,
+                                   unsigned int flags)
 {
-       struct dentry *dentry = ERR_PTR(-ENOENT), *old;
+       struct dentry *dentry, *old;
        struct inode *inode = dir->d_inode;
        DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
 
-       inode_lock_shared(inode);
        /* Don't go there if it's already dead */
        if (unlikely(IS_DEADDIR(inode)))
-               goto out;
+               return ERR_PTR(-ENOENT);
 again:
        dentry = d_alloc_parallel(dir, name, &wq);
        if (IS_ERR(dentry))
-               goto out;
+               return dentry;
        if (unlikely(!d_in_lookup(dentry))) {
                if (!(flags & LOOKUP_NO_REVAL)) {
                        int error = d_revalidate(dentry, flags);
@@ -1630,11 +1629,21 @@ again:
                        dentry = old;
                }
        }
-out:
-       inode_unlock_shared(inode);
        return dentry;
 }
 
+static struct dentry *lookup_slow(const struct qstr *name,
+                                 struct dentry *dir,
+                                 unsigned int flags)
+{
+       struct inode *inode = dir->d_inode;
+       struct dentry *res;
+       inode_lock_shared(inode);
+       res = __lookup_slow(name, dir, flags);
+       inode_unlock_shared(inode);
+       return res;
+}
+
 static inline int may_lookup(struct nameidata *nd)
 {
        if (nd->flags & LOOKUP_RCU) {