From da5911c311955038e5ed24a7ea7d7ef0c6717a69 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Fri, 22 Jan 2021 18:41:06 -0800 Subject: [PATCH] Use d_materialise_unique to splice dir dentries When we're splicing in dentries in lookup we can be splicing the result of changes on other nodes into a stale dcache. The stale dcache might contain dir entries and the dcache does not allow aliased directories. Use d_materialise_unique() to splice in dir inodes so that we remove all aliased dentries which must be stale. We can still use d_splice_alias() for all other inode types. Any existing stale dentries will fail revalidation before they're used. Signed-off-by: Zach Brown --- kmod/src/dir.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/kmod/src/dir.c b/kmod/src/dir.c index 8fdb29d0..0bfc0e7b 100644 --- a/kmod/src/dir.c +++ b/kmod/src/dir.c @@ -463,7 +463,18 @@ out: else inode = scoutfs_iget(sb, ino); - return d_splice_alias(inode, dentry); + /* + * We can't splice dir aliases into the dcache. dir entries + * might have changed on other nodes so our dcache could still + * contain them, rather than having been moved in rename. For + * dirs, we use d_materialize_unique to remove any existing + * aliases which must be stale. Our inode numbers aren't reused + * so inodes pointed to by entries can't change types. + */ + if (!IS_ERR_OR_NULL(inode) && S_ISDIR(inode->i_mode)) + return d_materialise_unique(dentry, inode); + else + return d_splice_alias(inode, dentry); } /*