On Sat, May 11, 2024 at 04:36:19AM +0100, Al Viro wrote: > Said that, I seriously suspect that there are loads where it would become > painful. unlink() + creat() is _not_ a rare sequence, and this would > shove an extra negative lookup into each of those. > > I would like to see the details on original posters' setup. Note that > successful rmdir() evicts all children, so that it would seem that their > arseloads of negative dentries come from a bunch of unlinks in surviving > directories. > > It would be interesting to see if using something like > mkdir graveyard > rename victim over there, then unlink in new place > rename next victim over there, then unlink in new place > .... > rmdir graveyard > would change the situation with memory pressure - it would trigger > eviction of all those negatives at controlled point(s) (rmdir). > I'm not saying that it's a good mitigation, but it would get more > details on that memory pressure. BTW, how about adding to do_vfs_ioctl() something like case FS_IOC_FORGET: shrink_dcache_parent(file->f_path.dentry); return 0; possibly with option for dropping only negatives? Even in the minimal form it would allow userland to force eviction in given directory tree, without disrupting things anywhere else. That's a trivial (completely untested) patch, really - diff --git a/fs/ioctl.c b/fs/ioctl.c index 1d5abfdf0f22..342bb71cf76c 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -878,6 +878,12 @@ static int do_vfs_ioctl(struct file *filp, unsigned int fd, case FS_IOC_GETFSSYSFSPATH: return ioctl_get_fs_sysfs_path(filp, argp); + case FS_IOC_FORGET: + if (arg != 0) // only 0 for now + break; + shrink_dcache_parent(filp->f_path.dentry); + return 0; + default: if (S_ISREG(inode->i_mode)) return file_ioctl(filp, cmd, argp); diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index 45e4e64fd664..143129510289 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h @@ -222,6 +222,7 @@ struct fsxattr { #define FS_IOC_GETFLAGS _IOR('f', 1, long) #define FS_IOC_SETFLAGS _IOW('f', 2, long) +#define FS_IOC_FORGET _IOW('f', 255, int) #define FS_IOC_GETVERSION _IOR('v', 1, long) #define FS_IOC_SETVERSION _IOW('v', 2, long) #define FS_IOC_FIEMAP _IOWR('f', 11, struct fiemap)