Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kmod: add test driver to stress test the module loader

This adds a new stress test driver for kmod: the kernel module loader.
The new stress test driver, test_kmod, is only enabled as a module right
now. It should be possible to load this as built-in and load tests
early (refer to the force_init_test module parameter), however since a
lot of test can get a system out of memory fast we leave this disabled
for now.

Using a system with 1024 MiB of RAM can *easily* get your kernel OOM
fast with this test driver.

The test_kmod driver exposes API knobs for us to fine tune simple
request_module() and get_fs_type() calls. Since these API calls only
allow each one parameter a test driver for these is rather simple.
Other factors that can help out test driver though are the number of
calls we issue and knowing current limitations of each. This exposes
configuration as much as possible through userspace to be able to build
tests directly from userspace.

Since it allows multiple misc devices its will eventually (once we add a
knob to let us create new devices at will) also be possible to perform
more tests in parallel, provided you have enough memory.

We only enable tests we know work as of right now.

Demo screenshots:

# tools/testing/selftests/kmod/kmod.sh
kmod_test_0001_driver: OK! - loading kmod test
kmod_test_0001_driver: OK! - Return value: 256 (MODULE_NOT_FOUND), expected MODULE_NOT_FOUND
kmod_test_0001_fs: OK! - loading kmod test
kmod_test_0001_fs: OK! - Return value: -22 (-EINVAL), expected -EINVAL
kmod_test_0002_driver: OK! - loading kmod test
kmod_test_0002_driver: OK! - Return value: 256 (MODULE_NOT_FOUND), expected MODULE_NOT_FOUND
kmod_test_0002_fs: OK! - loading kmod test
kmod_test_0002_fs: OK! - Return value: -22 (-EINVAL), expected -EINVAL
kmod_test_0003: OK! - loading kmod test
kmod_test_0003: OK! - Return value: 0 (SUCCESS), expected SUCCESS
kmod_test_0004: OK! - loading kmod test
kmod_test_0004: OK! - Return value: 0 (SUCCESS), expected SUCCESS
kmod_test_0005: OK! - loading kmod test
kmod_test_0005: OK! - Return value: 0 (SUCCESS), expected SUCCESS
kmod_test_0006: OK! - loading kmod test
kmod_test_0006: OK! - Return value: 0 (SUCCESS), expected SUCCESS
kmod_test_0005: OK! - loading kmod test
kmod_test_0005: OK! - Return value: 0 (SUCCESS), expected SUCCESS
kmod_test_0006: OK! - loading kmod test
kmod_test_0006: OK! - Return value: 0 (SUCCESS), expected SUCCESS
XXX: add test restult for 0007
Test completed

You can also request for specific tests:

# tools/testing/selftests/kmod/kmod.sh -t 0001
kmod_test_0001_driver: OK! - loading kmod test
kmod_test_0001_driver: OK! - Return value: 256 (MODULE_NOT_FOUND), expected MODULE_NOT_FOUND
kmod_test_0001_fs: OK! - loading kmod test
kmod_test_0001_fs: OK! - Return value: -22 (-EINVAL), expected -EINVAL
Test completed

Lastly, the current available number of tests:

# tools/testing/selftests/kmod/kmod.sh --help
Usage: tools/testing/selftests/kmod/kmod.sh [ -t <4-number-digit> ]
Valid tests: 0001-0009

0001 - Simple test - 1 thread for empty string
0002 - Simple test - 1 thread for modules/filesystems that do not exist
0003 - Simple test - 1 thread for get_fs_type() only
0004 - Simple test - 2 threads for get_fs_type() only
0005 - multithreaded tests with default setup - request_module() only
0006 - multithreaded tests with default setup - get_fs_type() only
0007 - multithreaded tests with default setup test request_module() and get_fs_type()
0008 - multithreaded - push kmod_concurrent over max_modprobes for request_module()
0009 - multithreaded - push kmod_concurrent over max_modprobes for get_fs_type()

The following test cases currently fail, as such they are not currently
enabled by default:

# tools/testing/selftests/kmod/kmod.sh -t 0008
# tools/testing/selftests/kmod/kmod.sh -t 0009

To be sure to run them as intended please unload both of the modules:

o test_module
o xfs

And ensure they are not loaded on your system prior to testing them. If
you use these paritions for your rootfs you can change the default test
driver used for get_fs_type() by exporting it into your environment. For
example of other test defaults you can override refer to kmod.sh
allow_user_defaults().

Behind the scenes this is how we fine tune at a test case prior to
hitting a trigger to run it:

cat /sys/devices/virtual/misc/test_kmod0/config
echo -n "2" > /sys/devices/virtual/misc/test_kmod0/config_test_case
echo -n "ext4" > /sys/devices/virtual/misc/test_kmod0/config_test_fs
echo -n "80" > /sys/devices/virtual/misc/test_kmod0/config_num_threads
cat /sys/devices/virtual/misc/test_kmod0/config
echo -n "1" > /sys/devices/virtual/misc/test_kmod0/config_num_threads

Finally to trigger:

echo -n "1" > /sys/devices/virtual/misc/test_kmod0/trigger_config

The kmod.sh script uses the above constructs to build different test cases.

A bit of interpretation of the current failures follows, first two
premises:

a) When request_module() is used userspace figures out an optimized
version of module order for us. Once it finds the modules it needs, as
per depmod symbol dep map, it will finit_module() the respective
modules which are needed for the original request_module() request.

b) We have an optimization in place whereby if a kernel uses
request_module() on a module already loaded we never bother userspace
as the module already is loaded. This is all handled by kernel/kmod.c.

A few things to consider to help identify root causes of issues:

0) kmod 19 has a broken heuristic for modules being assumed to be
built-in to your kernel and will return 0 even though request_module()
failed. Upgrade to a newer version of kmod.

1) A get_fs_type() call for "xfs" will request_module() for "fs-xfs",
not for "xfs". The optimization in kernel described in b) fails to
catch if we have a lot of consecutive get_fs_type() calls. The reason
is the optimization in place does not look for aliases. This means two
consecutive get_fs_type() calls will bump kmod_concurrent, whereas
request_module() will not.

This one explanation why test case 0009 fails at least once for
get_fs_type().

2) If a module fails to load --- for whatever reason (kmod_concurrent
limit reached, file not yet present due to rootfs switch, out of
memory) we have a period of time during which module request for the
same name either with request_module() or get_fs_type() will *also*
fail to load even if the file for the module is ready.

This explains why *multiple* NULLs are possible on test 0009.

3) finit_module() consumes quite a bit of memory.

4) Filesystems typically also have more dependent modules than other
modules, its important to note though that even though a get_fs_type()
call does not incur additional kmod_concurrent bumps, since userspace
loads dependencies it finds it needs via finit_module_fd(), it *will*
take much more memory to load a module with a lot of dependencies.

Because of 3) and 4) we will easily run into out of memory failures with
certain tests. For instance test 0006 fails on qemu with 1024 MiB of RAM.
It panics a box after reaping all userspace processes and still not
having enough memory to reap.

[arnd@arndb.de: add dependencies for test module]
Link: http://lkml.kernel.org/r/20170630154834.3689272-1-arnd@arndb.de
Link: http://lkml.kernel.org/r/20170628223155.26472-3-mcgrof@kernel.org
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
Cc: Jessica Yu <jeyu@redhat.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Michal Marek <mmarek@suse.com>
Cc: Petr Mladek <pmladek@suse.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Luis R. Rodriguez and committed by
Linus Torvalds
d9c6a72d 062b8740

+1929
+2
MAINTAINERS
··· 7560 7560 S: Maintained 7561 7561 F: kernel/kmod.c 7562 7562 F: include/linux/kmod.h 7563 + F: lib/test_kmod.c 7564 + F: tools/testing/selftests/kmod/ 7563 7565 7564 7566 KPROBES 7565 7567 M: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com>
+27
lib/Kconfig.debug
··· 1847 1847 1848 1848 If unsure, say N. 1849 1849 1850 + config 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 + 1850 1877 source "samples/Kconfig" 1851 1878 1852 1879 source "lib/Kconfig.kgdb"
+1
lib/Makefile
··· 61 61 obj-$(CONFIG_TEST_BITMAP) += test_bitmap.o 62 62 obj-$(CONFIG_TEST_UUID) += test_uuid.o 63 63 obj-$(CONFIG_TEST_PARMAN) += test_parman.o 64 + obj-$(CONFIG_TEST_KMOD) += test_kmod.o 64 65 65 66 ifeq ($(CONFIG_DEBUG_KOBJECT),y) 66 67 CFLAGS_kobject.o += -DDEBUG
+1246
lib/test_kmod.c
··· 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 + 45 + static bool force_init_test = false; 46 + module_param(force_init_test, bool_enable_only, 0644); 47 + MODULE_PARM_DESC(force_init_test, 48 + "Force kicking a test immediately after driver loads"); 49 + 50 + /* 51 + * For device allocation / registration 52 + */ 53 + static DEFINE_MUTEX(reg_dev_mutex); 54 + static 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 + */ 60 + static 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 + */ 71 + enum 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 + 80 + struct 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 + 88 + struct 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 + */ 104 + struct 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 + */ 129 + struct 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 + 147 + static 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 + 159 + static struct miscdevice *dev_to_misc_dev(struct device *dev) 160 + { 161 + return dev_get_drvdata(dev); 162 + } 163 + 164 + static 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 + 169 + static 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 */ 179 + static 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 + 195 + static 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 + 217 + static 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 + 249 + static 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 + */ 291 + static 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 + 319 + static 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 + 343 + err_out: 344 + info->ret_sync = fail_ret; 345 + mutex_unlock(&test_dev->thread_mutex); 346 + 347 + return fail_ret; 348 + } 349 + 350 + static 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 + */ 388 + static 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 + 425 + static 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 + 442 + static 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 + 459 + static 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 + } 502 + static DEVICE_ATTR_RO(config); 503 + 504 + /* 505 + * This ensures we don't allow kicking threads through if our configuration 506 + * is faulty. 507 + */ 508 + static 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 + 527 + static 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 + 556 + out: 557 + mutex_unlock(&test_dev->config_mutex); 558 + mutex_unlock(&test_dev->trigger_mutex); 559 + 560 + return ret; 561 + } 562 + 563 + static ssize_t 564 + trigger_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; 594 + out: 595 + return ret; 596 + } 597 + static 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 + */ 604 + static 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 + 612 + static 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 + 620 + static 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 + 626 + static 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 + 638 + static 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 + 652 + static 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 + */ 674 + static 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 + 687 + static 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 + } 697 + static DEVICE_ATTR(config_test_driver, 0644, config_test_driver_show, 698 + config_test_driver_store); 699 + 700 + static 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 + 719 + static 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 + } 729 + static DEVICE_ATTR(config_test_fs, 0644, config_test_fs_show, 730 + config_test_fs_store); 731 + 732 + static 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 + 773 + static void free_test_dev_info(struct kmod_test_device *test_dev) 774 + { 775 + vfree(test_dev->info); 776 + test_dev->info = NULL; 777 + } 778 + 779 + static 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 799 + static unsigned int kmod_init_test_thread_limit(void) 800 + { 801 + return get_kmod_umh_limit(); 802 + } 803 + #else 804 + static unsigned int kmod_init_test_thread_limit(void) 805 + { 806 + return TEST_START_NUM_THREADS; 807 + } 808 + #endif 809 + 810 + static 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 + 839 + err_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 + 848 + static 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 + 869 + out: 870 + mutex_unlock(&test_dev->config_mutex); 871 + mutex_unlock(&test_dev->trigger_mutex); 872 + 873 + return ret; 874 + } 875 + static DEVICE_ATTR_WO(reset); 876 + 877 + static 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 + 914 + static 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 + 938 + static 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 + 959 + static 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 + 972 + static 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 + 985 + static 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 + 996 + static 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 + 1008 + static 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 + } 1017 + static DEVICE_ATTR(config_num_threads, 0644, config_num_threads_show, 1018 + config_num_threads_store); 1019 + 1020 + static 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 + 1033 + static 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 + } 1042 + static DEVICE_ATTR(config_test_case, 0644, config_test_case_show, 1043 + config_test_case_store); 1044 + 1045 + static 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 + } 1054 + static DEVICE_ATTR(test_result, 0644, test_result_show, test_result_store); 1055 + 1056 + #define TEST_KMOD_DEV_ATTR(name) &dev_attr_##name.attr 1057 + 1058 + static 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 + 1072 + ATTRIBUTE_GROUPS(test_dev); 1073 + 1074 + static 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 + 1085 + static 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 + 1122 + err_out_free_config: 1123 + free_test_dev_info(test_dev); 1124 + kmod_config_free(test_dev); 1125 + err_out_free: 1126 + vfree(test_dev); 1127 + test_dev = NULL; 1128 + err_out: 1129 + return NULL; 1130 + } 1131 + 1132 + static 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 + 1144 + static 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 + 1174 + out: 1175 + mutex_unlock(&reg_dev_mutex); 1176 + 1177 + return test_dev; 1178 + 1179 + } 1180 + 1181 + static 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 + } 1212 + late_initcall(test_kmod_init); 1213 + 1214 + static 1215 + void 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 + 1232 + static 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 + } 1243 + module_exit(test_kmod_exit); 1244 + 1245 + MODULE_AUTHOR("Luis R. Rodriguez <mcgrof@kernel.org>"); 1246 + MODULE_LICENSE("GPL");
+11
tools/testing/selftests/kmod/Makefile
··· 1 + # Makefile for kmod loading selftests 2 + 3 + # No binaries, but make sure arg-less "make" doesn't trigger "run_tests" 4 + all: 5 + 6 + TEST_PROGS := kmod.sh 7 + 8 + include ../lib.mk 9 + 10 + # Nothing to clean up. 11 + clean:
+7
tools/testing/selftests/kmod/config
··· 1 + CONFIG_TEST_KMOD=m 2 + CONFIG_TEST_LKM=m 3 + CONFIG_XFS_FS=m 4 + 5 + # For the module parameter force_init_test is used 6 + CONFIG_TUN=m 7 + CONFIG_BTRFS_FS=m
+635
tools/testing/selftests/kmod/kmod.sh
··· 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 + 39 + set -e 40 + 41 + TEST_NAME="kmod" 42 + TEST_DRIVER="test_${TEST_NAME}" 43 + TEST_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. 55 + ALL_TESTS="0001:3:1" 56 + ALL_TESTS="$ALL_TESTS 0002:3:1" 57 + ALL_TESTS="$ALL_TESTS 0003:1:1" 58 + ALL_TESTS="$ALL_TESTS 0004:1:1" 59 + ALL_TESTS="$ALL_TESTS 0005:10:1" 60 + ALL_TESTS="$ALL_TESTS 0006:10:1" 61 + ALL_TESTS="$ALL_TESTS 0007:5:1" 62 + 63 + # Disabled tests: 64 + # 65 + # 0008 x 150 - multithreaded - push kmod_concurrent over max_modprobes for request_module()" 66 + # Current best-effort failure interpretation: 67 + # Enough module requests get loaded in place fast enough to reach over the 68 + # max_modprobes limit and trigger a failure -- before we're even able to 69 + # start processing pending requests. 70 + ALL_TESTS="$ALL_TESTS 0008:150:0" 71 + 72 + # 0009 x 150 - multithreaded - push kmod_concurrent over max_modprobes for get_fs_type()" 73 + # Current best-effort failure interpretation: 74 + # 75 + # get_fs_type() requests modules using aliases as such the optimization in 76 + # place today to look for already loaded modules will not take effect and 77 + # we end up requesting a new module to load, this bumps the kmod_concurrent, 78 + # and in certain circumstances can lead to pushing the kmod_concurrent over 79 + # the max_modprobe limit. 80 + # 81 + # This test fails much easier than test 0008 since the alias optimizations 82 + # are not in place. 83 + ALL_TESTS="$ALL_TESTS 0009:150:0" 84 + 85 + test_modprobe() 86 + { 87 + if [ ! -d $DIR ]; then 88 + echo "$0: $DIR not present" >&2 89 + echo "You must have the following enabled in your kernel:" >&2 90 + cat $TEST_DIR/config >&2 91 + exit 1 92 + fi 93 + } 94 + 95 + function allow_user_defaults() 96 + { 97 + if [ -z $DEFAULT_KMOD_DRIVER ]; then 98 + DEFAULT_KMOD_DRIVER="test_module" 99 + fi 100 + 101 + if [ -z $DEFAULT_KMOD_FS ]; then 102 + DEFAULT_KMOD_FS="xfs" 103 + fi 104 + 105 + if [ -z $PROC_DIR ]; then 106 + PROC_DIR="/proc/sys/kernel/" 107 + fi 108 + 109 + if [ -z $MODPROBE_LIMIT ]; then 110 + MODPROBE_LIMIT=50 111 + fi 112 + 113 + if [ -z $DIR ]; then 114 + DIR="/sys/devices/virtual/misc/${TEST_DRIVER}0/" 115 + fi 116 + 117 + if [ -z $DEFAULT_NUM_TESTS ]; then 118 + DEFAULT_NUM_TESTS=150 119 + fi 120 + 121 + MODPROBE_LIMIT_FILE="${PROC_DIR}/kmod-limit" 122 + } 123 + 124 + test_reqs() 125 + { 126 + if ! which modprobe 2> /dev/null > /dev/null; then 127 + echo "$0: You need modprobe installed" >&2 128 + exit 1 129 + fi 130 + 131 + if ! which kmod 2> /dev/null > /dev/null; then 132 + echo "$0: You need kmod installed" >&2 133 + exit 1 134 + fi 135 + 136 + # kmod 19 has a bad bug where it returns 0 when modprobe 137 + # gets called *even* if the module was not loaded due to 138 + # some bad heuristics. For details see: 139 + # 140 + # A work around is possible in-kernel but its rather 141 + # complex. 142 + KMOD_VERSION=$(kmod --version | awk '{print $3}') 143 + if [[ $KMOD_VERSION -le 19 ]]; then 144 + echo "$0: You need at least kmod 20" >&2 145 + echo "kmod <= 19 is buggy, for details see:" >&2 146 + echo "http://git.kernel.org/cgit/utils/kernel/kmod/kmod.git/commit/libkmod/libkmod-module.c?id=fd44a98ae2eb5eb32161088954ab21e58e19dfc4" >&2 147 + exit 1 148 + fi 149 + 150 + uid=$(id -u) 151 + if [ $uid -ne 0 ]; then 152 + echo $msg must be run as root >&2 153 + exit 0 154 + fi 155 + } 156 + 157 + function load_req_mod() 158 + { 159 + trap "test_modprobe" EXIT 160 + 161 + if [ ! -d $DIR ]; then 162 + # Alanis: "Oh isn't it ironic?" 163 + modprobe $TEST_DRIVER 164 + fi 165 + } 166 + 167 + test_finish() 168 + { 169 + echo "Test completed" 170 + } 171 + 172 + errno_name_to_val() 173 + { 174 + case "$1" in 175 + # kmod calls modprobe and upon of a module not found 176 + # modprobe returns just 1... However in the kernel we 177 + # *sometimes* see 256... 178 + MODULE_NOT_FOUND) 179 + echo 256;; 180 + SUCCESS) 181 + echo 0;; 182 + -EPERM) 183 + echo -1;; 184 + -ENOENT) 185 + echo -2;; 186 + -EINVAL) 187 + echo -22;; 188 + -ERR_ANY) 189 + echo -123456;; 190 + *) 191 + echo invalid;; 192 + esac 193 + } 194 + 195 + errno_val_to_name() 196 + case "$1" in 197 + 256) 198 + echo MODULE_NOT_FOUND;; 199 + 0) 200 + echo SUCCESS;; 201 + -1) 202 + echo -EPERM;; 203 + -2) 204 + echo -ENOENT;; 205 + -22) 206 + echo -EINVAL;; 207 + -123456) 208 + echo -ERR_ANY;; 209 + *) 210 + echo invalid;; 211 + esac 212 + 213 + config_set_test_case_driver() 214 + { 215 + if ! echo -n 1 >$DIR/config_test_case; then 216 + echo "$0: Unable to set to test case to driver" >&2 217 + exit 1 218 + fi 219 + } 220 + 221 + config_set_test_case_fs() 222 + { 223 + if ! echo -n 2 >$DIR/config_test_case; then 224 + echo "$0: Unable to set to test case to fs" >&2 225 + exit 1 226 + fi 227 + } 228 + 229 + config_num_threads() 230 + { 231 + if ! echo -n $1 >$DIR/config_num_threads; then 232 + echo "$0: Unable to set to number of threads" >&2 233 + exit 1 234 + fi 235 + } 236 + 237 + config_get_modprobe_limit() 238 + { 239 + if [[ -f ${MODPROBE_LIMIT_FILE} ]] ; then 240 + MODPROBE_LIMIT=$(cat $MODPROBE_LIMIT_FILE) 241 + fi 242 + echo $MODPROBE_LIMIT 243 + } 244 + 245 + config_num_thread_limit_extra() 246 + { 247 + MODPROBE_LIMIT=$(config_get_modprobe_limit) 248 + let EXTRA_LIMIT=$MODPROBE_LIMIT+$1 249 + config_num_threads $EXTRA_LIMIT 250 + } 251 + 252 + # For special characters use printf directly, 253 + # refer to kmod_test_0001 254 + config_set_driver() 255 + { 256 + if ! echo -n $1 >$DIR/config_test_driver; then 257 + echo "$0: Unable to set driver" >&2 258 + exit 1 259 + fi 260 + } 261 + 262 + config_set_fs() 263 + { 264 + if ! echo -n $1 >$DIR/config_test_fs; then 265 + echo "$0: Unable to set driver" >&2 266 + exit 1 267 + fi 268 + } 269 + 270 + config_get_driver() 271 + { 272 + cat $DIR/config_test_driver 273 + } 274 + 275 + config_get_test_result() 276 + { 277 + cat $DIR/test_result 278 + } 279 + 280 + config_reset() 281 + { 282 + if ! echo -n "1" >"$DIR"/reset; then 283 + echo "$0: reset shuld have worked" >&2 284 + exit 1 285 + fi 286 + } 287 + 288 + config_show_config() 289 + { 290 + echo "----------------------------------------------------" 291 + cat "$DIR"/config 292 + echo "----------------------------------------------------" 293 + } 294 + 295 + config_trigger() 296 + { 297 + if ! echo -n "1" >"$DIR"/trigger_config 2>/dev/null; then 298 + echo "$1: FAIL - loading should have worked" 299 + config_show_config 300 + exit 1 301 + fi 302 + echo "$1: OK! - loading kmod test" 303 + } 304 + 305 + config_trigger_want_fail() 306 + { 307 + if echo "1" > $DIR/trigger_config 2>/dev/null; then 308 + echo "$1: FAIL - test case was expected to fail" 309 + config_show_config 310 + exit 1 311 + fi 312 + echo "$1: OK! - kmod test case failed as expected" 313 + } 314 + 315 + config_expect_result() 316 + { 317 + RC=$(config_get_test_result) 318 + RC_NAME=$(errno_val_to_name $RC) 319 + 320 + ERRNO_NAME=$2 321 + ERRNO=$(errno_name_to_val $ERRNO_NAME) 322 + 323 + if [[ $ERRNO_NAME = "-ERR_ANY" ]]; then 324 + if [[ $RC -ge 0 ]]; then 325 + echo "$1: FAIL, test expects $ERRNO_NAME - got $RC_NAME ($RC)" >&2 326 + config_show_config 327 + exit 1 328 + fi 329 + elif [[ $RC != $ERRNO ]]; then 330 + echo "$1: FAIL, test expects $ERRNO_NAME ($ERRNO) - got $RC_NAME ($RC)" >&2 331 + config_show_config 332 + exit 1 333 + fi 334 + echo "$1: OK! - Return value: $RC ($RC_NAME), expected $ERRNO_NAME" 335 + } 336 + 337 + kmod_defaults_driver() 338 + { 339 + config_reset 340 + modprobe -r $DEFAULT_KMOD_DRIVER 341 + config_set_driver $DEFAULT_KMOD_DRIVER 342 + } 343 + 344 + kmod_defaults_fs() 345 + { 346 + config_reset 347 + modprobe -r $DEFAULT_KMOD_FS 348 + config_set_fs $DEFAULT_KMOD_FS 349 + config_set_test_case_fs 350 + } 351 + 352 + kmod_test_0001_driver() 353 + { 354 + NAME='\000' 355 + 356 + kmod_defaults_driver 357 + config_num_threads 1 358 + printf '\000' >"$DIR"/config_test_driver 359 + config_trigger ${FUNCNAME[0]} 360 + config_expect_result ${FUNCNAME[0]} MODULE_NOT_FOUND 361 + } 362 + 363 + kmod_test_0001_fs() 364 + { 365 + NAME='\000' 366 + 367 + kmod_defaults_fs 368 + config_num_threads 1 369 + printf '\000' >"$DIR"/config_test_fs 370 + config_trigger ${FUNCNAME[0]} 371 + config_expect_result ${FUNCNAME[0]} -EINVAL 372 + } 373 + 374 + kmod_test_0001() 375 + { 376 + kmod_test_0001_driver 377 + kmod_test_0001_fs 378 + } 379 + 380 + kmod_test_0002_driver() 381 + { 382 + NAME="nope-$DEFAULT_KMOD_DRIVER" 383 + 384 + kmod_defaults_driver 385 + config_set_driver $NAME 386 + config_num_threads 1 387 + config_trigger ${FUNCNAME[0]} 388 + config_expect_result ${FUNCNAME[0]} MODULE_NOT_FOUND 389 + } 390 + 391 + kmod_test_0002_fs() 392 + { 393 + NAME="nope-$DEFAULT_KMOD_FS" 394 + 395 + kmod_defaults_fs 396 + config_set_fs $NAME 397 + config_trigger ${FUNCNAME[0]} 398 + config_expect_result ${FUNCNAME[0]} -EINVAL 399 + } 400 + 401 + kmod_test_0002() 402 + { 403 + kmod_test_0002_driver 404 + kmod_test_0002_fs 405 + } 406 + 407 + kmod_test_0003() 408 + { 409 + kmod_defaults_fs 410 + config_num_threads 1 411 + config_trigger ${FUNCNAME[0]} 412 + config_expect_result ${FUNCNAME[0]} SUCCESS 413 + } 414 + 415 + kmod_test_0004() 416 + { 417 + kmod_defaults_fs 418 + config_num_threads 2 419 + config_trigger ${FUNCNAME[0]} 420 + config_expect_result ${FUNCNAME[0]} SUCCESS 421 + } 422 + 423 + kmod_test_0005() 424 + { 425 + kmod_defaults_driver 426 + config_trigger ${FUNCNAME[0]} 427 + config_expect_result ${FUNCNAME[0]} SUCCESS 428 + } 429 + 430 + kmod_test_0006() 431 + { 432 + kmod_defaults_fs 433 + config_trigger ${FUNCNAME[0]} 434 + config_expect_result ${FUNCNAME[0]} SUCCESS 435 + } 436 + 437 + kmod_test_0007() 438 + { 439 + kmod_test_0005 440 + kmod_test_0006 441 + } 442 + 443 + kmod_test_0008() 444 + { 445 + kmod_defaults_driver 446 + MODPROBE_LIMIT=$(config_get_modprobe_limit) 447 + let EXTRA=$MODPROBE_LIMIT/6 448 + config_num_thread_limit_extra $EXTRA 449 + config_trigger ${FUNCNAME[0]} 450 + config_expect_result ${FUNCNAME[0]} SUCCESS 451 + } 452 + 453 + kmod_test_0009() 454 + { 455 + kmod_defaults_fs 456 + MODPROBE_LIMIT=$(config_get_modprobe_limit) 457 + let EXTRA=$MODPROBE_LIMIT/4 458 + config_num_thread_limit_extra $EXTRA 459 + config_trigger ${FUNCNAME[0]} 460 + config_expect_result ${FUNCNAME[0]} SUCCESS 461 + } 462 + 463 + list_tests() 464 + { 465 + echo "Test ID list:" 466 + echo 467 + echo "TEST_ID x NUM_TEST" 468 + echo "TEST_ID: Test ID" 469 + echo "NUM_TESTS: Number of recommended times to run the test" 470 + echo 471 + echo "0001 x $(get_test_count 0001) - Simple test - 1 thread for empty string" 472 + echo "0002 x $(get_test_count 0002) - Simple test - 1 thread for modules/filesystems that do not exist" 473 + echo "0003 x $(get_test_count 0003) - Simple test - 1 thread for get_fs_type() only" 474 + echo "0004 x $(get_test_count 0004) - Simple test - 2 threads for get_fs_type() only" 475 + echo "0005 x $(get_test_count 0005) - multithreaded tests with default setup - request_module() only" 476 + echo "0006 x $(get_test_count 0006) - multithreaded tests with default setup - get_fs_type() only" 477 + echo "0007 x $(get_test_count 0007) - multithreaded tests with default setup test request_module() and get_fs_type()" 478 + echo "0008 x $(get_test_count 0008) - multithreaded - push kmod_concurrent over max_modprobes for request_module()" 479 + echo "0009 x $(get_test_count 0009) - multithreaded - push kmod_concurrent over max_modprobes for get_fs_type()" 480 + } 481 + 482 + usage() 483 + { 484 + NUM_TESTS=$(grep -o ' ' <<<"$ALL_TESTS" | grep -c .) 485 + let NUM_TESTS=$NUM_TESTS+1 486 + MAX_TEST=$(printf "%04d\n" $NUM_TESTS) 487 + echo "Usage: $0 [ -t <4-number-digit> ] | [ -w <4-number-digit> ] |" 488 + echo " [ -s <4-number-digit> ] | [ -c <4-number-digit> <test- count>" 489 + echo " [ all ] [ -h | --help ] [ -l ]" 490 + echo "" 491 + echo "Valid tests: 0001-$MAX_TEST" 492 + echo "" 493 + echo " all Runs all tests (default)" 494 + echo " -t Run test ID the number amount of times is recommended" 495 + echo " -w Watch test ID run until it runs into an error" 496 + echo " -c Run test ID once" 497 + echo " -s Run test ID x test-count number of times" 498 + echo " -l List all test ID list" 499 + echo " -h|--help Help" 500 + echo 501 + echo "If an error every occurs execution will immediately terminate." 502 + echo "If you are adding a new test try using -w <test-ID> first to" 503 + echo "make sure the test passes a series of tests." 504 + echo 505 + echo Example uses: 506 + echo 507 + echo "${TEST_NAME}.sh -- executes all tests" 508 + echo "${TEST_NAME}.sh -t 0008 -- Executes test ID 0008 number of times is recomended" 509 + echo "${TEST_NAME}.sh -w 0008 -- Watch test ID 0008 run until an error occurs" 510 + echo "${TEST_NAME}.sh -s 0008 -- Run test ID 0008 once" 511 + echo "${TEST_NAME}.sh -c 0008 3 -- Run test ID 0008 three times" 512 + echo 513 + list_tests 514 + exit 1 515 + } 516 + 517 + function test_num() 518 + { 519 + re='^[0-9]+$' 520 + if ! [[ $1 =~ $re ]]; then 521 + usage 522 + fi 523 + } 524 + 525 + function get_test_count() 526 + { 527 + test_num $1 528 + TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$1'}') 529 + LAST_TWO=${TEST_DATA#*:*} 530 + echo ${LAST_TWO%:*} 531 + } 532 + 533 + function get_test_enabled() 534 + { 535 + test_num $1 536 + TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$1'}') 537 + echo ${TEST_DATA#*:*:} 538 + } 539 + 540 + function run_all_tests() 541 + { 542 + for i in $ALL_TESTS ; do 543 + TEST_ID=${i%:*:*} 544 + ENABLED=$(get_test_enabled $TEST_ID) 545 + TEST_COUNT=$(get_test_count $TEST_ID) 546 + if [[ $ENABLED -eq "1" ]]; then 547 + test_case $TEST_ID $TEST_COUNT 548 + fi 549 + done 550 + } 551 + 552 + function watch_log() 553 + { 554 + if [ $# -ne 3 ]; then 555 + clear 556 + fi 557 + date 558 + echo "Running test: $2 - run #$1" 559 + } 560 + 561 + function watch_case() 562 + { 563 + i=0 564 + while [ 1 ]; do 565 + 566 + if [ $# -eq 1 ]; then 567 + test_num $1 568 + watch_log $i ${TEST_NAME}_test_$1 569 + ${TEST_NAME}_test_$1 570 + else 571 + watch_log $i all 572 + run_all_tests 573 + fi 574 + let i=$i+1 575 + done 576 + } 577 + 578 + function test_case() 579 + { 580 + NUM_TESTS=$DEFAULT_NUM_TESTS 581 + if [ $# -eq 2 ]; then 582 + NUM_TESTS=$2 583 + fi 584 + 585 + i=0 586 + while [ $i -lt $NUM_TESTS ]; do 587 + test_num $1 588 + watch_log $i ${TEST_NAME}_test_$1 noclear 589 + RUN_TEST=${TEST_NAME}_test_$1 590 + $RUN_TEST 591 + let i=$i+1 592 + done 593 + } 594 + 595 + function parse_args() 596 + { 597 + if [ $# -eq 0 ]; then 598 + run_all_tests 599 + else 600 + if [[ "$1" = "all" ]]; then 601 + run_all_tests 602 + elif [[ "$1" = "-w" ]]; then 603 + shift 604 + watch_case $@ 605 + elif [[ "$1" = "-t" ]]; then 606 + shift 607 + test_num $1 608 + test_case $1 $(get_test_count $1) 609 + elif [[ "$1" = "-c" ]]; then 610 + shift 611 + test_num $1 612 + test_num $2 613 + test_case $1 $2 614 + elif [[ "$1" = "-s" ]]; then 615 + shift 616 + test_case $1 1 617 + elif [[ "$1" = "-l" ]]; then 618 + list_tests 619 + elif [[ "$1" = "-h" || "$1" = "--help" ]]; then 620 + usage 621 + else 622 + usage 623 + fi 624 + fi 625 + } 626 + 627 + test_reqs 628 + allow_user_defaults 629 + load_req_mod 630 + 631 + trap "test_finish" EXIT 632 + 633 + parse_args $@ 634 + 635 + exit 0