diff mbox series

[1/4,v2] fs/dcache: d_add_ci() needs to complete parallel lookup.

Message ID 20220727114904.130761-2-bigeasy@linutronix.de (mailing list archive)
State New, archived
Headers show
Series fs/dcache: Resolve the last RT woes. | expand

Commit Message

Sebastian Sewior July 27, 2022, 11:49 a.m. UTC
From: Al Viro <viro@zeniv.linux.org.uk>

Result of d_alloc_parallel() in d_add_ci() is fed to d_splice_alias(), which
*NORMALLY* feeds it to __d_add() or __d_move() in a way that will have
__d_lookup_done() applied to it.

However, there is a nasty possibility - d_splice_alias() might legitimately
fail without having marked the sucker not in-lookup. dentry will get dropped
by d_add_ci(), so ->d_wait won't end up pointing to freed object, but it's
still a bug - retain_dentry() will scream bloody murder upon seeing that, and
for a good reason; we'll get hash chain corrupted. It's impossible to hit
without corrupted fs image (ntfs or case-insensitive xfs), but it's a bug.

Invoke d_lookup_done() after d_splice_alias() to ensure that the
in-lookip flag is always cleared.

Fixes: d9171b9345261 ("parallel lookups machinery, part 4 (and last)")
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 fs/dcache.c |    1 +
 1 file changed, 1 insertion(+)
diff mbox series

Patch

--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -2239,6 +2239,7 @@  struct dentry *d_add_ci(struct dentry *d
 		} 
 	}
 	res = d_splice_alias(inode, found);
+	d_lookup_done(found);
 	if (res) {
 		dput(found);
 		return res;