Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2e2e88ea authored by Nick Piggin's avatar Nick Piggin Committed by Al Viro
Browse files

fs: fix do_lookup false negative



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: default avatarNick Piggin <npiggin@kernel.dk>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 3a48ee8a
Loading
Loading
Loading
Loading
+2 −8
Original line number Diff line number Diff line
@@ -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 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
	 * 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);