fs: fix do_lookup false negative
authorNick Piggin <npiggin@kernel.dk>
Tue, 17 Aug 2010 18:37:30 +0000 (04:37 +1000)
committerAl Viro <viro@zeniv.linux.org.uk>
Wed, 18 Aug 2010 12:35:45 +0000 (08:35 -0400)
fs: fix do_lookup false negative

In do_lookup, if we initially find no dentry, we take the directory i_mutex and
re-check the lookup. If we find a dentry there, then we revalidate it if
needed. However if that revalidate asks for the dentry to be invalidated, we
return -ENOENT from do_lookup. What should happen instead is an attempt to
allocate and lookup a new dentry.

This is probably not noticed because it is rare. It is only reached if a
concurrent create races in first (in which case, the dentry probably won't be
invalidated anyway), or if the racy __d_lookup has failed due to a
false-negative (which is very rare).

Fix this by removing code and have it use the normal reval path.

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

index 17ea76bf2fbee41e9ff8a20616e0523781ed2315..c2742b7dec595207aed06e78fec1bffed8c9db70 100644 (file)
@@ -709,6 +709,7 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
        dentry = __d_lookup(nd->path.dentry, name);
        if (!dentry)
                goto need_lookup;
+found:
        if (dentry->d_op && dentry->d_op->d_revalidate)
                goto need_revalidate;
 done:
@@ -766,14 +767,7 @@ out_unlock:
         * we waited on the semaphore. Need to revalidate.
         */
        mutex_unlock(&dir->i_mutex);
-       if (dentry->d_op && dentry->d_op->d_revalidate) {
-               dentry = do_revalidate(dentry, nd);
-               if (!dentry)
-                       dentry = ERR_PTR(-ENOENT);
-       }
-       if (IS_ERR(dentry))
-               goto fail;
-       goto done;
+       goto found;
 
 need_revalidate:
        dentry = do_revalidate(dentry, nd);