[Devel] [PATCH RHEL8 COMMIT] mm: add warning about high order allocations

Konstantin Khorenko khorenko at virtuozzo.com
Thu May 7 22:41:45 MSK 2020


The commit is pushed to "branch-rh8-4.18.0-80.1.2.vz8.3.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh8-4.18.0-80.1.2.vz8.3.8
------>
commit 354452735c968284bd23dd537588adb2a73f5a09
Author: Andrey Ryabinin <aryabinin at virtuozzo.com>
Date:   Thu Jan 18 16:35:05 2018 +0300

    mm: add warning about high order allocations
    
    Add sysctl vm.warn_high_order. If set it will warn about
    about allocations with order >= vm.warn_high_order.
    Prints only 32 warning at most and skips all __GFP_NOWARN allocations.
    Disabled by default.
    
    https://jira.sw.ru/browse/PSBM-79892
    Signed-off-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
    
    +++
    mm: fix high order allocation warning limits
    
    After sysctl parameter 'vm.warn_high_order' is modified it can't be
    returned back to the default value MAX_ORDER+1, only to the fixed
    value 10.
    
    Set the maximum value to 100 which is always larger than any maximum
    order. Also set the default value to MAX_ORDER as it is already the
    value which can never be allocated.
    
    Also there is a logic to stop generating the warning after 32 occurences,
    but the logic is broken (the warning is generated even after the counter
    becomes less than zero). Modify the procedure of checking the counter.
    
    mFixes: 1ab81385c03f ("mm: add warning about high order allocations")
    
    https://jira.sw.ru/browse/PSBM-82202
    
    Signed-off-by: Oleg Babin <obabin at virtuozzo.com>
    Acked-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
    
    https://jira.sw.ru/browse/PSBM-103814
    
    (cherry picked from commit d853914118665ae6fe7b87bd4702215ba6f5daef)
    Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
---
 kernel/sysctl.c | 14 ++++++++++++++
 mm/page_alloc.c | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+)

diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index c40eea882001..898ec305032a 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -171,6 +171,11 @@ extern int unaligned_dump_stack;
 extern int no_unaligned_warning;
 #endif
 
+extern int warn_order;
+extern int proc_warn_high_order(struct ctl_table *table, int write,
+			void __user *buffer, size_t *lenp, loff_t *ppos);
+
+
 static bool virtual_ptr(void **ptr, void *base, size_t size, void *cur);
 #define sysctl_virtual(sysctl)							\
 int sysctl ## _virtual(struct ctl_table *table, int write,			\
@@ -1684,6 +1689,15 @@ static struct ctl_table vm_table[] = {
 		.extra2		= (void *)&mmap_rnd_compat_bits_max,
 	},
 #endif
+	{
+		.procname	= "warn_high_order",
+		.data		= &warn_order,
+		.maxlen		= sizeof(warn_order),
+		.mode		= 0644,
+		.proc_handler	= &proc_warn_high_order,
+		.extra1		= &zero,
+		.extra2		= &one_hundred,
+	},
 	{ }
 };
 
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index aadcc166bd0f..cbd6ee3ed01e 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -4393,6 +4393,37 @@ static inline void finalise_ac(gfp_t gfp_mask, struct alloc_context *ac)
 					ac->high_zoneidx, ac->nodemask);
 }
 
+struct static_key warn_high_order_key = STATIC_KEY_INIT_FALSE;
+int warn_order = MAX_ORDER;
+
+int proc_warn_high_order(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 (!ret) {
+		smp_wmb();
+		static_key_slow_inc(&warn_high_order_key);
+	}
+
+	return ret;
+}
+
+static __always_inline void warn_high_order(int order, gfp_t gfp_mask)
+{
+	static atomic_t warn_count = ATOMIC_INIT(32);
+
+	if (static_key_false(&warn_high_order_key)) {
+		int tmp_warn_order = smp_load_acquire(&warn_order);
+
+		if (order >= tmp_warn_order && !(gfp_mask & __GFP_NOWARN))
+			WARN(atomic_dec_if_positive(&warn_count) >= 0,
+				"order %d >= %d, gfp 0x%x\n",
+				order, tmp_warn_order, gfp_mask);
+	}
+}
+
 /*
  * This is the 'heart' of the zoned buddy allocator.
  */
@@ -4407,6 +4438,9 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, int preferred_nid,
 
 	gfp_mask &= gfp_allowed_mask;
 	alloc_mask = gfp_mask;
+
+	warn_high_order(order, gfp_mask);
+
 	if (!prepare_alloc_pages(gfp_mask, order, preferred_nid, nodemask, &ac, &alloc_mask, &alloc_flags))
 		return NULL;
 


More information about the Devel mailing list