hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8NIKC
--------------------------------
Add /pros/sys/vm/cache_limit_mbytes to set page cache limit. This interface set the upper limit of page cache, if usage of page cache is over cache_limit_mbytes, it will trigger memory reclaim, the reclaim size and reclaim interval are decided by interfaces /proc/sys/vm/cache_reclaim_s and /proc/sys/vm/cache_reclaim_weight, these two intefaces are introduced in previous patch.
Signed-off-by: Ze Zuo zuoze1@huawei.com --- Documentation/admin-guide/sysctl/vm.rst | 8 ++++ mm/page_cache_limit.c | 64 +++++++++++++++++++++++++ 2 files changed, 72 insertions(+)
diff --git a/Documentation/admin-guide/sysctl/vm.rst b/Documentation/admin-guide/sysctl/vm.rst index dc2705cbdcb8..2025b524028c 100644 --- a/Documentation/admin-guide/sysctl/vm.rst +++ b/Documentation/admin-guide/sysctl/vm.rst @@ -78,6 +78,7 @@ Currently, these files are in /proc/sys/vm: - cache_reclaim_s - cache_reclaim_weight - cache_reclaim_enable +- cache_limit_mbytes
admin_reserve_kbytes @@ -1079,3 +1080,10 @@ cache_reclaim_enable ====================
This is used to switch on/off periodical memory reclaim feature. + + +cache_limit_mbytes +================== + +This is used to set the upper limit of page cache in megabytes. +Page cache will be reclaimed periodically if page cache is over limit. diff --git a/mm/page_cache_limit.c b/mm/page_cache_limit.c index 3ad89f21d585..1ab00225f8ac 100644 --- a/mm/page_cache_limit.c +++ b/mm/page_cache_limit.c @@ -15,6 +15,7 @@ static int vm_cache_reclaim_s_max = 43200; static int vm_cache_reclaim_weight __read_mostly = 1; static int vm_cache_reclaim_weight_max = 100; static int vm_cache_reclaim_enable = 1; +static unsigned long vm_cache_limit_mbytes __read_mostly;
static void shrink_shepherd(struct work_struct *w); static DECLARE_DEFERRABLE_WORK(shepherd, shrink_shepherd); @@ -32,6 +33,31 @@ static unsigned long node_reclaim_num(void) return SWAP_CLUSTER_MAX * nr_cpus_node(nid) * vm_cache_reclaim_weight; }
+static bool page_cache_over_limit(void) +{ + unsigned long lru_file; + unsigned long limit; + + limit = vm_cache_limit_mbytes << (20 - PAGE_SHIFT); + lru_file = global_node_page_state(NR_ACTIVE_FILE) + + global_node_page_state(NR_INACTIVE_FILE); + if (lru_file > limit) + return true; + + return false; +} + +static bool should_reclaim_page_cache(void) +{ + if (!should_periodical_reclaim()) + return false; + + if (!vm_cache_limit_mbytes) + return false; + + return true; +} + int cache_reclaim_enable_handler(struct ctl_table *table, int write, void *buffer, size_t *length, loff_t *ppos) { @@ -65,6 +91,37 @@ int cache_reclaim_sysctl_handler(struct ctl_table *table, int write, return ret; }
+int cache_limit_mbytes_sysctl_handler(struct ctl_table *table, int write, + void __user *buffer, size_t *length, loff_t *ppos) +{ + int ret; + unsigned long vm_cache_limit_mbytes_max; + unsigned long origin_mbytes = vm_cache_limit_mbytes; + int nr_retries = MAX_RECLAIM_RETRIES; + + vm_cache_limit_mbytes_max = totalram_pages() >> (20 - PAGE_SHIFT); + ret = proc_doulongvec_minmax(table, write, buffer, length, ppos); + if (ret || !write) + return ret; + + if (vm_cache_limit_mbytes > vm_cache_limit_mbytes_max) { + vm_cache_limit_mbytes = origin_mbytes; + return -EINVAL; + } + + if (write) { + while (should_reclaim_page_cache() && page_cache_over_limit() && + nr_retries--) { + if (signal_pending(current)) + return -EINTR; + + shrink_memory(node_reclaim_num(), false); + } + } + + return 0; +} + static void shrink_shepherd(struct work_struct *w) { int node; @@ -122,6 +179,13 @@ static struct ctl_table page_cache_limit_table[] = { .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_ONE, }, + { + .procname = "cache_limit_mbytes", + .data = &vm_cache_limit_mbytes, + .maxlen = sizeof(vm_cache_limit_mbytes), + .mode = 0644, + .proc_handler = cache_limit_mbytes_sysctl_handler, + }, };
static int __init shrink_page_init(void)