rcu: Provide diagnostic option to slow down grace-period initialization
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Fri, 23 Jan 2015 02:24:08 +0000 (18:24 -0800)
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Wed, 11 Mar 2015 20:22:38 +0000 (13:22 -0700)
Grace-period initialization normally proceeds quite quickly, so
that it is very difficult to reproduce races against grace-period
initialization.  This commit therefore allows grace-period
initialization to be artificially slowed down, increasing
race-reproduction probability.  A pair of new Kconfig parameters are
provided, CONFIG_RCU_TORTURE_TEST_SLOW_INIT to enable the slowdowns, and
CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY to specify the number of jiffies
of slowdown to apply.  A boot-time parameter named rcutree.gp_init_delay
allows boot-time delay to be specified.  By default, no delay will be
applied even if CONFIG_RCU_TORTURE_TEST_SLOW_INIT is set.

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Documentation/kernel-parameters.txt
kernel/rcu/tree.c
lib/Kconfig.debug

index bfcb1a6..94de410 100644 (file)
@@ -2968,6 +2968,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        Set maximum number of finished RCU callbacks to
                        process in one batch.
 
+       rcutree.gp_init_delay=  [KNL]
+                       Set the number of jiffies to delay each step of
+                       RCU grace-period initialization.  This only has
+                       effect when CONFIG_RCU_TORTURE_TEST_SLOW_INIT is
+                       set.
+
        rcutree.rcu_fanout_leaf= [KNL]
                        Increase the number of CPUs assigned to each
                        leaf rcu_node structure.  Useful for very large
index 3b7e413..b42001f 100644 (file)
@@ -160,6 +160,12 @@ static void invoke_rcu_callbacks(struct rcu_state *rsp, struct rcu_data *rdp);
 static int kthread_prio = CONFIG_RCU_KTHREAD_PRIO;
 module_param(kthread_prio, int, 0644);
 
+/* Delay in jiffies for grace-period initialization delays. */
+static int gp_init_delay = IS_ENABLED(CONFIG_RCU_TORTURE_TEST_SLOW_INIT)
+                               ? CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY
+                               : 0;
+module_param(gp_init_delay, int, 0644);
+
 /*
  * Track the rcutorture test sequence number and the update version
  * number within a given test.  The rcutorture_testseq is incremented
@@ -1769,6 +1775,10 @@ static int rcu_gp_init(struct rcu_state *rsp)
                raw_spin_unlock_irq(&rnp->lock);
                cond_resched_rcu_qs();
                ACCESS_ONCE(rsp->gp_activity) = jiffies;
+               if (IS_ENABLED(CONFIG_RCU_TORTURE_TEST_SLOW_INIT) &&
+                   gp_init_delay > 0 &&
+                   !(rsp->gpnum % (rcu_num_nodes * 10)))
+                       schedule_timeout_uninterruptible(gp_init_delay);
        }
 
        mutex_unlock(&rsp->onoff_mutex);
index c5cefb3..feee8da 100644 (file)
@@ -1257,6 +1257,30 @@ config RCU_TORTURE_TEST_RUNNABLE
          Say N here if you want the RCU torture tests to start only
          after being manually enabled via /proc.
 
+config RCU_TORTURE_TEST_SLOW_INIT
+       bool "Slow down RCU grace-period initialization to expose races"
+       depends on RCU_TORTURE_TEST
+       help
+         This option makes grace-period initialization block for a
+         few jiffies between initializing each pair of consecutive
+         rcu_node structures.  This helps to expose races involving
+         grace-period initialization, in other words, it makes your
+         kernel less stable.  It can also greatly increase grace-period
+         latency, especially on systems with large numbers of CPUs.
+         This is useful when torture-testing RCU, but in almost no
+         other circumstance.
+
+         Say Y here if you want your system to crash and hang more often.
+         Say N if you want a sane system.
+
+config RCU_TORTURE_TEST_SLOW_INIT_DELAY
+       int "How much to slow down RCU grace-period initialization"
+       range 0 5
+       default 0
+       help
+         This option specifies the number of jiffies to wait between
+         each rcu_node structure initialization.
+
 config RCU_CPU_STALL_TIMEOUT
        int "RCU CPU stall timeout in seconds"
        depends on RCU_STALL_COMMON