All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jason Miu <jasonmiu@google.com>
To: Andrew Morton <akpm@linux-foundation.org>,
	David Hildenbrand <david@kernel.org>,
	 Shuah Khan <shuah@kernel.org>,
	David Rientjes <rientjes@google.com>,
	 Shakeel Butt <shakeel.butt@linux.dev>
Cc: Lorenzo Stoakes <ljs@kernel.org>,
	"Liam R . Howlett" <liam@infradead.org>,
	 Vlastimil Babka <vbabka@kernel.org>,
	Mike Rapoport <rppt@kernel.org>,
	 Suren Baghdasaryan <surenb@google.com>,
	Michal Hocko <mhocko@suse.com>, Greg Thelen <gthelen@google.com>,
	 linux-kernel@vger.kernel.org, linux-mm@kvack.org,
	 linux-kselftest@vger.kernel.org, Jason Miu <jasonmiu@google.com>
Subject: [PATCH 1/3] lib/test_mempress_timer: add module to generate kernel allocation pressure
Date: Wed, 19 Aug 2026 00:05:36 -0700	[thread overview]
Message-ID: <20260819070538.2404983-2-jasonmiu@google.com> (raw)
In-Reply-To: <20260819070538.2404983-1-jasonmiu@google.com>

Update lib/Kconfig.debug and lib/Makefile to introduce
test_mempress_timer, a kernel testing module designed to generate
synthetic memory allocation pressure within SoftIRQ contexts.

Bind independent timers to each online CPU to continuously execute
atomic page allocations (GFP_ATOMIC | __GFP_NOWARN). Provide this
workload generator to repeatedly emulate heavy kernel allocation demands.

Add a configurable termination threshold (test_duration_secs) to prevent
permanent test-node lockups, and provide batching control via the
allocs_per_iteration module parameter.

Signed-off-by: Jason Miu <jasonmiu@google.com>
---
 lib/Kconfig.debug         |  11 +++
 lib/Makefile              |   1 +
 lib/test_mempress_timer.c | 140 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 152 insertions(+)
 create mode 100644 lib/test_mempress_timer.c

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 1244dcac2294..00d32012e476 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -2635,6 +2635,17 @@ config TEST_BITOPS
 
 	  If unsure, say N.
 
+config TEST_MEMPRESS_TIMER
+	tristate "Test module for memory pressure and allocation stall timing"
+	default n
+	help
+	  This builds the "test_mempress_timer" module that can be used to
+	  provoke and profile page allocation stalls and direct reclaim
+	  slowness. It periodically does a atomic page allocation to generate a
+	  memory pressure.
+
+	  If unsure, say N.
+
 config TEST_VMALLOC
 	tristate "Test module for stress/performance analysis of vmalloc allocator"
 	default n
diff --git a/lib/Makefile b/lib/Makefile
index 7f75cc6edf94..0f35c2b78970 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -78,6 +78,7 @@ CFLAGS_test_ubsan.o += $(call cc-disable-warning, unused-but-set-variable)
 UBSAN_SANITIZE_test_ubsan.o := y
 obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
 obj-$(CONFIG_TEST_LKM) += test_module.o
+obj-$(CONFIG_TEST_MEMPRESS_TIMER) += test_mempress_timer.o
 obj-$(CONFIG_TEST_VMALLOC) += test_vmalloc.o
 obj-$(CONFIG_TEST_WORKQUEUE) += test_workqueue.o
 obj-$(CONFIG_TEST_RHASHTABLE) += test_rhashtable.o
diff --git a/lib/test_mempress_timer.c b/lib/test_mempress_timer.c
new file mode 100644
index 000000000000..a102ac4f6725
--- /dev/null
+++ b/lib/test_mempress_timer.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * test_mempress_timer.c
+ *
+ * Simulates kernelspace memory allocation pressure via timers.
+ * This module binds individual timers to each online CPU to independently
+ * allocate and free physical pages concurrently. It serves as a workload
+ * generator to reproduce and measure page allocation stalls under system
+ * memory contention.
+ *
+ * Module Parameters:
+ *  - allocs_per_iteration: Number of atomic page allocations executed
+ *                          during each timer callback.
+ *                          Default: 1000
+ *  - test_duration_secs:   Total duration in seconds to run the pressure test
+ *                          before automatically disengaging.
+ *                          Default: 900 (15 minutes)
+ *
+ * Usage:
+ * insmod test_mempress_timer.ko test_duration_secs=900 allocs_per_iteration=1000
+ */
+
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/timer.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <net/tcp.h>
+
+struct mempress_timer {
+	struct timer_list timer;
+	struct list_head list;
+	struct list_head page_list;
+	int cpu;
+};
+
+static LIST_HEAD(timers);
+static bool stop_timers;
+
+static unsigned long interval = 2;
+
+static unsigned long allocs_per_iteration = 1000;
+module_param(allocs_per_iteration, long, 0444);
+
+static unsigned long test_duration_secs = 900; /* 15 mins default */
+module_param(test_duration_secs, ulong, 0444);
+
+static unsigned long end_jiffies;
+
+static void alloc_pages_atomics(struct mempress_timer *test)
+{
+	int i;
+	struct page *page;
+
+	for (i = 0; i < allocs_per_iteration; i++) {
+		page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
+		if (!page) {
+			pr_warn("page allocation failure from cpu %d at iteration %d\n",
+				test->cpu, i);
+			break;
+		}
+		list_add(&page->lru, &test->page_list);
+	}
+}
+
+static void free_pages_atomics(struct mempress_timer *test)
+{
+	struct list_head *page;
+	struct list_head *iter;
+
+	list_for_each_safe(page, iter, &test->page_list)
+		__free_page(container_of(page, struct page, lru));
+	INIT_LIST_HEAD(&test->page_list);
+}
+
+static void atomic_timer_allocator(struct timer_list *timer)
+{
+	struct mempress_timer *test = timer_container_of(test, timer, timer);
+	bool is_expired = (test_duration_secs > 0 &&
+			   time_after(jiffies, end_jiffies));
+
+	if (list_empty(&test->page_list) && !is_expired)
+		alloc_pages_atomics(test);
+	else
+		free_pages_atomics(test);
+
+	if (!READ_ONCE(stop_timers) && !is_expired) {
+		test->timer.expires = jiffies + interval;
+		add_timer_on(&test->timer, test->cpu);
+	} else if (is_expired) {
+		pr_info_once("Duration (%lu secs) reached, stopping.\n", test_duration_secs);
+	}
+}
+
+static int __init mempress_timers_init(void)
+{
+	int cpu;
+	struct mempress_timer *test;
+
+	if (test_duration_secs > 0)
+		end_jiffies = jiffies + (test_duration_secs * HZ);
+
+	for_each_online_cpu(cpu) {
+		test = kzalloc(sizeof(*test), GFP_KERNEL | __GFP_NOFAIL);
+
+		timer_setup(&test->timer, atomic_timer_allocator, 0);
+		list_add(&test->list, &timers);
+		INIT_LIST_HEAD(&test->page_list);
+		test->cpu = cpu;
+
+		/* For start, use 90 seconds. */
+		test->timer.expires = jiffies + (90 * HZ);
+		add_timer_on(&test->timer, test->cpu);
+	}
+
+	return 0;
+}
+module_init(mempress_timers_init);
+
+static void mempress_timers_exit(void)
+{
+	struct mempress_timer *test, *n;
+
+	pr_crit("exiting\n");
+	stop_timers = true;
+
+	list_for_each_entry_safe(test, n, &timers, list) {
+		timer_delete_sync(&test->timer);
+		list_del(&test->list);
+		cond_resched();
+		free_pages_atomics(test);
+		kfree(test);
+	}
+}
+module_exit(mempress_timers_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Test memory pressure from timers");
-- 
2.55.0.691.gc56d675ccc-goog



  reply	other threads:[~2026-08-19  7:05 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-19  7:05 [RFC PATCH 0/3] selftests: mm: introduce page allocation stall reproducer Jason Miu
2026-08-19  7:05 ` Jason Miu [this message]
2026-08-19  7:05 ` [PATCH 2/3] selftests: mm: add script to induce userspace memory contention Jason Miu
2026-08-19  7:05 ` [PATCH 3/3] selftests: mm: add script for memory allocation stall test Jason Miu
2026-08-21  0:03 ` [RFC PATCH 0/3] selftests: mm: introduce page allocation stall reproducer Andrew Morton
2026-08-21  9:53   ` David Hildenbrand (Arm)
2026-08-21 10:44     ` Lorenzo Stoakes (ARM)

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260819070538.2404983-2-jasonmiu@google.com \
    --to=jasonmiu@google.com \
    --cc=akpm@linux-foundation.org \
    --cc=david@kernel.org \
    --cc=gthelen@google.com \
    --cc=liam@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=ljs@kernel.org \
    --cc=mhocko@suse.com \
    --cc=rientjes@google.com \
    --cc=rppt@kernel.org \
    --cc=shakeel.butt@linux.dev \
    --cc=shuah@kernel.org \
    --cc=surenb@google.com \
    --cc=vbabka@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.