From: Ye Bin <yebin10@xxxxxxxxxx> In order to better analyze the issue of file system uninstallation caused by kernel module opening files, it is necessary to perform dentry recycling on a single file system. But now, apart from global dentry recycling, it is not supported to do dentry recycling on a single file system separately. This feature has usage scenarios in problem localization scenarios.At the same time, it also provides users with a slightly fine-grained pagecache/entry recycling mechanism. This patch supports the recycling of pagecache/entry for individual file systems. Signed-off-by: Ye Bin <yebin10@xxxxxxxxxx> --- fs/drop_caches.c | 43 +++++++++++++++++++++++++++++++++++++++++++ include/linux/mm.h | 2 ++ kernel/sysctl.c | 9 +++++++++ 3 files changed, 54 insertions(+) diff --git a/fs/drop_caches.c b/fs/drop_caches.c index d45ef541d848..99d412cf3e52 100644 --- a/fs/drop_caches.c +++ b/fs/drop_caches.c @@ -77,3 +77,46 @@ int drop_caches_sysctl_handler(const struct ctl_table *table, int write, } return 0; } + +int drop_fs_caches_sysctl_handler(const struct ctl_table *table, int write, + void *buffer, size_t *length, loff_t *ppos) +{ + unsigned int major, minor; + unsigned int ctl; + struct super_block *sb; + static int stfu; + + if (!write) + return 0; + + if (sscanf(buffer, "%u:%u:%u", &major, &minor, &ctl) != 3) + return -EINVAL; + + if (ctl < *((int *)table->extra1) || ctl > *((int *)table->extra2)) + return -EINVAL; + + sb = user_get_super(MKDEV(major, minor), false); + if (!sb) + return -EINVAL; + + if (ctl & 1) { + lru_add_drain_all(); + drop_pagecache_sb(sb, NULL); + count_vm_event(DROP_PAGECACHE); + } + + if (ctl & 2) { + shrink_dcache_sb(sb); + shrink_icache_sb(sb); + count_vm_event(DROP_SLAB); + } + + drop_super(sb); + + if (!stfu) + pr_info("%s (%d): drop_fs_caches: %u:%u:%d\n", current->comm, + task_pid_nr(current), major, minor, ctl); + stfu |= ctl & 4; + + return 0; +} diff --git a/include/linux/mm.h b/include/linux/mm.h index 344541f8cba0..43079478296f 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -3788,6 +3788,8 @@ extern bool process_shares_mm(struct task_struct *p, struct mm_struct *mm); extern int sysctl_drop_caches; int drop_caches_sysctl_handler(const struct ctl_table *, int, void *, size_t *, loff_t *); +int drop_fs_caches_sysctl_handler(const struct ctl_table *table, int write, + void *buffer, size_t *length, loff_t *ppos); #endif void drop_slab(void); diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 79e6cb1d5c48..d434cbe10e47 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -2101,6 +2101,15 @@ static struct ctl_table vm_table[] = { .extra1 = SYSCTL_ONE, .extra2 = SYSCTL_FOUR, }, + { + .procname = "drop_fs_caches", + .data = NULL, + .maxlen = 256, + .mode = 0200, + .proc_handler = drop_fs_caches_sysctl_handler, + .extra1 = SYSCTL_ONE, + .extra2 = SYSCTL_FOUR, + }, { .procname = "page_lock_unfairness", .data = &sysctl_page_lock_unfairness, -- 2.31.1