未验证 提交 f5784b3d 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!269 Reduce the memory usage by kernel

Merge Pull Request from: @liushixin2 
 
Backport four patches which are used to reduce the memory usage by kernel.

The first three patches are used to reduce the memory occupied by zswap when zswap is not used. Before these patches, whether zswap is enabled or not, it occupies at least 18MB memory. With these patches,
the initialization of zswap will be delayed until it is enabled first time and we can save 18MB memory if we never use zswap.

The last patch doesn't reduce memory directly, it introduces a new interface to control the batchsize and high of percpu pageset. With this patch, we can limit the high of percpu pageset to a lower value, which can increase free memory displayed in meminfo. 
 
Link:https://gitee.com/openeuler/kernel/pulls/269 
Reviewed-by: Zheng Zengkai <zhengzengkai@huawei.com> 
Reviewed-by: Kefeng Wang <wangkefeng.wang@huawei.com> 
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com> 
...@@ -65,6 +65,7 @@ Currently, these files are in /proc/sys/vm: ...@@ -65,6 +65,7 @@ Currently, these files are in /proc/sys/vm:
- page-cluster - page-cluster
- panic_on_oom - panic_on_oom
- percpu_pagelist_fraction - percpu_pagelist_fraction
- percpu_max_batchsize
- stat_interval - stat_interval
- stat_refresh - stat_refresh
- numa_stat - numa_stat
...@@ -856,6 +857,15 @@ the high water marks for each per cpu page list. If the user writes '0' to this ...@@ -856,6 +857,15 @@ the high water marks for each per cpu page list. If the user writes '0' to this
sysctl, it will revert to this default behavior. sysctl, it will revert to this default behavior.
percpu_max_batchsize
========================
This is used to setup the max batch and high size of percpu in each zone.
The default value is set to (256 * 1024) / PAGE_SIZE.
The max value is limited to (512 * 1024) / PAGE_SIZE.
The min value is limited to (64 * 1024) / PAGE_SIZE.
stat_interval stat_interval
============= =============
......
...@@ -1009,6 +1009,8 @@ int lowmem_reserve_ratio_sysctl_handler(struct ctl_table *, int, void *, ...@@ -1009,6 +1009,8 @@ int lowmem_reserve_ratio_sysctl_handler(struct ctl_table *, int, void *,
size_t *, loff_t *); size_t *, loff_t *);
int percpu_pagelist_fraction_sysctl_handler(struct ctl_table *, int, int percpu_pagelist_fraction_sysctl_handler(struct ctl_table *, int,
void *, size_t *, loff_t *); void *, size_t *, loff_t *);
int percpu_max_batchsize_sysctl_handler(struct ctl_table *, int,
void *, size_t *, loff_t *);
int sysctl_min_unmapped_ratio_sysctl_handler(struct ctl_table *, int, int sysctl_min_unmapped_ratio_sysctl_handler(struct ctl_table *, int,
void *, size_t *, loff_t *); void *, size_t *, loff_t *);
int sysctl_min_slab_ratio_sysctl_handler(struct ctl_table *, int, int sysctl_min_slab_ratio_sysctl_handler(struct ctl_table *, int,
...@@ -1016,6 +1018,7 @@ int sysctl_min_slab_ratio_sysctl_handler(struct ctl_table *, int, ...@@ -1016,6 +1018,7 @@ int sysctl_min_slab_ratio_sysctl_handler(struct ctl_table *, int,
int numa_zonelist_order_handler(struct ctl_table *, int, int numa_zonelist_order_handler(struct ctl_table *, int,
void *, size_t *, loff_t *); void *, size_t *, loff_t *);
extern int percpu_pagelist_fraction; extern int percpu_pagelist_fraction;
extern int percpu_max_batchsize;
extern char numa_zonelist_order[]; extern char numa_zonelist_order[];
#define NUMA_ZONELIST_ORDER_LEN 16 #define NUMA_ZONELIST_ORDER_LEN 16
......
...@@ -2993,6 +2993,14 @@ static struct ctl_table vm_table[] = { ...@@ -2993,6 +2993,14 @@ static struct ctl_table vm_table[] = {
.proc_handler = percpu_pagelist_fraction_sysctl_handler, .proc_handler = percpu_pagelist_fraction_sysctl_handler,
.extra1 = SYSCTL_ZERO, .extra1 = SYSCTL_ZERO,
}, },
{
.procname = "percpu_max_batchsize",
.data = &percpu_max_batchsize,
.maxlen = sizeof(percpu_max_batchsize),
.mode = 0644,
.proc_handler = percpu_max_batchsize_sysctl_handler,
.extra1 = SYSCTL_ZERO,
},
{ {
.procname = "page_lock_unfairness", .procname = "page_lock_unfairness",
.data = &sysctl_page_lock_unfairness, .data = &sysctl_page_lock_unfairness,
......
...@@ -112,6 +112,8 @@ typedef int __bitwise fpi_t; ...@@ -112,6 +112,8 @@ typedef int __bitwise fpi_t;
/* prevent >1 _updater_ of zone percpu pageset ->high and ->batch fields */ /* prevent >1 _updater_ of zone percpu pageset ->high and ->batch fields */
static DEFINE_MUTEX(pcp_batch_high_lock); static DEFINE_MUTEX(pcp_batch_high_lock);
#define MIN_PERCPU_PAGELIST_FRACTION (8) #define MIN_PERCPU_PAGELIST_FRACTION (8)
#define MAX_PERCPU_MAX_BATCHSIZE ((512 * 1024) / PAGE_SIZE)
#define MIN_PERCPU_MAX_BATCHSIZE (MAX_PERCPU_MAX_BATCHSIZE / 8)
#ifdef CONFIG_USE_PERCPU_NUMA_NODE_ID #ifdef CONFIG_USE_PERCPU_NUMA_NODE_ID
DEFINE_PER_CPU(int, numa_node); DEFINE_PER_CPU(int, numa_node);
...@@ -167,6 +169,8 @@ unsigned long totalreserve_pages __read_mostly; ...@@ -167,6 +169,8 @@ unsigned long totalreserve_pages __read_mostly;
unsigned long totalcma_pages __read_mostly; unsigned long totalcma_pages __read_mostly;
int percpu_pagelist_fraction; int percpu_pagelist_fraction;
int percpu_max_batchsize = MAX_PERCPU_MAX_BATCHSIZE / 2;
gfp_t gfp_allowed_mask __read_mostly = GFP_BOOT_MASK; gfp_t gfp_allowed_mask __read_mostly = GFP_BOOT_MASK;
#ifdef CONFIG_INIT_ON_ALLOC_DEFAULT_ON #ifdef CONFIG_INIT_ON_ALLOC_DEFAULT_ON
DEFINE_STATIC_KEY_TRUE(init_on_alloc); DEFINE_STATIC_KEY_TRUE(init_on_alloc);
...@@ -6757,10 +6761,9 @@ static int zone_batchsize(struct zone *zone) ...@@ -6757,10 +6761,9 @@ static int zone_batchsize(struct zone *zone)
* size of the zone. * size of the zone.
*/ */
batch = zone_managed_pages(zone) / 1024; batch = zone_managed_pages(zone) / 1024;
/* But no more than a meg. */
if (batch * PAGE_SIZE > 1024 * 1024)
batch = (1024 * 1024) / PAGE_SIZE;
batch /= 4; /* We effectively *= 4 below */ batch /= 4; /* We effectively *= 4 below */
if (batch > percpu_max_batchsize)
batch = percpu_max_batchsize;
if (batch < 1) if (batch < 1)
batch = 1; batch = 1;
...@@ -8615,6 +8618,39 @@ int percpu_pagelist_fraction_sysctl_handler(struct ctl_table *table, int write, ...@@ -8615,6 +8618,39 @@ int percpu_pagelist_fraction_sysctl_handler(struct ctl_table *table, int write,
return ret; return ret;
} }
int percpu_max_batchsize_sysctl_handler(struct ctl_table *table, int write,
void *buffer, size_t *length, loff_t *ppos)
{
struct zone *zone;
int old_percpu_max_batchsize;
int ret;
mutex_lock(&pcp_batch_high_lock);
old_percpu_max_batchsize = percpu_max_batchsize;
ret = proc_dointvec_minmax(table, write, buffer, length, ppos);
if (!write || ret < 0)
goto out;
/* Sanity checking to avoid pcp imbalance */
if (percpu_max_batchsize > MAX_PERCPU_MAX_BATCHSIZE ||
percpu_max_batchsize < MIN_PERCPU_MAX_BATCHSIZE) {
percpu_max_batchsize = old_percpu_max_batchsize;
ret = -EINVAL;
goto out;
}
/* No change? */
if (percpu_max_batchsize == old_percpu_max_batchsize)
goto out;
for_each_populated_zone(zone)
zone_set_pageset_high_and_batch(zone);
out:
mutex_unlock(&pcp_batch_high_lock);
return ret;
}
#ifndef __HAVE_ARCH_RESERVED_KERNEL_PAGES #ifndef __HAVE_ARCH_RESERVED_KERNEL_PAGES
/* /*
* Returns the number of pages that arch has reserved but * Returns the number of pages that arch has reserved but
......
...@@ -79,6 +79,8 @@ static bool zswap_pool_reached_full; ...@@ -79,6 +79,8 @@ static bool zswap_pool_reached_full;
#define ZSWAP_PARAM_UNSET "" #define ZSWAP_PARAM_UNSET ""
static int zswap_setup(void);
/* Enable/disable zswap */ /* Enable/disable zswap */
static bool zswap_enabled = IS_ENABLED(CONFIG_ZSWAP_DEFAULT_ON); static bool zswap_enabled = IS_ENABLED(CONFIG_ZSWAP_DEFAULT_ON);
static int zswap_enabled_param_set(const char *, static int zswap_enabled_param_set(const char *,
...@@ -203,11 +205,14 @@ static DEFINE_SPINLOCK(zswap_pools_lock); ...@@ -203,11 +205,14 @@ static DEFINE_SPINLOCK(zswap_pools_lock);
/* pool counter to provide unique names to zpool */ /* pool counter to provide unique names to zpool */
static atomic_t zswap_pools_count = ATOMIC_INIT(0); static atomic_t zswap_pools_count = ATOMIC_INIT(0);
/* used by param callback function */ #define ZSWAP_UNINIT 0
static bool zswap_init_started; #define ZSWAP_INIT_SUCCEED 1
#define ZSWAP_INIT_FAILED 2
/* fatal error during init */ /* init state */
static bool zswap_init_failed; static int zswap_init_state;
/* used to ensure the integrity of initialization */
static DEFINE_MUTEX(zswap_init_lock);
/* init completed, but couldn't create the initial pool */ /* init completed, but couldn't create the initial pool */
static bool zswap_has_pool; static bool zswap_has_pool;
...@@ -261,13 +266,13 @@ static void zswap_update_total_size(void) ...@@ -261,13 +266,13 @@ static void zswap_update_total_size(void)
**********************************/ **********************************/
static struct kmem_cache *zswap_entry_cache; static struct kmem_cache *zswap_entry_cache;
static int __init zswap_entry_cache_create(void) static int zswap_entry_cache_create(void)
{ {
zswap_entry_cache = KMEM_CACHE(zswap_entry, 0); zswap_entry_cache = KMEM_CACHE(zswap_entry, 0);
return zswap_entry_cache == NULL; return zswap_entry_cache == NULL;
} }
static void __init zswap_entry_cache_destroy(void) static void zswap_entry_cache_destroy(void)
{ {
kmem_cache_destroy(zswap_entry_cache); kmem_cache_destroy(zswap_entry_cache);
} }
...@@ -648,7 +653,7 @@ static struct zswap_pool *zswap_pool_create(char *type, char *compressor) ...@@ -648,7 +653,7 @@ static struct zswap_pool *zswap_pool_create(char *type, char *compressor)
return NULL; return NULL;
} }
static __init struct zswap_pool *__zswap_pool_create_fallback(void) static struct zswap_pool *__zswap_pool_create_fallback(void)
{ {
bool has_comp, has_zpool; bool has_comp, has_zpool;
...@@ -757,7 +762,7 @@ static int __zswap_param_set(const char *val, const struct kernel_param *kp, ...@@ -757,7 +762,7 @@ static int __zswap_param_set(const char *val, const struct kernel_param *kp,
char *s = strstrip((char *)val); char *s = strstrip((char *)val);
int ret; int ret;
if (zswap_init_failed) { if (zswap_init_state == ZSWAP_INIT_FAILED) {
pr_err("can't set param, initialization failed\n"); pr_err("can't set param, initialization failed\n");
return -ENODEV; return -ENODEV;
} }
...@@ -766,11 +771,17 @@ static int __zswap_param_set(const char *val, const struct kernel_param *kp, ...@@ -766,11 +771,17 @@ static int __zswap_param_set(const char *val, const struct kernel_param *kp,
if (!strcmp(s, *(char **)kp->arg) && zswap_has_pool) if (!strcmp(s, *(char **)kp->arg) && zswap_has_pool)
return 0; return 0;
/* if this is load-time (pre-init) param setting, /*
* if zswap has not been initialized,
* don't create a pool; that's done during init. * don't create a pool; that's done during init.
*/ */
if (!zswap_init_started) mutex_lock(&zswap_init_lock);
return param_set_charp(s, kp); if (zswap_init_state == ZSWAP_UNINIT) {
ret = param_set_charp(s, kp);
mutex_unlock(&zswap_init_lock);
return ret;
}
mutex_unlock(&zswap_init_lock);
if (!type) { if (!type) {
if (!zpool_has_pool(s)) { if (!zpool_has_pool(s)) {
...@@ -860,11 +871,19 @@ static int zswap_zpool_param_set(const char *val, ...@@ -860,11 +871,19 @@ static int zswap_zpool_param_set(const char *val,
static int zswap_enabled_param_set(const char *val, static int zswap_enabled_param_set(const char *val,
const struct kernel_param *kp) const struct kernel_param *kp)
{ {
if (zswap_init_failed) { if (system_state == SYSTEM_RUNNING) {
mutex_lock(&zswap_init_lock);
if (zswap_setup()) {
mutex_unlock(&zswap_init_lock);
return -ENODEV;
}
mutex_unlock(&zswap_init_lock);
}
if (zswap_init_state == ZSWAP_INIT_FAILED) {
pr_err("can't enable, initialization failed\n"); pr_err("can't enable, initialization failed\n");
return -ENODEV; return -ENODEV;
} }
if (!zswap_has_pool && zswap_init_started) { if (!zswap_has_pool && zswap_init_state == ZSWAP_INIT_SUCCEED) {
pr_err("can't enable, no pool configured\n"); pr_err("can't enable, no pool configured\n");
return -ENODEV; return -ENODEV;
} }
...@@ -1390,7 +1409,7 @@ static struct frontswap_ops zswap_frontswap_ops = { ...@@ -1390,7 +1409,7 @@ static struct frontswap_ops zswap_frontswap_ops = {
static struct dentry *zswap_debugfs_root; static struct dentry *zswap_debugfs_root;
static int __init zswap_debugfs_init(void) static int zswap_debugfs_init(void)
{ {
if (!debugfs_initialized()) if (!debugfs_initialized())
return -ENODEV; return -ENODEV;
...@@ -1426,7 +1445,7 @@ static void __exit zswap_debugfs_exit(void) ...@@ -1426,7 +1445,7 @@ static void __exit zswap_debugfs_exit(void)
debugfs_remove_recursive(zswap_debugfs_root); debugfs_remove_recursive(zswap_debugfs_root);
} }
#else #else
static int __init zswap_debugfs_init(void) static int zswap_debugfs_init(void)
{ {
return 0; return 0;
} }
...@@ -1434,15 +1453,13 @@ static int __init zswap_debugfs_init(void) ...@@ -1434,15 +1453,13 @@ static int __init zswap_debugfs_init(void)
static void __exit zswap_debugfs_exit(void) { } static void __exit zswap_debugfs_exit(void) { }
#endif #endif
/********************************* static int zswap_setup(void)
* module init and exit
**********************************/
static int __init init_zswap(void)
{ {
struct zswap_pool *pool; struct zswap_pool *pool;
int ret; int ret;
zswap_init_started = true; if (zswap_init_state != ZSWAP_UNINIT)
return 0;
if (zswap_entry_cache_create()) { if (zswap_entry_cache_create()) {
pr_err("entry cache creation failed\n"); pr_err("entry cache creation failed\n");
...@@ -1481,6 +1498,7 @@ static int __init init_zswap(void) ...@@ -1481,6 +1498,7 @@ static int __init init_zswap(void)
frontswap_register_ops(&zswap_frontswap_ops); frontswap_register_ops(&zswap_frontswap_ops);
if (zswap_debugfs_init()) if (zswap_debugfs_init())
pr_warn("debugfs initialization failed\n"); pr_warn("debugfs initialization failed\n");
zswap_init_state = ZSWAP_INIT_SUCCEED;
return 0; return 0;
fallback_fail: fallback_fail:
...@@ -1492,10 +1510,22 @@ static int __init init_zswap(void) ...@@ -1492,10 +1510,22 @@ static int __init init_zswap(void)
zswap_entry_cache_destroy(); zswap_entry_cache_destroy();
cache_fail: cache_fail:
/* if built-in, we aren't unloaded on failure; don't allow use */ /* if built-in, we aren't unloaded on failure; don't allow use */
zswap_init_failed = true; zswap_init_state = ZSWAP_INIT_FAILED;
zswap_enabled = false; zswap_enabled = false;
return -ENOMEM; return -ENOMEM;
} }
/*********************************
* module init and exit
**********************************/
static int __init init_zswap(void)
{
/* skip init if zswap is disabled when system startup */
if (!zswap_enabled)
return 0;
return zswap_setup();
}
/* must be late so crypto has time to come up */ /* must be late so crypto has time to come up */
late_initcall(init_zswap); late_initcall(init_zswap);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册