From: Chen Wandun chenwandun@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I4HOXK
------------------------------------------
Add 3 proc interface to control page cache limit behavior: 1. switch of the this feature 2. control the page cache limit 3. control the ratio to reclaim when page cache beyond page cache limit
Signed-off-by: Chen Wandun chenwandun@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/page_cache_limit.h | 14 +++++++++ kernel/sysctl.c | 32 ++++++++++++++++++++ mm/Kconfig | 12 ++++++++ mm/Makefile | 1 + mm/page_cache_limit.c | 51 ++++++++++++++++++++++++++++++++ 5 files changed, 110 insertions(+) create mode 100644 include/linux/page_cache_limit.h create mode 100644 mm/page_cache_limit.c
diff --git a/include/linux/page_cache_limit.h b/include/linux/page_cache_limit.h new file mode 100644 index 000000000000..98f12734114b --- /dev/null +++ b/include/linux/page_cache_limit.h @@ -0,0 +1,14 @@ +#ifndef _PAGECACHE_H +#define _PAGECACHE_H + +#ifdef CONFIG_SHRINK_PAGECACHE +extern int pagecache_reclaim_enable; +extern int pagecache_limit_ratio; +extern int pagecache_reclaim_ratio; + +int proc_page_cache_limit(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos); +#else +#endif + +#endif diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 3ab6ea7853ba..b3ee0deaa8dd 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -103,6 +103,9 @@ #ifdef CONFIG_LOCKUP_DETECTOR #include <linux/nmi.h> #endif +#ifdef CONFIG_SHRINK_PAGECACHE +#include <linux/page_cache_limit.h> +#endif
#if defined(CONFIG_SYSCTL)
@@ -3192,6 +3195,35 @@ static struct ctl_table vm_table[] = { .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_ONE, }, +#endif +#ifdef CONFIG_SHRINK_PAGECACHE + { + .procname = "cache_reclaim_enable", + .data = &pagecache_reclaim_enable, + .maxlen = sizeof(pagecache_reclaim_enable), + .mode = 0600, + .proc_handler = proc_dointvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, + }, + { + .procname = "cache_limit_ratio", + .data = &pagecache_limit_ratio, + .maxlen = sizeof(pagecache_limit_ratio), + .mode = 0600, + .proc_handler = proc_page_cache_limit, + .extra1 = SYSCTL_ZERO, + .extra2 = (void *)&one_hundred, + }, + { + .procname = "cache_reclaim_ratio", + .data = &pagecache_reclaim_ratio, + .maxlen = sizeof(pagecache_reclaim_ratio), + .mode = 0600, + .proc_handler = proc_dointvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = (void *)&one_hundred, + }, #endif { } }; diff --git a/mm/Kconfig b/mm/Kconfig index 59fdace319fd..f565fc82c200 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -486,6 +486,18 @@ config FRONTSWAP
If unsure, say Y to enable frontswap.
+config SHRINK_PAGECACHE + bool "Enable shrinking the page cache" + depends on MMU + default n + help + SHRINK_PAGECACHE means that we do not want to keep the large number + of page cache in the system, even though page cache can greatly improve + the performance of the machine. Large number of page cache may result + in short of memory, which will result OOM at the same time, so in order + to keep page cache in a reasonable range, the number of page cache + should be limited, and that is what SHRINK_PAGECACHE does. + config MEMCG_QOS bool "Enable Memory Cgroup Priority" depends on MEMCG diff --git a/mm/Makefile b/mm/Makefile index 4d07adb60619..c14522bd17ed 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -125,3 +125,4 @@ obj-$(CONFIG_PTDUMP_CORE) += ptdump.o obj-$(CONFIG_PAGE_REPORTING) += page_reporting.o obj-$(CONFIG_HAVE_BOOTMEM_INFO_NODE) += bootmem_info.o obj-$(CONFIG_PIN_MEMORY) += pin_mem.o +obj-$(CONFIG_SHRINK_PAGECACHE) += page_cache_limit.o diff --git a/mm/page_cache_limit.c b/mm/page_cache_limit.c new file mode 100644 index 000000000000..55fdea087804 --- /dev/null +++ b/mm/page_cache_limit.c @@ -0,0 +1,51 @@ +#include <linux/mm.h> +#include <linux/sysctl.h> + +int pagecache_reclaim_enable; +int pagecache_limit_ratio; +int pagecache_reclaim_ratio; + +static unsigned long pagecache_limit_pages; +static unsigned long node_pagecache_limit_pages[MAX_NUMNODES]; + +static unsigned long get_node_total_pages(int nid) +{ + int zone_type; + unsigned long managed_pages = 0; + pg_data_t *pgdat = NODE_DATA(nid); + + if (!pgdat) + return 0; + + for (zone_type = 0; zone_type < MAX_NR_ZONES; zone_type++) + managed_pages += zone_managed_pages(&pgdat->node_zones[zone_type]); + + return managed_pages; +} + +static void setup_pagecache_limit(void) +{ + int i; + unsigned long node_total_pages; + + pagecache_limit_pages = pagecache_limit_ratio * totalram_pages() / 100; + + for (i = 0; i < MAX_NUMNODES; i++) { + node_total_pages = get_node_total_pages(i); + node_pagecache_limit_pages[i] = node_total_pages * + pagecache_limit_ratio / 100; + } +} + +int proc_page_cache_limit(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + int ret; + + ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); + + if (write && !ret) + setup_pagecache_limit(); + + return ret; +}