aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-07-15 00:57:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-15 00:57:25 -0400
commit867eacd7fb975273703766f52f485f08471a1ae9 (patch)
treebe3c024c940d34331d5329a61a8e2be64f21da17
parent077d2ba519b2e8bf1abd80cbade699b1de42cafe (diff)
parent6d7964a722afc8e4f880b947f174009063028c99 (diff)
Merge branch 'akpm' (patches from Andrew)
Merge even more updates from Andrew Morton: - a few leftovers - fault-injector rework - add a module loader test driver * emailed patches from Andrew Morton <akpm@linux-foundation.org>: kmod: throttle kmod thread limit kmod: add test driver to stress test the module loader MAINTAINERS: give kmod some maintainer love xtensa: use generic fb.h fault-inject: add /proc/<pid>/fail-nth fault-inject: simplify access check for fail-nth fault-inject: make fail-nth read/write interface symmetric fault-inject: parse as natural 1-based value for fail-nth write interface fault-inject: automatically detect the number base for fail-nth write interface kernel/watchdog.c: use better pr_fmt prefix MAINTAINERS: move the befs tree to kernel.org lib/atomic64_test.c: add a test that atomic64_inc_not_zero() returns an int mm: fix overflow check in expand_upwards()
-rw-r--r--Documentation/fault-injection/fault-injection.txt21
-rw-r--r--MAINTAINERS13
-rw-r--r--arch/xtensa/include/asm/Kbuild1
-rw-r--r--arch/xtensa/include/asm/fb.h12
-rw-r--r--fs/proc/base.c41
-rw-r--r--include/linux/sched.h2
-rw-r--r--kernel/kmod.c16
-rw-r--r--kernel/watchdog.c2
-rw-r--r--lib/Kconfig.debug27
-rw-r--r--lib/Makefile1
-rw-r--r--lib/atomic64_test.c7
-rw-r--r--lib/fault-inject.c7
-rw-r--r--lib/test_kmod.c1246
-rw-r--r--mm/mmap.c2
-rw-r--r--tools/testing/selftests/kmod/Makefile11
-rw-r--r--tools/testing/selftests/kmod/config7
-rw-r--r--tools/testing/selftests/kmod/kmod.sh615
17 files changed, 1969 insertions, 62 deletions
diff --git a/Documentation/fault-injection/fault-injection.txt b/Documentation/fault-injection/fault-injection.txt
index 192d8cbcc5f9..918972babcd8 100644
--- a/Documentation/fault-injection/fault-injection.txt
+++ b/Documentation/fault-injection/fault-injection.txt
@@ -136,12 +136,13 @@ use the boot option:
136 136
137o proc entries 137o proc entries
138 138
139- /proc/self/task/<current-tid>/fail-nth: 139- /proc/<pid>/fail-nth:
140- /proc/self/task/<tid>/fail-nth:
140 141
141 Write to this file of integer N makes N-th call in the current task fail 142 Write to this file of integer N makes N-th call in the task fail.
142 (N is 0-based). Read from this file returns a single char 'Y' or 'N' 143 Read from this file returns a integer value. A value of '0' indicates
143 that says if the fault setup with a previous write to this file was 144 that the fault setup with a previous write to this file was injected.
144 injected or not, and disables the fault if it wasn't yet injected. 145 A positive integer N indicates that the fault wasn't yet injected.
145 Note that this file enables all types of faults (slab, futex, etc). 146 Note that this file enables all types of faults (slab, futex, etc).
146 This setting takes precedence over all other generic debugfs settings 147 This setting takes precedence over all other generic debugfs settings
147 like probability, interval, times, etc. But per-capability settings 148 like probability, interval, times, etc. But per-capability settings
@@ -320,18 +321,19 @@ int main()
320 system("echo N > /sys/kernel/debug/failslab/ignore-gfp-wait"); 321 system("echo N > /sys/kernel/debug/failslab/ignore-gfp-wait");
321 sprintf(buf, "/proc/self/task/%ld/fail-nth", syscall(SYS_gettid)); 322 sprintf(buf, "/proc/self/task/%ld/fail-nth", syscall(SYS_gettid));
322 fail_nth = open(buf, O_RDWR); 323 fail_nth = open(buf, O_RDWR);
323 for (i = 0;; i++) { 324 for (i = 1;; i++) {
324 sprintf(buf, "%d", i); 325 sprintf(buf, "%d", i);
325 write(fail_nth, buf, strlen(buf)); 326 write(fail_nth, buf, strlen(buf));
326 res = socketpair(AF_LOCAL, SOCK_STREAM, 0, fds); 327 res = socketpair(AF_LOCAL, SOCK_STREAM, 0, fds);
327 err = errno; 328 err = errno;
328 read(fail_nth, buf, 1); 329 pread(fail_nth, buf, sizeof(buf), 0);
329 if (res == 0) { 330 if (res == 0) {
330 close(fds[0]); 331 close(fds[0]);
331 close(fds[1]); 332 close(fds[1]);
332 } 333 }
333 printf("%d-th fault %c: res=%d/%d\n", i, buf[0], res, err); 334 printf("%d-th fault %c: res=%d/%d\n", i, atoi(buf) ? 'N' : 'Y',
334 if (buf[0] != 'Y') 335 res, err);
336 if (atoi(buf))
335 break; 337 break;
336 } 338 }
337 return 0; 339 return 0;
@@ -339,7 +341,6 @@ int main()
339 341
340An example output: 342An example output:
341 343
3420-th fault Y: res=-1/23
3431-th fault Y: res=-1/23 3441-th fault Y: res=-1/23
3442-th fault Y: res=-1/23 3452-th fault Y: res=-1/23
3453-th fault Y: res=-1/12 3463-th fault Y: res=-1/12
diff --git a/MAINTAINERS b/MAINTAINERS
index 4bae99c37635..428e042dcd21 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2516,10 +2516,10 @@ S: Supported
2516F: drivers/media/platform/sti/delta 2516F: drivers/media/platform/sti/delta
2517 2517
2518BEFS FILE SYSTEM 2518BEFS FILE SYSTEM
2519M: Luis de Bethencourt <luisbg@osg.samsung.com> 2519M: Luis de Bethencourt <luisbg@kernel.org>
2520M: Salah Triki <salah.triki@gmail.com> 2520M: Salah Triki <salah.triki@gmail.com>
2521S: Maintained 2521S: Maintained
2522T: git git://github.com/luisbg/linux-befs.git 2522T: git git://git.kernel.org/pub/scm/linux/kernel/git/luisbg/linux-befs.git
2523F: Documentation/filesystems/befs.txt 2523F: Documentation/filesystems/befs.txt
2524F: fs/befs/ 2524F: fs/befs/
2525 2525
@@ -7554,6 +7554,15 @@ F: include/linux/kmemleak.h
7554F: mm/kmemleak.c 7554F: mm/kmemleak.c
7555F: mm/kmemleak-test.c 7555F: mm/kmemleak-test.c
7556 7556
7557KMOD MODULE USERMODE HELPER
7558M: "Luis R. Rodriguez" <mcgrof@kernel.org>
7559L: linux-kernel@vger.kernel.org
7560S: Maintained
7561F: kernel/kmod.c
7562F: include/linux/kmod.h
7563F: lib/test_kmod.c
7564F: tools/testing/selftests/kmod/
7565
7557KPROBES 7566KPROBES
7558M: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com> 7567M: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com>
7559M: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> 7568M: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index c04efde775a5..2d716ebc5a5e 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -5,6 +5,7 @@ generic-y += dma-contiguous.h
5generic-y += emergency-restart.h 5generic-y += emergency-restart.h
6generic-y += exec.h 6generic-y += exec.h
7generic-y += extable.h 7generic-y += extable.h
8generic-y += fb.h
8generic-y += hardirq.h 9generic-y += hardirq.h
9generic-y += irq_regs.h 10generic-y += irq_regs.h
10generic-y += irq_work.h 11generic-y += irq_work.h
diff --git a/arch/xtensa/include/asm/fb.h b/arch/xtensa/include/asm/fb.h
deleted file mode 100644
index c7df38030992..000000000000
--- a/arch/xtensa/include/asm/fb.h
+++ /dev/null
@@ -1,12 +0,0 @@
1#ifndef _ASM_FB_H_
2#define _ASM_FB_H_
3#include <linux/fb.h>
4
5#define fb_pgprotect(...) do {} while (0)
6
7static inline int fb_is_primary_device(struct fb_info *info)
8{
9 return 0;
10}
11
12#endif /* _ASM_FB_H_ */
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 88b773f318cd..719c2e943ea1 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1360,20 +1360,19 @@ static ssize_t proc_fail_nth_write(struct file *file, const char __user *buf,
1360 size_t count, loff_t *ppos) 1360 size_t count, loff_t *ppos)
1361{ 1361{
1362 struct task_struct *task; 1362 struct task_struct *task;
1363 int err, n; 1363 int err;
1364 unsigned int n;
1365
1366 err = kstrtouint_from_user(buf, count, 0, &n);
1367 if (err)
1368 return err;
1364 1369
1365 task = get_proc_task(file_inode(file)); 1370 task = get_proc_task(file_inode(file));
1366 if (!task) 1371 if (!task)
1367 return -ESRCH; 1372 return -ESRCH;
1373 WRITE_ONCE(task->fail_nth, n);
1368 put_task_struct(task); 1374 put_task_struct(task);
1369 if (task != current) 1375
1370 return -EPERM;
1371 err = kstrtoint_from_user(buf, count, 10, &n);
1372 if (err)
1373 return err;
1374 if (n < 0 || n == INT_MAX)
1375 return -EINVAL;
1376 current->fail_nth = n + 1;
1377 return count; 1376 return count;
1378} 1377}
1379 1378
@@ -1381,21 +1380,18 @@ static ssize_t proc_fail_nth_read(struct file *file, char __user *buf,
1381 size_t count, loff_t *ppos) 1380 size_t count, loff_t *ppos)
1382{ 1381{
1383 struct task_struct *task; 1382 struct task_struct *task;
1384 int err; 1383 char numbuf[PROC_NUMBUF];
1384 ssize_t len;
1385 1385
1386 task = get_proc_task(file_inode(file)); 1386 task = get_proc_task(file_inode(file));
1387 if (!task) 1387 if (!task)
1388 return -ESRCH; 1388 return -ESRCH;
1389 len = snprintf(numbuf, sizeof(numbuf), "%u\n",
1390 READ_ONCE(task->fail_nth));
1391 len = simple_read_from_buffer(buf, count, ppos, numbuf, len);
1389 put_task_struct(task); 1392 put_task_struct(task);
1390 if (task != current) 1393
1391 return -EPERM; 1394 return len;
1392 if (count < 1)
1393 return -EINVAL;
1394 err = put_user((char)(current->fail_nth ? 'N' : 'Y'), buf);
1395 if (err)
1396 return err;
1397 current->fail_nth = 0;
1398 return 1;
1399} 1395}
1400 1396
1401static const struct file_operations proc_fail_nth_operations = { 1397static const struct file_operations proc_fail_nth_operations = {
@@ -2966,6 +2962,7 @@ static const struct pid_entry tgid_base_stuff[] = {
2966#endif 2962#endif
2967#ifdef CONFIG_FAULT_INJECTION 2963#ifdef CONFIG_FAULT_INJECTION
2968 REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), 2964 REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
2965 REG("fail-nth", 0644, proc_fail_nth_operations),
2969#endif 2966#endif
2970#ifdef CONFIG_ELF_CORE 2967#ifdef CONFIG_ELF_CORE
2971 REG("coredump_filter", S_IRUGO|S_IWUSR, proc_coredump_filter_operations), 2968 REG("coredump_filter", S_IRUGO|S_IWUSR, proc_coredump_filter_operations),
@@ -3358,11 +3355,7 @@ static const struct pid_entry tid_base_stuff[] = {
3358#endif 3355#endif
3359#ifdef CONFIG_FAULT_INJECTION 3356#ifdef CONFIG_FAULT_INJECTION
3360 REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), 3357 REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
3361 /* 3358 REG("fail-nth", 0644, proc_fail_nth_operations),
3362 * Operations on the file check that the task is current,
3363 * so we create it with 0666 to support testing under unprivileged user.
3364 */
3365 REG("fail-nth", 0666, proc_fail_nth_operations),
3366#endif 3359#endif
3367#ifdef CONFIG_TASK_IO_ACCOUNTING 3360#ifdef CONFIG_TASK_IO_ACCOUNTING
3368 ONE("io", S_IRUSR, proc_tid_io_accounting), 3361 ONE("io", S_IRUSR, proc_tid_io_accounting),
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 3822d749fc9e..2ba9ec93423f 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -974,7 +974,7 @@ struct task_struct {
974 974
975#ifdef CONFIG_FAULT_INJECTION 975#ifdef CONFIG_FAULT_INJECTION
976 int make_it_fail; 976 int make_it_fail;
977 int fail_nth; 977 unsigned int fail_nth;
978#endif 978#endif
979 /* 979 /*
980 * When (nr_dirtied >= nr_dirtied_pause), it's time to call 980 * When (nr_dirtied >= nr_dirtied_pause), it's time to call
diff --git a/kernel/kmod.c b/kernel/kmod.c
index ff68198fe83b..6d016c5d97c8 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -68,6 +68,7 @@ static DECLARE_RWSEM(umhelper_sem);
68 */ 68 */
69#define MAX_KMOD_CONCURRENT 50 69#define MAX_KMOD_CONCURRENT 50
70static atomic_t kmod_concurrent_max = ATOMIC_INIT(MAX_KMOD_CONCURRENT); 70static atomic_t kmod_concurrent_max = ATOMIC_INIT(MAX_KMOD_CONCURRENT);
71static DECLARE_WAIT_QUEUE_HEAD(kmod_wq);
71 72
72/* 73/*
73 modprobe_path is set via /proc/sys. 74 modprobe_path is set via /proc/sys.
@@ -140,7 +141,6 @@ int __request_module(bool wait, const char *fmt, ...)
140 va_list args; 141 va_list args;
141 char module_name[MODULE_NAME_LEN]; 142 char module_name[MODULE_NAME_LEN];
142 int ret; 143 int ret;
143 static int kmod_loop_msg;
144 144
145 /* 145 /*
146 * We don't allow synchronous module loading from async. Module 146 * We don't allow synchronous module loading from async. Module
@@ -164,14 +164,11 @@ int __request_module(bool wait, const char *fmt, ...)
164 return ret; 164 return ret;
165 165
166 if (atomic_dec_if_positive(&kmod_concurrent_max) < 0) { 166 if (atomic_dec_if_positive(&kmod_concurrent_max) < 0) {
167 /* We may be blaming an innocent here, but unlikely */ 167 pr_warn_ratelimited("request_module: kmod_concurrent_max (%u) close to 0 (max_modprobes: %u), for module %s, throttling...",
168 if (kmod_loop_msg < 5) { 168 atomic_read(&kmod_concurrent_max),
169 printk(KERN_ERR 169 MAX_KMOD_CONCURRENT, module_name);
170 "request_module: runaway loop modprobe %s\n", 170 wait_event_interruptible(kmod_wq,
171 module_name); 171 atomic_dec_if_positive(&kmod_concurrent_max) >= 0);
172 kmod_loop_msg++;
173 }
174 return -ENOMEM;
175 } 172 }
176 173
177 trace_module_request(module_name, wait, _RET_IP_); 174 trace_module_request(module_name, wait, _RET_IP_);
@@ -179,6 +176,7 @@ int __request_module(bool wait, const char *fmt, ...)
179 ret = call_modprobe(module_name, wait ? UMH_WAIT_PROC : UMH_WAIT_EXEC); 176 ret = call_modprobe(module_name, wait ? UMH_WAIT_PROC : UMH_WAIT_EXEC);
180 177
181 atomic_inc(&kmod_concurrent_max); 178 atomic_inc(&kmod_concurrent_max);
179 wake_up(&kmod_wq);
182 180
183 return ret; 181 return ret;
184} 182}
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index cabe3e9fb620..06d3389bca0d 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -9,7 +9,7 @@
9 * to those contributors as well. 9 * to those contributors as well.
10 */ 10 */
11 11
12#define pr_fmt(fmt) "NMI watchdog: " fmt 12#define pr_fmt(fmt) "watchdog: " fmt
13 13
14#include <linux/mm.h> 14#include <linux/mm.h>
15#include <linux/cpu.h> 15#include <linux/cpu.h>
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index b0d01c6d4e03..789c6e9e5e01 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1847,6 +1847,33 @@ config BUG_ON_DATA_CORRUPTION
1847 1847
1848 If unsure, say N. 1848 If unsure, say N.
1849 1849
1850config TEST_KMOD
1851 tristate "kmod stress tester"
1852 default n
1853 depends on m
1854 depends on BLOCK && (64BIT || LBDAF) # for XFS, BTRFS
1855 depends on NETDEVICES && NET_CORE && INET # for TUN
1856 select TEST_LKM
1857 select XFS_FS
1858 select TUN
1859 select BTRFS_FS
1860 help
1861 Test the kernel's module loading mechanism: kmod. kmod implements
1862 support to load modules using the Linux kernel's usermode helper.
1863 This test provides a series of tests against kmod.
1864
1865 Although technically you can either build test_kmod as a module or
1866 into the kernel we disallow building it into the kernel since
1867 it stress tests request_module() and this will very likely cause
1868 some issues by taking over precious threads available from other
1869 module load requests, ultimately this could be fatal.
1870
1871 To run tests run:
1872
1873 tools/testing/selftests/kmod/kmod.sh --help
1874
1875 If unsure, say N.
1876
1850source "samples/Kconfig" 1877source "samples/Kconfig"
1851 1878
1852source "lib/Kconfig.kgdb" 1879source "lib/Kconfig.kgdb"
diff --git a/lib/Makefile b/lib/Makefile
index 85e91e51a9fe..40c18372b301 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_TEST_PRINTF) += test_printf.o
61obj-$(CONFIG_TEST_BITMAP) += test_bitmap.o 61obj-$(CONFIG_TEST_BITMAP) += test_bitmap.o
62obj-$(CONFIG_TEST_UUID) += test_uuid.o 62obj-$(CONFIG_TEST_UUID) += test_uuid.o
63obj-$(CONFIG_TEST_PARMAN) += test_parman.o 63obj-$(CONFIG_TEST_PARMAN) += test_parman.o
64obj-$(CONFIG_TEST_KMOD) += test_kmod.o
64 65
65ifeq ($(CONFIG_DEBUG_KOBJECT),y) 66ifeq ($(CONFIG_DEBUG_KOBJECT),y)
66CFLAGS_kobject.o += -DDEBUG 67CFLAGS_kobject.o += -DDEBUG
diff --git a/lib/atomic64_test.c b/lib/atomic64_test.c
index fd70c0e0e673..62ab629f51ca 100644
--- a/lib/atomic64_test.c
+++ b/lib/atomic64_test.c
@@ -153,8 +153,10 @@ static __init void test_atomic64(void)
153 long long v0 = 0xaaa31337c001d00dLL; 153 long long v0 = 0xaaa31337c001d00dLL;
154 long long v1 = 0xdeadbeefdeafcafeLL; 154 long long v1 = 0xdeadbeefdeafcafeLL;
155 long long v2 = 0xfaceabadf00df001LL; 155 long long v2 = 0xfaceabadf00df001LL;
156 long long v3 = 0x8000000000000000LL;
156 long long onestwos = 0x1111111122222222LL; 157 long long onestwos = 0x1111111122222222LL;
157 long long one = 1LL; 158 long long one = 1LL;
159 int r_int;
158 160
159 atomic64_t v = ATOMIC64_INIT(v0); 161 atomic64_t v = ATOMIC64_INIT(v0);
160 long long r = v0; 162 long long r = v0;
@@ -240,6 +242,11 @@ static __init void test_atomic64(void)
240 BUG_ON(!atomic64_inc_not_zero(&v)); 242 BUG_ON(!atomic64_inc_not_zero(&v));
241 r += one; 243 r += one;
242 BUG_ON(v.counter != r); 244 BUG_ON(v.counter != r);
245
246 /* Confirm the return value fits in an int, even if the value doesn't */
247 INIT(v3);
248 r_int = atomic64_inc_not_zero(&v);
249 BUG_ON(!r_int);
243} 250}
244 251
245static __init int test_atomics_init(void) 252static __init int test_atomics_init(void)
diff --git a/lib/fault-inject.c b/lib/fault-inject.c
index 09ac73c177fd..7d315fdb9f13 100644
--- a/lib/fault-inject.c
+++ b/lib/fault-inject.c
@@ -107,9 +107,12 @@ static inline bool fail_stacktrace(struct fault_attr *attr)
107 107
108bool should_fail(struct fault_attr *attr, ssize_t size) 108bool should_fail(struct fault_attr *attr, ssize_t size)
109{ 109{
110 if (in_task() && current->fail_nth) { 110 if (in_task()) {
111 if (--current->fail_nth == 0) 111 unsigned int fail_nth = READ_ONCE(current->fail_nth);
112
113 if (fail_nth && !WRITE_ONCE(current->fail_nth, fail_nth - 1))
112 goto fail; 114 goto fail;
115
113 return false; 116 return false;
114 } 117 }
115 118
diff --git a/lib/test_kmod.c b/lib/test_kmod.c
new file mode 100644
index 000000000000..6c1d678bcf8b
--- /dev/null
+++ b/lib/test_kmod.c
@@ -0,0 +1,1246 @@
1/*
2 * kmod stress test driver
3 *
4 * Copyright (C) 2017 Luis R. Rodriguez <mcgrof@kernel.org>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or at your option any
9 * later version; or, when distributed separately from the Linux kernel or
10 * when incorporated into other software packages, subject to the following
11 * license:
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of copyleft-next (version 0.3.1 or later) as published
15 * at http://copyleft-next.org/.
16 */
17#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18
19/*
20 * This driver provides an interface to trigger and test the kernel's
21 * module loader through a series of configurations and a few triggers.
22 * To test this driver use the following script as root:
23 *
24 * tools/testing/selftests/kmod/kmod.sh --help
25 */
26
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/kmod.h>
30#include <linux/printk.h>
31#include <linux/kthread.h>
32#include <linux/sched.h>
33#include <linux/fs.h>
34#include <linux/miscdevice.h>
35#include <linux/vmalloc.h>
36#include <linux/slab.h>
37#include <linux/device.h>
38
39#define TEST_START_NUM_THREADS 50
40#define TEST_START_DRIVER "test_module"
41#define TEST_START_TEST_FS "xfs"
42#define TEST_START_TEST_CASE TEST_KMOD_DRIVER
43
44
45static bool force_init_test = false;
46module_param(force_init_test, bool_enable_only, 0644);
47MODULE_PARM_DESC(force_init_test,
48 "Force kicking a test immediately after driver loads");
49
50/*
51 * For device allocation / registration
52 */
53static DEFINE_MUTEX(reg_dev_mutex);
54static LIST_HEAD(reg_test_devs);
55
56/*
57 * num_test_devs actually represents the *next* ID of the next
58 * device we will allow to create.
59 */
60static int num_test_devs;
61
62/**
63 * enum kmod_test_case - linker table test case
64 *
65 * If you add a test case, please be sure to review if you need to se
66 * @need_mod_put for your tests case.
67 *
68 * @TEST_KMOD_DRIVER: stress tests request_module()
69 * @TEST_KMOD_FS_TYPE: stress tests get_fs_type()
70 */
71enum kmod_test_case {
72 __TEST_KMOD_INVALID = 0,
73
74 TEST_KMOD_DRIVER,
75 TEST_KMOD_FS_TYPE,
76
77 __TEST_KMOD_MAX,
78};
79
80struct test_config {
81 char *test_driver;
82 char *test_fs;
83 unsigned int num_threads;
84 enum kmod_test_case test_case;
85 int test_result;
86};
87
88struct kmod_test_device;
89
90/**
91 * kmod_test_device_info - thread info
92 *
93 * @ret_sync: return value if request_module() is used, sync request for
94 * @TEST_KMOD_DRIVER
95 * @fs_sync: return value of get_fs_type() for @TEST_KMOD_FS_TYPE
96 * @thread_idx: thread ID
97 * @test_dev: test device test is being performed under
98 * @need_mod_put: Some tests (get_fs_type() is one) requires putting the module
99 * (module_put(fs_sync->owner)) when done, otherwise you will not be able
100 * to unload the respective modules and re-test. We use this to keep
101 * accounting of when we need this and to help out in case we need to
102 * error out and deal with module_put() on error.
103 */
104struct kmod_test_device_info {
105 int ret_sync;
106 struct file_system_type *fs_sync;
107 struct task_struct *task_sync;
108 unsigned int thread_idx;
109 struct kmod_test_device *test_dev;
110 bool need_mod_put;
111};
112
113/**
114 * kmod_test_device - test device to help test kmod
115 *
116 * @dev_idx: unique ID for test device
117 * @config: configuration for the test
118 * @misc_dev: we use a misc device under the hood
119 * @dev: pointer to misc_dev's own struct device
120 * @config_mutex: protects configuration of test
121 * @trigger_mutex: the test trigger can only be fired once at a time
122 * @thread_lock: protects @done count, and the @info per each thread
123 * @done: number of threads which have completed or failed
124 * @test_is_oom: when we run out of memory, use this to halt moving forward
125 * @kthreads_done: completion used to signal when all work is done
126 * @list: needed to be part of the reg_test_devs
127 * @info: array of info for each thread
128 */
129struct kmod_test_device {
130 int dev_idx;
131 struct test_config config;
132 struct miscdevice misc_dev;
133 struct device *dev;
134 struct mutex config_mutex;
135 struct mutex trigger_mutex;
136 struct mutex thread_mutex;
137
138 unsigned int done;
139
140 bool test_is_oom;
141 struct completion kthreads_done;
142 struct list_head list;
143
144 struct kmod_test_device_info *info;
145};
146
147static const char *test_case_str(enum kmod_test_case test_case)
148{
149 switch (test_case) {
150 case TEST_KMOD_DRIVER:
151 return "TEST_KMOD_DRIVER";
152 case TEST_KMOD_FS_TYPE:
153 return "TEST_KMOD_FS_TYPE";
154 default:
155 return "invalid";
156 }
157}
158
159static struct miscdevice *dev_to_misc_dev(struct device *dev)
160{
161 return dev_get_drvdata(dev);
162}
163
164static struct kmod_test_device *misc_dev_to_test_dev(struct miscdevice *misc_dev)
165{
166 return container_of(misc_dev, struct kmod_test_device, misc_dev);
167}
168
169static struct kmod_test_device *dev_to_test_dev(struct device *dev)
170{
171 struct miscdevice *misc_dev;
172
173 misc_dev = dev_to_misc_dev(dev);
174
175 return misc_dev_to_test_dev(misc_dev);
176}
177
178/* Must run with thread_mutex held */
179static void kmod_test_done_check(struct kmod_test_device *test_dev,
180 unsigned int idx)
181{
182 struct test_config *config = &test_dev->config;
183
184 test_dev->done++;
185 dev_dbg(test_dev->dev, "Done thread count: %u\n", test_dev->done);
186
187 if (test_dev->done == config->num_threads) {
188 dev_info(test_dev->dev, "Done: %u threads have all run now\n",
189 test_dev->done);
190 dev_info(test_dev->dev, "Last thread to run: %u\n", idx);
191 complete(&test_dev->kthreads_done);
192 }
193}
194
195static void test_kmod_put_module(struct kmod_test_device_info *info)
196{
197 struct kmod_test_device *test_dev = info->test_dev;
198 struct test_config *config = &test_dev->config;
199
200 if (!info->need_mod_put)
201 return;
202
203 switch (config->test_case) {
204 case TEST_KMOD_DRIVER:
205 break;
206 case TEST_KMOD_FS_TYPE:
207 if (info && info->fs_sync && info->fs_sync->owner)
208 module_put(info->fs_sync->owner);
209 break;
210 default:
211 BUG();
212 }
213
214 info->need_mod_put = true;
215}
216
217static int run_request(void *data)
218{
219 struct kmod_test_device_info *info = data;
220 struct kmod_test_device *test_dev = info->test_dev;
221 struct test_config *config = &test_dev->config;
222
223 switch (config->test_case) {
224 case TEST_KMOD_DRIVER:
225 info->ret_sync = request_module("%s", config->test_driver);
226 break;
227 case TEST_KMOD_FS_TYPE:
228 info->fs_sync = get_fs_type(config->test_fs);
229 info->need_mod_put = true;
230 break;
231 default:
232 /* __trigger_config_run() already checked for test sanity */
233 BUG();
234 return -EINVAL;
235 }
236
237 dev_dbg(test_dev->dev, "Ran thread %u\n", info->thread_idx);
238
239 test_kmod_put_module(info);
240
241 mutex_lock(&test_dev->thread_mutex);
242 info->task_sync = NULL;
243 kmod_test_done_check(test_dev, info->thread_idx);
244 mutex_unlock(&test_dev->thread_mutex);
245
246 return 0;
247}
248
249static int tally_work_test(struct kmod_test_device_info *info)
250{
251 struct kmod_test_device *test_dev = info->test_dev;
252 struct test_config *config = &test_dev->config;
253 int err_ret = 0;
254
255 switch (config->test_case) {
256 case TEST_KMOD_DRIVER:
257 /*
258 * Only capture errors, if one is found that's
259 * enough, for now.
260 */
261 if (info->ret_sync != 0)
262 err_ret = info->ret_sync;
263 dev_info(test_dev->dev,
264 "Sync thread %d return status: %d\n",
265 info->thread_idx, info->ret_sync);
266 break;
267 case TEST_KMOD_FS_TYPE:
268 /* For now we make this simple */
269 if (!info->fs_sync)
270 err_ret = -EINVAL;
271 dev_info(test_dev->dev, "Sync thread %u fs: %s\n",
272 info->thread_idx, info->fs_sync ? config->test_fs :
273 "NULL");
274 break;
275 default:
276 BUG();
277 }
278
279 return err_ret;
280}
281
282/*
283 * XXX: add result option to display if all errors did not match.
284 * For now we just keep any error code if one was found.
285 *
286 * If this ran it means *all* tasks were created fine and we
287 * are now just collecting results.
288 *
289 * Only propagate errors, do not override with a subsequent sucess case.
290 */
291static void tally_up_work(struct kmod_test_device *test_dev)
292{
293 struct test_config *config = &test_dev->config;
294 struct kmod_test_device_info *info;
295 unsigned int idx;
296 int err_ret = 0;
297 int ret = 0;
298
299 mutex_lock(&test_dev->thread_mutex);
300
301 dev_info(test_dev->dev, "Results:\n");
302
303 for (idx=0; idx < config->num_threads; idx++) {
304 info = &test_dev->info[idx];
305 ret = tally_work_test(info);
306 if (ret)
307 err_ret = ret;
308 }
309
310 /*
311 * Note: request_module() returns 256 for a module not found even
312 * though modprobe itself returns 1.
313 */
314 config->test_result = err_ret;
315
316 mutex_unlock(&test_dev->thread_mutex);
317}
318
319static int try_one_request(struct kmod_test_device *test_dev, unsigned int idx)
320{
321 struct kmod_test_device_info *info = &test_dev->info[idx];
322 int fail_ret = -ENOMEM;
323
324 mutex_lock(&test_dev->thread_mutex);
325
326 info->thread_idx = idx;
327 info->test_dev = test_dev;
328 info->task_sync = kthread_run(run_request, info, "%s-%u",
329 KBUILD_MODNAME, idx);
330
331 if (!info->task_sync || IS_ERR(info->task_sync)) {
332 test_dev->test_is_oom = true;
333 dev_err(test_dev->dev, "Setting up thread %u failed\n", idx);
334 info->task_sync = NULL;
335 goto err_out;
336 } else
337 dev_dbg(test_dev->dev, "Kicked off thread %u\n", idx);
338
339 mutex_unlock(&test_dev->thread_mutex);
340
341 return 0;
342
343err_out:
344 info->ret_sync = fail_ret;
345 mutex_unlock(&test_dev->thread_mutex);
346
347 return fail_ret;
348}
349
350static void test_dev_kmod_stop_tests(struct kmod_test_device *test_dev)
351{
352 struct test_config *config = &test_dev->config;
353 struct kmod_test_device_info *info;
354 unsigned int i;
355
356 dev_info(test_dev->dev, "Ending request_module() tests\n");
357
358 mutex_lock(&test_dev->thread_mutex);
359
360 for (i=0; i < config->num_threads; i++) {
361 info = &test_dev->info[i];
362 if (info->task_sync && !IS_ERR(info->task_sync)) {
363 dev_info(test_dev->dev,
364 "Stopping still-running thread %i\n", i);
365 kthread_stop(info->task_sync);
366 }
367
368 /*
369 * info->task_sync is well protected, it can only be
370 * NULL or a pointer to a struct. If its NULL we either
371 * never ran, or we did and we completed the work. Completed
372 * tasks *always* put the module for us. This is a sanity
373 * check -- just in case.
374 */
375 if (info->task_sync && info->need_mod_put)
376 test_kmod_put_module(info);
377 }
378
379 mutex_unlock(&test_dev->thread_mutex);
380}
381
382/*
383 * Only wait *iff* we did not run into any errors during all of our thread
384 * set up. If run into any issues we stop threads and just bail out with
385 * an error to the trigger. This also means we don't need any tally work
386 * for any threads which fail.
387 */
388static int try_requests(struct kmod_test_device *test_dev)
389{
390 struct test_config *config = &test_dev->config;
391 unsigned int idx;
392 int ret;
393 bool any_error = false;
394
395 for (idx=0; idx < config->num_threads; idx++) {
396 if (test_dev->test_is_oom) {
397 any_error = true;
398 break;
399 }
400
401 ret = try_one_request(test_dev, idx);
402 if (ret) {
403 any_error = true;
404 break;
405 }
406 }
407
408 if (!any_error) {
409 test_dev->test_is_oom = false;
410 dev_info(test_dev->dev,
411 "No errors were found while initializing threads\n");
412 wait_for_completion(&test_dev->kthreads_done);
413 tally_up_work(test_dev);
414 } else {
415 test_dev->test_is_oom = true;
416 dev_info(test_dev->dev,
417 "At least one thread failed to start, stop all work\n");
418 test_dev_kmod_stop_tests(test_dev);
419 return -ENOMEM;
420 }
421
422 return 0;
423}
424
425static int run_test_driver(struct kmod_test_device *test_dev)
426{
427 struct test_config *config = &test_dev->config;
428
429 dev_info(test_dev->dev, "Test case: %s (%u)\n",
430 test_case_str(config->test_case),
431 config->test_case);
432 dev_info(test_dev->dev, "Test driver to load: %s\n",
433 config->test_driver);
434 dev_info(test_dev->dev, "Number of threads to run: %u\n",
435 config->num_threads);
436 dev_info(test_dev->dev, "Thread IDs will range from 0 - %u\n",
437 config->num_threads - 1);
438
439 return try_requests(test_dev);
440}
441
442static int run_test_fs_type(struct kmod_test_device *test_dev)
443{
444 struct test_config *config = &test_dev->config;
445
446 dev_info(test_dev->dev, "Test case: %s (%u)\n",
447 test_case_str(config->test_case),
448 config->test_case);
449 dev_info(test_dev->dev, "Test filesystem to load: %s\n",
450 config->test_fs);
451 dev_info(test_dev->dev, "Number of threads to run: %u\n",
452 config->num_threads);
453 dev_info(test_dev->dev, "Thread IDs will range from 0 - %u\n",
454 config->num_threads - 1);
455
456 return try_requests(test_dev);
457}
458
459static ssize_t config_show(struct device *dev,
460 struct device_attribute *attr,
461 char *buf)
462{
463 struct kmod_test_device *test_dev = dev_to_test_dev(dev);
464 struct test_config *config = &test_dev->config;
465 int len = 0;
466
467 mutex_lock(&test_dev->config_mutex);
468
469 len += snprintf(buf, PAGE_SIZE,
470 "Custom trigger configuration for: %s\n",
471 dev_name(dev));
472
473 len += snprintf(buf+len, PAGE_SIZE - len,
474 "Number of threads:\t%u\n",
475 config->num_threads);
476
477 len += snprintf(buf+len, PAGE_SIZE - len,
478 "Test_case:\t%s (%u)\n",
479 test_case_str(config->test_case),
480 config->test_case);
481
482 if (config->test_driver)
483 len += snprintf(buf+len, PAGE_SIZE - len,
484 "driver:\t%s\n",
485 config->test_driver);
486 else
487 len += snprintf(buf+len, PAGE_SIZE - len,
488 "driver:\tEMTPY\n");
489
490 if (config->test_fs)
491 len += snprintf(buf+len, PAGE_SIZE - len,
492 "fs:\t%s\n",
493 config->test_fs);
494 else
495 len += snprintf(buf+len, PAGE_SIZE - len,
496 "fs:\tEMTPY\n");
497
498 mutex_unlock(&test_dev->config_mutex);
499
500 return len;
501}
502static DEVICE_ATTR_RO(config);
503
504/*
505 * This ensures we don't allow kicking threads through if our configuration
506 * is faulty.
507 */
508static int __trigger_config_run(struct kmod_test_device *test_dev)
509{
510 struct test_config *config = &test_dev->config;
511
512 test_dev->done = 0;
513
514 switch (config->test_case) {
515 case TEST_KMOD_DRIVER:
516 return run_test_driver(test_dev);
517 case TEST_KMOD_FS_TYPE:
518 return run_test_fs_type(test_dev);
519 default:
520 dev_warn(test_dev->dev,
521 "Invalid test case requested: %u\n",
522 config->test_case);
523 return -EINVAL;
524 }
525}
526
527static int trigger_config_run(struct kmod_test_device *test_dev)
528{
529 struct test_config *config = &test_dev->config;
530 int ret;
531
532 mutex_lock(&test_dev->trigger_mutex);
533 mutex_lock(&test_dev->config_mutex);
534
535 ret = __trigger_config_run(test_dev);
536 if (ret < 0)
537 goto out;
538 dev_info(test_dev->dev, "General test result: %d\n",
539 config->test_result);
540
541 /*
542 * We must return 0 after a trigger even unless something went
543 * wrong with the setup of the test. If the test setup went fine
544 * then userspace must just check the result of config->test_result.
545 * One issue with relying on the return from a call in the kernel
546 * is if the kernel returns a possitive value using this trigger
547 * will not return the value to userspace, it would be lost.
548 *
549 * By not relying on capturing the return value of tests we are using
550 * through the trigger it also us to run tests with set -e and only
551 * fail when something went wrong with the driver upon trigger
552 * requests.
553 */
554 ret = 0;
555
556out:
557 mutex_unlock(&test_dev->config_mutex);
558 mutex_unlock(&test_dev->trigger_mutex);
559
560 return ret;
561}
562
563static ssize_t
564trigger_config_store(struct device *dev,
565 struct device_attribute *attr,
566 const char *buf, size_t count)
567{
568 struct kmod_test_device *test_dev = dev_to_test_dev(dev);
569 int ret;
570
571 if (test_dev->test_is_oom)
572 return -ENOMEM;
573
574 /* For all intents and purposes we don't care what userspace
575 * sent this trigger, we care only that we were triggered.
576 * We treat the return value only for caputuring issues with
577 * the test setup. At this point all the test variables should
578 * have been allocated so typically this should never fail.
579 */
580 ret = trigger_config_run(test_dev);
581 if (unlikely(ret < 0))
582 goto out;
583
584 /*
585 * Note: any return > 0 will be treated as success
586 * and the error value will not be available to userspace.
587 * Do not rely on trying to send to userspace a test value
588 * return value as possitive return errors will be lost.
589 */
590 if (WARN_ON(ret > 0))
591 return -EINVAL;
592
593 ret = count;
594out:
595 return ret;
596}
597static DEVICE_ATTR_WO(trigger_config);
598
599/*
600 * XXX: move to kstrncpy() once merged.
601 *
602 * Users should use kfree_const() when freeing these.
603 */
604static int __kstrncpy(char **dst, const char *name, size_t count, gfp_t gfp)
605{
606 *dst = kstrndup(name, count, gfp);
607 if (!*dst)
608 return -ENOSPC;
609 return count;
610}
611
612static int config_copy_test_driver_name(struct test_config *config,
613 const char *name,
614 size_t count)
615{
616 return __kstrncpy(&config->test_driver, name, count, GFP_KERNEL);
617}
618
619
620static int config_copy_test_fs(struct test_config *config, const char *name,
621 size_t count)
622{
623 return __kstrncpy(&config->test_fs, name, count, GFP_KERNEL);
624}
625
626static void __kmod_config_free(struct test_config *config)
627{
628 if (!config)
629 return;
630
631 kfree_const(config->test_driver);
632 config->test_driver = NULL;
633
634 kfree_const(config->test_fs);
635 config->test_driver = NULL;
636}
637
638static void kmod_config_free(struct kmod_test_device *test_dev)
639{
640 struct test_config *config;
641
642 if (!test_dev)
643 return;
644
645 config = &test_dev->config;
646
647 mutex_lock(&test_dev->config_mutex);
648 __kmod_config_free(config);
649 mutex_unlock(&test_dev->config_mutex);
650}
651
652static ssize_t config_test_driver_store(struct device *dev,
653 struct device_attribute *attr,
654 const char *buf, size_t count)
655{
656 struct kmod_test_device *test_dev = dev_to_test_dev(dev);
657 struct test_config *config = &test_dev->config;
658 int copied;
659
660 mutex_lock(&test_dev->config_mutex);
661
662 kfree_const(config->test_driver);
663 config->test_driver = NULL;
664
665 copied = config_copy_test_driver_name(config, buf, count);
666 mutex_unlock(&test_dev->config_mutex);
667
668 return copied;
669}
670
671/*
672 * As per sysfs_kf_seq_show() the buf is max PAGE_SIZE.
673 */
674static ssize_t config_test_show_str(struct mutex *config_mutex,
675 char *dst,
676 char *src)
677{
678 int len;
679
680 mutex_lock(config_mutex);
681 len = snprintf(dst, PAGE_SIZE, "%s\n", src);
682 mutex_unlock(config_mutex);
683
684 return len;
685}
686
687static ssize_t config_test_driver_show(struct device *dev,
688 struct device_attribute *attr,
689 char *buf)
690{
691 struct kmod_test_device *test_dev = dev_to_test_dev(dev);
692 struct test_config *config = &test_dev->config;
693
694 return config_test_show_str(&test_dev->config_mutex, buf,
695 config->test_driver);
696}
697static DEVICE_ATTR(config_test_driver, 0644, config_test_driver_show,
698 config_test_driver_store);
699
700static ssize_t config_test_fs_store(struct device *dev,
701 struct device_attribute *attr,
702 const char *buf, size_t count)
703{
704 struct kmod_test_device *test_dev = dev_to_test_dev(dev);
705 struct test_config *config = &test_dev->config;
706 int copied;
707
708 mutex_lock(&test_dev->config_mutex);
709
710 kfree_const(config->test_fs);
711 config->test_fs = NULL;
712
713 copied = config_copy_test_fs(config, buf, count);
714 mutex_unlock(&test_dev->config_mutex);
715
716 return copied;
717}
718
719static ssize_t config_test_fs_show(struct device *dev,
720 struct device_attribute *attr,
721 char *buf)
722{
723 struct kmod_test_device *test_dev = dev_to_test_dev(dev);
724 struct test_config *config = &test_dev->config;
725
726 return config_test_show_str(&test_dev->config_mutex, buf,
727 config->test_fs);
728}
729static DEVICE_ATTR(config_test_fs, 0644, config_test_fs_show,
730 config_test_fs_store);
731
732static int trigger_config_run_type(struct kmod_test_device *test_dev,
733 enum kmod_test_case test_case,
734 const char *test_str)
735{
736 int copied = 0;
737 struct test_config *config = &test_dev->config;
738
739 mutex_lock(&test_dev->config_mutex);
740
741 switch (test_case) {
742 case TEST_KMOD_DRIVER:
743 kfree_const(config->test_driver);
744 config->test_driver = NULL;
745 copied = config_copy_test_driver_name(config, test_str,
746 strlen(test_str));
747 break;
748 case TEST_KMOD_FS_TYPE:
749 break;
750 kfree_const(config->test_fs);
751 config->test_driver = NULL;
752 copied = config_copy_test_fs(config, test_str,
753 strlen(test_str));
754 default:
755 mutex_unlock(&test_dev->config_mutex);
756 return -EINVAL;
757 }
758
759 config->test_case = test_case;
760
761 mutex_unlock(&test_dev->config_mutex);
762
763 if (copied <= 0 || copied != strlen(test_str)) {
764 test_dev->test_is_oom = true;
765 return -ENOMEM;
766 }
767
768 test_dev->test_is_oom = false;
769
770 return trigger_config_run(test_dev);
771}
772
773static void free_test_dev_info(struct kmod_test_device *test_dev)
774{
775 vfree(test_dev->info);
776 test_dev->info = NULL;
777}
778
779static int kmod_config_sync_info(struct kmod_test_device *test_dev)
780{
781 struct test_config *config = &test_dev->config;
782
783 free_test_dev_info(test_dev);
784 test_dev->info = vzalloc(config->num_threads *
785 sizeof(struct kmod_test_device_info));
786 if (!test_dev->info) {
787 dev_err(test_dev->dev, "Cannot alloc test_dev info\n");
788 return -ENOMEM;
789 }
790
791 return 0;
792}
793
794/*
795 * Old kernels may not have this, if you want to port this code to
796 * test it on older kernels.
797 */
798#ifdef get_kmod_umh_limit
799static unsigned int kmod_init_test_thread_limit(void)
800{
801 return get_kmod_umh_limit();
802}
803#else
804static unsigned int kmod_init_test_thread_limit(void)
805{
806 return TEST_START_NUM_THREADS;
807}
808#endif
809
810static int __kmod_config_init(struct kmod_test_device *test_dev)
811{
812 struct test_config *config = &test_dev->config;
813 int ret = -ENOMEM, copied;
814
815 __kmod_config_free(config);
816
817 copied = config_copy_test_driver_name(config, TEST_START_DRIVER,
818 strlen(TEST_START_DRIVER));
819 if (copied != strlen(TEST_START_DRIVER))
820 goto err_out;
821
822 copied = config_copy_test_fs(config, TEST_START_TEST_FS,
823 strlen(TEST_START_TEST_FS));
824 if (copied != strlen(TEST_START_TEST_FS))
825 goto err_out;
826
827 config->num_threads = kmod_init_test_thread_limit();
828 config->test_result = 0;
829 config->test_case = TEST_START_TEST_CASE;
830
831 ret = kmod_config_sync_info(test_dev);
832 if (ret)
833 goto err_out;
834
835 test_dev->test_is_oom = false;
836
837 return 0;
838
839err_out:
840 test_dev->test_is_oom = true;
841 WARN_ON(test_dev->test_is_oom);
842
843 __kmod_config_free(config);
844
845 return ret;
846}
847
848static ssize_t reset_store(struct device *dev,
849 struct device_attribute *attr,
850 const char *buf, size_t count)
851{
852 struct kmod_test_device *test_dev = dev_to_test_dev(dev);
853 int ret;
854
855 mutex_lock(&test_dev->trigger_mutex);
856 mutex_lock(&test_dev->config_mutex);
857
858 ret = __kmod_config_init(test_dev);
859 if (ret < 0) {
860 ret = -ENOMEM;
861 dev_err(dev, "could not alloc settings for config trigger: %d\n",
862 ret);
863 goto out;
864 }
865
866 dev_info(dev, "reset\n");
867 ret = count;
868
869out:
870 mutex_unlock(&test_dev->config_mutex);
871 mutex_unlock(&test_dev->trigger_mutex);
872
873 return ret;
874}
875static DEVICE_ATTR_WO(reset);
876
877static int test_dev_config_update_uint_sync(struct kmod_test_device *test_dev,
878 const char *buf, size_t size,
879 unsigned int *config,
880 int (*test_sync)(struct kmod_test_device *test_dev))
881{
882 int ret;
883 long new;
884 unsigned int old_val;
885
886 ret = kstrtol(buf, 10, &new);
887 if (ret)
888 return ret;
889
890 if (new > UINT_MAX)
891 return -EINVAL;
892
893 mutex_lock(&test_dev->config_mutex);
894
895 old_val = *config;
896 *(unsigned int *)config = new;
897
898 ret = test_sync(test_dev);
899 if (ret) {
900 *(unsigned int *)config = old_val;
901
902 ret = test_sync(test_dev);
903 WARN_ON(ret);
904
905 mutex_unlock(&test_dev->config_mutex);
906 return -EINVAL;
907 }
908
909 mutex_unlock(&test_dev->config_mutex);
910 /* Always return full write size even if we didn't consume all */
911 return size;
912}
913
914static int test_dev_config_update_uint_range(struct kmod_test_device *test_dev,
915 const char *buf, size_t size,
916 unsigned int *config,
917 unsigned int min,
918 unsigned int max)
919{
920 int ret;
921 long new;
922
923 ret = kstrtol(buf, 10, &new);
924 if (ret)
925 return ret;
926
927 if (new < min || new > max || new > UINT_MAX)
928 return -EINVAL;
929
930 mutex_lock(&test_dev->config_mutex);
931 *config = new;
932 mutex_unlock(&test_dev->config_mutex);
933
934 /* Always return full write size even if we didn't consume all */
935 return size;
936}
937
938static int test_dev_config_update_int(struct kmod_test_device *test_dev,
939 const char *buf, size_t size,
940 int *config)
941{
942 int ret;
943 long new;
944
945 ret = kstrtol(buf, 10, &new);
946 if (ret)
947 return ret;
948
949 if (new > INT_MAX || new < INT_MIN)
950 return -EINVAL;
951
952 mutex_lock(&test_dev->config_mutex);
953 *config = new;
954 mutex_unlock(&test_dev->config_mutex);
955 /* Always return full write size even if we didn't consume all */
956 return size;
957}
958
959static ssize_t test_dev_config_show_int(struct kmod_test_device *test_dev,
960 char *buf,
961 int config)
962{
963 int val;
964
965 mutex_lock(&test_dev->config_mutex);
966 val = config;
967 mutex_unlock(&test_dev->config_mutex);
968
969 return snprintf(buf, PAGE_SIZE, "%d\n", val);
970}
971
972static ssize_t test_dev_config_show_uint(struct kmod_test_device *test_dev,
973 char *buf,
974 unsigned int config)
975{
976 unsigned int val;
977
978 mutex_lock(&test_dev->config_mutex);
979 val = config;
980 mutex_unlock(&test_dev->config_mutex);
981
982 return snprintf(buf, PAGE_SIZE, "%u\n", val);
983}
984
985static ssize_t test_result_store(struct device *dev,
986 struct device_attribute *attr,
987 const char *buf, size_t count)
988{
989 struct kmod_test_device *test_dev = dev_to_test_dev(dev);
990 struct test_config *config = &test_dev->config;
991
992 return test_dev_config_update_int(test_dev, buf, count,
993 &config->test_result);
994}
995
996static ssize_t config_num_threads_store(struct device *dev,
997 struct device_attribute *attr,
998 const char *buf, size_t count)
999{
1000 struct kmod_test_device *test_dev = dev_to_test_dev(dev);
1001 struct test_config *config = &test_dev->config;
1002
1003 return test_dev_config_update_uint_sync(test_dev, buf, count,
1004 &config->num_threads,
1005 kmod_config_sync_info);
1006}
1007
1008static ssize_t config_num_threads_show(struct device *dev,
1009 struct device_attribute *attr,
1010 char *buf)
1011{
1012 struct kmod_test_device *test_dev = dev_to_test_dev(dev);
1013 struct test_config *config = &test_dev->config;
1014
1015 return test_dev_config_show_int(test_dev, buf, config->num_threads);
1016}
1017static DEVICE_ATTR(config_num_threads, 0644, config_num_threads_show,
1018 config_num_threads_store);
1019
1020static ssize_t config_test_case_store(struct device *dev,
1021 struct device_attribute *attr,
1022 const char *buf, size_t count)
1023{
1024 struct kmod_test_device *test_dev = dev_to_test_dev(dev);
1025 struct test_config *config = &test_dev->config;
1026
1027 return test_dev_config_update_uint_range(test_dev, buf, count,
1028 &config->test_case,
1029 __TEST_KMOD_INVALID + 1,
1030 __TEST_KMOD_MAX - 1);
1031}
1032
1033static ssize_t config_test_case_show(struct device *dev,
1034 struct device_attribute *attr,
1035 char *buf)
1036{
1037 struct kmod_test_device *test_dev = dev_to_test_dev(dev);
1038 struct test_config *config = &test_dev->config;
1039
1040 return test_dev_config_show_uint(test_dev, buf, config->test_case);
1041}
1042static DEVICE_ATTR(config_test_case, 0644, config_test_case_show,
1043 config_test_case_store);
1044
1045static ssize_t test_result_show(struct device *dev,
1046 struct device_attribute *attr,
1047 char *buf)
1048{
1049 struct kmod_test_device *test_dev = dev_to_test_dev(dev);
1050 struct test_config *config = &test_dev->config;
1051
1052 return test_dev_config_show_int(test_dev, buf, config->test_result);
1053}
1054static DEVICE_ATTR(test_result, 0644, test_result_show, test_result_store);
1055
1056#define TEST_KMOD_DEV_ATTR(name) &dev_attr_##name.attr
1057
1058static struct attribute *test_dev_attrs[] = {
1059 TEST_KMOD_DEV_ATTR(trigger_config),
1060 TEST_KMOD_DEV_ATTR(config),
1061 TEST_KMOD_DEV_ATTR(reset),
1062
1063 TEST_KMOD_DEV_ATTR(config_test_driver),
1064 TEST_KMOD_DEV_ATTR(config_test_fs),
1065 TEST_KMOD_DEV_ATTR(config_num_threads),
1066 TEST_KMOD_DEV_ATTR(config_test_case),
1067 TEST_KMOD_DEV_ATTR(test_result),
1068
1069 NULL,
1070};
1071
1072ATTRIBUTE_GROUPS(test_dev);
1073
1074static int kmod_config_init(struct kmod_test_device *test_dev)
1075{
1076 int ret;
1077
1078 mutex_lock(&test_dev->config_mutex);
1079 ret = __kmod_config_init(test_dev);
1080 mutex_unlock(&test_dev->config_mutex);
1081
1082 return ret;
1083}
1084
1085static struct kmod_test_device *alloc_test_dev_kmod(int idx)
1086{
1087 int ret;
1088 struct kmod_test_device *test_dev;
1089 struct miscdevice *misc_dev;
1090
1091 test_dev = vzalloc(sizeof(struct kmod_test_device));
1092 if (!test_dev) {
1093 pr_err("Cannot alloc test_dev\n");
1094 goto err_out;
1095 }
1096
1097 mutex_init(&test_dev->config_mutex);
1098 mutex_init(&test_dev->trigger_mutex);
1099 mutex_init(&test_dev->thread_mutex);
1100
1101 init_completion(&test_dev->kthreads_done);
1102
1103 ret = kmod_config_init(test_dev);
1104 if (ret < 0) {
1105 pr_err("Cannot alloc kmod_config_init()\n");
1106 goto err_out_free;
1107 }
1108
1109 test_dev->dev_idx = idx;
1110 misc_dev = &test_dev->misc_dev;
1111
1112 misc_dev->minor = MISC_DYNAMIC_MINOR;
1113 misc_dev->name = kasprintf(GFP_KERNEL, "test_kmod%d", idx);
1114 if (!misc_dev->name) {
1115 pr_err("Cannot alloc misc_dev->name\n");
1116 goto err_out_free_config;
1117 }
1118 misc_dev->groups = test_dev_groups;
1119
1120 return test_dev;
1121
1122err_out_free_config:
1123 free_test_dev_info(test_dev);
1124 kmod_config_free(test_dev);
1125err_out_free:
1126 vfree(test_dev);
1127 test_dev = NULL;
1128err_out:
1129 return NULL;
1130}
1131
1132static void free_test_dev_kmod(struct kmod_test_device *test_dev)
1133{
1134 if (test_dev) {
1135 kfree_const(test_dev->misc_dev.name);
1136 test_dev->misc_dev.name = NULL;
1137 free_test_dev_info(test_dev);
1138 kmod_config_free(test_dev);
1139 vfree(test_dev);
1140 test_dev = NULL;
1141 }
1142}
1143
1144static struct kmod_test_device *register_test_dev_kmod(void)
1145{
1146 struct kmod_test_device *test_dev = NULL;
1147 int ret;
1148
1149 mutex_unlock(&reg_dev_mutex);
1150
1151 /* int should suffice for number of devices, test for wrap */
1152 if (unlikely(num_test_devs + 1) < 0) {
1153 pr_err("reached limit of number of test devices\n");
1154 goto out;
1155 }
1156
1157 test_dev = alloc_test_dev_kmod(num_test_devs);
1158 if (!test_dev)
1159 goto out;
1160
1161 ret = misc_register(&test_dev->misc_dev);
1162 if (ret) {
1163 pr_err("could not register misc device: %d\n", ret);
1164 free_test_dev_kmod(test_dev);
1165 goto out;
1166 }
1167
1168 test_dev->dev = test_dev->misc_dev.this_device;
1169 list_add_tail(&test_dev->list, &reg_test_devs);
1170 dev_info(test_dev->dev, "interface ready\n");
1171
1172 num_test_devs++;
1173
1174out:
1175 mutex_unlock(&reg_dev_mutex);
1176
1177 return test_dev;
1178
1179}
1180
1181static int __init test_kmod_init(void)
1182{
1183 struct kmod_test_device *test_dev;
1184 int ret;
1185
1186 test_dev = register_test_dev_kmod();
1187 if (!test_dev) {
1188 pr_err("Cannot add first test kmod device\n");
1189 return -ENODEV;
1190 }
1191
1192 /*
1193 * With some work we might be able to gracefully enable
1194 * testing with this driver built-in, for now this seems
1195 * rather risky. For those willing to try have at it,
1196 * and enable the below. Good luck! If that works, try
1197 * lowering the init level for more fun.
1198 */
1199 if (force_init_test) {
1200 ret = trigger_config_run_type(test_dev,
1201 TEST_KMOD_DRIVER, "tun");
1202 if (WARN_ON(ret))
1203 return ret;
1204 ret = trigger_config_run_type(test_dev,
1205 TEST_KMOD_FS_TYPE, "btrfs");
1206 if (WARN_ON(ret))
1207 return ret;
1208 }
1209
1210 return 0;
1211}
1212late_initcall(test_kmod_init);
1213
1214static
1215void unregister_test_dev_kmod(struct kmod_test_device *test_dev)
1216{
1217 mutex_lock(&test_dev->trigger_mutex);
1218 mutex_lock(&test_dev->config_mutex);
1219
1220 test_dev_kmod_stop_tests(test_dev);
1221
1222 dev_info(test_dev->dev, "removing interface\n");
1223 misc_deregister(&test_dev->misc_dev);
1224 kfree(&test_dev->misc_dev.name);
1225
1226 mutex_unlock(&test_dev->config_mutex);
1227 mutex_unlock(&test_dev->trigger_mutex);
1228
1229 free_test_dev_kmod(test_dev);
1230}
1231
1232static void __exit test_kmod_exit(void)
1233{
1234 struct kmod_test_device *test_dev, *tmp;
1235
1236 mutex_lock(&reg_dev_mutex);
1237 list_for_each_entry_safe(test_dev, tmp, &reg_test_devs, list) {
1238 list_del(&test_dev->list);
1239 unregister_test_dev_kmod(test_dev);
1240 }
1241 mutex_unlock(&reg_dev_mutex);
1242}
1243module_exit(test_kmod_exit);
1244
1245MODULE_AUTHOR("Luis R. Rodriguez <mcgrof@kernel.org>");
1246MODULE_LICENSE("GPL");
diff --git a/mm/mmap.c b/mm/mmap.c
index 7fa6759322d1..f19efcf75418 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2231,7 +2231,7 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address)
2231 2231
2232 /* Guard against exceeding limits of the address space. */ 2232 /* Guard against exceeding limits of the address space. */
2233 address &= PAGE_MASK; 2233 address &= PAGE_MASK;
2234 if (address >= TASK_SIZE) 2234 if (address >= (TASK_SIZE & PAGE_MASK))
2235 return -ENOMEM; 2235 return -ENOMEM;
2236 address += PAGE_SIZE; 2236 address += PAGE_SIZE;
2237 2237
diff --git a/tools/testing/selftests/kmod/Makefile b/tools/testing/selftests/kmod/Makefile
new file mode 100644
index 000000000000..fa2ccc5fb3de
--- /dev/null
+++ b/tools/testing/selftests/kmod/Makefile
@@ -0,0 +1,11 @@
1# Makefile for kmod loading selftests
2
3# No binaries, but make sure arg-less "make" doesn't trigger "run_tests"
4all:
5
6TEST_PROGS := kmod.sh
7
8include ../lib.mk
9
10# Nothing to clean up.
11clean:
diff --git a/tools/testing/selftests/kmod/config b/tools/testing/selftests/kmod/config
new file mode 100644
index 000000000000..259f4fd6b5e2
--- /dev/null
+++ b/tools/testing/selftests/kmod/config
@@ -0,0 +1,7 @@
1CONFIG_TEST_KMOD=m
2CONFIG_TEST_LKM=m
3CONFIG_XFS_FS=m
4
5# For the module parameter force_init_test is used
6CONFIG_TUN=m
7CONFIG_BTRFS_FS=m
diff --git a/tools/testing/selftests/kmod/kmod.sh b/tools/testing/selftests/kmod/kmod.sh
new file mode 100644
index 000000000000..8cecae9a8bca
--- /dev/null
+++ b/tools/testing/selftests/kmod/kmod.sh
@@ -0,0 +1,615 @@
1#!/bin/bash
2#
3# Copyright (C) 2017 Luis R. Rodriguez <mcgrof@kernel.org>
4#
5# This program is free software; you can redistribute it and/or modify it
6# under the terms of the GNU General Public License as published by the Free
7# Software Foundation; either version 2 of the License, or at your option any
8# later version; or, when distributed separately from the Linux kernel or
9# when incorporated into other software packages, subject to the following
10# license:
11#
12# This program is free software; you can redistribute it and/or modify it
13# under the terms of copyleft-next (version 0.3.1 or later) as published
14# at http://copyleft-next.org/.
15
16# This is a stress test script for kmod, the kernel module loader. It uses
17# test_kmod which exposes a series of knobs for the API for us so we can
18# tweak each test in userspace rather than in kernelspace.
19#
20# The way kmod works is it uses the kernel's usermode helper API to eventually
21# call /sbin/modprobe. It has a limit of the number of concurrent calls
22# possible. The kernel interface to load modules is request_module(), however
23# mount uses get_fs_type(). Both behave slightly differently, but the
24# differences are important enough to test each call separately. For this
25# reason test_kmod starts by providing tests for both calls.
26#
27# The test driver test_kmod assumes a series of defaults which you can
28# override by exporting to your environment prior running this script.
29# For instance this script assumes you do not have xfs loaded upon boot.
30# If this is false, export DEFAULT_KMOD_FS="ext4" prior to running this
31# script if the filesyste module you don't have loaded upon bootup
32# is ext4 instead. Refer to allow_user_defaults() for a list of user
33# override variables possible.
34#
35# You'll want at least 4 GiB of RAM to expect to run these tests
36# without running out of memory on them. For other requirements refer
37# to test_reqs()
38
39set -e
40
41TEST_NAME="kmod"
42TEST_DRIVER="test_${TEST_NAME}"
43TEST_DIR=$(dirname $0)
44
45# This represents
46#
47# TEST_ID:TEST_COUNT:ENABLED
48#
49# TEST_ID: is the test id number
50# TEST_COUNT: number of times we should run the test
51# ENABLED: 1 if enabled, 0 otherwise
52#
53# Once these are enabled please leave them as-is. Write your own test,
54# we have tons of space.
55ALL_TESTS="0001:3:1"
56ALL_TESTS="$ALL_TESTS 0002:3:1"
57ALL_TESTS="$ALL_TESTS 0003:1:1"
58ALL_TESTS="$ALL_TESTS 0004:1:1"
59ALL_TESTS="$ALL_TESTS 0005:10:1"
60ALL_TESTS="$ALL_TESTS 0006:10:1"
61ALL_TESTS="$ALL_TESTS 0007:5:1"
62ALL_TESTS="$ALL_TESTS 0008:150:1"
63ALL_TESTS="$ALL_TESTS 0009:150:1"
64
65test_modprobe()
66{
67 if [ ! -d $DIR ]; then
68 echo "$0: $DIR not present" >&2
69 echo "You must have the following enabled in your kernel:" >&2
70 cat $TEST_DIR/config >&2
71 exit 1
72 fi
73}
74
75function allow_user_defaults()
76{
77 if [ -z $DEFAULT_KMOD_DRIVER ]; then
78 DEFAULT_KMOD_DRIVER="test_module"
79 fi
80
81 if [ -z $DEFAULT_KMOD_FS ]; then
82 DEFAULT_KMOD_FS="xfs"
83 fi
84
85 if [ -z $PROC_DIR ]; then
86 PROC_DIR="/proc/sys/kernel/"
87 fi
88
89 if [ -z $MODPROBE_LIMIT ]; then
90 MODPROBE_LIMIT=50
91 fi
92
93 if [ -z $DIR ]; then
94 DIR="/sys/devices/virtual/misc/${TEST_DRIVER}0/"
95 fi
96
97 if [ -z $DEFAULT_NUM_TESTS ]; then
98 DEFAULT_NUM_TESTS=150
99 fi
100
101 MODPROBE_LIMIT_FILE="${PROC_DIR}/kmod-limit"
102}
103
104test_reqs()
105{
106 if ! which modprobe 2> /dev/null > /dev/null; then
107 echo "$0: You need modprobe installed" >&2
108 exit 1
109 fi
110
111 if ! which kmod 2> /dev/null > /dev/null; then
112 echo "$0: You need kmod installed" >&2
113 exit 1
114 fi
115
116 # kmod 19 has a bad bug where it returns 0 when modprobe
117 # gets called *even* if the module was not loaded due to
118 # some bad heuristics. For details see:
119 #
120 # A work around is possible in-kernel but its rather
121 # complex.
122 KMOD_VERSION=$(kmod --version | awk '{print $3}')
123 if [[ $KMOD_VERSION -le 19 ]]; then
124 echo "$0: You need at least kmod 20" >&2
125 echo "kmod <= 19 is buggy, for details see:" >&2
126 echo "http://git.kernel.org/cgit/utils/kernel/kmod/kmod.git/commit/libkmod/libkmod-module.c?id=fd44a98ae2eb5eb32161088954ab21e58e19dfc4" >&2
127 exit 1
128 fi
129
130 uid=$(id -u)
131 if [ $uid -ne 0 ]; then
132 echo $msg must be run as root >&2
133 exit 0
134 fi
135}
136
137function load_req_mod()
138{
139 trap "test_modprobe" EXIT
140
141 if [ ! -d $DIR ]; then
142 # Alanis: "Oh isn't it ironic?"
143 modprobe $TEST_DRIVER
144 fi
145}
146
147test_finish()
148{
149 echo "Test completed"
150}
151
152errno_name_to_val()
153{
154 case "$1" in
155 # kmod calls modprobe and upon of a module not found
156 # modprobe returns just 1... However in the kernel we
157 # *sometimes* see 256...
158 MODULE_NOT_FOUND)
159 echo 256;;
160 SUCCESS)
161 echo 0;;
162 -EPERM)
163 echo -1;;
164 -ENOENT)
165 echo -2;;
166 -EINVAL)
167 echo -22;;
168 -ERR_ANY)
169 echo -123456;;
170 *)
171 echo invalid;;
172 esac
173}
174
175errno_val_to_name()
176 case "$1" in
177 256)
178 echo MODULE_NOT_FOUND;;
179 0)
180 echo SUCCESS;;
181 -1)
182 echo -EPERM;;
183 -2)
184 echo -ENOENT;;
185 -22)
186 echo -EINVAL;;
187 -123456)
188 echo -ERR_ANY;;
189 *)
190 echo invalid;;
191 esac
192
193config_set_test_case_driver()
194{
195 if ! echo -n 1 >$DIR/config_test_case; then
196 echo "$0: Unable to set to test case to driver" >&2
197 exit 1
198 fi
199}
200
201config_set_test_case_fs()
202{
203 if ! echo -n 2 >$DIR/config_test_case; then
204 echo "$0: Unable to set to test case to fs" >&2
205 exit 1
206 fi
207}
208
209config_num_threads()
210{
211 if ! echo -n $1 >$DIR/config_num_threads; then
212 echo "$0: Unable to set to number of threads" >&2
213 exit 1
214 fi
215}
216
217config_get_modprobe_limit()
218{
219 if [[ -f ${MODPROBE_LIMIT_FILE} ]] ; then
220 MODPROBE_LIMIT=$(cat $MODPROBE_LIMIT_FILE)
221 fi
222 echo $MODPROBE_LIMIT
223}
224
225config_num_thread_limit_extra()
226{
227 MODPROBE_LIMIT=$(config_get_modprobe_limit)
228 let EXTRA_LIMIT=$MODPROBE_LIMIT+$1
229 config_num_threads $EXTRA_LIMIT
230}
231
232# For special characters use printf directly,
233# refer to kmod_test_0001
234config_set_driver()
235{
236 if ! echo -n $1 >$DIR/config_test_driver; then
237 echo "$0: Unable to set driver" >&2
238 exit 1
239 fi
240}
241
242config_set_fs()
243{
244 if ! echo -n $1 >$DIR/config_test_fs; then
245 echo "$0: Unable to set driver" >&2
246 exit 1
247 fi
248}
249
250config_get_driver()
251{
252 cat $DIR/config_test_driver
253}
254
255config_get_test_result()
256{
257 cat $DIR/test_result
258}
259
260config_reset()
261{
262 if ! echo -n "1" >"$DIR"/reset; then
263 echo "$0: reset shuld have worked" >&2
264 exit 1
265 fi
266}
267
268config_show_config()
269{
270 echo "----------------------------------------------------"
271 cat "$DIR"/config
272 echo "----------------------------------------------------"
273}
274
275config_trigger()
276{
277 if ! echo -n "1" >"$DIR"/trigger_config 2>/dev/null; then
278 echo "$1: FAIL - loading should have worked"
279 config_show_config
280 exit 1
281 fi
282 echo "$1: OK! - loading kmod test"
283}
284
285config_trigger_want_fail()
286{
287 if echo "1" > $DIR/trigger_config 2>/dev/null; then
288 echo "$1: FAIL - test case was expected to fail"
289 config_show_config
290 exit 1
291 fi
292 echo "$1: OK! - kmod test case failed as expected"
293}
294
295config_expect_result()
296{
297 RC=$(config_get_test_result)
298 RC_NAME=$(errno_val_to_name $RC)
299
300 ERRNO_NAME=$2
301 ERRNO=$(errno_name_to_val $ERRNO_NAME)
302
303 if [[ $ERRNO_NAME = "-ERR_ANY" ]]; then
304 if [[ $RC -ge 0 ]]; then
305 echo "$1: FAIL, test expects $ERRNO_NAME - got $RC_NAME ($RC)" >&2
306 config_show_config
307 exit 1
308 fi
309 elif [[ $RC != $ERRNO ]]; then
310 echo "$1: FAIL, test expects $ERRNO_NAME ($ERRNO) - got $RC_NAME ($RC)" >&2
311 config_show_config
312 exit 1
313 fi
314 echo "$1: OK! - Return value: $RC ($RC_NAME), expected $ERRNO_NAME"
315}
316
317kmod_defaults_driver()
318{
319 config_reset
320 modprobe -r $DEFAULT_KMOD_DRIVER
321 config_set_driver $DEFAULT_KMOD_DRIVER
322}
323
324kmod_defaults_fs()
325{
326 config_reset
327 modprobe -r $DEFAULT_KMOD_FS
328 config_set_fs $DEFAULT_KMOD_FS
329 config_set_test_case_fs
330}
331
332kmod_test_0001_driver()
333{
334 NAME='\000'
335
336 kmod_defaults_driver
337 config_num_threads 1
338 printf '\000' >"$DIR"/config_test_driver
339 config_trigger ${FUNCNAME[0]}
340 config_expect_result ${FUNCNAME[0]} MODULE_NOT_FOUND
341}
342
343kmod_test_0001_fs()
344{
345 NAME='\000'
346
347 kmod_defaults_fs
348 config_num_threads 1
349 printf '\000' >"$DIR"/config_test_fs
350 config_trigger ${FUNCNAME[0]}
351 config_expect_result ${FUNCNAME[0]} -EINVAL
352}
353
354kmod_test_0001()
355{
356 kmod_test_0001_driver
357 kmod_test_0001_fs
358}
359
360kmod_test_0002_driver()
361{
362 NAME="nope-$DEFAULT_KMOD_DRIVER"
363
364 kmod_defaults_driver
365 config_set_driver $NAME
366 config_num_threads 1
367 config_trigger ${FUNCNAME[0]}
368 config_expect_result ${FUNCNAME[0]} MODULE_NOT_FOUND
369}
370
371kmod_test_0002_fs()
372{
373 NAME="nope-$DEFAULT_KMOD_FS"
374
375 kmod_defaults_fs
376 config_set_fs $NAME
377 config_trigger ${FUNCNAME[0]}
378 config_expect_result ${FUNCNAME[0]} -EINVAL
379}
380
381kmod_test_0002()
382{
383 kmod_test_0002_driver
384 kmod_test_0002_fs
385}
386
387kmod_test_0003()
388{
389 kmod_defaults_fs
390 config_num_threads 1
391 config_trigger ${FUNCNAME[0]}
392 config_expect_result ${FUNCNAME[0]} SUCCESS
393}
394
395kmod_test_0004()
396{
397 kmod_defaults_fs
398 config_num_threads 2
399 config_trigger ${FUNCNAME[0]}
400 config_expect_result ${FUNCNAME[0]} SUCCESS
401}
402
403kmod_test_0005()
404{
405 kmod_defaults_driver
406 config_trigger ${FUNCNAME[0]}
407 config_expect_result ${FUNCNAME[0]} SUCCESS
408}
409
410kmod_test_0006()
411{
412 kmod_defaults_fs
413 config_trigger ${FUNCNAME[0]}
414 config_expect_result ${FUNCNAME[0]} SUCCESS
415}
416
417kmod_test_0007()
418{
419 kmod_test_0005
420 kmod_test_0006
421}
422
423kmod_test_0008()
424{
425 kmod_defaults_driver
426 MODPROBE_LIMIT=$(config_get_modprobe_limit)
427 let EXTRA=$MODPROBE_LIMIT/6
428 config_num_thread_limit_extra $EXTRA
429 config_trigger ${FUNCNAME[0]}
430 config_expect_result ${FUNCNAME[0]} SUCCESS
431}
432
433kmod_test_0009()
434{
435 kmod_defaults_fs
436 MODPROBE_LIMIT=$(config_get_modprobe_limit)
437 let EXTRA=$MODPROBE_LIMIT/4
438 config_num_thread_limit_extra $EXTRA
439 config_trigger ${FUNCNAME[0]}
440 config_expect_result ${FUNCNAME[0]} SUCCESS
441}
442
443list_tests()
444{
445 echo "Test ID list:"
446 echo
447 echo "TEST_ID x NUM_TEST"
448 echo "TEST_ID: Test ID"
449 echo "NUM_TESTS: Number of recommended times to run the test"
450 echo
451 echo "0001 x $(get_test_count 0001) - Simple test - 1 thread for empty string"
452 echo "0002 x $(get_test_count 0002) - Simple test - 1 thread for modules/filesystems that do not exist"
453 echo "0003 x $(get_test_count 0003) - Simple test - 1 thread for get_fs_type() only"
454 echo "0004 x $(get_test_count 0004) - Simple test - 2 threads for get_fs_type() only"
455 echo "0005 x $(get_test_count 0005) - multithreaded tests with default setup - request_module() only"
456 echo "0006 x $(get_test_count 0006) - multithreaded tests with default setup - get_fs_type() only"
457 echo "0007 x $(get_test_count 0007) - multithreaded tests with default setup test request_module() and get_fs_type()"
458 echo "0008 x $(get_test_count 0008) - multithreaded - push kmod_concurrent over max_modprobes for request_module()"
459 echo "0009 x $(get_test_count 0009) - multithreaded - push kmod_concurrent over max_modprobes for get_fs_type()"
460}
461
462usage()
463{
464 NUM_TESTS=$(grep -o ' ' <<<"$ALL_TESTS" | grep -c .)
465 let NUM_TESTS=$NUM_TESTS+1
466 MAX_TEST=$(printf "%04d\n" $NUM_TESTS)
467 echo "Usage: $0 [ -t <4-number-digit> ] | [ -w <4-number-digit> ] |"
468 echo " [ -s <4-number-digit> ] | [ -c <4-number-digit> <test- count>"
469 echo " [ all ] [ -h | --help ] [ -l ]"
470 echo ""
471 echo "Valid tests: 0001-$MAX_TEST"
472 echo ""
473 echo " all Runs all tests (default)"
474 echo " -t Run test ID the number amount of times is recommended"
475 echo " -w Watch test ID run until it runs into an error"
476 echo " -c Run test ID once"
477 echo " -s Run test ID x test-count number of times"
478 echo " -l List all test ID list"
479 echo " -h|--help Help"
480 echo
481 echo "If an error every occurs execution will immediately terminate."
482 echo "If you are adding a new test try using -w <test-ID> first to"
483 echo "make sure the test passes a series of tests."
484 echo
485 echo Example uses:
486 echo
487 echo "${TEST_NAME}.sh -- executes all tests"
488 echo "${TEST_NAME}.sh -t 0008 -- Executes test ID 0008 number of times is recomended"
489 echo "${TEST_NAME}.sh -w 0008 -- Watch test ID 0008 run until an error occurs"
490 echo "${TEST_NAME}.sh -s 0008 -- Run test ID 0008 once"
491 echo "${TEST_NAME}.sh -c 0008 3 -- Run test ID 0008 three times"
492 echo
493 list_tests
494 exit 1
495}
496
497function test_num()
498{
499 re='^[0-9]+$'
500 if ! [[ $1 =~ $re ]]; then
501 usage
502 fi
503}
504
505function get_test_count()
506{
507 test_num $1
508 TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$1'}')
509 LAST_TWO=${TEST_DATA#*:*}
510 echo ${LAST_TWO%:*}
511}
512
513function get_test_enabled()
514{
515 test_num $1
516 TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$1'}')
517 echo ${TEST_DATA#*:*:}
518}
519
520function run_all_tests()
521{
522 for i in $ALL_TESTS ; do
523 TEST_ID=${i%:*:*}
524 ENABLED=$(get_test_enabled $TEST_ID)
525 TEST_COUNT=$(get_test_count $TEST_ID)
526 if [[ $ENABLED -eq "1" ]]; then
527 test_case $TEST_ID $TEST_COUNT
528 fi
529 done
530}
531
532function watch_log()
533{
534 if [ $# -ne 3 ]; then
535 clear
536 fi
537 date
538 echo "Running test: $2 - run #$1"
539}
540
541function watch_case()
542{
543 i=0
544 while [ 1 ]; do
545
546 if [ $# -eq 1 ]; then
547 test_num $1
548 watch_log $i ${TEST_NAME}_test_$1
549 ${TEST_NAME}_test_$1
550 else
551 watch_log $i all
552 run_all_tests
553 fi
554 let i=$i+1
555 done
556}
557
558function test_case()
559{
560 NUM_TESTS=$DEFAULT_NUM_TESTS
561 if [ $# -eq 2 ]; then
562 NUM_TESTS=$2
563 fi
564
565 i=0
566 while [ $i -lt $NUM_TESTS ]; do
567 test_num $1
568 watch_log $i ${TEST_NAME}_test_$1 noclear
569 RUN_TEST=${TEST_NAME}_test_$1
570 $RUN_TEST
571 let i=$i+1
572 done
573}
574
575function parse_args()
576{
577 if [ $# -eq 0 ]; then
578 run_all_tests
579 else
580 if [[ "$1" = "all" ]]; then
581 run_all_tests
582 elif [[ "$1" = "-w" ]]; then
583 shift
584 watch_case $@
585 elif [[ "$1" = "-t" ]]; then
586 shift
587 test_num $1
588 test_case $1 $(get_test_count $1)
589 elif [[ "$1" = "-c" ]]; then
590 shift
591 test_num $1
592 test_num $2
593 test_case $1 $2
594 elif [[ "$1" = "-s" ]]; then
595 shift
596 test_case $1 1
597 elif [[ "$1" = "-l" ]]; then
598 list_tests
599 elif [[ "$1" = "-h" || "$1" = "--help" ]]; then
600 usage
601 else
602 usage
603 fi
604 fi
605}
606
607test_reqs
608allow_user_defaults
609load_req_mod
610
611trap "test_finish" EXIT
612
613parse_args $@
614
615exit 0