diff options
author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2014-01-28 18:58:22 -0500 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2014-02-23 12:01:06 -0500 |
commit | 2e9e8081d2e7a4efb582a240aa7fee991bbbabb0 (patch) | |
tree | 21b3850bb6568d7bc61b432305c20b2423de24d7 /kernel/torture.c | |
parent | 3808dc9fab05913060626d7f0edd0f195cb9dcab (diff) |
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>
Diffstat (limited to 'kernel/torture.c')
-rw-r--r-- | kernel/torture.c | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/kernel/torture.c b/kernel/torture.c index 26058f20ee83..a7ec8a7d561e 100644 --- a/kernel/torture.c +++ b/kernel/torture.c | |||
@@ -54,6 +54,192 @@ EXPORT_SYMBOL_GPL(fullstop); | |||
54 | DEFINE_MUTEX(fullstop_mutex); | 54 | DEFINE_MUTEX(fullstop_mutex); |
55 | EXPORT_SYMBOL_GPL(fullstop_mutex); | 55 | EXPORT_SYMBOL_GPL(fullstop_mutex); |
56 | 56 | ||
57 | #ifdef CONFIG_HOTPLUG_CPU | ||
58 | |||
59 | /* | ||
60 | * Variables for online-offline handling. Only present if CPU hotplug | ||
61 | * is enabled, otherwise does nothing. | ||
62 | */ | ||
63 | |||
64 | static struct task_struct *onoff_task; | ||
65 | static long onoff_holdoff; | ||
66 | static long onoff_interval; | ||
67 | static long n_offline_attempts; | ||
68 | static long n_offline_successes; | ||
69 | static unsigned long sum_offline; | ||
70 | static int min_offline = -1; | ||
71 | static int max_offline; | ||
72 | static long n_online_attempts; | ||
73 | static long n_online_successes; | ||
74 | static unsigned long sum_online; | ||
75 | static int min_online = -1; | ||
76 | static int max_online; | ||
77 | |||
78 | /* | ||
79 | * Execute random CPU-hotplug operations at the interval specified | ||
80 | * by the onoff_interval. | ||
81 | */ | ||
82 | static int | ||
83 | torture_onoff(void *arg) | ||
84 | { | ||
85 | int cpu; | ||
86 | unsigned long delta; | ||
87 | int maxcpu = -1; | ||
88 | DEFINE_TORTURE_RANDOM(rand); | ||
89 | int ret; | ||
90 | unsigned long starttime; | ||
91 | |||
92 | VERBOSE_TOROUT_STRING("torture_onoff task started"); | ||
93 | for_each_online_cpu(cpu) | ||
94 | maxcpu = cpu; | ||
95 | WARN_ON(maxcpu < 0); | ||
96 | if (onoff_holdoff > 0) { | ||
97 | VERBOSE_TOROUT_STRING("torture_onoff begin holdoff"); | ||
98 | schedule_timeout_interruptible(onoff_holdoff); | ||
99 | VERBOSE_TOROUT_STRING("torture_onoff end holdoff"); | ||
100 | } | ||
101 | while (!torture_must_stop()) { | ||
102 | cpu = (torture_random(&rand) >> 4) % (maxcpu + 1); | ||
103 | if (cpu_online(cpu) && cpu_is_hotpluggable(cpu)) { | ||
104 | if (verbose) | ||
105 | pr_alert("%s" TORTURE_FLAG | ||
106 | "torture_onoff task: offlining %d\n", | ||
107 | torture_type, cpu); | ||
108 | starttime = jiffies; | ||
109 | n_offline_attempts++; | ||
110 | ret = cpu_down(cpu); | ||
111 | if (ret) { | ||
112 | if (verbose) | ||
113 | pr_alert("%s" TORTURE_FLAG | ||
114 | "torture_onoff task: offline %d failed: errno %d\n", | ||
115 | torture_type, cpu, ret); | ||
116 | } else { | ||
117 | if (verbose) | ||
118 | pr_alert("%s" TORTURE_FLAG | ||
119 | "torture_onoff task: offlined %d\n", | ||
120 | torture_type, cpu); | ||
121 | n_offline_successes++; | ||
122 | delta = jiffies - starttime; | ||
123 | sum_offline += delta; | ||
124 | if (min_offline < 0) { | ||
125 | min_offline = delta; | ||
126 | max_offline = delta; | ||
127 | } | ||
128 | if (min_offline > delta) | ||
129 | min_offline = delta; | ||
130 | if (max_offline < delta) | ||
131 | max_offline = delta; | ||
132 | } | ||
133 | } else if (cpu_is_hotpluggable(cpu)) { | ||
134 | if (verbose) | ||
135 | pr_alert("%s" TORTURE_FLAG | ||
136 | "torture_onoff task: onlining %d\n", | ||
137 | torture_type, cpu); | ||
138 | starttime = jiffies; | ||
139 | n_online_attempts++; | ||
140 | ret = cpu_up(cpu); | ||
141 | if (ret) { | ||
142 | if (verbose) | ||
143 | pr_alert("%s" TORTURE_FLAG | ||
144 | "torture_onoff task: online %d failed: errno %d\n", | ||
145 | torture_type, cpu, ret); | ||
146 | } else { | ||
147 | if (verbose) | ||
148 | pr_alert("%s" TORTURE_FLAG | ||
149 | "torture_onoff task: onlined %d\n", | ||
150 | torture_type, cpu); | ||
151 | n_online_successes++; | ||
152 | delta = jiffies - starttime; | ||
153 | sum_online += delta; | ||
154 | if (min_online < 0) { | ||
155 | min_online = delta; | ||
156 | max_online = delta; | ||
157 | } | ||
158 | if (min_online > delta) | ||
159 | min_online = delta; | ||
160 | if (max_online < delta) | ||
161 | max_online = delta; | ||
162 | } | ||
163 | } | ||
164 | schedule_timeout_interruptible(onoff_interval); | ||
165 | } | ||
166 | VERBOSE_TOROUT_STRING("torture_onoff task stopping"); | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | #endif /* #ifdef CONFIG_HOTPLUG_CPU */ | ||
171 | |||
172 | /* | ||
173 | * Initiate online-offline handling. | ||
174 | */ | ||
175 | int torture_onoff_init(long ooholdoff, long oointerval) | ||
176 | { | ||
177 | #ifdef CONFIG_HOTPLUG_CPU | ||
178 | int ret; | ||
179 | |||
180 | onoff_holdoff = ooholdoff; | ||
181 | onoff_interval = oointerval; | ||
182 | if (onoff_interval <= 0) | ||
183 | return 0; | ||
184 | onoff_task = kthread_run(torture_onoff, NULL, "torture_onoff"); | ||
185 | if (IS_ERR(onoff_task)) { | ||
186 | ret = PTR_ERR(onoff_task); | ||
187 | onoff_task = NULL; | ||
188 | return ret; | ||
189 | } | ||
190 | torture_shuffle_task_register(onoff_task); | ||
191 | #endif /* #ifdef CONFIG_HOTPLUG_CPU */ | ||
192 | return 0; | ||
193 | } | ||
194 | EXPORT_SYMBOL_GPL(torture_onoff_init); | ||
195 | |||
196 | /* | ||
197 | * Clean up after online/offline testing. | ||
198 | */ | ||
199 | void torture_onoff_cleanup(void) | ||
200 | { | ||
201 | #ifdef CONFIG_HOTPLUG_CPU | ||
202 | if (onoff_task == NULL) | ||
203 | return; | ||
204 | VERBOSE_TOROUT_STRING("Stopping torture_onoff task"); | ||
205 | kthread_stop(onoff_task); | ||
206 | onoff_task = NULL; | ||
207 | #endif /* #ifdef CONFIG_HOTPLUG_CPU */ | ||
208 | } | ||
209 | EXPORT_SYMBOL_GPL(torture_onoff_cleanup); | ||
210 | |||
211 | /* | ||
212 | * Print online/offline testing statistics. | ||
213 | */ | ||
214 | char *torture_onoff_stats(char *page) | ||
215 | { | ||
216 | #ifdef CONFIG_HOTPLUG_CPU | ||
217 | page += sprintf(page, | ||
218 | "onoff: %ld/%ld:%ld/%ld %d,%d:%d,%d %lu:%lu (HZ=%d) ", | ||
219 | n_online_successes, n_online_attempts, | ||
220 | n_offline_successes, n_offline_attempts, | ||
221 | min_online, max_online, | ||
222 | min_offline, max_offline, | ||
223 | sum_online, sum_offline, HZ); | ||
224 | #endif /* #ifdef CONFIG_HOTPLUG_CPU */ | ||
225 | return page; | ||
226 | } | ||
227 | EXPORT_SYMBOL_GPL(torture_onoff_stats); | ||
228 | |||
229 | /* | ||
230 | * Were all the online/offline operations successful? | ||
231 | */ | ||
232 | bool torture_onoff_failures(void) | ||
233 | { | ||
234 | #ifdef CONFIG_HOTPLUG_CPU | ||
235 | return n_online_successes != n_online_attempts || | ||
236 | n_offline_successes != n_offline_attempts; | ||
237 | #else /* #ifdef CONFIG_HOTPLUG_CPU */ | ||
238 | return false; | ||
239 | #endif /* #else #ifdef CONFIG_HOTPLUG_CPU */ | ||
240 | } | ||
241 | EXPORT_SYMBOL_GPL(torture_onoff_failures); | ||
242 | |||
57 | #define TORTURE_RANDOM_MULT 39916801 /* prime */ | 243 | #define TORTURE_RANDOM_MULT 39916801 /* prime */ |
58 | #define TORTURE_RANDOM_ADD 479001701 /* prime */ | 244 | #define TORTURE_RANDOM_ADD 479001701 /* prime */ |
59 | #define TORTURE_RANDOM_REFRESH 10000 | 245 | #define TORTURE_RANDOM_REFRESH 10000 |