aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavidlohr Bueso <dave@stgolabs.net>2014-09-11 23:40:21 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2014-09-16 16:41:06 -0400
commitd36a7a0d5e8b5bff1671723d733eb61621b0cee4 (patch)
tree17cbd1c2542a4b587890a593446757606a4a7834
parent1e6757a92189278c484799ea98fc69bdc528940e (diff)
torture: Address race in module cleanup
When performing module cleanups by calling torture_cleanup() the 'torture_type' string in nullified However, callers are not necessarily done, and might still need to reference the variable. This impacts both rcutorture and locktorture, causing printing things like: [ 94.226618] (null)-torture: Stopping lock_torture_writer task [ 94.226624] (null)-torture: Stopping lock_torture_stats task Thus delay this operation until the very end of the cleanup process. The consequence (which shouldn't matter for this kid of program) is, of course, that we delay the window between rmmod and modprobing, for instance in module_torture_begin(). Signed-off-by: Davidlohr Bueso <dbueso@suse.de> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-rw-r--r--include/linux/torture.h3
-rw-r--r--kernel/locking/locktorture.c3
-rw-r--r--kernel/rcu/rcutorture.c3
-rw-r--r--kernel/torture.c16
4 files changed, 19 insertions, 6 deletions
diff --git a/include/linux/torture.h b/include/linux/torture.h
index fec46f8c08eb..7759fc3c622d 100644
--- a/include/linux/torture.h
+++ b/include/linux/torture.h
@@ -77,7 +77,8 @@ int torture_stutter_init(int s);
77/* Initialization and cleanup. */ 77/* Initialization and cleanup. */
78bool torture_init_begin(char *ttype, bool v, int *runnable); 78bool torture_init_begin(char *ttype, bool v, int *runnable);
79void torture_init_end(void); 79void torture_init_end(void);
80bool torture_cleanup(void); 80bool torture_cleanup_begin(void);
81void torture_cleanup_end(void);
81bool torture_must_stop(void); 82bool torture_must_stop(void);
82bool torture_must_stop_irq(void); 83bool torture_must_stop_irq(void);
83void torture_kthread_stopping(char *title); 84void torture_kthread_stopping(char *title);
diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c
index de703a769c1d..988267cc92c1 100644
--- a/kernel/locking/locktorture.c
+++ b/kernel/locking/locktorture.c
@@ -361,7 +361,7 @@ static void lock_torture_cleanup(void)
361{ 361{
362 int i; 362 int i;
363 363
364 if (torture_cleanup()) 364 if (torture_cleanup_begin())
365 return; 365 return;
366 366
367 if (writer_tasks) { 367 if (writer_tasks) {
@@ -384,6 +384,7 @@ static void lock_torture_cleanup(void)
384 else 384 else
385 lock_torture_print_module_parms(cur_ops, 385 lock_torture_print_module_parms(cur_ops,
386 "End of test: SUCCESS"); 386 "End of test: SUCCESS");
387 torture_cleanup_end();
387} 388}
388 389
389static int __init lock_torture_init(void) 390static int __init lock_torture_init(void)
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 6d1509500d2b..04c4b5afb759 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -1514,7 +1514,7 @@ rcu_torture_cleanup(void)
1514 int i; 1514 int i;
1515 1515
1516 rcutorture_record_test_transition(); 1516 rcutorture_record_test_transition();
1517 if (torture_cleanup()) { 1517 if (torture_cleanup_begin()) {
1518 if (cur_ops->cb_barrier != NULL) 1518 if (cur_ops->cb_barrier != NULL)
1519 cur_ops->cb_barrier(); 1519 cur_ops->cb_barrier();
1520 return; 1520 return;
@@ -1566,6 +1566,7 @@ rcu_torture_cleanup(void)
1566 "End of test: RCU_HOTPLUG"); 1566 "End of test: RCU_HOTPLUG");
1567 else 1567 else
1568 rcu_torture_print_module_parms(cur_ops, "End of test: SUCCESS"); 1568 rcu_torture_print_module_parms(cur_ops, "End of test: SUCCESS");
1569 torture_cleanup_end();
1569} 1570}
1570 1571
1571#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD 1572#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
diff --git a/kernel/torture.c b/kernel/torture.c
index ede8b25ec1ae..dd70993c266c 100644
--- a/kernel/torture.c
+++ b/kernel/torture.c
@@ -633,8 +633,13 @@ EXPORT_SYMBOL_GPL(torture_init_end);
633 * 633 *
634 * This must be called before the caller starts shutting down its own 634 * This must be called before the caller starts shutting down its own
635 * kthreads. 635 * kthreads.
636 *
637 * Both torture_cleanup_begin() and torture_cleanup_end() must be paired,
638 * in order to correctly perform the cleanup. They are separated because
639 * threads can still need to reference the torture_type type, thus nullify
640 * only after completing all other relevant calls.
636 */ 641 */
637bool torture_cleanup(void) 642bool torture_cleanup_begin(void)
638{ 643{
639 mutex_lock(&fullstop_mutex); 644 mutex_lock(&fullstop_mutex);
640 if (ACCESS_ONCE(fullstop) == FULLSTOP_SHUTDOWN) { 645 if (ACCESS_ONCE(fullstop) == FULLSTOP_SHUTDOWN) {
@@ -649,12 +654,17 @@ bool torture_cleanup(void)
649 torture_shuffle_cleanup(); 654 torture_shuffle_cleanup();
650 torture_stutter_cleanup(); 655 torture_stutter_cleanup();
651 torture_onoff_cleanup(); 656 torture_onoff_cleanup();
657 return false;
658}
659EXPORT_SYMBOL_GPL(torture_cleanup_begin);
660
661void torture_cleanup_end(void)
662{
652 mutex_lock(&fullstop_mutex); 663 mutex_lock(&fullstop_mutex);
653 torture_type = NULL; 664 torture_type = NULL;
654 mutex_unlock(&fullstop_mutex); 665 mutex_unlock(&fullstop_mutex);
655 return false;
656} 666}
657EXPORT_SYMBOL_GPL(torture_cleanup); 667EXPORT_SYMBOL_GPL(torture_cleanup_end);
658 668
659/* 669/*
660 * Is it time for the current torture test to stop? 670 * Is it time for the current torture test to stop?