Skip to content

Commit 2024891

Browse files
committed
rcutorture: Fix rcu_torture_one_read()/rcu_torture_writer() data race
The ->rtort_pipe_count field in the rcu_torture structure checks for too-short grace periods, and is therefore read by rcutorture's readers while being updated by rcutorture's writers. This commit therefore adds the needed READ_ONCE() and WRITE_ONCE() invocations. This data race was reported by KCSAN. Not appropriate for backporting due to failure being unlikely and due to this being rcutorture. Signed-off-by: Paul E. McKenney <[email protected]>
1 parent beabc80 commit 2024891

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

kernel/rcu/rcutorture.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -375,11 +375,12 @@ rcu_torture_pipe_update_one(struct rcu_torture *rp)
375375
{
376376
int i;
377377

378-
i = rp->rtort_pipe_count;
378+
i = READ_ONCE(rp->rtort_pipe_count);
379379
if (i > RCU_TORTURE_PIPE_LEN)
380380
i = RCU_TORTURE_PIPE_LEN;
381381
atomic_inc(&rcu_torture_wcount[i]);
382-
if (++rp->rtort_pipe_count >= RCU_TORTURE_PIPE_LEN) {
382+
WRITE_ONCE(rp->rtort_pipe_count, i + 1);
383+
if (rp->rtort_pipe_count >= RCU_TORTURE_PIPE_LEN) {
383384
rp->rtort_mbtest = 0;
384385
return true;
385386
}
@@ -1015,7 +1016,8 @@ rcu_torture_writer(void *arg)
10151016
if (i > RCU_TORTURE_PIPE_LEN)
10161017
i = RCU_TORTURE_PIPE_LEN;
10171018
atomic_inc(&rcu_torture_wcount[i]);
1018-
old_rp->rtort_pipe_count++;
1019+
WRITE_ONCE(old_rp->rtort_pipe_count,
1020+
old_rp->rtort_pipe_count + 1);
10191021
switch (synctype[torture_random(&rand) % nsynctypes]) {
10201022
case RTWS_DEF_FREE:
10211023
rcu_torture_writer_state = RTWS_DEF_FREE;
@@ -1291,7 +1293,7 @@ static bool rcu_torture_one_read(struct torture_random_state *trsp)
12911293
atomic_inc(&n_rcu_torture_mberror);
12921294
rtrsp = rcutorture_loop_extend(&readstate, trsp, rtrsp);
12931295
preempt_disable();
1294-
pipe_count = p->rtort_pipe_count;
1296+
pipe_count = READ_ONCE(p->rtort_pipe_count);
12951297
if (pipe_count > RCU_TORTURE_PIPE_LEN) {
12961298
/* Should not happen, but... */
12971299
pipe_count = RCU_TORTURE_PIPE_LEN;

0 commit comments

Comments
 (0)