mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 02:17:36 -04:00
rcutorture: Fully test lazy RCU
Currently, rcutorture bypasses lazy RCU by using call_rcu_hurry(). This works, avoiding the dreaded rtort_pipe_count WARN(), but fails to fully test lazy RCU. The rtort_pipe_count WARN() splats because lazy RCU could delay the start of an RCU grace period for a full stutter period, which defaults to only three seconds. This commit therefore reverts the call_rcu_hurry() instances back to call_rcu(), but, in kernels built with CONFIG_RCU_LAZY=y, queues a workqueue handler just before the call to stutter_wait() in rcu_torture_writer(). This workqueue handler invokes rcu_barrier(), which motivates any lingering lazy callbacks, thus avoiding the splat. Reported-by: Saravana Kannan <saravanak@kernel.org> Signed-off-by: Paul E. McKenney <paulmck@kernel.org> Signed-off-by: Uladzislau Rezki (Sony) <urezki@gmail.com>
This commit is contained in:
committed by
Uladzislau Rezki (Sony)
parent
5200f5f493
commit
aa61e8b4fb
@@ -572,7 +572,7 @@ static unsigned long rcu_no_completed(void)
|
||||
|
||||
static void rcu_torture_deferred_free(struct rcu_torture *p)
|
||||
{
|
||||
call_rcu_hurry(&p->rtort_rcu, rcu_torture_cb);
|
||||
call_rcu(&p->rtort_rcu, rcu_torture_cb);
|
||||
}
|
||||
|
||||
static void rcu_sync_torture_init(void)
|
||||
@@ -619,7 +619,7 @@ static struct rcu_torture_ops rcu_ops = {
|
||||
.poll_gp_state_exp = poll_state_synchronize_rcu,
|
||||
.cond_sync_exp = cond_synchronize_rcu_expedited,
|
||||
.cond_sync_exp_full = cond_synchronize_rcu_expedited_full,
|
||||
.call = call_rcu_hurry,
|
||||
.call = call_rcu,
|
||||
.cb_barrier = rcu_barrier,
|
||||
.fqs = rcu_force_quiescent_state,
|
||||
.gp_kthread_dbg = show_rcu_gp_kthreads,
|
||||
@@ -1145,7 +1145,7 @@ static void rcu_tasks_torture_deferred_free(struct rcu_torture *p)
|
||||
|
||||
static void synchronize_rcu_mult_test(void)
|
||||
{
|
||||
synchronize_rcu_mult(call_rcu_tasks, call_rcu_hurry);
|
||||
synchronize_rcu_mult(call_rcu_tasks, call_rcu);
|
||||
}
|
||||
|
||||
static struct rcu_torture_ops tasks_ops = {
|
||||
@@ -1631,6 +1631,17 @@ static void do_rtws_sync(struct torture_random_state *trsp, void (*sync)(void))
|
||||
cpus_read_unlock();
|
||||
}
|
||||
|
||||
/*
|
||||
* Do an rcu_barrier() to motivate lazy callbacks during a stutter
|
||||
* pause. Without this, we can get false-positives rtort_pipe_count
|
||||
* splats.
|
||||
*/
|
||||
static void rcu_torture_writer_work(struct work_struct *work)
|
||||
{
|
||||
if (cur_ops->cb_barrier)
|
||||
cur_ops->cb_barrier();
|
||||
}
|
||||
|
||||
/*
|
||||
* RCU torture writer kthread. Repeatedly substitutes a new structure
|
||||
* for that pointed to by rcu_torture_current, freeing the old structure
|
||||
@@ -1651,6 +1662,7 @@ rcu_torture_writer(void *arg)
|
||||
int i;
|
||||
int idx;
|
||||
unsigned long j;
|
||||
struct work_struct lazy_work;
|
||||
int oldnice = task_nice(current);
|
||||
struct rcu_gp_oldstate *rgo = NULL;
|
||||
int rgo_size = 0;
|
||||
@@ -1703,6 +1715,9 @@ rcu_torture_writer(void *arg)
|
||||
pr_alert("%s" TORTURE_FLAG " Waited %lu jiffies for boot to complete.\n",
|
||||
torture_type, jiffies - j);
|
||||
|
||||
if (IS_ENABLED(CONFIG_RCU_LAZY))
|
||||
INIT_WORK_ONSTACK(&lazy_work, rcu_torture_writer_work);
|
||||
|
||||
do {
|
||||
rcu_torture_writer_state = RTWS_FIXED_DELAY;
|
||||
torture_hrtimeout_us(500, 1000, &rand);
|
||||
@@ -1895,6 +1910,8 @@ rcu_torture_writer(void *arg)
|
||||
!rcu_gp_is_normal();
|
||||
}
|
||||
rcu_torture_writer_state = RTWS_STUTTER;
|
||||
if (IS_ENABLED(CONFIG_RCU_LAZY))
|
||||
queue_work(system_percpu_wq, &lazy_work);
|
||||
stutter_waited = stutter_wait("rcu_torture_writer");
|
||||
if (stutter_waited &&
|
||||
!atomic_read(&rcu_fwd_cb_nodelay) &&
|
||||
@@ -1925,6 +1942,12 @@ rcu_torture_writer(void *arg)
|
||||
pr_alert("%s" TORTURE_FLAG
|
||||
" Dynamic grace-period expediting was disabled.\n",
|
||||
torture_type);
|
||||
|
||||
if (IS_ENABLED(CONFIG_RCU_LAZY)) {
|
||||
cancel_work_sync(&lazy_work);
|
||||
destroy_work_on_stack(&lazy_work);
|
||||
}
|
||||
|
||||
kfree(ulo);
|
||||
kfree(rgo);
|
||||
rcu_torture_writer_state = RTWS_STOPPING;
|
||||
|
||||
Reference in New Issue
Block a user