mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-25 16:11:45 +00:00
rcutorture: Abstract torture_onoff()
Because online/offline torturing is not specific to RCU, this commit abstracts it into the kernel/torture.c module to allow other torture tests to use it. Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Reviewed-by: Josh Triplett <josh@joshtriplett.org>
This commit is contained in:
parent
3808dc9fab
commit
2e9e8081d2
3 changed files with 202 additions and 158 deletions
|
@ -61,6 +61,18 @@ extern bool verbose;
|
||||||
#define VERBOSE_TOROUT_ERRSTRING(s) \
|
#define VERBOSE_TOROUT_ERRSTRING(s) \
|
||||||
do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! " s "\n", torture_type); } while (0)
|
do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! " s "\n", torture_type); } while (0)
|
||||||
|
|
||||||
|
/* Definitions for a non-string torture-test module parameter. */
|
||||||
|
#define torture_parm(type, name, init, msg) \
|
||||||
|
static type name = init; \
|
||||||
|
module_param(name, type, 0444); \
|
||||||
|
MODULE_PARM_DESC(name, msg);
|
||||||
|
|
||||||
|
/* Definitions for online/offline exerciser. */
|
||||||
|
int torture_onoff_init(long ooholdoff, long oointerval);
|
||||||
|
void torture_onoff_cleanup(void);
|
||||||
|
char *torture_onoff_stats(char *page);
|
||||||
|
bool torture_onoff_failures(void);
|
||||||
|
|
||||||
/* Low-rider random number generator. */
|
/* Low-rider random number generator. */
|
||||||
struct torture_random_state {
|
struct torture_random_state {
|
||||||
unsigned long trs_state;
|
unsigned long trs_state;
|
||||||
|
|
|
@ -110,9 +110,6 @@ static struct task_struct *stutter_task;
|
||||||
static struct task_struct *fqs_task;
|
static struct task_struct *fqs_task;
|
||||||
static struct task_struct *boost_tasks[NR_CPUS];
|
static struct task_struct *boost_tasks[NR_CPUS];
|
||||||
static struct task_struct *shutdown_task;
|
static struct task_struct *shutdown_task;
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
|
||||||
static struct task_struct *onoff_task;
|
|
||||||
#endif /* #ifdef CONFIG_HOTPLUG_CPU */
|
|
||||||
static struct task_struct *stall_task;
|
static struct task_struct *stall_task;
|
||||||
static struct task_struct **barrier_cbs_tasks;
|
static struct task_struct **barrier_cbs_tasks;
|
||||||
static struct task_struct *barrier_task;
|
static struct task_struct *barrier_task;
|
||||||
|
@ -147,16 +144,6 @@ static long n_rcu_torture_boost_rterror;
|
||||||
static long n_rcu_torture_boost_failure;
|
static long n_rcu_torture_boost_failure;
|
||||||
static long n_rcu_torture_boosts;
|
static long n_rcu_torture_boosts;
|
||||||
static long n_rcu_torture_timers;
|
static long n_rcu_torture_timers;
|
||||||
static long n_offline_attempts;
|
|
||||||
static long n_offline_successes;
|
|
||||||
static unsigned long sum_offline;
|
|
||||||
static int min_offline = -1;
|
|
||||||
static int max_offline;
|
|
||||||
static long n_online_attempts;
|
|
||||||
static long n_online_successes;
|
|
||||||
static unsigned long sum_online;
|
|
||||||
static int min_online = -1;
|
|
||||||
static int max_online;
|
|
||||||
static long n_barrier_attempts;
|
static long n_barrier_attempts;
|
||||||
static long n_barrier_successes;
|
static long n_barrier_successes;
|
||||||
static struct list_head rcu_torture_removed;
|
static struct list_head rcu_torture_removed;
|
||||||
|
@ -994,13 +981,7 @@ rcu_torture_printk(char *page)
|
||||||
n_rcu_torture_boost_failure,
|
n_rcu_torture_boost_failure,
|
||||||
n_rcu_torture_boosts,
|
n_rcu_torture_boosts,
|
||||||
n_rcu_torture_timers);
|
n_rcu_torture_timers);
|
||||||
page += sprintf(page,
|
page = torture_onoff_stats(page);
|
||||||
"onoff: %ld/%ld:%ld/%ld %d,%d:%d,%d %lu:%lu (HZ=%d) ",
|
|
||||||
n_online_successes, n_online_attempts,
|
|
||||||
n_offline_successes, n_offline_attempts,
|
|
||||||
min_online, max_online,
|
|
||||||
min_offline, max_offline,
|
|
||||||
sum_online, sum_offline, HZ);
|
|
||||||
page += sprintf(page, "barrier: %ld/%ld:%ld",
|
page += sprintf(page, "barrier: %ld/%ld:%ld",
|
||||||
n_barrier_successes,
|
n_barrier_successes,
|
||||||
n_barrier_attempts,
|
n_barrier_attempts,
|
||||||
|
@ -1204,140 +1185,6 @@ rcu_torture_shutdown(void *arg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Execute random CPU-hotplug operations at the interval specified
|
|
||||||
* by the onoff_interval.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
rcu_torture_onoff(void *arg)
|
|
||||||
{
|
|
||||||
int cpu;
|
|
||||||
unsigned long delta;
|
|
||||||
int maxcpu = -1;
|
|
||||||
DEFINE_TORTURE_RANDOM(rand);
|
|
||||||
int ret;
|
|
||||||
unsigned long starttime;
|
|
||||||
|
|
||||||
VERBOSE_TOROUT_STRING("rcu_torture_onoff task started");
|
|
||||||
for_each_online_cpu(cpu)
|
|
||||||
maxcpu = cpu;
|
|
||||||
WARN_ON(maxcpu < 0);
|
|
||||||
if (onoff_holdoff > 0) {
|
|
||||||
VERBOSE_TOROUT_STRING("rcu_torture_onoff begin holdoff");
|
|
||||||
schedule_timeout_interruptible(onoff_holdoff * HZ);
|
|
||||||
VERBOSE_TOROUT_STRING("rcu_torture_onoff end holdoff");
|
|
||||||
}
|
|
||||||
while (!kthread_should_stop()) {
|
|
||||||
cpu = (torture_random(&rand) >> 4) % (maxcpu + 1);
|
|
||||||
if (cpu_online(cpu) && cpu_is_hotpluggable(cpu)) {
|
|
||||||
if (verbose)
|
|
||||||
pr_alert("%s" TORTURE_FLAG
|
|
||||||
"rcu_torture_onoff task: offlining %d\n",
|
|
||||||
torture_type, cpu);
|
|
||||||
starttime = jiffies;
|
|
||||||
n_offline_attempts++;
|
|
||||||
ret = cpu_down(cpu);
|
|
||||||
if (ret) {
|
|
||||||
if (verbose)
|
|
||||||
pr_alert("%s" TORTURE_FLAG
|
|
||||||
"rcu_torture_onoff task: offline %d failed: errno %d\n",
|
|
||||||
torture_type, cpu, ret);
|
|
||||||
} else {
|
|
||||||
if (verbose)
|
|
||||||
pr_alert("%s" TORTURE_FLAG
|
|
||||||
"rcu_torture_onoff task: offlined %d\n",
|
|
||||||
torture_type, cpu);
|
|
||||||
n_offline_successes++;
|
|
||||||
delta = jiffies - starttime;
|
|
||||||
sum_offline += delta;
|
|
||||||
if (min_offline < 0) {
|
|
||||||
min_offline = delta;
|
|
||||||
max_offline = delta;
|
|
||||||
}
|
|
||||||
if (min_offline > delta)
|
|
||||||
min_offline = delta;
|
|
||||||
if (max_offline < delta)
|
|
||||||
max_offline = delta;
|
|
||||||
}
|
|
||||||
} else if (cpu_is_hotpluggable(cpu)) {
|
|
||||||
if (verbose)
|
|
||||||
pr_alert("%s" TORTURE_FLAG
|
|
||||||
"rcu_torture_onoff task: onlining %d\n",
|
|
||||||
torture_type, cpu);
|
|
||||||
starttime = jiffies;
|
|
||||||
n_online_attempts++;
|
|
||||||
ret = cpu_up(cpu);
|
|
||||||
if (ret) {
|
|
||||||
if (verbose)
|
|
||||||
pr_alert("%s" TORTURE_FLAG
|
|
||||||
"rcu_torture_onoff task: online %d failed: errno %d\n",
|
|
||||||
torture_type, cpu, ret);
|
|
||||||
} else {
|
|
||||||
if (verbose)
|
|
||||||
pr_alert("%s" TORTURE_FLAG
|
|
||||||
"rcu_torture_onoff task: onlined %d\n",
|
|
||||||
torture_type, cpu);
|
|
||||||
n_online_successes++;
|
|
||||||
delta = jiffies - starttime;
|
|
||||||
sum_online += delta;
|
|
||||||
if (min_online < 0) {
|
|
||||||
min_online = delta;
|
|
||||||
max_online = delta;
|
|
||||||
}
|
|
||||||
if (min_online > delta)
|
|
||||||
min_online = delta;
|
|
||||||
if (max_online < delta)
|
|
||||||
max_online = delta;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
schedule_timeout_interruptible(onoff_interval * HZ);
|
|
||||||
}
|
|
||||||
VERBOSE_TOROUT_STRING("rcu_torture_onoff task stopping");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
rcu_torture_onoff_init(void)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (onoff_interval <= 0)
|
|
||||||
return 0;
|
|
||||||
onoff_task = kthread_run(rcu_torture_onoff, NULL, "rcu_torture_onoff");
|
|
||||||
if (IS_ERR(onoff_task)) {
|
|
||||||
ret = PTR_ERR(onoff_task);
|
|
||||||
onoff_task = NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
torture_shuffle_task_register(onoff_task);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rcu_torture_onoff_cleanup(void)
|
|
||||||
{
|
|
||||||
if (onoff_task == NULL)
|
|
||||||
return;
|
|
||||||
VERBOSE_TOROUT_STRING("Stopping rcu_torture_onoff task");
|
|
||||||
kthread_stop(onoff_task);
|
|
||||||
onoff_task = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* #ifdef CONFIG_HOTPLUG_CPU */
|
|
||||||
|
|
||||||
static int
|
|
||||||
rcu_torture_onoff_init(void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rcu_torture_onoff_cleanup(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* #else #ifdef CONFIG_HOTPLUG_CPU */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CPU-stall kthread. It waits as specified by stall_cpu_holdoff, then
|
* CPU-stall kthread. It waits as specified by stall_cpu_holdoff, then
|
||||||
* induces a CPU stall for the time specified by stall_cpu.
|
* induces a CPU stall for the time specified by stall_cpu.
|
||||||
|
@ -1657,7 +1504,7 @@ rcu_torture_cleanup(void)
|
||||||
kthread_stop(shutdown_task);
|
kthread_stop(shutdown_task);
|
||||||
}
|
}
|
||||||
shutdown_task = NULL;
|
shutdown_task = NULL;
|
||||||
rcu_torture_onoff_cleanup();
|
torture_onoff_cleanup();
|
||||||
|
|
||||||
/* Wait for all RCU callbacks to fire. */
|
/* Wait for all RCU callbacks to fire. */
|
||||||
|
|
||||||
|
@ -1668,8 +1515,7 @@ rcu_torture_cleanup(void)
|
||||||
|
|
||||||
if (atomic_read(&n_rcu_torture_error) || n_rcu_torture_barrier_error)
|
if (atomic_read(&n_rcu_torture_error) || n_rcu_torture_barrier_error)
|
||||||
rcu_torture_print_module_parms(cur_ops, "End of test: FAILURE");
|
rcu_torture_print_module_parms(cur_ops, "End of test: FAILURE");
|
||||||
else if (n_online_successes != n_online_attempts ||
|
else if (torture_onoff_failures())
|
||||||
n_offline_successes != n_offline_attempts)
|
|
||||||
rcu_torture_print_module_parms(cur_ops,
|
rcu_torture_print_module_parms(cur_ops,
|
||||||
"End of test: RCU_HOTPLUG");
|
"End of test: RCU_HOTPLUG");
|
||||||
else
|
else
|
||||||
|
@ -1935,7 +1781,7 @@ rcu_torture_init(void)
|
||||||
torture_shuffle_task_register(shutdown_task);
|
torture_shuffle_task_register(shutdown_task);
|
||||||
wake_up_process(shutdown_task);
|
wake_up_process(shutdown_task);
|
||||||
}
|
}
|
||||||
i = rcu_torture_onoff_init();
|
i = torture_onoff_init(onoff_holdoff * HZ, onoff_interval * HZ);
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
firsterr = i;
|
firsterr = i;
|
||||||
goto unwind;
|
goto unwind;
|
||||||
|
|
186
kernel/torture.c
186
kernel/torture.c
|
@ -54,6 +54,192 @@ EXPORT_SYMBOL_GPL(fullstop);
|
||||||
DEFINE_MUTEX(fullstop_mutex);
|
DEFINE_MUTEX(fullstop_mutex);
|
||||||
EXPORT_SYMBOL_GPL(fullstop_mutex);
|
EXPORT_SYMBOL_GPL(fullstop_mutex);
|
||||||
|
|
||||||
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Variables for online-offline handling. Only present if CPU hotplug
|
||||||
|
* is enabled, otherwise does nothing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static struct task_struct *onoff_task;
|
||||||
|
static long onoff_holdoff;
|
||||||
|
static long onoff_interval;
|
||||||
|
static long n_offline_attempts;
|
||||||
|
static long n_offline_successes;
|
||||||
|
static unsigned long sum_offline;
|
||||||
|
static int min_offline = -1;
|
||||||
|
static int max_offline;
|
||||||
|
static long n_online_attempts;
|
||||||
|
static long n_online_successes;
|
||||||
|
static unsigned long sum_online;
|
||||||
|
static int min_online = -1;
|
||||||
|
static int max_online;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Execute random CPU-hotplug operations at the interval specified
|
||||||
|
* by the onoff_interval.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
torture_onoff(void *arg)
|
||||||
|
{
|
||||||
|
int cpu;
|
||||||
|
unsigned long delta;
|
||||||
|
int maxcpu = -1;
|
||||||
|
DEFINE_TORTURE_RANDOM(rand);
|
||||||
|
int ret;
|
||||||
|
unsigned long starttime;
|
||||||
|
|
||||||
|
VERBOSE_TOROUT_STRING("torture_onoff task started");
|
||||||
|
for_each_online_cpu(cpu)
|
||||||
|
maxcpu = cpu;
|
||||||
|
WARN_ON(maxcpu < 0);
|
||||||
|
if (onoff_holdoff > 0) {
|
||||||
|
VERBOSE_TOROUT_STRING("torture_onoff begin holdoff");
|
||||||
|
schedule_timeout_interruptible(onoff_holdoff);
|
||||||
|
VERBOSE_TOROUT_STRING("torture_onoff end holdoff");
|
||||||
|
}
|
||||||
|
while (!torture_must_stop()) {
|
||||||
|
cpu = (torture_random(&rand) >> 4) % (maxcpu + 1);
|
||||||
|
if (cpu_online(cpu) && cpu_is_hotpluggable(cpu)) {
|
||||||
|
if (verbose)
|
||||||
|
pr_alert("%s" TORTURE_FLAG
|
||||||
|
"torture_onoff task: offlining %d\n",
|
||||||
|
torture_type, cpu);
|
||||||
|
starttime = jiffies;
|
||||||
|
n_offline_attempts++;
|
||||||
|
ret = cpu_down(cpu);
|
||||||
|
if (ret) {
|
||||||
|
if (verbose)
|
||||||
|
pr_alert("%s" TORTURE_FLAG
|
||||||
|
"torture_onoff task: offline %d failed: errno %d\n",
|
||||||
|
torture_type, cpu, ret);
|
||||||
|
} else {
|
||||||
|
if (verbose)
|
||||||
|
pr_alert("%s" TORTURE_FLAG
|
||||||
|
"torture_onoff task: offlined %d\n",
|
||||||
|
torture_type, cpu);
|
||||||
|
n_offline_successes++;
|
||||||
|
delta = jiffies - starttime;
|
||||||
|
sum_offline += delta;
|
||||||
|
if (min_offline < 0) {
|
||||||
|
min_offline = delta;
|
||||||
|
max_offline = delta;
|
||||||
|
}
|
||||||
|
if (min_offline > delta)
|
||||||
|
min_offline = delta;
|
||||||
|
if (max_offline < delta)
|
||||||
|
max_offline = delta;
|
||||||
|
}
|
||||||
|
} else if (cpu_is_hotpluggable(cpu)) {
|
||||||
|
if (verbose)
|
||||||
|
pr_alert("%s" TORTURE_FLAG
|
||||||
|
"torture_onoff task: onlining %d\n",
|
||||||
|
torture_type, cpu);
|
||||||
|
starttime = jiffies;
|
||||||
|
n_online_attempts++;
|
||||||
|
ret = cpu_up(cpu);
|
||||||
|
if (ret) {
|
||||||
|
if (verbose)
|
||||||
|
pr_alert("%s" TORTURE_FLAG
|
||||||
|
"torture_onoff task: online %d failed: errno %d\n",
|
||||||
|
torture_type, cpu, ret);
|
||||||
|
} else {
|
||||||
|
if (verbose)
|
||||||
|
pr_alert("%s" TORTURE_FLAG
|
||||||
|
"torture_onoff task: onlined %d\n",
|
||||||
|
torture_type, cpu);
|
||||||
|
n_online_successes++;
|
||||||
|
delta = jiffies - starttime;
|
||||||
|
sum_online += delta;
|
||||||
|
if (min_online < 0) {
|
||||||
|
min_online = delta;
|
||||||
|
max_online = delta;
|
||||||
|
}
|
||||||
|
if (min_online > delta)
|
||||||
|
min_online = delta;
|
||||||
|
if (max_online < delta)
|
||||||
|
max_online = delta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
schedule_timeout_interruptible(onoff_interval);
|
||||||
|
}
|
||||||
|
VERBOSE_TOROUT_STRING("torture_onoff task stopping");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* #ifdef CONFIG_HOTPLUG_CPU */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initiate online-offline handling.
|
||||||
|
*/
|
||||||
|
int torture_onoff_init(long ooholdoff, long oointerval)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
onoff_holdoff = ooholdoff;
|
||||||
|
onoff_interval = oointerval;
|
||||||
|
if (onoff_interval <= 0)
|
||||||
|
return 0;
|
||||||
|
onoff_task = kthread_run(torture_onoff, NULL, "torture_onoff");
|
||||||
|
if (IS_ERR(onoff_task)) {
|
||||||
|
ret = PTR_ERR(onoff_task);
|
||||||
|
onoff_task = NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
torture_shuffle_task_register(onoff_task);
|
||||||
|
#endif /* #ifdef CONFIG_HOTPLUG_CPU */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(torture_onoff_init);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clean up after online/offline testing.
|
||||||
|
*/
|
||||||
|
void torture_onoff_cleanup(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
|
if (onoff_task == NULL)
|
||||||
|
return;
|
||||||
|
VERBOSE_TOROUT_STRING("Stopping torture_onoff task");
|
||||||
|
kthread_stop(onoff_task);
|
||||||
|
onoff_task = NULL;
|
||||||
|
#endif /* #ifdef CONFIG_HOTPLUG_CPU */
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(torture_onoff_cleanup);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print online/offline testing statistics.
|
||||||
|
*/
|
||||||
|
char *torture_onoff_stats(char *page)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
|
page += sprintf(page,
|
||||||
|
"onoff: %ld/%ld:%ld/%ld %d,%d:%d,%d %lu:%lu (HZ=%d) ",
|
||||||
|
n_online_successes, n_online_attempts,
|
||||||
|
n_offline_successes, n_offline_attempts,
|
||||||
|
min_online, max_online,
|
||||||
|
min_offline, max_offline,
|
||||||
|
sum_online, sum_offline, HZ);
|
||||||
|
#endif /* #ifdef CONFIG_HOTPLUG_CPU */
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(torture_onoff_stats);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Were all the online/offline operations successful?
|
||||||
|
*/
|
||||||
|
bool torture_onoff_failures(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
|
return n_online_successes != n_online_attempts ||
|
||||||
|
n_offline_successes != n_offline_attempts;
|
||||||
|
#else /* #ifdef CONFIG_HOTPLUG_CPU */
|
||||||
|
return false;
|
||||||
|
#endif /* #else #ifdef CONFIG_HOTPLUG_CPU */
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(torture_onoff_failures);
|
||||||
|
|
||||||
#define TORTURE_RANDOM_MULT 39916801 /* prime */
|
#define TORTURE_RANDOM_MULT 39916801 /* prime */
|
||||||
#define TORTURE_RANDOM_ADD 479001701 /* prime */
|
#define TORTURE_RANDOM_ADD 479001701 /* prime */
|
||||||
#define TORTURE_RANDOM_REFRESH 10000
|
#define TORTURE_RANDOM_REFRESH 10000
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue