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(®_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, ®_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(®_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(®_dev_mutex);
d9c6a72d6fa29 (Luis R. Rodriguez 2017-07-14 14:50:08 -0700 1223) list_for_each_entry_safe(test_dev, tmp, ®_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(®_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");