rcutorture: Add grace period after CPU offline
Beyond a certain point in the CPU-hotplug offline process, timers get stranded on the outgoing CPU, and won't fire until that CPU comes back online, which might well be never. This commit therefore adds a hook in torture_onoff_init() that is invoked from torture_offline(), which rcutorture uses to occasionally wait for a grace period. This should result in failures for RCU implementations that rely on stranded timers eventually firing in the absence of the CPU coming back online. Reported-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Paul E. McKenney <paulmck@linux.ibm.com>
This commit is contained in:
parent
0d8a9ea976
commit
3a6cb58f15
|
@ -50,11 +50,12 @@
|
|||
do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! %s\n", torture_type, s); } while (0)
|
||||
|
||||
/* Definitions for online/offline exerciser. */
|
||||
typedef void torture_ofl_func(void);
|
||||
bool torture_offline(int cpu, long *n_onl_attempts, long *n_onl_successes,
|
||||
unsigned long *sum_offl, int *min_onl, int *max_onl);
|
||||
bool torture_online(int cpu, long *n_onl_attempts, long *n_onl_successes,
|
||||
unsigned long *sum_onl, int *min_onl, int *max_onl);
|
||||
int torture_onoff_init(long ooholdoff, long oointerval);
|
||||
int torture_onoff_init(long ooholdoff, long oointerval, torture_ofl_func *f);
|
||||
void torture_onoff_stats(void);
|
||||
bool torture_onoff_failures(void);
|
||||
|
||||
|
|
|
@ -970,7 +970,7 @@ static int __init lock_torture_init(void)
|
|||
/* Prepare torture context. */
|
||||
if (onoff_interval > 0) {
|
||||
firsterr = torture_onoff_init(onoff_holdoff * HZ,
|
||||
onoff_interval * HZ);
|
||||
onoff_interval * HZ, NULL);
|
||||
if (firsterr)
|
||||
goto unwind;
|
||||
}
|
||||
|
|
|
@ -2243,6 +2243,14 @@ static void rcu_test_debug_objects(void)
|
|||
#endif /* #else #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
|
||||
}
|
||||
|
||||
static void rcutorture_sync(void)
|
||||
{
|
||||
static unsigned long n;
|
||||
|
||||
if (cur_ops->sync && !(++n & 0xfff))
|
||||
cur_ops->sync();
|
||||
}
|
||||
|
||||
static int __init
|
||||
rcu_torture_init(void)
|
||||
{
|
||||
|
@ -2404,7 +2412,8 @@ rcu_torture_init(void)
|
|||
firsterr = torture_shutdown_init(shutdown_secs, rcu_torture_cleanup);
|
||||
if (firsterr)
|
||||
goto unwind;
|
||||
firsterr = torture_onoff_init(onoff_holdoff * HZ, onoff_interval);
|
||||
firsterr = torture_onoff_init(onoff_holdoff * HZ, onoff_interval,
|
||||
rcutorture_sync);
|
||||
if (firsterr)
|
||||
goto unwind;
|
||||
firsterr = rcu_torture_stall_init();
|
||||
|
|
|
@ -75,6 +75,7 @@ static DEFINE_MUTEX(fullstop_mutex);
|
|||
static struct task_struct *onoff_task;
|
||||
static long onoff_holdoff;
|
||||
static long onoff_interval;
|
||||
static torture_ofl_func *onoff_f;
|
||||
static long n_offline_attempts;
|
||||
static long n_offline_successes;
|
||||
static unsigned long sum_offline;
|
||||
|
@ -118,6 +119,8 @@ bool torture_offline(int cpu, long *n_offl_attempts, long *n_offl_successes,
|
|||
pr_alert("%s" TORTURE_FLAG
|
||||
"torture_onoff task: offlined %d\n",
|
||||
torture_type, cpu);
|
||||
if (onoff_f)
|
||||
onoff_f();
|
||||
(*n_offl_successes)++;
|
||||
delta = jiffies - starttime;
|
||||
*sum_offl += delta;
|
||||
|
@ -243,11 +246,12 @@ stop:
|
|||
/*
|
||||
* Initiate online-offline handling.
|
||||
*/
|
||||
int torture_onoff_init(long ooholdoff, long oointerval)
|
||||
int torture_onoff_init(long ooholdoff, long oointerval, torture_ofl_func *f)
|
||||
{
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
onoff_holdoff = ooholdoff;
|
||||
onoff_interval = oointerval;
|
||||
onoff_f = f;
|
||||
if (onoff_interval <= 0)
|
||||
return 0;
|
||||
return torture_create_kthread(torture_onoff, NULL, onoff_task);
|
||||
|
|
Loading…
Reference in New Issue