VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700    1) /*
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700    2)  * kmod stress test driver
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700    3)  *
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700    4)  * Copyright (C) 2017 Luis R. Rodriguez <mcgrof@kernel.org>
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700    5)  *
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700    6)  * This program is free software; you can redistribute it and/or modify it
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700    7)  * under the terms of the GNU General Public License as published by the Free
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700    8)  * Software Foundation; either version 2 of the License, or at your option any
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700    9)  * later version; or, when distributed separately from the Linux kernel or
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   10)  * when incorporated into other software packages, subject to the following
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   11)  * license:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   12)  *
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   13)  * This program is free software; you can redistribute it and/or modify it
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   14)  * under the terms of copyleft-next (version 0.3.1 or later) as published
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   15)  * at http://copyleft-next.org/.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   16)  */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   17) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   18) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   19) /*
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   20)  * This driver provides an interface to trigger and test the kernel's
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   21)  * module loader through a series of configurations and a few triggers.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   22)  * To test this driver use the following script as root:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   23)  *
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   24)  * tools/testing/selftests/kmod/kmod.sh --help
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   25)  */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   26) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   27) #include <linux/kernel.h>
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   28) #include <linux/module.h>
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   29) #include <linux/kmod.h>
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   30) #include <linux/printk.h>
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   31) #include <linux/kthread.h>
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   32) #include <linux/sched.h>
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   33) #include <linux/fs.h>
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   34) #include <linux/miscdevice.h>
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   35) #include <linux/vmalloc.h>
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   36) #include <linux/slab.h>
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   37) #include <linux/device.h>
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   38) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   39) #define TEST_START_NUM_THREADS	50
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   40) #define TEST_START_DRIVER	"test_module"
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   41) #define TEST_START_TEST_FS	"xfs"
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   42) #define TEST_START_TEST_CASE	TEST_KMOD_DRIVER
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   43) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   44) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   45) static bool force_init_test = false;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   46) module_param(force_init_test, bool_enable_only, 0644);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   47) MODULE_PARM_DESC(force_init_test,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   48) 		 "Force kicking a test immediately after driver loads");
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   49) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   50) /*
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   51)  * For device allocation / registration
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   52)  */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   53) static DEFINE_MUTEX(reg_dev_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   54) static LIST_HEAD(reg_test_devs);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   55) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   56) /*
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   57)  * num_test_devs actually represents the *next* ID of the next
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   58)  * device we will allow to create.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   59)  */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   60) static int num_test_devs;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   61) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   62) /**
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   63)  * enum kmod_test_case - linker table test case
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   64)  *
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   65)  * If you add a  test case, please be sure to review if you need to se
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   66)  * @need_mod_put for your tests case.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   67)  *
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   68)  * @TEST_KMOD_DRIVER: stress tests request_module()
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   69)  * @TEST_KMOD_FS_TYPE: stress tests get_fs_type()
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   70)  */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   71) enum kmod_test_case {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   72) 	__TEST_KMOD_INVALID = 0,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   73) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   74) 	TEST_KMOD_DRIVER,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   75) 	TEST_KMOD_FS_TYPE,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   76) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   77) 	__TEST_KMOD_MAX,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   78) };
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   79) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   80) struct test_config {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   81) 	char *test_driver;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   82) 	char *test_fs;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   83) 	unsigned int num_threads;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   84) 	enum kmod_test_case test_case;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   85) 	int test_result;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   86) };
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   87) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   88) struct kmod_test_device;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   89) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   90) /**
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   91)  * kmod_test_device_info - thread info
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   92)  *
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   93)  * @ret_sync: return value if request_module() is used, sync request for
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   94)  * 	@TEST_KMOD_DRIVER
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   95)  * @fs_sync: return value of get_fs_type() for @TEST_KMOD_FS_TYPE
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   96)  * @thread_idx: thread ID
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   97)  * @test_dev: test device test is being performed under
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   98)  * @need_mod_put: Some tests (get_fs_type() is one) requires putting the module
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700   99)  *	(module_put(fs_sync->owner)) when done, otherwise you will not be able
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  100)  *	to unload the respective modules and re-test. We use this to keep
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  101)  *	accounting of when we need this and to help out in case we need to
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  102)  *	error out and deal with module_put() on error.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  103)  */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  104) struct kmod_test_device_info {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  105) 	int ret_sync;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  106) 	struct file_system_type *fs_sync;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  107) 	struct task_struct *task_sync;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  108) 	unsigned int thread_idx;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  109) 	struct kmod_test_device *test_dev;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  110) 	bool need_mod_put;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  111) };
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  112) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  113) /**
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  114)  * kmod_test_device - test device to help test kmod
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  115)  *
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  116)  * @dev_idx: unique ID for test device
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  117)  * @config: configuration for the test
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  118)  * @misc_dev: we use a misc device under the hood
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  119)  * @dev: pointer to misc_dev's own struct device
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  120)  * @config_mutex: protects configuration of test
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  121)  * @trigger_mutex: the test trigger can only be fired once at a time
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  122)  * @thread_lock: protects @done count, and the @info per each thread
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  123)  * @done: number of threads which have completed or failed
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  124)  * @test_is_oom: when we run out of memory, use this to halt moving forward
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  125)  * @kthreads_done: completion used to signal when all work is done
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  126)  * @list: needed to be part of the reg_test_devs
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  127)  * @info: array of info for each thread
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  128)  */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  129) struct kmod_test_device {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  130) 	int dev_idx;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  131) 	struct test_config config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  132) 	struct miscdevice misc_dev;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  133) 	struct device *dev;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  134) 	struct mutex config_mutex;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  135) 	struct mutex trigger_mutex;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  136) 	struct mutex thread_mutex;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  137) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  138) 	unsigned int done;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  139) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  140) 	bool test_is_oom;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  141) 	struct completion kthreads_done;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  142) 	struct list_head list;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  143) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  144) 	struct kmod_test_device_info *info;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  145) };
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  146) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  147) static const char *test_case_str(enum kmod_test_case test_case)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  148) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  149) 	switch (test_case) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  150) 	case TEST_KMOD_DRIVER:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  151) 		return "TEST_KMOD_DRIVER";
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  152) 	case TEST_KMOD_FS_TYPE:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  153) 		return "TEST_KMOD_FS_TYPE";
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  154) 	default:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  155) 		return "invalid";
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  156) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  157) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  158) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  159) static struct miscdevice *dev_to_misc_dev(struct device *dev)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  160) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  161) 	return dev_get_drvdata(dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  162) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  163) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  164) static struct kmod_test_device *misc_dev_to_test_dev(struct miscdevice *misc_dev)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  165) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  166) 	return container_of(misc_dev, struct kmod_test_device, misc_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  167) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  168) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  169) static struct kmod_test_device *dev_to_test_dev(struct device *dev)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  170) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  171) 	struct miscdevice *misc_dev;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  172) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  173) 	misc_dev = dev_to_misc_dev(dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  174) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  175) 	return misc_dev_to_test_dev(misc_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  176) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  177) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  178) /* Must run with thread_mutex held */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  179) static void kmod_test_done_check(struct kmod_test_device *test_dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  180) 				 unsigned int idx)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  181) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  182) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  183) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  184) 	test_dev->done++;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  185) 	dev_dbg(test_dev->dev, "Done thread count: %u\n", test_dev->done);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  186) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  187) 	if (test_dev->done == config->num_threads) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  188) 		dev_info(test_dev->dev, "Done: %u threads have all run now\n",
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  189) 			 test_dev->done);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  190) 		dev_info(test_dev->dev, "Last thread to run: %u\n", idx);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  191) 		complete(&test_dev->kthreads_done);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  192) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  193) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  194) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  195) static void test_kmod_put_module(struct kmod_test_device_info *info)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  196) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  197) 	struct kmod_test_device *test_dev = info->test_dev;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  198) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  199) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  200) 	if (!info->need_mod_put)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  201) 		return;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  202) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  203) 	switch (config->test_case) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  204) 	case TEST_KMOD_DRIVER:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  205) 		break;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  206) 	case TEST_KMOD_FS_TYPE:
8f0259c27c850 (Dan Carpenter     2020-04-06 20:10:35 -0700  207) 		if (info->fs_sync && info->fs_sync->owner)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  208) 			module_put(info->fs_sync->owner);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  209) 		break;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  210) 	default:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  211) 		BUG();
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  212) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  213) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  214) 	info->need_mod_put = true;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  215) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  216) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  217) static int run_request(void *data)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  218) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  219) 	struct kmod_test_device_info *info = data;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  220) 	struct kmod_test_device *test_dev = info->test_dev;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  221) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  222) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  223) 	switch (config->test_case) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  224) 	case TEST_KMOD_DRIVER:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  225) 		info->ret_sync = request_module("%s", config->test_driver);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  226) 		break;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  227) 	case TEST_KMOD_FS_TYPE:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  228) 		info->fs_sync = get_fs_type(config->test_fs);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  229) 		info->need_mod_put = true;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  230) 		break;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  231) 	default:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  232) 		/* __trigger_config_run() already checked for test sanity */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  233) 		BUG();
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  234) 		return -EINVAL;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  235) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  236) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  237) 	dev_dbg(test_dev->dev, "Ran thread %u\n", info->thread_idx);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  238) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  239) 	test_kmod_put_module(info);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  240) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  241) 	mutex_lock(&test_dev->thread_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  242) 	info->task_sync = NULL;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  243) 	kmod_test_done_check(test_dev, info->thread_idx);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  244) 	mutex_unlock(&test_dev->thread_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  245) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  246) 	return 0;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  247) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  248) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  249) static int tally_work_test(struct kmod_test_device_info *info)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  250) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  251) 	struct kmod_test_device *test_dev = info->test_dev;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  252) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  253) 	int err_ret = 0;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  254) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  255) 	switch (config->test_case) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  256) 	case TEST_KMOD_DRIVER:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  257) 		/*
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  258) 		 * Only capture errors, if one is found that's
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  259) 		 * enough, for now.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  260) 		 */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  261) 		if (info->ret_sync != 0)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  262) 			err_ret = info->ret_sync;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  263) 		dev_info(test_dev->dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  264) 			 "Sync thread %d return status: %d\n",
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  265) 			 info->thread_idx, info->ret_sync);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  266) 		break;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  267) 	case TEST_KMOD_FS_TYPE:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  268) 		/* For now we make this simple */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  269) 		if (!info->fs_sync)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  270) 			err_ret = -EINVAL;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  271) 		dev_info(test_dev->dev, "Sync thread %u fs: %s\n",
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  272) 			 info->thread_idx, info->fs_sync ? config->test_fs :
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  273) 			 "NULL");
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  274) 		break;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  275) 	default:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  276) 		BUG();
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  277) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  278) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  279) 	return err_ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  280) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  281) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  282) /*
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  283)  * XXX: add result option to display if all errors did not match.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  284)  * For now we just keep any error code if one was found.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  285)  *
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  286)  * If this ran it means *all* tasks were created fine and we
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  287)  * are now just collecting results.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  288)  *
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  289)  * Only propagate errors, do not override with a subsequent sucess case.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  290)  */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  291) static void tally_up_work(struct kmod_test_device *test_dev)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  292) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  293) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  294) 	struct kmod_test_device_info *info;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  295) 	unsigned int idx;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  296) 	int err_ret = 0;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  297) 	int ret = 0;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  298) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  299) 	mutex_lock(&test_dev->thread_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  300) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  301) 	dev_info(test_dev->dev, "Results:\n");
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  302) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  303) 	for (idx=0; idx < config->num_threads; idx++) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  304) 		info = &test_dev->info[idx];
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  305) 		ret = tally_work_test(info);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  306) 		if (ret)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  307) 			err_ret = ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  308) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  309) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  310) 	/*
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  311) 	 * Note: request_module() returns 256 for a module not found even
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  312) 	 * though modprobe itself returns 1.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  313) 	 */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  314) 	config->test_result = err_ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  315) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  316) 	mutex_unlock(&test_dev->thread_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  317) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  318) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  319) static int try_one_request(struct kmod_test_device *test_dev, unsigned int idx)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  320) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  321) 	struct kmod_test_device_info *info = &test_dev->info[idx];
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  322) 	int fail_ret = -ENOMEM;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  323) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  324) 	mutex_lock(&test_dev->thread_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  325) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  326) 	info->thread_idx = idx;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  327) 	info->test_dev = test_dev;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  328) 	info->task_sync = kthread_run(run_request, info, "%s-%u",
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  329) 				      KBUILD_MODNAME, idx);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  330) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  331) 	if (!info->task_sync || IS_ERR(info->task_sync)) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  332) 		test_dev->test_is_oom = true;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  333) 		dev_err(test_dev->dev, "Setting up thread %u failed\n", idx);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  334) 		info->task_sync = NULL;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  335) 		goto err_out;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  336) 	} else
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  337) 		dev_dbg(test_dev->dev, "Kicked off thread %u\n", idx);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  338) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  339) 	mutex_unlock(&test_dev->thread_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  340) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  341) 	return 0;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  342) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  343) err_out:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  344) 	info->ret_sync = fail_ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  345) 	mutex_unlock(&test_dev->thread_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  346) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  347) 	return fail_ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  348) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  349) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  350) static void test_dev_kmod_stop_tests(struct kmod_test_device *test_dev)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  351) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  352) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  353) 	struct kmod_test_device_info *info;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  354) 	unsigned int i;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  355) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  356) 	dev_info(test_dev->dev, "Ending request_module() tests\n");
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  357) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  358) 	mutex_lock(&test_dev->thread_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  359) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  360) 	for (i=0; i < config->num_threads; i++) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  361) 		info = &test_dev->info[i];
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  362) 		if (info->task_sync && !IS_ERR(info->task_sync)) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  363) 			dev_info(test_dev->dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  364) 				 "Stopping still-running thread %i\n", i);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  365) 			kthread_stop(info->task_sync);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  366) 		}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  367) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  368) 		/*
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  369) 		 * info->task_sync is well protected, it can only be
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  370) 		 * NULL or a pointer to a struct. If its NULL we either
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  371) 		 * never ran, or we did and we completed the work. Completed
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  372) 		 * tasks *always* put the module for us. This is a sanity
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  373) 		 * check -- just in case.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  374) 		 */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  375) 		if (info->task_sync && info->need_mod_put)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  376) 			test_kmod_put_module(info);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  377) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  378) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  379) 	mutex_unlock(&test_dev->thread_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  380) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  381) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  382) /*
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  383)  * Only wait *iff* we did not run into any errors during all of our thread
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  384)  * set up. If run into any issues we stop threads and just bail out with
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  385)  * an error to the trigger. This also means we don't need any tally work
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  386)  * for any threads which fail.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  387)  */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  388) static int try_requests(struct kmod_test_device *test_dev)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  389) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  390) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  391) 	unsigned int idx;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  392) 	int ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  393) 	bool any_error = false;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  394) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  395) 	for (idx=0; idx < config->num_threads; idx++) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  396) 		if (test_dev->test_is_oom) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  397) 			any_error = true;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  398) 			break;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  399) 		}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  400) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  401) 		ret = try_one_request(test_dev, idx);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  402) 		if (ret) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  403) 			any_error = true;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  404) 			break;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  405) 		}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  406) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  407) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  408) 	if (!any_error) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  409) 		test_dev->test_is_oom = false;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  410) 		dev_info(test_dev->dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  411) 			 "No errors were found while initializing threads\n");
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  412) 		wait_for_completion(&test_dev->kthreads_done);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  413) 		tally_up_work(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  414) 	} else {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  415) 		test_dev->test_is_oom = true;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  416) 		dev_info(test_dev->dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  417) 			 "At least one thread failed to start, stop all work\n");
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  418) 		test_dev_kmod_stop_tests(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  419) 		return -ENOMEM;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  420) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  421) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  422) 	return 0;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  423) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  424) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  425) static int run_test_driver(struct kmod_test_device *test_dev)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  426) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  427) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  428) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  429) 	dev_info(test_dev->dev, "Test case: %s (%u)\n",
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  430) 		 test_case_str(config->test_case),
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  431) 		 config->test_case);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  432) 	dev_info(test_dev->dev, "Test driver to load: %s\n",
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  433) 		 config->test_driver);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  434) 	dev_info(test_dev->dev, "Number of threads to run: %u\n",
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  435) 		 config->num_threads);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  436) 	dev_info(test_dev->dev, "Thread IDs will range from 0 - %u\n",
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  437) 		 config->num_threads - 1);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  438) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  439) 	return try_requests(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  440) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  441) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  442) static int run_test_fs_type(struct kmod_test_device *test_dev)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  443) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  444) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  445) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  446) 	dev_info(test_dev->dev, "Test case: %s (%u)\n",
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  447) 		 test_case_str(config->test_case),
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  448) 		 config->test_case);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  449) 	dev_info(test_dev->dev, "Test filesystem to load: %s\n",
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  450) 		 config->test_fs);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  451) 	dev_info(test_dev->dev, "Number of threads to run: %u\n",
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  452) 		 config->num_threads);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  453) 	dev_info(test_dev->dev, "Thread IDs will range from 0 - %u\n",
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  454) 		 config->num_threads - 1);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  455) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  456) 	return try_requests(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  457) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  458) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  459) static ssize_t config_show(struct device *dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  460) 			   struct device_attribute *attr,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  461) 			   char *buf)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  462) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  463) 	struct kmod_test_device *test_dev = dev_to_test_dev(dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  464) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  465) 	int len = 0;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  466) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  467) 	mutex_lock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  468) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  469) 	len += snprintf(buf, PAGE_SIZE,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  470) 			"Custom trigger configuration for: %s\n",
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  471) 			dev_name(dev));
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  472) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  473) 	len += snprintf(buf+len, PAGE_SIZE - len,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  474) 			"Number of threads:\t%u\n",
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  475) 			config->num_threads);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  476) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  477) 	len += snprintf(buf+len, PAGE_SIZE - len,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  478) 			"Test_case:\t%s (%u)\n",
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  479) 			test_case_str(config->test_case),
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  480) 			config->test_case);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  481) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  482) 	if (config->test_driver)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  483) 		len += snprintf(buf+len, PAGE_SIZE - len,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  484) 				"driver:\t%s\n",
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  485) 				config->test_driver);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  486) 	else
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  487) 		len += snprintf(buf+len, PAGE_SIZE - len,
a4afe8cdec164 (Colin Ian King    2017-08-10 15:23:40 -0700  488) 				"driver:\tEMPTY\n");
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  489) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  490) 	if (config->test_fs)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  491) 		len += snprintf(buf+len, PAGE_SIZE - len,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  492) 				"fs:\t%s\n",
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  493) 				config->test_fs);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  494) 	else
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  495) 		len += snprintf(buf+len, PAGE_SIZE - len,
a4afe8cdec164 (Colin Ian King    2017-08-10 15:23:40 -0700  496) 				"fs:\tEMPTY\n");
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  497) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  498) 	mutex_unlock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  499) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  500) 	return len;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  501) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  502) static DEVICE_ATTR_RO(config);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  503) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  504) /*
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  505)  * This ensures we don't allow kicking threads through if our configuration
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  506)  * is faulty.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  507)  */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  508) static int __trigger_config_run(struct kmod_test_device *test_dev)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  509) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  510) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  511) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  512) 	test_dev->done = 0;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  513) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  514) 	switch (config->test_case) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  515) 	case TEST_KMOD_DRIVER:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  516) 		return run_test_driver(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  517) 	case TEST_KMOD_FS_TYPE:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  518) 		return run_test_fs_type(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  519) 	default:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  520) 		dev_warn(test_dev->dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  521) 			 "Invalid test case requested: %u\n",
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  522) 			 config->test_case);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  523) 		return -EINVAL;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  524) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  525) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  526) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  527) static int trigger_config_run(struct kmod_test_device *test_dev)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  528) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  529) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  530) 	int ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  531) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  532) 	mutex_lock(&test_dev->trigger_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  533) 	mutex_lock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  534) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  535) 	ret = __trigger_config_run(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  536) 	if (ret < 0)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  537) 		goto out;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  538) 	dev_info(test_dev->dev, "General test result: %d\n",
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  539) 		 config->test_result);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  540) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  541) 	/*
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  542) 	 * We must return 0 after a trigger even unless something went
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  543) 	 * wrong with the setup of the test. If the test setup went fine
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  544) 	 * then userspace must just check the result of config->test_result.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  545) 	 * One issue with relying on the return from a call in the kernel
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  546) 	 * is if the kernel returns a possitive value using this trigger
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  547) 	 * will not return the value to userspace, it would be lost.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  548) 	 *
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  549) 	 * By not relying on capturing the return value of tests we are using
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  550) 	 * through the trigger it also us to run tests with set -e and only
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  551) 	 * fail when something went wrong with the driver upon trigger
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  552) 	 * requests.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  553) 	 */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  554) 	ret = 0;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  555) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  556) out:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  557) 	mutex_unlock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  558) 	mutex_unlock(&test_dev->trigger_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  559) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  560) 	return ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  561) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  562) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  563) static ssize_t
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  564) trigger_config_store(struct device *dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  565) 		     struct device_attribute *attr,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  566) 		     const char *buf, size_t count)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  567) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  568) 	struct kmod_test_device *test_dev = dev_to_test_dev(dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  569) 	int ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  570) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  571) 	if (test_dev->test_is_oom)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  572) 		return -ENOMEM;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  573) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  574) 	/* For all intents and purposes we don't care what userspace
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  575) 	 * sent this trigger, we care only that we were triggered.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  576) 	 * We treat the return value only for caputuring issues with
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  577) 	 * the test setup. At this point all the test variables should
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  578) 	 * have been allocated so typically this should never fail.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  579) 	 */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  580) 	ret = trigger_config_run(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  581) 	if (unlikely(ret < 0))
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  582) 		goto out;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  583) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  584) 	/*
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  585) 	 * Note: any return > 0 will be treated as success
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  586) 	 * and the error value will not be available to userspace.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  587) 	 * Do not rely on trying to send to userspace a test value
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  588) 	 * return value as possitive return errors will be lost.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  589) 	 */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  590) 	if (WARN_ON(ret > 0))
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  591) 		return -EINVAL;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  592) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  593) 	ret = count;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  594) out:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  595) 	return ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  596) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  597) static DEVICE_ATTR_WO(trigger_config);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  598) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  599) /*
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  600)  * XXX: move to kstrncpy() once merged.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  601)  *
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  602)  * Users should use kfree_const() when freeing these.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  603)  */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  604) static int __kstrncpy(char **dst, const char *name, size_t count, gfp_t gfp)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  605) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  606) 	*dst = kstrndup(name, count, gfp);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  607) 	if (!*dst)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  608) 		return -ENOSPC;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  609) 	return count;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  610) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  611) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  612) static int config_copy_test_driver_name(struct test_config *config,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  613) 				    const char *name,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  614) 				    size_t count)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  615) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  616) 	return __kstrncpy(&config->test_driver, name, count, GFP_KERNEL);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  617) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  618) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  619) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  620) static int config_copy_test_fs(struct test_config *config, const char *name,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  621) 			       size_t count)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  622) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  623) 	return __kstrncpy(&config->test_fs, name, count, GFP_KERNEL);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  624) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  625) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  626) static void __kmod_config_free(struct test_config *config)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  627) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  628) 	if (!config)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  629) 		return;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  630) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  631) 	kfree_const(config->test_driver);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  632) 	config->test_driver = NULL;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  633) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  634) 	kfree_const(config->test_fs);
db7ddeab3ce5d (Dan Carpenter     2019-02-01 14:20:58 -0800  635) 	config->test_fs = NULL;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  636) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  637) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  638) static void kmod_config_free(struct kmod_test_device *test_dev)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  639) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  640) 	struct test_config *config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  641) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  642) 	if (!test_dev)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  643) 		return;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  644) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  645) 	config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  646) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  647) 	mutex_lock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  648) 	__kmod_config_free(config);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  649) 	mutex_unlock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  650) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  651) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  652) static ssize_t config_test_driver_store(struct device *dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  653) 					struct device_attribute *attr,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  654) 					const char *buf, size_t count)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  655) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  656) 	struct kmod_test_device *test_dev = dev_to_test_dev(dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  657) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  658) 	int copied;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  659) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  660) 	mutex_lock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  661) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  662) 	kfree_const(config->test_driver);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  663) 	config->test_driver = NULL;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  664) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  665) 	copied = config_copy_test_driver_name(config, buf, count);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  666) 	mutex_unlock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  667) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  668) 	return copied;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  669) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  670) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  671) /*
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  672)  * As per sysfs_kf_seq_show() the buf is max PAGE_SIZE.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  673)  */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  674) static ssize_t config_test_show_str(struct mutex *config_mutex,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  675) 				    char *dst,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  676) 				    char *src)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  677) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  678) 	int len;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  679) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  680) 	mutex_lock(config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  681) 	len = snprintf(dst, PAGE_SIZE, "%s\n", src);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  682) 	mutex_unlock(config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  683) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  684) 	return len;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  685) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  686) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  687) static ssize_t config_test_driver_show(struct device *dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  688) 					struct device_attribute *attr,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  689) 					char *buf)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  690) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  691) 	struct kmod_test_device *test_dev = dev_to_test_dev(dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  692) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  693) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  694) 	return config_test_show_str(&test_dev->config_mutex, buf,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  695) 				    config->test_driver);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  696) }
b6b996b6cdeec (Joe Perches       2017-12-19 10:15:07 -0800  697) static DEVICE_ATTR_RW(config_test_driver);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  698) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  699) static ssize_t config_test_fs_store(struct device *dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  700) 				    struct device_attribute *attr,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  701) 				    const char *buf, size_t count)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  702) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  703) 	struct kmod_test_device *test_dev = dev_to_test_dev(dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  704) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  705) 	int copied;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  706) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  707) 	mutex_lock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  708) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  709) 	kfree_const(config->test_fs);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  710) 	config->test_fs = NULL;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  711) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  712) 	copied = config_copy_test_fs(config, buf, count);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  713) 	mutex_unlock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  714) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  715) 	return copied;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  716) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  717) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  718) static ssize_t config_test_fs_show(struct device *dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  719) 				   struct device_attribute *attr,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  720) 				   char *buf)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  721) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  722) 	struct kmod_test_device *test_dev = dev_to_test_dev(dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  723) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  724) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  725) 	return config_test_show_str(&test_dev->config_mutex, buf,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  726) 				    config->test_fs);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  727) }
b6b996b6cdeec (Joe Perches       2017-12-19 10:15:07 -0800  728) static DEVICE_ATTR_RW(config_test_fs);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  729) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  730) static int trigger_config_run_type(struct kmod_test_device *test_dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  731) 				   enum kmod_test_case test_case,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  732) 				   const char *test_str)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  733) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  734) 	int copied = 0;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  735) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  736) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  737) 	mutex_lock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  738) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  739) 	switch (test_case) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  740) 	case TEST_KMOD_DRIVER:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  741) 		kfree_const(config->test_driver);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  742) 		config->test_driver = NULL;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  743) 		copied = config_copy_test_driver_name(config, test_str,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  744) 						      strlen(test_str));
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  745) 		break;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  746) 	case TEST_KMOD_FS_TYPE:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  747) 		kfree_const(config->test_fs);
0776d1231bec0 (Tiezhu Yang       2020-08-11 18:36:16 -0700  748) 		config->test_fs = NULL;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  749) 		copied = config_copy_test_fs(config, test_str,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  750) 					     strlen(test_str));
4e98ebe5f435f (Dan Carpenter     2017-08-10 15:23:50 -0700  751) 		break;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  752) 	default:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  753) 		mutex_unlock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  754) 		return -EINVAL;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  755) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  756) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  757) 	config->test_case = test_case;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  758) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  759) 	mutex_unlock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  760) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  761) 	if (copied <= 0 || copied != strlen(test_str)) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  762) 		test_dev->test_is_oom = true;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  763) 		return -ENOMEM;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  764) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  765) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  766) 	test_dev->test_is_oom = false;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  767) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  768) 	return trigger_config_run(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  769) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  770) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  771) static void free_test_dev_info(struct kmod_test_device *test_dev)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  772) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  773) 	vfree(test_dev->info);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  774) 	test_dev->info = NULL;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  775) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  776) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  777) static int kmod_config_sync_info(struct kmod_test_device *test_dev)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  778) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  779) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  780) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  781) 	free_test_dev_info(test_dev);
fad953ce0b22c (Kees Cook         2018-06-12 14:27:37 -0700  782) 	test_dev->info =
fad953ce0b22c (Kees Cook         2018-06-12 14:27:37 -0700  783) 		vzalloc(array_size(sizeof(struct kmod_test_device_info),
fad953ce0b22c (Kees Cook         2018-06-12 14:27:37 -0700  784) 				   config->num_threads));
dc2bf000a2848 (Markus Elfring    2017-11-17 15:28:00 -0800  785) 	if (!test_dev->info)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  786) 		return -ENOMEM;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  787) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  788) 	return 0;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  789) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  790) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  791) /*
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  792)  * Old kernels may not have this, if you want to port this code to
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  793)  * test it on older kernels.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  794)  */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  795) #ifdef get_kmod_umh_limit
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  796) static unsigned int kmod_init_test_thread_limit(void)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  797) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  798) 	return get_kmod_umh_limit();
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  799) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  800) #else
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  801) static unsigned int kmod_init_test_thread_limit(void)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  802) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  803) 	return TEST_START_NUM_THREADS;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  804) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  805) #endif
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  806) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  807) static int __kmod_config_init(struct kmod_test_device *test_dev)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  808) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  809) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  810) 	int ret = -ENOMEM, copied;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  811) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  812) 	__kmod_config_free(config);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  813) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  814) 	copied = config_copy_test_driver_name(config, TEST_START_DRIVER,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  815) 					      strlen(TEST_START_DRIVER));
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  816) 	if (copied != strlen(TEST_START_DRIVER))
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  817) 		goto err_out;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  818) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  819) 	copied = config_copy_test_fs(config, TEST_START_TEST_FS,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  820) 				     strlen(TEST_START_TEST_FS));
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  821) 	if (copied != strlen(TEST_START_TEST_FS))
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  822) 		goto err_out;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  823) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  824) 	config->num_threads = kmod_init_test_thread_limit();
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  825) 	config->test_result = 0;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  826) 	config->test_case = TEST_START_TEST_CASE;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  827) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  828) 	ret = kmod_config_sync_info(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  829) 	if (ret)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  830) 		goto err_out;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  831) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  832) 	test_dev->test_is_oom = false;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  833) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  834) 	return 0;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  835) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  836) err_out:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  837) 	test_dev->test_is_oom = true;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  838) 	WARN_ON(test_dev->test_is_oom);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  839) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  840) 	__kmod_config_free(config);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  841) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  842) 	return ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  843) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  844) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  845) static ssize_t reset_store(struct device *dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  846) 			   struct device_attribute *attr,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  847) 			   const char *buf, size_t count)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  848) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  849) 	struct kmod_test_device *test_dev = dev_to_test_dev(dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  850) 	int ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  851) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  852) 	mutex_lock(&test_dev->trigger_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  853) 	mutex_lock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  854) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  855) 	ret = __kmod_config_init(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  856) 	if (ret < 0) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  857) 		ret = -ENOMEM;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  858) 		dev_err(dev, "could not alloc settings for config trigger: %d\n",
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  859) 		       ret);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  860) 		goto out;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  861) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  862) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  863) 	dev_info(dev, "reset\n");
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  864) 	ret = count;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  865) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  866) out:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  867) 	mutex_unlock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  868) 	mutex_unlock(&test_dev->trigger_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  869) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  870) 	return ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  871) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  872) static DEVICE_ATTR_WO(reset);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  873) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  874) static int test_dev_config_update_uint_sync(struct kmod_test_device *test_dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  875) 					    const char *buf, size_t size,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  876) 					    unsigned int *config,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  877) 					    int (*test_sync)(struct kmod_test_device *test_dev))
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  878) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  879) 	int ret;
506dfc9906e5c (Alexey Dobriyan   2020-12-15 20:44:00 -0800  880) 	unsigned int val;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  881) 	unsigned int old_val;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  882) 
506dfc9906e5c (Alexey Dobriyan   2020-12-15 20:44:00 -0800  883) 	ret = kstrtouint(buf, 10, &val);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  884) 	if (ret)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  885) 		return ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  886) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  887) 	mutex_lock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  888) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  889) 	old_val = *config;
506dfc9906e5c (Alexey Dobriyan   2020-12-15 20:44:00 -0800  890) 	*(unsigned int *)config = val;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  891) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  892) 	ret = test_sync(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  893) 	if (ret) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  894) 		*(unsigned int *)config = old_val;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  895) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  896) 		ret = test_sync(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  897) 		WARN_ON(ret);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  898) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  899) 		mutex_unlock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  900) 		return -EINVAL;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  901) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  902) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  903) 	mutex_unlock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  904) 	/* Always return full write size even if we didn't consume all */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  905) 	return size;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  906) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  907) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  908) static int test_dev_config_update_uint_range(struct kmod_test_device *test_dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  909) 					     const char *buf, size_t size,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  910) 					     unsigned int *config,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  911) 					     unsigned int min,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  912) 					     unsigned int max)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  913) {
506dfc9906e5c (Alexey Dobriyan   2020-12-15 20:44:00 -0800  914) 	unsigned int val;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  915) 	int ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  916) 
506dfc9906e5c (Alexey Dobriyan   2020-12-15 20:44:00 -0800  917) 	ret = kstrtouint(buf, 10, &val);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  918) 	if (ret)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  919) 		return ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  920) 
506dfc9906e5c (Alexey Dobriyan   2020-12-15 20:44:00 -0800  921) 	if (val < min || val > max)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  922) 		return -EINVAL;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  923) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  924) 	mutex_lock(&test_dev->config_mutex);
506dfc9906e5c (Alexey Dobriyan   2020-12-15 20:44:00 -0800  925) 	*config = val;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  926) 	mutex_unlock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  927) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  928) 	/* Always return full write size even if we didn't consume all */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  929) 	return size;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  930) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  931) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  932) static int test_dev_config_update_int(struct kmod_test_device *test_dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  933) 				      const char *buf, size_t size,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  934) 				      int *config)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  935) {
506dfc9906e5c (Alexey Dobriyan   2020-12-15 20:44:00 -0800  936) 	int val;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  937) 	int ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  938) 
506dfc9906e5c (Alexey Dobriyan   2020-12-15 20:44:00 -0800  939) 	ret = kstrtoint(buf, 10, &val);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  940) 	if (ret)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  941) 		return ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  942) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  943) 	mutex_lock(&test_dev->config_mutex);
506dfc9906e5c (Alexey Dobriyan   2020-12-15 20:44:00 -0800  944) 	*config = val;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  945) 	mutex_unlock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  946) 	/* Always return full write size even if we didn't consume all */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  947) 	return size;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  948) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  949) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  950) static ssize_t test_dev_config_show_int(struct kmod_test_device *test_dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  951) 					char *buf,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  952) 					int config)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  953) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  954) 	int val;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  955) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  956) 	mutex_lock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  957) 	val = config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  958) 	mutex_unlock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  959) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  960) 	return snprintf(buf, PAGE_SIZE, "%d\n", val);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  961) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  962) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  963) static ssize_t test_dev_config_show_uint(struct kmod_test_device *test_dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  964) 					 char *buf,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  965) 					 unsigned int config)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  966) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  967) 	unsigned int val;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  968) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  969) 	mutex_lock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  970) 	val = config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  971) 	mutex_unlock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  972) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  973) 	return snprintf(buf, PAGE_SIZE, "%u\n", val);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  974) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  975) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  976) static ssize_t test_result_store(struct device *dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  977) 				 struct device_attribute *attr,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  978) 				 const char *buf, size_t count)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  979) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  980) 	struct kmod_test_device *test_dev = dev_to_test_dev(dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  981) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  982) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  983) 	return test_dev_config_update_int(test_dev, buf, count,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  984) 					  &config->test_result);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  985) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  986) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  987) static ssize_t config_num_threads_store(struct device *dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  988) 					struct device_attribute *attr,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  989) 					const char *buf, size_t count)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  990) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  991) 	struct kmod_test_device *test_dev = dev_to_test_dev(dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  992) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  993) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  994) 	return test_dev_config_update_uint_sync(test_dev, buf, count,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  995) 						&config->num_threads,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  996) 						kmod_config_sync_info);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  997) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  998) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700  999) static ssize_t config_num_threads_show(struct device *dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1000) 				       struct device_attribute *attr,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1001) 				       char *buf)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1002) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1003) 	struct kmod_test_device *test_dev = dev_to_test_dev(dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1004) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1005) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1006) 	return test_dev_config_show_int(test_dev, buf, config->num_threads);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1007) }
b6b996b6cdeec (Joe Perches       2017-12-19 10:15:07 -0800 1008) static DEVICE_ATTR_RW(config_num_threads);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1009) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1010) static ssize_t config_test_case_store(struct device *dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1011) 				      struct device_attribute *attr,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1012) 				      const char *buf, size_t count)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1013) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1014) 	struct kmod_test_device *test_dev = dev_to_test_dev(dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1015) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1016) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1017) 	return test_dev_config_update_uint_range(test_dev, buf, count,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1018) 						 &config->test_case,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1019) 						 __TEST_KMOD_INVALID + 1,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1020) 						 __TEST_KMOD_MAX - 1);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1021) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1022) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1023) static ssize_t config_test_case_show(struct device *dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1024) 				     struct device_attribute *attr,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1025) 				     char *buf)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1026) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1027) 	struct kmod_test_device *test_dev = dev_to_test_dev(dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1028) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1029) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1030) 	return test_dev_config_show_uint(test_dev, buf, config->test_case);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1031) }
b6b996b6cdeec (Joe Perches       2017-12-19 10:15:07 -0800 1032) static DEVICE_ATTR_RW(config_test_case);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1033) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1034) static ssize_t test_result_show(struct device *dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1035) 				struct device_attribute *attr,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1036) 				char *buf)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1037) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1038) 	struct kmod_test_device *test_dev = dev_to_test_dev(dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1039) 	struct test_config *config = &test_dev->config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1040) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1041) 	return test_dev_config_show_int(test_dev, buf, config->test_result);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1042) }
b6b996b6cdeec (Joe Perches       2017-12-19 10:15:07 -0800 1043) static DEVICE_ATTR_RW(test_result);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1044) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1045) #define TEST_KMOD_DEV_ATTR(name)		&dev_attr_##name.attr
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1046) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1047) static struct attribute *test_dev_attrs[] = {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1048) 	TEST_KMOD_DEV_ATTR(trigger_config),
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1049) 	TEST_KMOD_DEV_ATTR(config),
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1050) 	TEST_KMOD_DEV_ATTR(reset),
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1051) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1052) 	TEST_KMOD_DEV_ATTR(config_test_driver),
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1053) 	TEST_KMOD_DEV_ATTR(config_test_fs),
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1054) 	TEST_KMOD_DEV_ATTR(config_num_threads),
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1055) 	TEST_KMOD_DEV_ATTR(config_test_case),
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1056) 	TEST_KMOD_DEV_ATTR(test_result),
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1057) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1058) 	NULL,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1059) };
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1060) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1061) ATTRIBUTE_GROUPS(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1062) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1063) static int kmod_config_init(struct kmod_test_device *test_dev)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1064) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1065) 	int ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1066) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1067) 	mutex_lock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1068) 	ret = __kmod_config_init(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1069) 	mutex_unlock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1070) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1071) 	return ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1072) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1073) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1074) static struct kmod_test_device *alloc_test_dev_kmod(int idx)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1075) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1076) 	int ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1077) 	struct kmod_test_device *test_dev;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1078) 	struct miscdevice *misc_dev;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1079) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1080) 	test_dev = vzalloc(sizeof(struct kmod_test_device));
dc2bf000a2848 (Markus Elfring    2017-11-17 15:28:00 -0800 1081) 	if (!test_dev)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1082) 		goto err_out;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1083) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1084) 	mutex_init(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1085) 	mutex_init(&test_dev->trigger_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1086) 	mutex_init(&test_dev->thread_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1087) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1088) 	init_completion(&test_dev->kthreads_done);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1089) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1090) 	ret = kmod_config_init(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1091) 	if (ret < 0) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1092) 		pr_err("Cannot alloc kmod_config_init()\n");
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1093) 		goto err_out_free;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1094) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1095) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1096) 	test_dev->dev_idx = idx;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1097) 	misc_dev = &test_dev->misc_dev;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1098) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1099) 	misc_dev->minor = MISC_DYNAMIC_MINOR;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1100) 	misc_dev->name = kasprintf(GFP_KERNEL, "test_kmod%d", idx);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1101) 	if (!misc_dev->name) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1102) 		pr_err("Cannot alloc misc_dev->name\n");
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1103) 		goto err_out_free_config;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1104) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1105) 	misc_dev->groups = test_dev_groups;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1106) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1107) 	return test_dev;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1108) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1109) err_out_free_config:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1110) 	free_test_dev_info(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1111) 	kmod_config_free(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1112) err_out_free:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1113) 	vfree(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1114) 	test_dev = NULL;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1115) err_out:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1116) 	return NULL;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1117) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1118) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1119) static void free_test_dev_kmod(struct kmod_test_device *test_dev)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1120) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1121) 	if (test_dev) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1122) 		kfree_const(test_dev->misc_dev.name);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1123) 		test_dev->misc_dev.name = NULL;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1124) 		free_test_dev_info(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1125) 		kmod_config_free(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1126) 		vfree(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1127) 		test_dev = NULL;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1128) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1129) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1130) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1131) static struct kmod_test_device *register_test_dev_kmod(void)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1132) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1133) 	struct kmod_test_device *test_dev = NULL;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1134) 	int ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1135) 
9c56771316ef5 (Dan Carpenter     2017-08-10 15:23:47 -0700 1136) 	mutex_lock(&reg_dev_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1137) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1138) 	/* int should suffice for number of devices, test for wrap */
ac68b1b3b9c73 (Luis R. Rodriguez 2018-03-09 15:51:20 -0800 1139) 	if (num_test_devs + 1 == INT_MAX) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1140) 		pr_err("reached limit of number of test devices\n");
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1141) 		goto out;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1142) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1143) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1144) 	test_dev = alloc_test_dev_kmod(num_test_devs);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1145) 	if (!test_dev)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1146) 		goto out;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1147) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1148) 	ret = misc_register(&test_dev->misc_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1149) 	if (ret) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1150) 		pr_err("could not register misc device: %d\n", ret);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1151) 		free_test_dev_kmod(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1152) 		goto out;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1153) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1154) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1155) 	test_dev->dev = test_dev->misc_dev.this_device;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1156) 	list_add_tail(&test_dev->list, &reg_test_devs);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1157) 	dev_info(test_dev->dev, "interface ready\n");
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1158) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1159) 	num_test_devs++;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1160) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1161) out:
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1162) 	mutex_unlock(&reg_dev_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1163) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1164) 	return test_dev;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1165) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1166) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1167) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1168) static int __init test_kmod_init(void)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1169) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1170) 	struct kmod_test_device *test_dev;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1171) 	int ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1172) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1173) 	test_dev = register_test_dev_kmod();
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1174) 	if (!test_dev) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1175) 		pr_err("Cannot add first test kmod device\n");
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1176) 		return -ENODEV;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1177) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1178) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1179) 	/*
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1180) 	 * With some work we might be able to gracefully enable
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1181) 	 * testing with this driver built-in, for now this seems
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1182) 	 * rather risky. For those willing to try have at it,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1183) 	 * and enable the below. Good luck! If that works, try
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1184) 	 * lowering the init level for more fun.
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1185) 	 */
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1186) 	if (force_init_test) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1187) 		ret = trigger_config_run_type(test_dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1188) 					      TEST_KMOD_DRIVER, "tun");
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1189) 		if (WARN_ON(ret))
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1190) 			return ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1191) 		ret = trigger_config_run_type(test_dev,
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1192) 					      TEST_KMOD_FS_TYPE, "btrfs");
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1193) 		if (WARN_ON(ret))
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1194) 			return ret;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1195) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1196) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1197) 	return 0;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1198) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1199) late_initcall(test_kmod_init);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1200) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1201) static
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1202) void unregister_test_dev_kmod(struct kmod_test_device *test_dev)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1203) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1204) 	mutex_lock(&test_dev->trigger_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1205) 	mutex_lock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1206) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1207) 	test_dev_kmod_stop_tests(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1208) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1209) 	dev_info(test_dev->dev, "removing interface\n");
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1210) 	misc_deregister(&test_dev->misc_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1211) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1212) 	mutex_unlock(&test_dev->config_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1213) 	mutex_unlock(&test_dev->trigger_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1214) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1215) 	free_test_dev_kmod(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1216) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1217) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1218) static void __exit test_kmod_exit(void)
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1219) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1220) 	struct kmod_test_device *test_dev, *tmp;
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1221) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1222) 	mutex_lock(&reg_dev_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1223) 	list_for_each_entry_safe(test_dev, tmp, &reg_test_devs, list) {
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1224) 		list_del(&test_dev->list);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1225) 		unregister_test_dev_kmod(test_dev);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1226) 	}
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1227) 	mutex_unlock(&reg_dev_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1228) }
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1229) module_exit(test_kmod_exit);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1230) 
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1231) MODULE_AUTHOR("Luis R. Rodriguez <mcgrof@kernel.org>");
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1232) MODULE_LICENSE("GPL");