linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC v2 0/3] test driver to analyse vmalloc allocator
@ 2018-12-31 13:26 Uladzislau Rezki (Sony)
  2018-12-31 13:26 ` [RFC v2 1/3] vmalloc: export __vmalloc_node_range for CONFIG_TEST_VMALLOC_MODULE Uladzislau Rezki (Sony)
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Uladzislau Rezki (Sony) @ 2018-12-31 13:26 UTC (permalink / raw)
  To: Michal Hocko, Kees Cook, Shuah Khan, Andrew Morton, linux-mm
  Cc: LKML, Matthew Wilcox, Oleksiy Avramchenko, Thomas Gleixner,
	Uladzislau Rezki (Sony)

Hello.

The first RFC was here: https://lkml.org/lkml/2018/11/13/957
Please have a look there for detailed description and discussion.
Here i will just specify what has been done since last RFC:

Changes in v2:
    - Code cleanup to make it more simple;
    - Now __vmalloc_node_range() is exported if CONFIG_TEST_VMALLOC_MODULE=m
    - Integrate vmalloc test suite into tools/testing/selftests/vm

I hope this test suite is more or less ready to go with. Appreciate your
comments and feedback anyway, so please RFC v2.

Thanks.

Uladzislau Rezks (Sony) (3):
  vmalloc: export __vmalloc_node_range for CONFIG_TEST_VMALLOC_MODULE
  vmalloc: add test driver to analyse vmalloc allocator
  selftests/vm: add script helper for CONFIG_TEST_VMALLOC_MODULE

 lib/Kconfig.debug                          |  12 +
 lib/Makefile                               |   1 +
 lib/test_vmalloc.c                         | 543 +++++++++++++++++++++++++++++
 mm/vmalloc.c                               |   9 +
 tools/testing/selftests/vm/run_vmtests     |  11 +
 tools/testing/selftests/vm/test_vmalloc.sh | 173 +++++++++
 6 files changed, 749 insertions(+)
 create mode 100644 lib/test_vmalloc.c
 create mode 100755 tools/testing/selftests/vm/test_vmalloc.sh

-- 
2.11.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [RFC v2 1/3] vmalloc: export __vmalloc_node_range for CONFIG_TEST_VMALLOC_MODULE
  2018-12-31 13:26 [RFC v2 0/3] test driver to analyse vmalloc allocator Uladzislau Rezki (Sony)
@ 2018-12-31 13:26 ` Uladzislau Rezki (Sony)
  2018-12-31 18:50   ` Matthew Wilcox
  2018-12-31 13:26 ` [RFC v2 2/3] vmalloc: add test driver to analyse vmalloc allocator Uladzislau Rezki (Sony)
  2018-12-31 13:26 ` [RFC v2 3/3] selftests/vm: add script helper for CONFIG_TEST_VMALLOC_MODULE Uladzislau Rezki (Sony)
  2 siblings, 1 reply; 8+ messages in thread
From: Uladzislau Rezki (Sony) @ 2018-12-31 13:26 UTC (permalink / raw)
  To: Michal Hocko, Kees Cook, Shuah Khan, Andrew Morton, linux-mm
  Cc: LKML, Matthew Wilcox, Oleksiy Avramchenko, Thomas Gleixner,
	Uladzislau Rezki (Sony)

Export __vmaloc_node_range() function if CONFIG_TEST_VMALLOC_MODULE is
enabled. Some test cases in vmalloc test suite module require and make
use of that function. Please note, that it is not supposed to be used
for other purposes.

We need it only for performance analysis, stressing and stability check
of vmalloc allocator.

Signed-off-by: Uladzislau Rezki (Sony) <urezki@gmail.com>
---
 mm/vmalloc.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index cfea25be7754..50ccb8bdfad8 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -1764,6 +1764,15 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align,
 	return NULL;
 }
 
+/*
+ * This is only for performance analysis of vmalloc and stress purpose.
+ * It is required by vmalloc test module, therefore do not use it other
+ * than that.
+ */
+#ifdef CONFIG_TEST_VMALLOC_MODULE
+EXPORT_SYMBOL(__vmalloc_node_range);
+#endif
+
 /**
  *	__vmalloc_node  -  allocate virtually contiguous memory
  *	@size:		allocation size
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [RFC v2 2/3] vmalloc: add test driver to analyse vmalloc allocator
  2018-12-31 13:26 [RFC v2 0/3] test driver to analyse vmalloc allocator Uladzislau Rezki (Sony)
  2018-12-31 13:26 ` [RFC v2 1/3] vmalloc: export __vmalloc_node_range for CONFIG_TEST_VMALLOC_MODULE Uladzislau Rezki (Sony)
@ 2018-12-31 13:26 ` Uladzislau Rezki (Sony)
  2018-12-31 13:26 ` [RFC v2 3/3] selftests/vm: add script helper for CONFIG_TEST_VMALLOC_MODULE Uladzislau Rezki (Sony)
  2 siblings, 0 replies; 8+ messages in thread
From: Uladzislau Rezki (Sony) @ 2018-12-31 13:26 UTC (permalink / raw)
  To: Michal Hocko, Kees Cook, Shuah Khan, Andrew Morton, linux-mm
  Cc: LKML, Matthew Wilcox, Oleksiy Avramchenko, Thomas Gleixner,
	Uladzislau Rezki (Sony)

This adds a new kernel module for analysis of vmalloc allocator. It is
only enabled as a module. There are two main reasons this module should
be used for: performance evaluation and stressing of vmalloc subsystem.

It consists of several test cases. As of now there are 8. The module
has five parameters we can specify to change its the behaviour.

1) run_test_mask - set of tests to be run

id: 1,   name: fix_size_alloc_test
id: 2,   name: full_fit_alloc_test
id: 4,   name: long_busy_list_alloc_test
id: 8,   name: random_size_alloc_test
id: 16,  name: fix_align_alloc_test
id: 32,  name: random_size_align_alloc_test
id: 64,  name: align_shift_alloc_test
id: 128, name: pcpu_alloc_test

By default all tests are in run test mask. If you want to select some
specific tests it is possible to pass the mask. For example for first,
second and fourth tests we go 11 value.

2) test_repeat_count - how many times each test should be repeated
By default it is one time per test. It is possible to pass any number.
As high the value is the test duration gets increased.

3) test_loop_count - internal test loop counter. By default it is set
to 1000000.

4) single_cpu_test - use one CPU to run the tests
By default this parameter is set to false. It means that all online
CPUs execute tests. By setting it to 1, the tests are executed by
first online CPU only.

5) sequential_test_order - run tests in sequential order
By default this parameter is set to false. It means that before running
tests the order is shuffled. It is possible to make it sequential, just
set it to 1.

Performance analysis:
In order to evaluate performance of vmalloc allocations, usually it
makes sense to use only one CPU that runs tests, use sequential order,
number of repeat tests can be different as well as set of test mask.

For example if we want to run all tests, to use one CPU and repeat each
test 3 times. Insert the module passing following parameters:

single_cpu_test=1 sequential_test_order=1 test_repeat_count=3

with following output:

<snip>
Summary: fix_size_alloc_test passed: 3 failed: 0 repeat: 3 loops: 1000000 avg: 901177 usec
Summary: full_fit_alloc_test passed: 3 failed: 0 repeat: 3 loops: 1000000 avg: 1039341 usec
Summary: long_busy_list_alloc_test passed: 3 failed: 0 repeat: 3 loops: 1000000 avg: 11775763 usec
Summary: random_size_alloc_test passed 3: failed: 0 repeat: 3 loops: 1000000 avg: 6081992 usec
Summary: fix_align_alloc_test passed: 3 failed: 0 repeat: 3, loops: 1000000 avg: 2003712 usec
Summary: random_size_align_alloc_test passed: 3 failed: 0 repeat: 3 loops: 1000000 avg: 2895689 usec
Summary: align_shift_alloc_test passed: 0 failed: 3 repeat: 3 loops: 1000000 avg: 573 usec
Summary: pcpu_alloc_test passed: 3 failed: 0 repeat: 3 loops: 1000000 avg: 95802 usec
All test took CPU0=192945605995 cycles
<snip>

The align_shift_alloc_test is expected to be failed.

Stressing:
In order to stress the vmalloc subsystem we run all available test cases
on all available CPUs simultaneously. In order to prevent constant behaviour
pattern, the test cases array is shuffled by default to randomize the order
of test execution.

For example if we want to run all tests(default), use all online CPUs(default)
with shuffled order(default) and to repeat each test 30 times. The command
would be like:

modprobe vmalloc_test test_repeat_count=30

Expected results are the system is alive, there are no any BUG_ONs or Kernel
Panics the tests are completed, no memory leaks.

Signed-off-by: Uladzislau Rezki (Sony) <urezki@gmail.com>
---
 lib/Kconfig.debug  |  12 ++
 lib/Makefile       |   1 +
 lib/test_vmalloc.c | 543 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 556 insertions(+)
 create mode 100644 lib/test_vmalloc.c

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 8838d1158d19..ca8a1a55d777 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1851,6 +1851,18 @@ config TEST_LKM
 
 	  If unsure, say N.
 
+config TEST_VMALLOC
+	tristate "Test module for stress/performance analysis of vmalloc allocator"
+	default n
+	depends on m
+	help
+	  This builds the "vmalloc_test" module that should be used for
+	  stress and performance analysis. So, any new change for vmalloc
+	  subsystem can be evaluated from performance and stability point
+	  of view.
+
+	  If unsure, say N.
+
 config TEST_USER_COPY
 	tristate "Test user/kernel boundary protections"
 	default n
diff --git a/lib/Makefile b/lib/Makefile
index 90dc5520b784..2caa6161b417 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -57,6 +57,7 @@ UBSAN_SANITIZE_test_ubsan.o := y
 obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
 obj-$(CONFIG_TEST_LIST_SORT) += test_list_sort.o
 obj-$(CONFIG_TEST_LKM) += test_module.o
+obj-$(CONFIG_TEST_VMALLOC) += test_vmalloc.o
 obj-$(CONFIG_TEST_OVERFLOW) += test_overflow.o
 obj-$(CONFIG_TEST_RHASHTABLE) += test_rhashtable.o
 obj-$(CONFIG_TEST_SORT) += test_sort.o
diff --git a/lib/test_vmalloc.c b/lib/test_vmalloc.c
new file mode 100644
index 000000000000..f852b404f436
--- /dev/null
+++ b/lib/test_vmalloc.c
@@ -0,0 +1,543 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Test module for stress and analyze performance of vmalloc allocator.
+ * (C) 2018 Uladzislau Rezki (Sony) <urezki@gmail.com>
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/random.h>
+#include <linux/kthread.h>
+#include <linux/moduleparam.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/rwsem.h>
+#include <linux/mm.h>
+
+#define __param(type, name, init, msg)		\
+	static type name = init;				\
+	module_param(name, type, 0444);			\
+	MODULE_PARM_DESC(name, msg)				\
+
+__param(bool, single_cpu_test, false,
+	"Use single first online CPU to run tests");
+
+__param(bool, sequential_test_order, false,
+	"Use sequential stress tests order");
+
+__param(int, test_repeat_count, 1,
+	"Set test repeat counter");
+
+__param(int, test_loop_count, 1000000,
+	"Set test loop counter");
+
+__param(int, run_test_mask, INT_MAX,
+	"Set tests specified in the mask.\n\n"
+		"\t\tid: 1,   name: fix_size_alloc_test\n"
+		"\t\tid: 2,   name: full_fit_alloc_test\n"
+		"\t\tid: 4,   name: long_busy_list_alloc_test\n"
+		"\t\tid: 8,   name: random_size_alloc_test\n"
+		"\t\tid: 16,  name: fix_align_alloc_test\n"
+		"\t\tid: 32,  name: random_size_align_alloc_test\n"
+		"\t\tid: 64,  name: align_shift_alloc_test\n"
+		"\t\tid: 128, name: pcpu_alloc_test\n"
+		/* Add a new test case description here. */
+);
+
+/*
+ * Depends on single_cpu_test parameter. If it is true, then
+ * use first online CPU to trigger a test on, otherwise go with
+ * all online CPUs.
+ */
+static cpumask_t cpus_run_test_mask = CPU_MASK_NONE;
+
+/*
+ * Read write semaphore for synchronization of setup
+ * phase that is done in main thread and workers.
+ */
+static DECLARE_RWSEM(prepare_for_test_rwsem);
+
+/*
+ * Completion tracking for worker threads.
+ */
+static DECLARE_COMPLETION(test_all_done_comp);
+static atomic_t test_n_undone = ATOMIC_INIT(0);
+
+static inline void
+test_report_one_done(void)
+{
+	if (atomic_dec_and_test(&test_n_undone))
+		complete(&test_all_done_comp);
+}
+
+static int random_size_align_alloc_test(void)
+{
+	unsigned long size, align, rnd;
+	void *ptr;
+	int i;
+
+	for (i = 0; i < test_loop_count; i++) {
+		get_random_bytes(&rnd, sizeof(rnd));
+
+		/*
+		 * Maximum 1024 pages, if PAGE_SIZE is 4096.
+		 */
+		align = 1 << (rnd % 23);
+
+		/*
+		 * Maximum 10 pages.
+		 */
+		size = ((rnd % 10) + 1) * PAGE_SIZE;
+
+		ptr = __vmalloc_node_range(size, align,
+		   VMALLOC_START, VMALLOC_END,
+		   GFP_KERNEL | __GFP_ZERO,
+		   PAGE_KERNEL,
+		   0, 0, __builtin_return_address(0));
+
+		if (!ptr)
+			return -1;
+
+		vfree(ptr);
+	}
+
+	return 0;
+}
+
+/*
+ * This test case is supposed to be failed.
+ */
+static int align_shift_alloc_test(void)
+{
+	unsigned long align;
+	void *ptr;
+	int i;
+
+	for (i = 0; i < BITS_PER_LONG; i++) {
+		align = ((unsigned long) 1) << i;
+
+		ptr = __vmalloc_node_range(PAGE_SIZE, align,
+			VMALLOC_START, VMALLOC_END,
+			GFP_KERNEL | __GFP_ZERO,
+			PAGE_KERNEL,
+			0, 0, __builtin_return_address(0));
+
+		if (!ptr)
+			return -1;
+
+		vfree(ptr);
+	}
+
+	return 0;
+}
+
+static int fix_align_alloc_test(void)
+{
+	void *ptr;
+	int i;
+
+	for (i = 0; i < test_loop_count; i++) {
+		ptr = __vmalloc_node_range(5 * PAGE_SIZE,
+			THREAD_ALIGN << 1,
+			VMALLOC_START, VMALLOC_END,
+			GFP_KERNEL | __GFP_ZERO,
+			PAGE_KERNEL,
+			0, 0, __builtin_return_address(0));
+
+		if (!ptr)
+			return -1;
+
+		vfree(ptr);
+	}
+
+	return 0;
+}
+
+static int random_size_alloc_test(void)
+{
+	unsigned int n;
+	void *p;
+	int i;
+
+	for (i = 0; i < test_loop_count; i++) {
+		get_random_bytes(&n, sizeof(i));
+		n = (n % 100) + 1;
+
+		p = vmalloc(n * PAGE_SIZE);
+
+		if (!p)
+			return -1;
+
+		*((__u8 *)p) = 1;
+		vfree(p);
+	}
+
+	return 0;
+}
+
+static int long_busy_list_alloc_test(void)
+{
+	void *ptr_1, *ptr_2;
+	void **ptr;
+	int rv = -1;
+	int i;
+
+	ptr = vmalloc(sizeof(void *) * 15000);
+	if (!ptr)
+		return rv;
+
+	for (i = 0; i < 15000; i++)
+		ptr[i] = vmalloc(1 * PAGE_SIZE);
+
+	for (i = 0; i < test_loop_count; i++) {
+		ptr_1 = vmalloc(100 * PAGE_SIZE);
+		if (!ptr_1)
+			goto leave;
+
+		ptr_2 = vmalloc(1 * PAGE_SIZE);
+		if (!ptr_2) {
+			vfree(ptr_1);
+			goto leave;
+		}
+
+		*((__u8 *)ptr_1) = 0;
+		*((__u8 *)ptr_2) = 1;
+
+		vfree(ptr_1);
+		vfree(ptr_2);
+	}
+
+	/*  Success */
+	rv = 0;
+
+leave:
+	for (i = 0; i < 15000; i++)
+		vfree(ptr[i]);
+
+	vfree(ptr);
+	return rv;
+}
+
+static int full_fit_alloc_test(void)
+{
+	void **ptr, **junk_ptr, *tmp;
+	int junk_length;
+	int rv = -1;
+	int i;
+
+	junk_length = fls(num_online_cpus());
+	junk_length *= (32 * 1024 * 1024 / PAGE_SIZE);
+
+	ptr = vmalloc(sizeof(void *) * junk_length);
+	if (!ptr)
+		return rv;
+
+	junk_ptr = vmalloc(sizeof(void *) * junk_length);
+	if (!junk_ptr) {
+		vfree(ptr);
+		return rv;
+	}
+
+	for (i = 0; i < junk_length; i++) {
+		ptr[i] = vmalloc(1 * PAGE_SIZE);
+		junk_ptr[i] = vmalloc(1 * PAGE_SIZE);
+	}
+
+	for (i = 0; i < junk_length; i++)
+		vfree(junk_ptr[i]);
+
+	for (i = 0; i < test_loop_count; i++) {
+		tmp = vmalloc(1 * PAGE_SIZE);
+
+		if (!tmp)
+			goto error;
+
+		*((__u8 *)tmp) = 1;
+		vfree(tmp);
+	}
+
+	/* Success */
+	rv = 0;
+
+error:
+	for (i = 0; i < junk_length; i++)
+		vfree(ptr[i]);
+
+	vfree(ptr);
+	vfree(junk_ptr);
+
+	return rv;
+}
+
+static int fix_size_alloc_test(void)
+{
+	void *ptr;
+	int i;
+
+	for (i = 0; i < test_loop_count; i++) {
+		ptr = vmalloc(3 * PAGE_SIZE);
+
+		if (!ptr)
+			return -1;
+
+		*((__u8 *)ptr) = 0;
+
+		vfree(ptr);
+	}
+
+	return 0;
+}
+
+static int
+pcpu_alloc_test(void)
+{
+	int rv = 0;
+#ifndef CONFIG_NEED_PER_CPU_KM
+	void __percpu **pcpu;
+	size_t size, align;
+	int i;
+
+	pcpu = vmalloc(sizeof(void __percpu *) * 35000);
+	if (!pcpu)
+		return -1;
+
+	for (i = 0; i < 35000; i++) {
+		unsigned int r;
+
+		get_random_bytes(&r, sizeof(i));
+		size = (r % (PAGE_SIZE / 4)) + 1;
+
+		/*
+		 * Maximum PAGE_SIZE
+		 */
+		get_random_bytes(&r, sizeof(i));
+		align = 1 << ((i % 11) + 1);
+
+		pcpu[i] = __alloc_percpu(size, align);
+		if (!pcpu[i])
+			rv = -1;
+	}
+
+	for (i = 0; i < 35000; i++)
+		free_percpu(pcpu[i]);
+
+	vfree(pcpu);
+#endif
+	return rv;
+}
+
+struct test_case_desc {
+	const char *test_name;
+	int (*test_func)(void);
+};
+
+static struct test_case_desc test_case_array[] = {
+	{ "fix_size_alloc_test", fix_size_alloc_test },
+	{ "full_fit_alloc_test", full_fit_alloc_test },
+	{ "long_busy_list_alloc_test", long_busy_list_alloc_test },
+	{ "random_size_alloc_test", random_size_alloc_test },
+	{ "fix_align_alloc_test", fix_align_alloc_test },
+	{ "random_size_align_alloc_test", random_size_align_alloc_test },
+	{ "align_shift_alloc_test", align_shift_alloc_test },
+	{ "pcpu_alloc_test", pcpu_alloc_test },
+	/* Add a new test case here. */
+};
+
+struct test_case_data {
+	int test_failed;
+	int test_passed;
+	s64 time;
+};
+
+/* Split it to get rid of: WARNING: line over 80 characters */
+static struct test_case_data
+	per_cpu_test_data[NR_CPUS][ARRAY_SIZE(test_case_array)];
+
+static struct test_driver {
+	struct task_struct *task;
+	unsigned long start;
+	unsigned long stop;
+	int cpu;
+} per_cpu_test_driver[NR_CPUS];
+
+static void shuffle_array(int *arr, int n)
+{
+	unsigned int rnd;
+	int i, j, x;
+
+	for (i = n - 1; i > 0; i--)  {
+		get_random_bytes(&rnd, sizeof(rnd));
+
+		/* Cut the range. */
+		j = rnd % i;
+
+		/* Swap indexes. */
+		x = arr[i];
+		arr[i] = arr[j];
+		arr[j] = x;
+	}
+}
+
+static int test_func(void *private)
+{
+	struct test_driver *t = private;
+	cpumask_t newmask = CPU_MASK_NONE;
+	int random_array[ARRAY_SIZE(test_case_array)];
+	int index, i, j, ret;
+	ktime_t kt;
+
+	cpumask_set_cpu(t->cpu, &newmask);
+	set_cpus_allowed_ptr(current, &newmask);
+
+	for (i = 0; i < ARRAY_SIZE(test_case_array); i++)
+		random_array[i] = i;
+
+	if (!sequential_test_order)
+		shuffle_array(random_array, ARRAY_SIZE(test_case_array));
+
+	/*
+	 * Block until initialization is done.
+	 */
+	down_read(&prepare_for_test_rwsem);
+
+	t->start = get_cycles();
+	for (i = 0; i < ARRAY_SIZE(test_case_array); i++) {
+		index = random_array[i];
+
+		/*
+		 * Skip tests if run_test_mask has been specified.
+		 */
+		if (!((run_test_mask & (1 << index)) >> index))
+			continue;
+
+		kt = ktime_get();
+		for (j = 0; j < test_repeat_count; j++) {
+			ret = test_case_array[index].test_func();
+			if (!ret)
+				per_cpu_test_data[t->cpu][index].test_passed++;
+			else
+				per_cpu_test_data[t->cpu][index].test_failed++;
+		}
+
+		/*
+		 * Take an average time that test took.
+		 */
+		per_cpu_test_data[t->cpu][index].time =
+			ktime_us_delta(ktime_get(), kt) / test_repeat_count;
+	}
+	t->stop = get_cycles();
+
+	up_read(&prepare_for_test_rwsem);
+	test_report_one_done();
+
+	/*
+	 * Wait for the kthread_stop() call.
+	 */
+	while (!kthread_should_stop())
+		msleep(10);
+
+	return 0;
+}
+
+static void
+init_test_configurtion(void)
+{
+	/*
+	 * Reset all data of all CPUs.
+	 */
+	memset(per_cpu_test_data, 0, sizeof(per_cpu_test_data));
+
+	if (single_cpu_test)
+		cpumask_set_cpu(cpumask_first(cpu_online_mask),
+			&cpus_run_test_mask);
+	else
+		cpumask_and(&cpus_run_test_mask, cpu_online_mask,
+			cpu_online_mask);
+
+	if (test_repeat_count <= 0)
+		test_repeat_count = 1;
+
+	if (test_loop_count <= 0)
+		test_loop_count = 1;
+}
+
+static void do_concurrent_test(void)
+{
+	int cpu;
+
+	/*
+	 * Set some basic configurations plus sanity check.
+	 */
+	init_test_configurtion();
+
+	/*
+	 * Put on hold all workers.
+	 */
+	down_write(&prepare_for_test_rwsem);
+
+	for_each_cpu(cpu, &cpus_run_test_mask) {
+		struct test_driver *t = &per_cpu_test_driver[cpu];
+
+		t->cpu = cpu;
+		t->task = kthread_run(test_func, t, "vmalloc_test/%d", cpu);
+
+		if (!IS_ERR(t->task))
+			/* Success. */
+			atomic_inc(&test_n_undone);
+		else
+			pr_err("Failed to start kthread for %d CPU\n", cpu);
+	}
+
+	/*
+	 * Now let the workers do their job.
+	 */
+	up_write(&prepare_for_test_rwsem);
+
+	/*
+	 * Sleep quiet until all workers are done.
+	 */
+	wait_for_completion(&test_all_done_comp);
+
+	for_each_cpu(cpu, &cpus_run_test_mask) {
+		struct test_driver *t = &per_cpu_test_driver[cpu];
+		int i;
+
+		if (!IS_ERR(t->task))
+			kthread_stop(t->task);
+
+		for (i = 0; i < ARRAY_SIZE(test_case_array); i++) {
+			if (!((run_test_mask & (1 << i)) >> i))
+				continue;
+
+			pr_info(
+				"Summary: %s passed: %d failed: %d repeat: %d loops: %d avg: %llu usec\n",
+				test_case_array[i].test_name,
+				per_cpu_test_data[cpu][i].test_passed,
+				per_cpu_test_data[cpu][i].test_failed,
+				test_repeat_count, test_loop_count,
+				per_cpu_test_data[cpu][i].time);
+		}
+
+		pr_info("All test took CPU%d=%lu cycles\n",
+			cpu, t->stop - t->start);
+	}
+}
+
+static int vmalloc_test_init(void)
+{
+	do_concurrent_test();
+	return -EAGAIN; /* Fail will directly unload the module */
+}
+
+static void vmalloc_test_exit(void)
+{
+}
+
+module_init(vmalloc_test_init)
+module_exit(vmalloc_test_exit)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Uladzislau Rezki");
+MODULE_DESCRIPTION("vmalloc test module");
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [RFC v2 3/3] selftests/vm: add script helper for CONFIG_TEST_VMALLOC_MODULE
  2018-12-31 13:26 [RFC v2 0/3] test driver to analyse vmalloc allocator Uladzislau Rezki (Sony)
  2018-12-31 13:26 ` [RFC v2 1/3] vmalloc: export __vmalloc_node_range for CONFIG_TEST_VMALLOC_MODULE Uladzislau Rezki (Sony)
  2018-12-31 13:26 ` [RFC v2 2/3] vmalloc: add test driver to analyse vmalloc allocator Uladzislau Rezki (Sony)
@ 2018-12-31 13:26 ` Uladzislau Rezki (Sony)
  2018-12-31 17:47   ` shuah
  2 siblings, 1 reply; 8+ messages in thread
From: Uladzislau Rezki (Sony) @ 2018-12-31 13:26 UTC (permalink / raw)
  To: Michal Hocko, Kees Cook, Shuah Khan, Andrew Morton, linux-mm
  Cc: LKML, Matthew Wilcox, Oleksiy Avramchenko, Thomas Gleixner,
	Uladzislau Rezki (Sony)

Add the test script for the kernel test driver to analyse vmalloc
allocator for benchmarking and stressing purposes. It is just a kernel
module loader. You can specify and pass different parameters in order
to investigate allocations behaviour. See "usage" output for more
details.

Also add basic vmalloc smoke test to the "run_vmtests" suite.

Signed-off-by: Uladzislau Rezki (Sony) <urezki@gmail.com>
---
 tools/testing/selftests/vm/run_vmtests     |  11 ++
 tools/testing/selftests/vm/test_vmalloc.sh | 173 +++++++++++++++++++++++++++++
 2 files changed, 184 insertions(+)
 create mode 100755 tools/testing/selftests/vm/test_vmalloc.sh

diff --git a/tools/testing/selftests/vm/run_vmtests b/tools/testing/selftests/vm/run_vmtests
index 88cbe5575f0c..56053ac2bf47 100755
--- a/tools/testing/selftests/vm/run_vmtests
+++ b/tools/testing/selftests/vm/run_vmtests
@@ -200,4 +200,15 @@ else
     echo "[PASS]"
 fi
 
+echo "------------------------------------"
+echo "running vmalloc stability smoke test"
+echo "------------------------------------"
+./test_vmalloc.sh smoke
+if [ $? -ne 0 ]; then
+	echo "[FAIL]"
+	exitcode=1
+else
+	echo "[PASS]"
+fi
+
 exit $exitcode
diff --git a/tools/testing/selftests/vm/test_vmalloc.sh b/tools/testing/selftests/vm/test_vmalloc.sh
new file mode 100755
index 000000000000..f4f0d3990f2c
--- /dev/null
+++ b/tools/testing/selftests/vm/test_vmalloc.sh
@@ -0,0 +1,173 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (C) 2018 Uladzislau Rezki (Sony) <urezki@gmail.com>
+#
+# This is a test script for the kernel test driver to analyse vmalloc
+# allocator. Therefore it is just a kernel module loader. You can specify
+# and pass different parameters in order to:
+#     a) analyse performance of vmalloc allocations;
+#     b) stressing and stability check of vmalloc subsystem.
+
+TEST_NAME="vmalloc"
+DRIVER="test_${TEST_NAME}"
+
+# 1 if fails
+exitcode=1
+
+#
+# Static templates for performance, stressing and smoke tests.
+# Also it is possible to pass any supported parameters manualy.
+#
+PERF_PARAM="single_cpu_test=1 sequential_test_order=1 test_repeat_count=3"
+SMOKE_PARAM="single_cpu_test=1 test_loop_count=10000 test_repeat_count=10"
+STRESS_PARAM="test_repeat_count=20"
+
+check_test_requirements()
+{
+	uid=$(id -u)
+	if [ $uid -ne 0 ]; then
+		echo "$0: Must be run as root"
+		exit $exitcode
+	fi
+
+	if ! which modprobe > /dev/null 2>&1; then
+		echo "$0: You need modprobe installed"
+		exit $exitcode
+	fi
+
+	if ! modinfo $DRIVER > /dev/null 2>&1; then
+		echo "$0: You must have the following enabled in your kernel:"
+		echo "CONFIG_TEST_VMALLOC=m"
+		exit $exitcode
+	fi
+}
+
+run_perfformance_check()
+{
+	echo "Run performance tests to evaluate how fast vmalloc allocation is."
+	echo "It runs all test cases on one single CPU with sequential order."
+
+	modprobe $DRIVER $PERF_PARAM > /dev/null 2>&1
+	echo "Done."
+	echo "Ccheck the kernel message buffer to see the summary."
+}
+
+run_stability_check()
+{
+	echo "Run stability tests. In order to stress vmalloc subsystem we run"
+	echo "all available test cases on all available CPUs simultaneously."
+	echo "It will take time, so be patient."
+
+	modprobe $DRIVER $STRESS_PARAM > /dev/null 2>&1
+	echo "Done."
+	echo "Check the kernel ring buffer to see the summary."
+}
+
+run_smoke_check()
+{
+	echo "Run smoke test. Note, this test provides basic coverage."
+	echo "Please check $0 output how it can be used"
+	echo "for deep performance analysis as well as stress testing."
+
+	modprobe $DRIVER $SMOKE_PARAM > /dev/null 2>&1
+	echo "Done."
+	echo "Check the kernel ring buffer to see the summary."
+}
+
+usage()
+{
+	echo -n "Usage: $0 [ performance ] | [ stress ] | | [ smoke ] | "
+	echo "manual parameters"
+	echo
+	echo "Valid tests and parameters:"
+	echo
+	modinfo $DRIVER
+	echo
+	echo "Example usage:"
+	echo
+	echo "# Shows help message"
+	echo "./${DRIVER}.sh"
+	echo
+	echo "# Runs 1 test(id_1), repeats it 5 times on all online CPUs"
+	echo "./${DRIVER}.sh run_test_mask=1 test_repeat_count=5"
+	echo
+	echo -n "# Runs 4 tests(id_1|id_2|id_4|id_16) on one CPU with "
+	echo "sequential order"
+	echo -n "./${DRIVER}.sh single_cpu_test=1 sequential_test_order=1 "
+	echo "run_test_mask=23"
+	echo
+	echo -n "# Runs all tests on all online CPUs, shuffled order, repeats "
+	echo "20 times"
+	echo "./${DRIVER}.sh test_repeat_count=20"
+	echo
+	echo "# Performance analysis"
+	echo "./${DRIVER}.sh performance"
+	echo
+	echo "# Stress testing"
+	echo "./${DRIVER}.sh stress"
+	echo
+	exit $exitcode
+}
+
+function validate_passed_args()
+{
+	VALID_ARGS=`modinfo $DRIVER | awk '/parm:/ {print $2}' | sed 's/:.*//'`
+
+	#
+	# Something has been passed, check it.
+	#
+	for passed_arg in $@; do
+		key=${passed_arg//=*/}
+		val="${passed_arg:$((${#key}+1))}"
+		valid=0
+
+		for valid_arg in $VALID_ARGS; do
+			if [[ $key = $valid_arg ]] && [[ $val -gt 0 ]]; then
+				valid=1
+				break
+			fi
+		done
+
+		if [[ $valid -ne 1 ]]; then
+			echo "Error: key or value is not correct: ${key} $val"
+			exit $exitcode
+		fi
+	done
+}
+
+function run_manual_check()
+{
+	#
+	# Validate passed parameters. If there is wrong one,
+	# the script exists and does not execute further.
+	#
+	validate_passed_args $@
+
+	echo "Run the test with following parameters: $@"
+	modprobe $DRIVER $@ > /dev/null 2>&1
+	echo "Done."
+	echo "Check the kernel ring buffer to see the summary."
+}
+
+function run_test()
+{
+	if [ $# -eq 0 ]; then
+		usage
+	else
+		if [[ "$1" = "performance" ]]; then
+			run_perfformance_check
+		elif [[ "$1" = "stress" ]]; then
+			run_stability_check
+		elif [[ "$1" = "smoke" ]]; then
+			run_smoke_check
+		else
+			run_manual_check $@
+		fi
+	fi
+}
+
+check_test_requirements
+run_test $@
+
+exit 0
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [RFC v2 3/3] selftests/vm: add script helper for CONFIG_TEST_VMALLOC_MODULE
  2018-12-31 13:26 ` [RFC v2 3/3] selftests/vm: add script helper for CONFIG_TEST_VMALLOC_MODULE Uladzislau Rezki (Sony)
@ 2018-12-31 17:47   ` shuah
  2019-01-01 17:12     ` Uladzislau Rezki
  0 siblings, 1 reply; 8+ messages in thread
From: shuah @ 2018-12-31 17:47 UTC (permalink / raw)
  To: Uladzislau Rezki (Sony),
	Michal Hocko, Kees Cook, Andrew Morton, linux-mm
  Cc: LKML, Matthew Wilcox, Oleksiy Avramchenko, Thomas Gleixner, shuah

On 12/31/18 6:26 AM, Uladzislau Rezki (Sony) wrote:
> Add the test script for the kernel test driver to analyse vmalloc
> allocator for benchmarking and stressing purposes. It is just a kernel
> module loader. You can specify and pass different parameters in order
> to investigate allocations behaviour. See "usage" output for more
> details.
> 
> Also add basic vmalloc smoke test to the "run_vmtests" suite.

Thanks for the test. A few comments below.

> 
> Signed-off-by: Uladzislau Rezki (Sony) <urezki@gmail.com>
> ---
>   tools/testing/selftests/vm/run_vmtests     |  11 ++
>   tools/testing/selftests/vm/test_vmalloc.sh | 173 +++++++++++++++++++++++++++++
>   2 files changed, 184 insertions(+)
>   create mode 100755 tools/testing/selftests/vm/test_vmalloc.sh
> 
> diff --git a/tools/testing/selftests/vm/run_vmtests b/tools/testing/selftests/vm/run_vmtests
> index 88cbe5575f0c..56053ac2bf47 100755
> --- a/tools/testing/selftests/vm/run_vmtests
> +++ b/tools/testing/selftests/vm/run_vmtests
> @@ -200,4 +200,15 @@ else
>       echo "[PASS]"
>   fi
>   
> +echo "------------------------------------"
> +echo "running vmalloc stability smoke test"
> +echo "------------------------------------"
> +./test_vmalloc.sh smoke
> +if [ $? -ne 0 ]; then
> +	echo "[FAIL]"
> +	exitcode=1

Please handle skil cases - exit code for skip is 4.

> +else
> +	echo "[PASS]"
> +fi
> +
>   exit $exitcode
> diff --git a/tools/testing/selftests/vm/test_vmalloc.sh b/tools/testing/selftests/vm/test_vmalloc.sh
> new file mode 100755
> index 000000000000..f4f0d3990f2c
> --- /dev/null
> +++ b/tools/testing/selftests/vm/test_vmalloc.sh
> @@ -0,0 +1,173 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +# Copyright (C) 2018 Uladzislau Rezki (Sony) <urezki@gmail.com>
> +#
> +# This is a test script for the kernel test driver to analyse vmalloc
> +# allocator. Therefore it is just a kernel module loader. You can specify
> +# and pass different parameters in order to:
> +#     a) analyse performance of vmalloc allocations;
> +#     b) stressing and stability check of vmalloc subsystem.
> +
> +TEST_NAME="vmalloc"
> +DRIVER="test_${TEST_NAME}"
> +
> +# 1 if fails
> +exitcode=1
> +
> +#
> +# Static templates for performance, stressing and smoke tests.
> +# Also it is possible to pass any supported parameters manualy.
> +#
> +PERF_PARAM="single_cpu_test=1 sequential_test_order=1 test_repeat_count=3"
> +SMOKE_PARAM="single_cpu_test=1 test_loop_count=10000 test_repeat_count=10"
> +STRESS_PARAM="test_repeat_count=20"
> +
> +check_test_requirements()
> +{
> +	uid=$(id -u)
> +	if [ $uid -ne 0 ]; then
> +		echo "$0: Must be run as root"
> +		exit $exitcode

This is a skip and not a fail.

> +	fi
> +
> +	if ! which modprobe > /dev/null 2>&1; then
> +		echo "$0: You need modprobe installed"
> +		exit $exitcode

This is a skip and not a fail.

> +	fi
> +
> +	if ! modinfo $DRIVER > /dev/null 2>&1; then
> +		echo "$0: You must have the following enabled in your kernel:"
> +		echo "CONFIG_TEST_VMALLOC=m"
> +		exit $exitcode

This is a skip and not a fail.

> +	fi
> +}
> +
> +run_perfformance_check()
> +{
> +	echo "Run performance tests to evaluate how fast vmalloc allocation is."
> +	echo "It runs all test cases on one single CPU with sequential order."
> +
> +	modprobe $DRIVER $PERF_PARAM > /dev/null 2>&1
> +	echo "Done."
> +	echo "Ccheck the kernel message buffer to see the summary."
> +}
> +
> +run_stability_check()
> +{
> +	echo "Run stability tests. In order to stress vmalloc subsystem we run"
> +	echo "all available test cases on all available CPUs simultaneously."
> +	echo "It will take time, so be patient."
> +
> +	modprobe $DRIVER $STRESS_PARAM > /dev/null 2>&1
> +	echo "Done."
> +	echo "Check the kernel ring buffer to see the summary."
> +}
> +
> +run_smoke_check()
> +{
> +	echo "Run smoke test. Note, this test provides basic coverage."
> +	echo "Please check $0 output how it can be used"
> +	echo "for deep performance analysis as well as stress testing."
> +
> +	modprobe $DRIVER $SMOKE_PARAM > /dev/null 2>&1
> +	echo "Done."
> +	echo "Check the kernel ring buffer to see the summary."
> +}
> +
> +usage()
> +{
> +	echo -n "Usage: $0 [ performance ] | [ stress ] | | [ smoke ] | "
> +	echo "manual parameters"
> +	echo
> +	echo "Valid tests and parameters:"
> +	echo
> +	modinfo $DRIVER
> +	echo
> +	echo "Example usage:"
> +	echo
> +	echo "# Shows help message"
> +	echo "./${DRIVER}.sh"
> +	echo
> +	echo "# Runs 1 test(id_1), repeats it 5 times on all online CPUs"
> +	echo "./${DRIVER}.sh run_test_mask=1 test_repeat_count=5"
> +	echo
> +	echo -n "# Runs 4 tests(id_1|id_2|id_4|id_16) on one CPU with "
> +	echo "sequential order"
> +	echo -n "./${DRIVER}.sh single_cpu_test=1 sequential_test_order=1 "
> +	echo "run_test_mask=23"
> +	echo
> +	echo -n "# Runs all tests on all online CPUs, shuffled order, repeats "
> +	echo "20 times"
> +	echo "./${DRIVER}.sh test_repeat_count=20"
> +	echo
> +	echo "# Performance analysis"
> +	echo "./${DRIVER}.sh performance"
> +	echo
> +	echo "# Stress testing"
> +	echo "./${DRIVER}.sh stress"
> +	echo
> +	exit $exitcode
> +}
> +
> +function validate_passed_args()
> +{
> +	VALID_ARGS=`modinfo $DRIVER | awk '/parm:/ {print $2}' | sed 's/:.*//'`
> +
> +	#
> +	# Something has been passed, check it.
> +	#
> +	for passed_arg in $@; do
> +		key=${passed_arg//=*/}
> +		val="${passed_arg:$((${#key}+1))}"
> +		valid=0
> +
> +		for valid_arg in $VALID_ARGS; do
> +			if [[ $key = $valid_arg ]] && [[ $val -gt 0 ]]; then
> +				valid=1
> +				break
> +			fi
> +		done
> +
> +		if [[ $valid -ne 1 ]]; then
> +			echo "Error: key or value is not correct: ${key} $val"
> +			exit $exitcode
> +		fi
> +	done
> +}
> +
> +function run_manual_check()
> +{
> +	#
> +	# Validate passed parameters. If there is wrong one,
> +	# the script exists and does not execute further.
> +	#
> +	validate_passed_args $@
> +
> +	echo "Run the test with following parameters: $@"
> +	modprobe $DRIVER $@ > /dev/null 2>&1
> +	echo "Done."
> +	echo "Check the kernel ring buffer to see the summary."
> +}
> +
> +function run_test()
> +{
> +	if [ $# -eq 0 ]; then
> +		usage
> +	else
> +		if [[ "$1" = "performance" ]]; then
> +			run_perfformance_check
> +		elif [[ "$1" = "stress" ]]; then
> +			run_stability_check
> +		elif [[ "$1" = "smoke" ]]; then
> +			run_smoke_check
> +		else
> +			run_manual_check $@
> +		fi
> +	fi
> +}
> +
> +check_test_requirements
> +run_test $@
> +
> +exit 0
> 

thanks,
-- Shuah

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC v2 1/3] vmalloc: export __vmalloc_node_range for CONFIG_TEST_VMALLOC_MODULE
  2018-12-31 13:26 ` [RFC v2 1/3] vmalloc: export __vmalloc_node_range for CONFIG_TEST_VMALLOC_MODULE Uladzislau Rezki (Sony)
@ 2018-12-31 18:50   ` Matthew Wilcox
  2019-01-01 16:55     ` Uladzislau Rezki
  0 siblings, 1 reply; 8+ messages in thread
From: Matthew Wilcox @ 2018-12-31 18:50 UTC (permalink / raw)
  To: Uladzislau Rezki (Sony)
  Cc: Michal Hocko, Kees Cook, Shuah Khan, Andrew Morton, linux-mm,
	LKML, Oleksiy Avramchenko, Thomas Gleixner

On Mon, Dec 31, 2018 at 02:26:38PM +0100, Uladzislau Rezki (Sony) wrote:
> +#ifdef CONFIG_TEST_VMALLOC_MODULE
> +EXPORT_SYMBOL(__vmalloc_node_range);
> +#endif

Definitely needs to be _GPL.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC v2 1/3] vmalloc: export __vmalloc_node_range for CONFIG_TEST_VMALLOC_MODULE
  2018-12-31 18:50   ` Matthew Wilcox
@ 2019-01-01 16:55     ` Uladzislau Rezki
  0 siblings, 0 replies; 8+ messages in thread
From: Uladzislau Rezki @ 2019-01-01 16:55 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Uladzislau Rezki (Sony),
	Michal Hocko, Kees Cook, Shuah Khan, Andrew Morton, linux-mm,
	LKML, Oleksiy Avramchenko, Thomas Gleixner

On Mon, Dec 31, 2018 at 10:50:22AM -0800, Matthew Wilcox wrote:
> On Mon, Dec 31, 2018 at 02:26:38PM +0100, Uladzislau Rezki (Sony) wrote:
> > +#ifdef CONFIG_TEST_VMALLOC_MODULE
> > +EXPORT_SYMBOL(__vmalloc_node_range);
> > +#endif
> 
> Definitely needs to be _GPL.
Will upload updated variant. 

Thanks for the comment!

--
Vlad Rezki

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC v2 3/3] selftests/vm: add script helper for CONFIG_TEST_VMALLOC_MODULE
  2018-12-31 17:47   ` shuah
@ 2019-01-01 17:12     ` Uladzislau Rezki
  0 siblings, 0 replies; 8+ messages in thread
From: Uladzislau Rezki @ 2019-01-01 17:12 UTC (permalink / raw)
  To: shuah
  Cc: Uladzislau Rezki (Sony),
	Michal Hocko, Kees Cook, Andrew Morton, linux-mm, LKML,
	Matthew Wilcox, Oleksiy Avramchenko, Thomas Gleixner

On Mon, Dec 31, 2018 at 10:47:55AM -0700, shuah wrote:
> On 12/31/18 6:26 AM, Uladzislau Rezki (Sony) wrote:
> > Add the test script for the kernel test driver to analyse vmalloc
> > allocator for benchmarking and stressing purposes. It is just a kernel
> > module loader. You can specify and pass different parameters in order
> > to investigate allocations behaviour. See "usage" output for more
> > details.
> > 
> > Also add basic vmalloc smoke test to the "run_vmtests" suite.
> 
> Thanks for the test. A few comments below.
> 
> > 
> > Signed-off-by: Uladzislau Rezki (Sony) <urezki@gmail.com>
> > ---
> >   tools/testing/selftests/vm/run_vmtests     |  11 ++
> >   tools/testing/selftests/vm/test_vmalloc.sh | 173 +++++++++++++++++++++++++++++
> >   2 files changed, 184 insertions(+)
> >   create mode 100755 tools/testing/selftests/vm/test_vmalloc.sh
> > 
> > diff --git a/tools/testing/selftests/vm/run_vmtests b/tools/testing/selftests/vm/run_vmtests
> > index 88cbe5575f0c..56053ac2bf47 100755
> > --- a/tools/testing/selftests/vm/run_vmtests
> > +++ b/tools/testing/selftests/vm/run_vmtests
> > @@ -200,4 +200,15 @@ else
> >       echo "[PASS]"
> >   fi
> > +echo "------------------------------------"
> > +echo "running vmalloc stability smoke test"
> > +echo "------------------------------------"
> > +./test_vmalloc.sh smoke
> > +if [ $? -ne 0 ]; then
> > +	echo "[FAIL]"
> > +	exitcode=1
> 
> Please handle skil cases - exit code for skip is 4.
> 
Will add skip case.


> > +else
> > +	echo "[PASS]"
> > +fi
> > +
> >   exit $exitcode
> > diff --git a/tools/testing/selftests/vm/test_vmalloc.sh b/tools/testing/selftests/vm/test_vmalloc.sh
> > new file mode 100755
> > index 000000000000..f4f0d3990f2c
> > --- /dev/null
> > +++ b/tools/testing/selftests/vm/test_vmalloc.sh
> > @@ -0,0 +1,173 @@
> > +#!/bin/bash
> > +# SPDX-License-Identifier: GPL-2.0
> > +#
> > +# Copyright (C) 2018 Uladzislau Rezki (Sony) <urezki@gmail.com>
> > +#
> > +# This is a test script for the kernel test driver to analyse vmalloc
> > +# allocator. Therefore it is just a kernel module loader. You can specify
> > +# and pass different parameters in order to:
> > +#     a) analyse performance of vmalloc allocations;
> > +#     b) stressing and stability check of vmalloc subsystem.
> > +
> > +TEST_NAME="vmalloc"
> > +DRIVER="test_${TEST_NAME}"
> > +
> > +# 1 if fails
> > +exitcode=1
> > +
> > +#
> > +# Static templates for performance, stressing and smoke tests.
> > +# Also it is possible to pass any supported parameters manualy.
> > +#
> > +PERF_PARAM="single_cpu_test=1 sequential_test_order=1 test_repeat_count=3"
> > +SMOKE_PARAM="single_cpu_test=1 test_loop_count=10000 test_repeat_count=10"
> > +STRESS_PARAM="test_repeat_count=20"
> > +
> > +check_test_requirements()
> > +{
> > +	uid=$(id -u)
> > +	if [ $uid -ne 0 ]; then
> > +		echo "$0: Must be run as root"
> > +		exit $exitcode
> 
> This is a skip and not a fail.
> 
Will update it. Agree it should not interrupt test sequence.

> > +	fi
> > +
> > +	if ! which modprobe > /dev/null 2>&1; then
> > +		echo "$0: You need modprobe installed"
> > +		exit $exitcode
> 
> This is a skip and not a fail.
> 
Will update it.

> > +	fi
> > +
> > +	if ! modinfo $DRIVER > /dev/null 2>&1; then
> > +		echo "$0: You must have the following enabled in your kernel:"
> > +		echo "CONFIG_TEST_VMALLOC=m"
> > +		exit $exitcode
> 
> This is a skip and not a fail.
> 
Will update it.

> > +	fi
> > +}
> > +
> > +run_perfformance_check()
> > +{
> > +	echo "Run performance tests to evaluate how fast vmalloc allocation is."
> > +	echo "It runs all test cases on one single CPU with sequential order."
> > +
> > +	modprobe $DRIVER $PERF_PARAM > /dev/null 2>&1
> > +	echo "Done."
> > +	echo "Ccheck the kernel message buffer to see the summary."
> > +}
> > +
> > +run_stability_check()
> > +{
> > +	echo "Run stability tests. In order to stress vmalloc subsystem we run"
> > +	echo "all available test cases on all available CPUs simultaneously."
> > +	echo "It will take time, so be patient."
> > +
> > +	modprobe $DRIVER $STRESS_PARAM > /dev/null 2>&1
> > +	echo "Done."
> > +	echo "Check the kernel ring buffer to see the summary."
> > +}
> > +
> > +run_smoke_check()
> > +{
> > +	echo "Run smoke test. Note, this test provides basic coverage."
> > +	echo "Please check $0 output how it can be used"
> > +	echo "for deep performance analysis as well as stress testing."
> > +
> > +	modprobe $DRIVER $SMOKE_PARAM > /dev/null 2>&1
> > +	echo "Done."
> > +	echo "Check the kernel ring buffer to see the summary."
> > +}
> > +
> > +usage()
> > +{
> > +	echo -n "Usage: $0 [ performance ] | [ stress ] | | [ smoke ] | "
> > +	echo "manual parameters"
> > +	echo
> > +	echo "Valid tests and parameters:"
> > +	echo
> > +	modinfo $DRIVER
> > +	echo
> > +	echo "Example usage:"
> > +	echo
> > +	echo "# Shows help message"
> > +	echo "./${DRIVER}.sh"
> > +	echo
> > +	echo "# Runs 1 test(id_1), repeats it 5 times on all online CPUs"
> > +	echo "./${DRIVER}.sh run_test_mask=1 test_repeat_count=5"
> > +	echo
> > +	echo -n "# Runs 4 tests(id_1|id_2|id_4|id_16) on one CPU with "
> > +	echo "sequential order"
> > +	echo -n "./${DRIVER}.sh single_cpu_test=1 sequential_test_order=1 "
> > +	echo "run_test_mask=23"
> > +	echo
> > +	echo -n "# Runs all tests on all online CPUs, shuffled order, repeats "
> > +	echo "20 times"
> > +	echo "./${DRIVER}.sh test_repeat_count=20"
> > +	echo
> > +	echo "# Performance analysis"
> > +	echo "./${DRIVER}.sh performance"
> > +	echo
> > +	echo "# Stress testing"
> > +	echo "./${DRIVER}.sh stress"
> > +	echo
> > +	exit $exitcode
> > +}
> > +
> > +function validate_passed_args()
> > +{
> > +	VALID_ARGS=`modinfo $DRIVER | awk '/parm:/ {print $2}' | sed 's/:.*//'`
> > +
> > +	#
> > +	# Something has been passed, check it.
> > +	#
> > +	for passed_arg in $@; do
> > +		key=${passed_arg//=*/}
> > +		val="${passed_arg:$((${#key}+1))}"
> > +		valid=0
> > +
> > +		for valid_arg in $VALID_ARGS; do
> > +			if [[ $key = $valid_arg ]] && [[ $val -gt 0 ]]; then
> > +				valid=1
> > +				break
> > +			fi
> > +		done
> > +
> > +		if [[ $valid -ne 1 ]]; then
> > +			echo "Error: key or value is not correct: ${key} $val"
> > +			exit $exitcode
> > +		fi
> > +	done
> > +}
> > +
> > +function run_manual_check()
> > +{
> > +	#
> > +	# Validate passed parameters. If there is wrong one,
> > +	# the script exists and does not execute further.
> > +	#
> > +	validate_passed_args $@
> > +
> > +	echo "Run the test with following parameters: $@"
> > +	modprobe $DRIVER $@ > /dev/null 2>&1
> > +	echo "Done."
> > +	echo "Check the kernel ring buffer to see the summary."
> > +}
> > +
> > +function run_test()
> > +{
> > +	if [ $# -eq 0 ]; then
> > +		usage
> > +	else
> > +		if [[ "$1" = "performance" ]]; then
> > +			run_perfformance_check
> > +		elif [[ "$1" = "stress" ]]; then
> > +			run_stability_check
> > +		elif [[ "$1" = "smoke" ]]; then
> > +			run_smoke_check
> > +		else
> > +			run_manual_check $@
> > +		fi
> > +	fi
> > +}
> > +
> > +check_test_requirements
> > +run_test $@
> > +
> > +exit 0
> > 
> 
> thanks,
> -- Shuah

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2019-01-01 17:13 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-31 13:26 [RFC v2 0/3] test driver to analyse vmalloc allocator Uladzislau Rezki (Sony)
2018-12-31 13:26 ` [RFC v2 1/3] vmalloc: export __vmalloc_node_range for CONFIG_TEST_VMALLOC_MODULE Uladzislau Rezki (Sony)
2018-12-31 18:50   ` Matthew Wilcox
2019-01-01 16:55     ` Uladzislau Rezki
2018-12-31 13:26 ` [RFC v2 2/3] vmalloc: add test driver to analyse vmalloc allocator Uladzislau Rezki (Sony)
2018-12-31 13:26 ` [RFC v2 3/3] selftests/vm: add script helper for CONFIG_TEST_VMALLOC_MODULE Uladzislau Rezki (Sony)
2018-12-31 17:47   ` shuah
2019-01-01 17:12     ` Uladzislau Rezki

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).