summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2024-02-03 23:53:05 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2024-02-09 23:31:16 -0500
commit7e4a205fe56b9092f0143dad6aa5fee081139b09 (patch)
tree494c45bb1a3783b9bebb2ae87ebb879e1b6fc55b
parent6613476e225e090cc9aad49be7fa504e290dd33d (diff)
downloadlinux-stable-7e4a205fe56b9092f0143dad6aa5fee081139b09.tar.gz
linux-stable-7e4a205fe56b9092f0143dad6aa5fee081139b09.tar.bz2
linux-stable-7e4a205fe56b9092f0143dad6aa5fee081139b09.zip
Revert "get rid of DCACHE_GENOCIDE"
This reverts commit 57851607326a2beef21e67f83f4f53a90df8445a. Unfortunately, while we only call that thing once, the callback *can* be called more than once for the same dentry - all it takes is rename_lock being touched while we are in d_walk(). For now let's revert it. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/dcache.c5
-rw-r--r--include/linux/dcache.h1
2 files changed, 5 insertions, 1 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index b813528fb147..6ebccba33336 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -3061,7 +3061,10 @@ static enum d_walk_ret d_genocide_kill(void *data, struct dentry *dentry)
if (d_unhashed(dentry) || !dentry->d_inode)
return D_WALK_SKIP;
- dentry->d_lockref.count--;
+ if (!(dentry->d_flags & DCACHE_GENOCIDE)) {
+ dentry->d_flags |= DCACHE_GENOCIDE;
+ dentry->d_lockref.count--;
+ }
}
return D_WALK_CONTINUE;
}
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 1666c387861f..d07cf2f1bb7d 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -173,6 +173,7 @@ struct dentry_operations {
#define DCACHE_DONTCACHE BIT(7) /* Purge from memory on final dput() */
#define DCACHE_CANT_MOUNT BIT(8)
+#define DCACHE_GENOCIDE BIT(9)
#define DCACHE_SHRINK_LIST BIT(10)
#define DCACHE_OP_WEAK_REVALIDATE BIT(11)