diff options
author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2014-01-30 18:49:29 -0500 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2014-02-23 12:01:12 -0500 |
commit | 36970bb91d89618d3495babf44b934e9c9db6bbc (patch) | |
tree | cee37f3089c868338f626124124fe2f90c26cdbd | |
parent | 4622b487ecf0094401ac10e504606e5cbdea5a6e (diff) |
rcutorture: Privatize fullstop
This commit introduces the torture_must_stop() function in order to
keep use of the fullstop variable local to kernel/torture.c. There
is also a torture_must_stop_irq() counterpart for use from RCU callbacks,
timeout handlers, and the like.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
-rw-r--r-- | include/linux/torture.h | 8 | ||||
-rw-r--r-- | kernel/rcu/rcutorture.c | 38 | ||||
-rw-r--r-- | kernel/torture.c | 27 |
3 files changed, 42 insertions, 31 deletions
diff --git a/include/linux/torture.h b/include/linux/torture.h index 742d8a402f19..0259db38bfb0 100644 --- a/include/linux/torture.h +++ b/include/linux/torture.h | |||
@@ -41,12 +41,6 @@ | |||
41 | module_param(name, type, 0444); \ | 41 | module_param(name, type, 0444); \ |
42 | MODULE_PARM_DESC(name, msg); | 42 | MODULE_PARM_DESC(name, msg); |
43 | 43 | ||
44 | /* Mediate rmmod and system shutdown. Concurrent rmmod & shutdown illegal! */ | ||
45 | #define FULLSTOP_DONTSTOP 0 /* Normal operation. */ | ||
46 | #define FULLSTOP_SHUTDOWN 1 /* System shutdown with rcutorture running. */ | ||
47 | #define FULLSTOP_RMMOD 2 /* Normal rmmod of rcutorture. */ | ||
48 | extern int fullstop; | ||
49 | |||
50 | #define TORTURE_FLAG "-torture:" | 44 | #define TORTURE_FLAG "-torture:" |
51 | #define TOROUT_STRING(s) \ | 45 | #define TOROUT_STRING(s) \ |
52 | pr_alert("%s" TORTURE_FLAG s "\n", torture_type) | 46 | pr_alert("%s" TORTURE_FLAG s "\n", torture_type) |
@@ -85,5 +79,7 @@ void torture_shutdown_absorb(const char *title); | |||
85 | void torture_init_begin(char *ttype, bool v); | 79 | void torture_init_begin(char *ttype, bool v); |
86 | void torture_init_end(void); | 80 | void torture_init_end(void); |
87 | bool torture_cleanup(void); | 81 | bool torture_cleanup(void); |
82 | bool torture_must_stop(void); | ||
83 | bool torture_must_stop_irq(void); | ||
88 | 84 | ||
89 | #endif /* __LINUX_TORTURE_H */ | 85 | #endif /* __LINUX_TORTURE_H */ |
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index 2560e9313887..9357c88cc8cc 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c | |||
@@ -304,7 +304,7 @@ rcu_torture_cb(struct rcu_head *p) | |||
304 | int i; | 304 | int i; |
305 | struct rcu_torture *rp = container_of(p, struct rcu_torture, rtort_rcu); | 305 | struct rcu_torture *rp = container_of(p, struct rcu_torture, rtort_rcu); |
306 | 306 | ||
307 | if (fullstop != FULLSTOP_DONTSTOP) { | 307 | if (torture_must_stop_irq()) { |
308 | /* Test is ending, just drop callbacks on the floor. */ | 308 | /* Test is ending, just drop callbacks on the floor. */ |
309 | /* The next initialization will pick up the pieces. */ | 309 | /* The next initialization will pick up the pieces. */ |
310 | return; | 310 | return; |
@@ -572,8 +572,7 @@ static int rcu_torture_boost(void *arg) | |||
572 | while (ULONG_CMP_LT(jiffies, oldstarttime)) { | 572 | while (ULONG_CMP_LT(jiffies, oldstarttime)) { |
573 | schedule_timeout_interruptible(oldstarttime - jiffies); | 573 | schedule_timeout_interruptible(oldstarttime - jiffies); |
574 | rcu_stutter_wait("rcu_torture_boost"); | 574 | rcu_stutter_wait("rcu_torture_boost"); |
575 | if (kthread_should_stop() || | 575 | if (torture_must_stop()) |
576 | fullstop != FULLSTOP_DONTSTOP) | ||
577 | goto checkwait; | 576 | goto checkwait; |
578 | } | 577 | } |
579 | 578 | ||
@@ -595,8 +594,7 @@ static int rcu_torture_boost(void *arg) | |||
595 | } | 594 | } |
596 | cond_resched(); | 595 | cond_resched(); |
597 | rcu_stutter_wait("rcu_torture_boost"); | 596 | rcu_stutter_wait("rcu_torture_boost"); |
598 | if (kthread_should_stop() || | 597 | if (torture_must_stop()) |
599 | fullstop != FULLSTOP_DONTSTOP) | ||
600 | goto checkwait; | 598 | goto checkwait; |
601 | } | 599 | } |
602 | 600 | ||
@@ -621,7 +619,7 @@ static int rcu_torture_boost(void *arg) | |||
621 | 619 | ||
622 | /* Go do the stutter. */ | 620 | /* Go do the stutter. */ |
623 | checkwait: rcu_stutter_wait("rcu_torture_boost"); | 621 | checkwait: rcu_stutter_wait("rcu_torture_boost"); |
624 | } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); | 622 | } while (!torture_must_stop()); |
625 | 623 | ||
626 | /* Clean up and exit. */ | 624 | /* Clean up and exit. */ |
627 | VERBOSE_TOROUT_STRING("rcu_torture_boost task stopping"); | 625 | VERBOSE_TOROUT_STRING("rcu_torture_boost task stopping"); |
@@ -659,7 +657,7 @@ rcu_torture_fqs(void *arg) | |||
659 | fqs_burst_remaining -= fqs_holdoff; | 657 | fqs_burst_remaining -= fqs_holdoff; |
660 | } | 658 | } |
661 | rcu_stutter_wait("rcu_torture_fqs"); | 659 | rcu_stutter_wait("rcu_torture_fqs"); |
662 | } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); | 660 | } while (!torture_must_stop()); |
663 | VERBOSE_TOROUT_STRING("rcu_torture_fqs task stopping"); | 661 | VERBOSE_TOROUT_STRING("rcu_torture_fqs task stopping"); |
664 | torture_shutdown_absorb("rcu_torture_fqs"); | 662 | torture_shutdown_absorb("rcu_torture_fqs"); |
665 | while (!kthread_should_stop()) | 663 | while (!kthread_should_stop()) |
@@ -731,7 +729,7 @@ rcu_torture_writer(void *arg) | |||
731 | } | 729 | } |
732 | rcutorture_record_progress(++rcu_torture_current_version); | 730 | rcutorture_record_progress(++rcu_torture_current_version); |
733 | rcu_stutter_wait("rcu_torture_writer"); | 731 | rcu_stutter_wait("rcu_torture_writer"); |
734 | } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); | 732 | } while (!torture_must_stop()); |
735 | VERBOSE_TOROUT_STRING("rcu_torture_writer task stopping"); | 733 | VERBOSE_TOROUT_STRING("rcu_torture_writer task stopping"); |
736 | torture_shutdown_absorb("rcu_torture_writer"); | 734 | torture_shutdown_absorb("rcu_torture_writer"); |
737 | while (!kthread_should_stop()) | 735 | while (!kthread_should_stop()) |
@@ -768,7 +766,7 @@ rcu_torture_fakewriter(void *arg) | |||
768 | cur_ops->exp_sync(); | 766 | cur_ops->exp_sync(); |
769 | } | 767 | } |
770 | rcu_stutter_wait("rcu_torture_fakewriter"); | 768 | rcu_stutter_wait("rcu_torture_fakewriter"); |
771 | } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); | 769 | } while (!torture_must_stop()); |
772 | 770 | ||
773 | VERBOSE_TOROUT_STRING("rcu_torture_fakewriter task stopping"); | 771 | VERBOSE_TOROUT_STRING("rcu_torture_fakewriter task stopping"); |
774 | torture_shutdown_absorb("rcu_torture_fakewriter"); | 772 | torture_shutdown_absorb("rcu_torture_fakewriter"); |
@@ -913,7 +911,7 @@ rcu_torture_reader(void *arg) | |||
913 | cur_ops->readunlock(idx); | 911 | cur_ops->readunlock(idx); |
914 | schedule(); | 912 | schedule(); |
915 | rcu_stutter_wait("rcu_torture_reader"); | 913 | rcu_stutter_wait("rcu_torture_reader"); |
916 | } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); | 914 | } while (!torture_must_stop()); |
917 | VERBOSE_TOROUT_STRING("rcu_torture_reader task stopping"); | 915 | VERBOSE_TOROUT_STRING("rcu_torture_reader task stopping"); |
918 | torture_shutdown_absorb("rcu_torture_reader"); | 916 | torture_shutdown_absorb("rcu_torture_reader"); |
919 | if (irqreader && cur_ops->irq_capable) | 917 | if (irqreader && cur_ops->irq_capable) |
@@ -1022,9 +1020,6 @@ rcu_torture_stats_print(void) | |||
1022 | /* | 1020 | /* |
1023 | * Periodically prints torture statistics, if periodic statistics printing | 1021 | * Periodically prints torture statistics, if periodic statistics printing |
1024 | * was specified via the stat_interval module parameter. | 1022 | * was specified via the stat_interval module parameter. |
1025 | * | ||
1026 | * No need to worry about fullstop here, since this one doesn't reference | ||
1027 | * volatile state or register callbacks. | ||
1028 | */ | 1023 | */ |
1029 | static int | 1024 | static int |
1030 | rcu_torture_stats(void *arg) | 1025 | rcu_torture_stats(void *arg) |
@@ -1034,7 +1029,7 @@ rcu_torture_stats(void *arg) | |||
1034 | schedule_timeout_interruptible(stat_interval * HZ); | 1029 | schedule_timeout_interruptible(stat_interval * HZ); |
1035 | rcu_torture_stats_print(); | 1030 | rcu_torture_stats_print(); |
1036 | torture_shutdown_absorb("rcu_torture_stats"); | 1031 | torture_shutdown_absorb("rcu_torture_stats"); |
1037 | } while (!kthread_should_stop()); | 1032 | } while (!torture_must_stop()); |
1038 | VERBOSE_TOROUT_STRING("rcu_torture_stats task stopping"); | 1033 | VERBOSE_TOROUT_STRING("rcu_torture_stats task stopping"); |
1039 | return 0; | 1034 | return 0; |
1040 | } | 1035 | } |
@@ -1241,16 +1236,15 @@ static int rcu_torture_barrier_cbs(void *arg) | |||
1241 | wait_event(barrier_cbs_wq[myid], | 1236 | wait_event(barrier_cbs_wq[myid], |
1242 | (newphase = | 1237 | (newphase = |
1243 | ACCESS_ONCE(barrier_phase)) != lastphase || | 1238 | ACCESS_ONCE(barrier_phase)) != lastphase || |
1244 | kthread_should_stop() || | 1239 | torture_must_stop()); |
1245 | fullstop != FULLSTOP_DONTSTOP); | ||
1246 | lastphase = newphase; | 1240 | lastphase = newphase; |
1247 | smp_mb(); /* ensure barrier_phase load before ->call(). */ | 1241 | smp_mb(); /* ensure barrier_phase load before ->call(). */ |
1248 | if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP) | 1242 | if (torture_must_stop()) |
1249 | break; | 1243 | break; |
1250 | cur_ops->call(&rcu, rcu_torture_barrier_cbf); | 1244 | cur_ops->call(&rcu, rcu_torture_barrier_cbf); |
1251 | if (atomic_dec_and_test(&barrier_cbs_count)) | 1245 | if (atomic_dec_and_test(&barrier_cbs_count)) |
1252 | wake_up(&barrier_wq); | 1246 | wake_up(&barrier_wq); |
1253 | } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); | 1247 | } while (!torture_must_stop()); |
1254 | VERBOSE_TOROUT_STRING("rcu_torture_barrier_cbs task stopping"); | 1248 | VERBOSE_TOROUT_STRING("rcu_torture_barrier_cbs task stopping"); |
1255 | torture_shutdown_absorb("rcu_torture_barrier_cbs"); | 1249 | torture_shutdown_absorb("rcu_torture_barrier_cbs"); |
1256 | while (!kthread_should_stop()) | 1250 | while (!kthread_should_stop()) |
@@ -1275,9 +1269,8 @@ static int rcu_torture_barrier(void *arg) | |||
1275 | wake_up(&barrier_cbs_wq[i]); | 1269 | wake_up(&barrier_cbs_wq[i]); |
1276 | wait_event(barrier_wq, | 1270 | wait_event(barrier_wq, |
1277 | atomic_read(&barrier_cbs_count) == 0 || | 1271 | atomic_read(&barrier_cbs_count) == 0 || |
1278 | kthread_should_stop() || | 1272 | torture_must_stop()); |
1279 | fullstop != FULLSTOP_DONTSTOP); | 1273 | if (torture_must_stop()) |
1280 | if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP) | ||
1281 | break; | 1274 | break; |
1282 | n_barrier_attempts++; | 1275 | n_barrier_attempts++; |
1283 | cur_ops->cb_barrier(); /* Implies smp_mb() for wait_event(). */ | 1276 | cur_ops->cb_barrier(); /* Implies smp_mb() for wait_event(). */ |
@@ -1287,7 +1280,7 @@ static int rcu_torture_barrier(void *arg) | |||
1287 | } | 1280 | } |
1288 | n_barrier_successes++; | 1281 | n_barrier_successes++; |
1289 | schedule_timeout_interruptible(HZ / 10); | 1282 | schedule_timeout_interruptible(HZ / 10); |
1290 | } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); | 1283 | } while (!torture_must_stop()); |
1291 | VERBOSE_TOROUT_STRING("rcu_torture_barrier task stopping"); | 1284 | VERBOSE_TOROUT_STRING("rcu_torture_barrier task stopping"); |
1292 | torture_shutdown_absorb("rcu_torture_barrier"); | 1285 | torture_shutdown_absorb("rcu_torture_barrier"); |
1293 | while (!kthread_should_stop()) | 1286 | while (!kthread_should_stop()) |
@@ -1585,7 +1578,6 @@ rcu_torture_init(void) | |||
1585 | else | 1578 | else |
1586 | nrealreaders = 2 * num_online_cpus(); | 1579 | nrealreaders = 2 * num_online_cpus(); |
1587 | rcu_torture_print_module_parms(cur_ops, "Start of test"); | 1580 | rcu_torture_print_module_parms(cur_ops, "Start of test"); |
1588 | fullstop = FULLSTOP_DONTSTOP; | ||
1589 | 1581 | ||
1590 | /* Set up the freelist. */ | 1582 | /* Set up the freelist. */ |
1591 | 1583 | ||
diff --git a/kernel/torture.c b/kernel/torture.c index b02fa2785bbb..ed360cf948da 100644 --- a/kernel/torture.c +++ b/kernel/torture.c | |||
@@ -52,8 +52,11 @@ MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com>"); | |||
52 | static char *torture_type; | 52 | static char *torture_type; |
53 | static bool verbose; | 53 | static bool verbose; |
54 | 54 | ||
55 | int fullstop = FULLSTOP_RMMOD; | 55 | /* Mediate rmmod and system shutdown. Concurrent rmmod & shutdown illegal! */ |
56 | EXPORT_SYMBOL_GPL(fullstop); | 56 | #define FULLSTOP_DONTSTOP 0 /* Normal operation. */ |
57 | #define FULLSTOP_SHUTDOWN 1 /* System shutdown with torture running. */ | ||
58 | #define FULLSTOP_RMMOD 2 /* Normal rmmod of torture. */ | ||
59 | static int fullstop = FULLSTOP_RMMOD; | ||
57 | static DEFINE_MUTEX(fullstop_mutex); | 60 | static DEFINE_MUTEX(fullstop_mutex); |
58 | 61 | ||
59 | #ifdef CONFIG_HOTPLUG_CPU | 62 | #ifdef CONFIG_HOTPLUG_CPU |
@@ -458,6 +461,7 @@ void __init torture_init_begin(char *ttype, bool v) | |||
458 | mutex_lock(&fullstop_mutex); | 461 | mutex_lock(&fullstop_mutex); |
459 | torture_type = ttype; | 462 | torture_type = ttype; |
460 | verbose = v; | 463 | verbose = v; |
464 | fullstop = FULLSTOP_DONTSTOP; | ||
461 | 465 | ||
462 | } | 466 | } |
463 | EXPORT_SYMBOL_GPL(torture_init_begin); | 467 | EXPORT_SYMBOL_GPL(torture_init_begin); |
@@ -498,3 +502,22 @@ bool torture_cleanup(void) | |||
498 | return false; | 502 | return false; |
499 | } | 503 | } |
500 | EXPORT_SYMBOL_GPL(torture_cleanup); | 504 | EXPORT_SYMBOL_GPL(torture_cleanup); |
505 | |||
506 | /* | ||
507 | * Is it time for the current torture test to stop? | ||
508 | */ | ||
509 | bool torture_must_stop(void) | ||
510 | { | ||
511 | return torture_must_stop_irq() || kthread_should_stop(); | ||
512 | } | ||
513 | EXPORT_SYMBOL_GPL(torture_must_stop); | ||
514 | |||
515 | /* | ||
516 | * Is it time for the current torture test to stop? This is the irq-safe | ||
517 | * version, hence no check for kthread_should_stop(). | ||
518 | */ | ||
519 | bool torture_must_stop_irq(void) | ||
520 | { | ||
521 | return fullstop != FULLSTOP_DONTSTOP; | ||
522 | } | ||
523 | EXPORT_SYMBOL_GPL(torture_must_stop_irq); | ||