1 /* 2 * Module-based torture test facility for locking 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, you can access it online at 16 * http://www.gnu.org/licenses/gpl-2.0.html. 17 * 18 * Copyright (C) IBM Corporation, 2014 19 * 20 * Author: Paul E. McKenney <paulmck@us.ibm.com> 21 * Based on kernel/rcu/torture.c. 22 */ 23 #include <linux/types.h> 24 #include <linux/kernel.h> 25 #include <linux/init.h> 26 #include <linux/module.h> 27 #include <linux/kthread.h> 28 #include <linux/err.h> 29 #include <linux/spinlock.h> 30 #include <linux/smp.h> 31 #include <linux/interrupt.h> 32 #include <linux/sched.h> 33 #include <linux/atomic.h> 34 #include <linux/bitops.h> 35 #include <linux/completion.h> 36 #include <linux/moduleparam.h> 37 #include <linux/percpu.h> 38 #include <linux/notifier.h> 39 #include <linux/reboot.h> 40 #include <linux/freezer.h> 41 #include <linux/cpu.h> 42 #include <linux/delay.h> 43 #include <linux/stat.h> 44 #include <linux/slab.h> 45 #include <linux/trace_clock.h> 46 #include <asm/byteorder.h> 47 #include <linux/torture.h> 48 49 MODULE_LICENSE("GPL"); 50 MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com>"); 51 52 torture_param(int, nwriters_stress, -1, 53 "Number of write-locking stress-test threads"); 54 torture_param(int, onoff_holdoff, 0, "Time after boot before CPU hotplugs (s)"); 55 torture_param(int, onoff_interval, 0, 56 "Time between CPU hotplugs (s), 0=disable"); 57 torture_param(int, shuffle_interval, 3, 58 "Number of jiffies between shuffles, 0=disable"); 59 torture_param(int, shutdown_secs, 0, "Shutdown time (j), <= zero to disable."); 60 torture_param(int, stat_interval, 60, 61 "Number of seconds between stats printk()s"); 62 torture_param(int, stutter, 5, "Number of jiffies to run/halt test, 0=disable"); 63 torture_param(bool, verbose, true, 64 "Enable verbose debugging printk()s"); 65 66 static char *torture_type = "spin_lock"; 67 module_param(torture_type, charp, 0444); 68 MODULE_PARM_DESC(torture_type, 69 "Type of lock to torture (spin_lock, spin_lock_irq, ...)"); 70 71 static atomic_t n_lock_torture_errors; 72 73 static struct task_struct *stats_task; 74 static struct task_struct **writer_tasks; 75 76 static int nrealwriters_stress; 77 static bool lock_is_write_held; 78 79 struct lock_writer_stress_stats { 80 long n_write_lock_fail; 81 long n_write_lock_acquired; 82 }; 83 static struct lock_writer_stress_stats *lwsa; 84 85 #if defined(MODULE) 86 #define LOCKTORTURE_RUNNABLE_INIT 1 87 #else 88 #define LOCKTORTURE_RUNNABLE_INIT 0 89 #endif 90 int locktorture_runnable = LOCKTORTURE_RUNNABLE_INIT; 91 module_param(locktorture_runnable, int, 0444); 92 MODULE_PARM_DESC(locktorture_runnable, "Start locktorture at module init"); 93 94 /* Forward reference. */ 95 static void lock_torture_cleanup(void); 96 97 /* 98 * Operations vector for selecting different types of tests. 99 */ 100 struct lock_torture_ops { 101 void (*init)(void); 102 int (*writelock)(void); 103 void (*write_delay)(struct torture_random_state *trsp); 104 void (*writeunlock)(void); 105 unsigned long flags; 106 const char *name; 107 }; 108 109 static struct lock_torture_ops *cur_ops; 110 111 /* 112 * Definitions for lock torture testing. 113 */ 114 115 static int torture_lock_busted_write_lock(void) 116 { 117 return 0; /* BUGGY, do not use in real life!!! */ 118 } 119 120 static void torture_lock_busted_write_delay(struct torture_random_state *trsp) 121 { 122 const unsigned long longdelay_us = 100; 123 124 /* We want a long delay occasionally to force massive contention. */ 125 if (!(torture_random(trsp) % 126 (nrealwriters_stress * 2000 * longdelay_us))) 127 mdelay(longdelay_us); 128 #ifdef CONFIG_PREEMPT 129 if (!(torture_random(trsp) % (nrealwriters_stress * 20000))) 130 preempt_schedule(); /* Allow test to be preempted. */ 131 #endif 132 } 133 134 static void torture_lock_busted_write_unlock(void) 135 { 136 /* BUGGY, do not use in real life!!! */ 137 } 138 139 static struct lock_torture_ops lock_busted_ops = { 140 .writelock = torture_lock_busted_write_lock, 141 .write_delay = torture_lock_busted_write_delay, 142 .writeunlock = torture_lock_busted_write_unlock, 143 .name = "lock_busted" 144 }; 145 146 static DEFINE_SPINLOCK(torture_spinlock); 147 148 static int torture_spin_lock_write_lock(void) __acquires(torture_spinlock) 149 { 150 spin_lock(&torture_spinlock); 151 return 0; 152 } 153 154 static void torture_spin_lock_write_delay(struct torture_random_state *trsp) 155 { 156 const unsigned long shortdelay_us = 2; 157 const unsigned long longdelay_us = 100; 158 159 /* We want a short delay mostly to emulate likely code, and 160 * we want a long delay occasionally to force massive contention. 161 */ 162 if (!(torture_random(trsp) % 163 (nrealwriters_stress * 2000 * longdelay_us))) 164 mdelay(longdelay_us); 165 if (!(torture_random(trsp) % 166 (nrealwriters_stress * 2 * shortdelay_us))) 167 udelay(shortdelay_us); 168 #ifdef CONFIG_PREEMPT 169 if (!(torture_random(trsp) % (nrealwriters_stress * 20000))) 170 preempt_schedule(); /* Allow test to be preempted. */ 171 #endif 172 } 173 174 static void torture_spin_lock_write_unlock(void) __releases(torture_spinlock) 175 { 176 spin_unlock(&torture_spinlock); 177 } 178 179 static struct lock_torture_ops spin_lock_ops = { 180 .writelock = torture_spin_lock_write_lock, 181 .write_delay = torture_spin_lock_write_delay, 182 .writeunlock = torture_spin_lock_write_unlock, 183 .name = "spin_lock" 184 }; 185 186 static int torture_spin_lock_write_lock_irq(void) 187 __acquires(torture_spinlock_irq) 188 { 189 unsigned long flags; 190 191 spin_lock_irqsave(&torture_spinlock, flags); 192 cur_ops->flags = flags; 193 return 0; 194 } 195 196 static void torture_lock_spin_write_unlock_irq(void) 197 __releases(torture_spinlock) 198 { 199 spin_unlock_irqrestore(&torture_spinlock, cur_ops->flags); 200 } 201 202 static struct lock_torture_ops spin_lock_irq_ops = { 203 .writelock = torture_spin_lock_write_lock_irq, 204 .write_delay = torture_spin_lock_write_delay, 205 .writeunlock = torture_lock_spin_write_unlock_irq, 206 .name = "spin_lock_irq" 207 }; 208 209 /* 210 * Lock torture writer kthread. Repeatedly acquires and releases 211 * the lock, checking for duplicate acquisitions. 212 */ 213 static int lock_torture_writer(void *arg) 214 { 215 struct lock_writer_stress_stats *lwsp = arg; 216 static DEFINE_TORTURE_RANDOM(rand); 217 218 VERBOSE_TOROUT_STRING("lock_torture_writer task started"); 219 set_user_nice(current, MAX_NICE); 220 221 do { 222 if ((torture_random(&rand) & 0xfffff) == 0) 223 schedule_timeout_uninterruptible(1); 224 cur_ops->writelock(); 225 if (WARN_ON_ONCE(lock_is_write_held)) 226 lwsp->n_write_lock_fail++; 227 lock_is_write_held = 1; 228 lwsp->n_write_lock_acquired++; 229 cur_ops->write_delay(&rand); 230 lock_is_write_held = 0; 231 cur_ops->writeunlock(); 232 stutter_wait("lock_torture_writer"); 233 } while (!torture_must_stop()); 234 torture_kthread_stopping("lock_torture_writer"); 235 return 0; 236 } 237 238 /* 239 * Create an lock-torture-statistics message in the specified buffer. 240 */ 241 static void lock_torture_printk(char *page) 242 { 243 bool fail = 0; 244 int i; 245 long max = 0; 246 long min = lwsa[0].n_write_lock_acquired; 247 long long sum = 0; 248 249 for (i = 0; i < nrealwriters_stress; i++) { 250 if (lwsa[i].n_write_lock_fail) 251 fail = true; 252 sum += lwsa[i].n_write_lock_acquired; 253 if (max < lwsa[i].n_write_lock_fail) 254 max = lwsa[i].n_write_lock_fail; 255 if (min > lwsa[i].n_write_lock_fail) 256 min = lwsa[i].n_write_lock_fail; 257 } 258 page += sprintf(page, "%s%s ", torture_type, TORTURE_FLAG); 259 page += sprintf(page, 260 "Writes: Total: %lld Max/Min: %ld/%ld %s Fail: %d %s\n", 261 sum, max, min, max / 2 > min ? "???" : "", 262 fail, fail ? "!!!" : ""); 263 if (fail) 264 atomic_inc(&n_lock_torture_errors); 265 } 266 267 /* 268 * Print torture statistics. Caller must ensure that there is only one 269 * call to this function at a given time!!! This is normally accomplished 270 * by relying on the module system to only have one copy of the module 271 * loaded, and then by giving the lock_torture_stats kthread full control 272 * (or the init/cleanup functions when lock_torture_stats thread is not 273 * running). 274 */ 275 static void lock_torture_stats_print(void) 276 { 277 int size = nrealwriters_stress * 200 + 8192; 278 char *buf; 279 280 buf = kmalloc(size, GFP_KERNEL); 281 if (!buf) { 282 pr_err("lock_torture_stats_print: Out of memory, need: %d", 283 size); 284 return; 285 } 286 lock_torture_printk(buf); 287 pr_alert("%s", buf); 288 kfree(buf); 289 } 290 291 /* 292 * Periodically prints torture statistics, if periodic statistics printing 293 * was specified via the stat_interval module parameter. 294 * 295 * No need to worry about fullstop here, since this one doesn't reference 296 * volatile state or register callbacks. 297 */ 298 static int lock_torture_stats(void *arg) 299 { 300 VERBOSE_TOROUT_STRING("lock_torture_stats task started"); 301 do { 302 schedule_timeout_interruptible(stat_interval * HZ); 303 lock_torture_stats_print(); 304 torture_shutdown_absorb("lock_torture_stats"); 305 } while (!torture_must_stop()); 306 torture_kthread_stopping("lock_torture_stats"); 307 return 0; 308 } 309 310 static inline void 311 lock_torture_print_module_parms(struct lock_torture_ops *cur_ops, 312 const char *tag) 313 { 314 pr_alert("%s" TORTURE_FLAG 315 "--- %s: nwriters_stress=%d stat_interval=%d verbose=%d shuffle_interval=%d stutter=%d shutdown_secs=%d onoff_interval=%d onoff_holdoff=%d\n", 316 torture_type, tag, nrealwriters_stress, stat_interval, verbose, 317 shuffle_interval, stutter, shutdown_secs, 318 onoff_interval, onoff_holdoff); 319 } 320 321 static void lock_torture_cleanup(void) 322 { 323 int i; 324 325 if (torture_cleanup()) 326 return; 327 328 if (writer_tasks) { 329 for (i = 0; i < nrealwriters_stress; i++) 330 torture_stop_kthread(lock_torture_writer, 331 writer_tasks[i]); 332 kfree(writer_tasks); 333 writer_tasks = NULL; 334 } 335 336 torture_stop_kthread(lock_torture_stats, stats_task); 337 lock_torture_stats_print(); /* -After- the stats thread is stopped! */ 338 339 if (atomic_read(&n_lock_torture_errors)) 340 lock_torture_print_module_parms(cur_ops, 341 "End of test: FAILURE"); 342 else if (torture_onoff_failures()) 343 lock_torture_print_module_parms(cur_ops, 344 "End of test: LOCK_HOTPLUG"); 345 else 346 lock_torture_print_module_parms(cur_ops, 347 "End of test: SUCCESS"); 348 } 349 350 static int __init lock_torture_init(void) 351 { 352 int i; 353 int firsterr = 0; 354 static struct lock_torture_ops *torture_ops[] = { 355 &lock_busted_ops, &spin_lock_ops, &spin_lock_irq_ops, 356 }; 357 358 if (!torture_init_begin(torture_type, verbose, &locktorture_runnable)) 359 return -EBUSY; 360 361 /* Process args and tell the world that the torturer is on the job. */ 362 for (i = 0; i < ARRAY_SIZE(torture_ops); i++) { 363 cur_ops = torture_ops[i]; 364 if (strcmp(torture_type, cur_ops->name) == 0) 365 break; 366 } 367 if (i == ARRAY_SIZE(torture_ops)) { 368 pr_alert("lock-torture: invalid torture type: \"%s\"\n", 369 torture_type); 370 pr_alert("lock-torture types:"); 371 for (i = 0; i < ARRAY_SIZE(torture_ops); i++) 372 pr_alert(" %s", torture_ops[i]->name); 373 pr_alert("\n"); 374 torture_init_end(); 375 return -EINVAL; 376 } 377 if (cur_ops->init) 378 cur_ops->init(); /* no "goto unwind" prior to this point!!! */ 379 380 if (nwriters_stress >= 0) 381 nrealwriters_stress = nwriters_stress; 382 else 383 nrealwriters_stress = 2 * num_online_cpus(); 384 lock_torture_print_module_parms(cur_ops, "Start of test"); 385 386 /* Initialize the statistics so that each run gets its own numbers. */ 387 388 lock_is_write_held = 0; 389 lwsa = kmalloc(sizeof(*lwsa) * nrealwriters_stress, GFP_KERNEL); 390 if (lwsa == NULL) { 391 VERBOSE_TOROUT_STRING("lwsa: Out of memory"); 392 firsterr = -ENOMEM; 393 goto unwind; 394 } 395 for (i = 0; i < nrealwriters_stress; i++) { 396 lwsa[i].n_write_lock_fail = 0; 397 lwsa[i].n_write_lock_acquired = 0; 398 } 399 400 /* Start up the kthreads. */ 401 402 if (onoff_interval > 0) { 403 firsterr = torture_onoff_init(onoff_holdoff * HZ, 404 onoff_interval * HZ); 405 if (firsterr) 406 goto unwind; 407 } 408 if (shuffle_interval > 0) { 409 firsterr = torture_shuffle_init(shuffle_interval); 410 if (firsterr) 411 goto unwind; 412 } 413 if (shutdown_secs > 0) { 414 firsterr = torture_shutdown_init(shutdown_secs, 415 lock_torture_cleanup); 416 if (firsterr) 417 goto unwind; 418 } 419 if (stutter > 0) { 420 firsterr = torture_stutter_init(stutter); 421 if (firsterr) 422 goto unwind; 423 } 424 425 writer_tasks = kzalloc(nrealwriters_stress * sizeof(writer_tasks[0]), 426 GFP_KERNEL); 427 if (writer_tasks == NULL) { 428 VERBOSE_TOROUT_ERRSTRING("writer_tasks: Out of memory"); 429 firsterr = -ENOMEM; 430 goto unwind; 431 } 432 for (i = 0; i < nrealwriters_stress; i++) { 433 firsterr = torture_create_kthread(lock_torture_writer, &lwsa[i], 434 writer_tasks[i]); 435 if (firsterr) 436 goto unwind; 437 } 438 if (stat_interval > 0) { 439 firsterr = torture_create_kthread(lock_torture_stats, NULL, 440 stats_task); 441 if (firsterr) 442 goto unwind; 443 } 444 torture_init_end(); 445 return 0; 446 447 unwind: 448 torture_init_end(); 449 lock_torture_cleanup(); 450 return firsterr; 451 } 452 453 module_init(lock_torture_init); 454 module_exit(lock_torture_cleanup); 455