From: Ma Wupeng mawupeng1@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4SK3S CVE: NA
--------------------------------
Now reliable_debug will be consistent with boot parameter. If reliable_debug in boot parameter is set t "F", reliable_debug in proc will be 13 which means only fallback is closed.
Fixes: 851a3ff0b4de ("mm: Introduce proc interface to control memory reliable features") Signed-off-by: Ma Wupeng mawupeng1@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- mm/mem_reliable.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/mm/mem_reliable.c b/mm/mem_reliable.c index ae4e9609f43cf..7ce97184e08ec 100644 --- a/mm/mem_reliable.c +++ b/mm/mem_reliable.c @@ -275,10 +275,8 @@ static void mem_reliable_parse_ctrl_bits(unsigned long ctrl_bits) for (i = MEM_RELIABLE_FALLBACK; i < MEM_RELIABLE_MAX; i++) { status = !!test_bit(i, &ctrl_bits);
- if (mem_reliable_ctrl_bit_is_enabled(i) ^ status) { - mem_reliable_ctrl_bit_set(i, status); + if (mem_reliable_ctrl_bit_is_enabled(i) ^ status) mem_reliable_feature_set(i, status); - } } }
@@ -484,6 +482,8 @@ static int __init reliable_sysctl_init(void) return 0; } late_initcall(reliable_sysctl_init); +#else +static void mem_reliable_ctrl_bit_set(int idx, bool enable) {} #endif
static void mem_reliable_feature_set(int idx, bool enable) @@ -508,6 +508,7 @@ static void mem_reliable_feature_set(int idx, bool enable) return; }
+ mem_reliable_ctrl_bit_set(idx, enable); pr_info("%s is %s\n", str, enable ? "enabled" : "disabled"); }
From: Ma Wupeng mawupeng1@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I4SK3S CVE: NA
------------------------------------------
With the patch, Memory reliable features can only be disabled via /proc/sys/vm/reliable_debug. Pervious features can be enabled via this interface and this may lead to tricky counting or limit problem.
Signed-off-by: Ma Wupeng mawupeng1@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- Documentation/sysctl/vm.txt | 7 +++--- mm/mem_reliable.c | 45 ++++++++++++++----------------------- 2 files changed, 21 insertions(+), 31 deletions(-)
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt index b2a1e9ac4fb27..b3808f1236f89 100644 --- a/Documentation/sysctl/vm.txt +++ b/Documentation/sysctl/vm.txt @@ -928,7 +928,8 @@ configurations.
reliable_debug:
-reliable_debug is used to control memory reliable features. +reliable_debug is used to control memory reliable features and can only be +disabled via this interface.
Four bits are used to represent the following features - bit 0: memory reliable feature @@ -939,8 +940,8 @@ Four bits are used to represent the following features Bit 1~3 are valid if and only if the bit 0 is 1. If the first bit is 0, all other features will be closed no matter other bits's status.
-For example, you can enable reliable fallback feature by +For example, you can disable all features by
- $ echo 3 > /proc/sys/vm/reliable_debug + $ echo 0 > /proc/sys/vm/reliable_debug
============ End of Document ================================= diff --git a/mm/mem_reliable.c b/mm/mem_reliable.c index 7ce97184e08ec..d02159b0182fa 100644 --- a/mm/mem_reliable.c +++ b/mm/mem_reliable.c @@ -241,19 +241,16 @@ int reliable_limit_handler(struct ctl_table *table, int write, return ret; }
-static void mem_reliable_feature_set(int idx, bool enable); +static void mem_reliable_feature_disable(int idx);
#define CTRL_BITS_SHIFT MEM_RELIABLE_MAX #define CTRL_BITS_MASK ((1 << CTRL_BITS_SHIFT) - 1)
static unsigned long mem_reliable_ctrl_bits = CTRL_BITS_MASK;
-static void mem_reliable_ctrl_bit_set(int idx, bool enable) +static void mem_reliable_ctrl_bit_disabled(int idx) { - if (enable) - set_bit(idx, &mem_reliable_ctrl_bits); - else - clear_bit(idx, &mem_reliable_ctrl_bits); + clear_bit(idx, &mem_reliable_ctrl_bits); }
static bool mem_reliable_ctrl_bit_is_enabled(int idx) @@ -266,25 +263,16 @@ static void mem_reliable_parse_ctrl_bits(unsigned long ctrl_bits) bool status; int i;
- if (!mem_reliable_is_enabled()) { - static_branch_enable(&mem_reliable); - mem_reliable_ctrl_bit_set(MEM_RELIABLE_ALL, 1); - pr_info("memory reliable feature enabled.\n"); - } - for (i = MEM_RELIABLE_FALLBACK; i < MEM_RELIABLE_MAX; i++) { status = !!test_bit(i, &ctrl_bits);
- if (mem_reliable_ctrl_bit_is_enabled(i) ^ status) - mem_reliable_feature_set(i, status); + if (mem_reliable_ctrl_bit_is_enabled(i) && !status) + mem_reliable_feature_disable(i); } }
static void mem_reliable_disable_all(void) { - if (!mem_reliable_is_enabled()) - return; - mem_reliable_ctrl_bits = 0;
reliable_allow_fallback = false; @@ -306,7 +294,8 @@ int reliable_debug_handler(struct ctl_table *table, int write, old_ctrl_bits = mem_reliable_ctrl_bits; ret = proc_doulongvec_minmax(table, write, buffer, length, ppos); if (ret == 0 && write) { - if (mem_reliable_ctrl_bits > (1 << CTRL_BITS_SHIFT) - 1) { + if (!mem_reliable_is_enabled() || + (mem_reliable_ctrl_bits > (1 << CTRL_BITS_SHIFT) - 1)) { mem_reliable_ctrl_bits = old_ctrl_bits; mutex_unlock(&reliable_debug_mutex);
@@ -483,24 +472,24 @@ static int __init reliable_sysctl_init(void) } late_initcall(reliable_sysctl_init); #else -static void mem_reliable_ctrl_bit_set(int idx, bool enable) {} +static void mem_reliable_ctrl_bit_disabled(int idx) {} #endif
-static void mem_reliable_feature_set(int idx, bool enable) +static void mem_reliable_feature_disable(int idx) { char *str = NULL;
switch (idx) { case MEM_RELIABLE_FALLBACK: - reliable_allow_fallback = enable; + reliable_allow_fallback = false; str = "fallback"; break; case MEM_RELIABLE_SHM: - shmem_reliable = enable; + shmem_reliable = false; str = "shmem"; break; case MEM_RELIABLE_PAGECACHE: - pagecache_use_reliable_mem = enable; + pagecache_use_reliable_mem = false; str = "pagecache"; break; default: @@ -508,8 +497,8 @@ static void mem_reliable_feature_set(int idx, bool enable) return; }
- mem_reliable_ctrl_bit_set(idx, enable); - pr_info("%s is %s\n", str, enable ? "enabled" : "disabled"); + mem_reliable_ctrl_bit_disabled(idx); + pr_info("%s is disabled\n", str); }
void reliable_show_mem_info(void) @@ -556,13 +545,13 @@ static int __init setup_reliable_debug(char *str) for (; *str && *str != ','; str++) { switch (*str) { case 'F': - mem_reliable_feature_set(MEM_RELIABLE_FALLBACK, false); + mem_reliable_feature_disable(MEM_RELIABLE_FALLBACK); break; case 'S': - mem_reliable_feature_set(MEM_RELIABLE_SHM, false); + mem_reliable_feature_disable(MEM_RELIABLE_SHM); break; case 'P': - mem_reliable_feature_set(MEM_RELIABLE_PAGECACHE, false); + mem_reliable_feature_disable(MEM_RELIABLE_PAGECACHE); break; default: pr_err("reliable_debug option '%c' unknown. skipped\n",
From: Ma Wupeng mawupeng1@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4SK3S CVE: NA
------------------------------------------
Stub mirrored_kernelcore if CONFIG_HAVE_MEMBLOCK_NODE_MAP is not enabled. If CONFIG_HAVE_MEMBLOCK_NODE_MAP is disabled, mirrored_kernelcore in efi_find_mirror() will be undeclared and this will lead to compile problem.
Fixes: d7421c3f51a3 ("efi: Disable mirror feature if kernelcore is not spcified") Signed-off-by: Ma Wupeng mawupeng1@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- include/linux/mm.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/include/linux/mm.h b/include/linux/mm.h index 460b8d4cae877..72532a1d2d20e 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2272,6 +2272,8 @@ extern void sparse_memory_present_with_active_regions(int nid);
extern bool mirrored_kernelcore;
+#else +#define mirrored_kernelcore 0 #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
#if !defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP) && \
From: Ma Wupeng mawupeng1@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4SK3S CVE: NA
------------------------------------------
Memory allocation from buddy system will fallback to unmirrored memory if mirrored memory is not enough and reliable memory fallback is closed. ___GFP_NOFAIL flag will be checked in prepare_before_alloc().
Fixes: 45bd608ef89e ("mm: Introduce watermark check for memory reliable") Signed-off-by: Ma Wupeng mawupeng1@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- mm/page_alloc.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 571bfdecd5a0c..fd4354d9ebad0 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -4651,7 +4651,13 @@ static inline bool prepare_before_alloc(gfp_t *gfp_mask, unsigned int order) if (!mem_reliable_is_enabled()) return true;
+ if (*gfp_mask & __GFP_NOFAIL) + return true; + if (gfp_ori & ___GFP_RELIABILITY) { + if (!(gfp_ori & __GFP_HIGHMEM) || !(gfp_ori & __GFP_MOVABLE)) + return true; + if (mem_reliable_watermark_ok(1 << order)) { *gfp_mask |= ___GFP_RELIABILITY; return true;
From: Chen Wandun chenwandun@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4SK3S CVE: NA
--------------------------------
Reliable page cache should be account in update_lru_sizes and move_active_pages_to_lru.
update_lru_sizes is used to account page after pages are isolated from lru in batch.
move_active_pages_to_lru will add pages to lru, so statistic should update synchronously.
Signed-off-by: Chen Wandun chenwandun@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- include/linux/mem_reliable.h | 4 ++++ mm/mem_reliable.c | 17 +++++++++++++++-- mm/vmscan.c | 4 ++++ 3 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/include/linux/mem_reliable.h b/include/linux/mem_reliable.h index 00c915f583699..83ae566fac5fc 100644 --- a/include/linux/mem_reliable.h +++ b/include/linux/mem_reliable.h @@ -40,6 +40,8 @@ extern bool mem_reliable_status(void); extern void page_cache_reliable_lru_add(enum lru_list lru, struct page *page, int val); extern void page_cache_prepare_alloc(gfp_t *gfp); +extern void page_cache_reliable_lru_add_batch(int zid, enum lru_list lru, + int val);
static inline bool mem_reliable_is_enabled(void) { @@ -174,6 +176,8 @@ static inline void page_cache_reliable_lru_add(enum lru_list lru, struct page *page, int val) {} static inline void page_cache_prepare_alloc(gfp_t *gfp) {} +static inline void page_cache_reliable_lru_add_batch(int zid, enum lru_list lru, + int val) {} #endif
#endif diff --git a/mm/mem_reliable.c b/mm/mem_reliable.c index d02159b0182fa..8c664e0add91c 100644 --- a/mm/mem_reliable.c +++ b/mm/mem_reliable.c @@ -64,12 +64,25 @@ static bool reliable_and_lru_check(enum lru_list lru, struct page *page) if (!page_reliable(page)) return false;
- if (lru != LRU_ACTIVE_FILE && lru != LRU_INACTIVE_FILE) + if (!is_file_lru(lru)) return false;
return true; }
+void page_cache_reliable_lru_add_batch(int zid, enum lru_list lru, + int val) +{ + if (!mem_reliable_is_enabled()) + return; + + if (zid < 0 || zid >= MAX_NR_ZONES) + return; + + if (zid < ZONE_MOVABLE && is_file_lru(lru)) + this_cpu_add(pagecache_reliable_pages, val); +} + void page_cache_reliable_lru_add(enum lru_list lru, struct page *page, int val) { if (!reliable_and_lru_check(lru, page)) @@ -177,7 +190,7 @@ static void show_val_kb(struct seq_file *m, const char *s, unsigned long num) void reliable_report_meminfo(struct seq_file *m) { bool pagecache_enabled = pagecache_reliable_is_enabled(); - unsigned long nr_pagecache_pages = 0; + long nr_pagecache_pages = 0; long nr_buddy_pages = 0; int cpu;
diff --git a/mm/vmscan.c b/mm/vmscan.c index 15e5864c51050..994c116306aa2 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1683,6 +1683,8 @@ static __always_inline void update_lru_sizes(struct lruvec *lruvec, #ifdef CONFIG_MEMCG mem_cgroup_update_lru_size(lruvec, lru, zid, -nr_zone_taken[zid]); #endif + page_cache_reliable_lru_add_batch(zid, lru, + -nr_zone_taken[zid]); }
} @@ -2099,6 +2101,8 @@ static unsigned move_active_pages_to_lru(struct lruvec *lruvec, update_lru_size(lruvec, lru, page_zonenum(page), nr_pages); list_move(&page->lru, &lruvec->lists[lru]);
+ page_cache_reliable_lru_add(lru, page, nr_pages); + if (put_page_testzero(page)) { __ClearPageLRU(page); __ClearPageActive(page);