Commit 4622b487 authored by Paul E. McKenney's avatar Paul E. McKenney

rcutorture: Abstract torture_shutdown_notify()

Because handling the race between rmmod and system shutdown is not
specific to RCU, this commit abstracts torture_shutdown_notify(),
placing this code into kernel/torture.c.  This change also allows
fullstop_mutex to be private to kernel/torture.c.
Signed-off-by: default avatarPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Reviewed-by: default avatarJosh Triplett <josh@joshtriplett.org>
parent 3c626237
...@@ -46,8 +46,6 @@ ...@@ -46,8 +46,6 @@
#define FULLSTOP_SHUTDOWN 1 /* System shutdown with rcutorture running. */ #define FULLSTOP_SHUTDOWN 1 /* System shutdown with rcutorture running. */
#define FULLSTOP_RMMOD 2 /* Normal rmmod of rcutorture. */ #define FULLSTOP_RMMOD 2 /* Normal rmmod of rcutorture. */
extern int fullstop; extern int fullstop;
/* Protect fullstop transitions and spawning of kthreads. */
extern struct mutex fullstop_mutex;
#define TORTURE_FLAG "-torture:" #define TORTURE_FLAG "-torture:"
#define TOROUT_STRING(s) \ #define TOROUT_STRING(s) \
......
...@@ -189,23 +189,6 @@ static DECLARE_WAIT_QUEUE_HEAD(barrier_wq); ...@@ -189,23 +189,6 @@ static DECLARE_WAIT_QUEUE_HEAD(barrier_wq);
/* Forward reference. */ /* Forward reference. */
static void rcu_torture_cleanup(void); static void rcu_torture_cleanup(void);
/*
* Detect and respond to a system shutdown.
*/
static int
rcutorture_shutdown_notify(struct notifier_block *unused1,
unsigned long unused2, void *unused3)
{
mutex_lock(&fullstop_mutex);
if (fullstop == FULLSTOP_DONTSTOP)
fullstop = FULLSTOP_SHUTDOWN;
else
pr_warn(/* but going down anyway, so... */
"Concurrent 'rmmod rcutorture' and shutdown illegal!\n");
mutex_unlock(&fullstop_mutex);
return NOTIFY_DONE;
}
/* /*
* Allocate an element from the rcu_tortures pool. * Allocate an element from the rcu_tortures pool.
*/ */
...@@ -1098,10 +1081,6 @@ rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, const char *tag) ...@@ -1098,10 +1081,6 @@ rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, const char *tag)
onoff_interval, onoff_holdoff); onoff_interval, onoff_holdoff);
} }
static struct notifier_block rcutorture_shutdown_nb = {
.notifier_call = rcutorture_shutdown_notify,
};
static void rcutorture_booster_cleanup(int cpu) static void rcutorture_booster_cleanup(int cpu)
{ {
struct task_struct *t; struct task_struct *t;
...@@ -1428,7 +1407,6 @@ rcu_torture_cleanup(void) ...@@ -1428,7 +1407,6 @@ rcu_torture_cleanup(void)
cur_ops->cb_barrier(); cur_ops->cb_barrier();
return; return;
} }
unregister_reboot_notifier(&rcutorture_shutdown_nb);
rcu_torture_barrier_cleanup(); rcu_torture_barrier_cleanup();
rcu_torture_stall_cleanup(); rcu_torture_stall_cleanup();
...@@ -1774,7 +1752,6 @@ rcu_torture_init(void) ...@@ -1774,7 +1752,6 @@ rcu_torture_init(void)
firsterr = i; firsterr = i;
goto unwind; goto unwind;
} }
register_reboot_notifier(&rcutorture_shutdown_nb);
i = rcu_torture_stall_init(); i = rcu_torture_stall_init();
if (i != 0) { if (i != 0) {
firsterr = i; firsterr = i;
......
...@@ -54,8 +54,7 @@ static bool verbose; ...@@ -54,8 +54,7 @@ static bool verbose;
int fullstop = FULLSTOP_RMMOD; int fullstop = FULLSTOP_RMMOD;
EXPORT_SYMBOL_GPL(fullstop); EXPORT_SYMBOL_GPL(fullstop);
DEFINE_MUTEX(fullstop_mutex); static DEFINE_MUTEX(fullstop_mutex);
EXPORT_SYMBOL_GPL(fullstop_mutex);
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
...@@ -422,14 +421,32 @@ EXPORT_SYMBOL_GPL(torture_shuffle_cleanup); ...@@ -422,14 +421,32 @@ EXPORT_SYMBOL_GPL(torture_shuffle_cleanup);
void torture_shutdown_absorb(const char *title) void torture_shutdown_absorb(const char *title)
{ {
while (ACCESS_ONCE(fullstop) == FULLSTOP_SHUTDOWN) { while (ACCESS_ONCE(fullstop) == FULLSTOP_SHUTDOWN) {
pr_notice( pr_notice("torture thread %s parking due to system shutdown\n",
"torture thread %s parking due to system shutdown\n", title);
title);
schedule_timeout_uninterruptible(MAX_SCHEDULE_TIMEOUT); schedule_timeout_uninterruptible(MAX_SCHEDULE_TIMEOUT);
} }
} }
EXPORT_SYMBOL_GPL(torture_shutdown_absorb); EXPORT_SYMBOL_GPL(torture_shutdown_absorb);
/*
* Detect and respond to a system shutdown.
*/
static int torture_shutdown_notify(struct notifier_block *unused1,
unsigned long unused2, void *unused3)
{
mutex_lock(&fullstop_mutex);
if (fullstop == FULLSTOP_DONTSTOP)
fullstop = FULLSTOP_SHUTDOWN;
else
pr_warn("Concurrent rmmod and shutdown illegal!\n");
mutex_unlock(&fullstop_mutex);
return NOTIFY_DONE;
}
static struct notifier_block torture_shutdown_nb = {
.notifier_call = torture_shutdown_notify,
};
/* /*
* Initialize torture module. Please note that this is -not- invoked via * Initialize torture module. Please note that this is -not- invoked via
* the usual module_init() mechanism, but rather by an explicit call from * the usual module_init() mechanism, but rather by an explicit call from
...@@ -451,6 +468,7 @@ EXPORT_SYMBOL_GPL(torture_init_begin); ...@@ -451,6 +468,7 @@ EXPORT_SYMBOL_GPL(torture_init_begin);
void __init torture_init_end(void) void __init torture_init_end(void)
{ {
mutex_unlock(&fullstop_mutex); mutex_unlock(&fullstop_mutex);
register_reboot_notifier(&torture_shutdown_nb);
} }
EXPORT_SYMBOL_GPL(torture_init_end); EXPORT_SYMBOL_GPL(torture_init_end);
...@@ -474,6 +492,7 @@ bool torture_cleanup(void) ...@@ -474,6 +492,7 @@ bool torture_cleanup(void)
} }
fullstop = FULLSTOP_RMMOD; fullstop = FULLSTOP_RMMOD;
mutex_unlock(&fullstop_mutex); mutex_unlock(&fullstop_mutex);
unregister_reboot_notifier(&torture_shutdown_nb);
torture_shuffle_cleanup(); torture_shuffle_cleanup();
torture_onoff_cleanup(); torture_onoff_cleanup();
return false; return false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment