Skip to content

Commit 9385694

Browse files
paulmckrcuNeeraj Upadhyay (AMD)
authored andcommitted
rcutorture: Check for ->up_read() without matching ->down_read()
This commit creates counters in the rcu_torture_one_read_state_updown structure that check for a call to ->up_read() that lacks a matching call to ->down_read(). While in the area, add end-of-run cleanup code that prevents calls to rcu_torture_updown_hrt() from happening after the test has moved on. Yes, the srcu_barrier() at the end of the test will wait for them, but this could result in confusing states, statistics, and diagnostic information. So explicitly wait for them before we get to the end-of-test output. [ paulmck: Apply kernel test robot feedback. ] [ joel: Apply Boqun's fix for counter increment ordering. ] Signed-off-by: Paul E. McKenney <[email protected]> Tested-by: kernel test robot <[email protected]> Signed-off-by: Joel Fernandes <[email protected]> Signed-off-by: Neeraj Upadhyay (AMD) <[email protected]>
1 parent 62d92c9 commit 9385694

File tree

1 file changed

+13
-2
lines changed

1 file changed

+13
-2
lines changed

kernel/rcu/rcutorture.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2449,6 +2449,8 @@ struct rcu_torture_one_read_state_updown {
24492449
bool rtorsu_inuse;
24502450
ktime_t rtorsu_kt;
24512451
unsigned long rtorsu_j;
2452+
unsigned long rtorsu_ndowns;
2453+
unsigned long rtorsu_nups;
24522454
struct torture_random_state rtorsu_trs;
24532455
struct rcu_torture_one_read_state rtorsu_rtors;
24542456
};
@@ -2463,6 +2465,8 @@ static enum hrtimer_restart rcu_torture_updown_hrt(struct hrtimer *hrtp)
24632465

24642466
rtorsup = container_of(hrtp, struct rcu_torture_one_read_state_updown, rtorsu_hrt);
24652467
rcu_torture_one_read_end(&rtorsup->rtorsu_rtors, &rtorsup->rtorsu_trs, -1);
2468+
WARN_ONCE(rtorsup->rtorsu_nups >= rtorsup->rtorsu_ndowns, "%s: Up without matching down #%zu.\n", __func__, rtorsup - updownreaders);
2469+
rtorsup->rtorsu_nups++;
24662470
smp_store_release(&rtorsup->rtorsu_inuse, false);
24672471
return HRTIMER_NORESTART;
24682472
}
@@ -2507,8 +2511,12 @@ static void rcu_torture_updown_cleanup(void)
25072511
for (rtorsup = updownreaders; rtorsup < &updownreaders[n_up_down]; rtorsup++) {
25082512
if (!smp_load_acquire(&rtorsup->rtorsu_inuse))
25092513
continue;
2510-
if (!hrtimer_cancel(&rtorsup->rtorsu_hrt))
2511-
WARN_ON_ONCE(rtorsup->rtorsu_inuse);
2514+
if (hrtimer_cancel(&rtorsup->rtorsu_hrt) || WARN_ON_ONCE(rtorsup->rtorsu_inuse)) {
2515+
rcu_torture_one_read_end(&rtorsup->rtorsu_rtors, &rtorsup->rtorsu_trs, -1);
2516+
WARN_ONCE(rtorsup->rtorsu_nups >= rtorsup->rtorsu_ndowns, "%s: Up without matching down #%zu.\n", __func__, rtorsup - updownreaders);
2517+
rtorsup->rtorsu_nups++;
2518+
smp_store_release(&rtorsup->rtorsu_inuse, false);
2519+
}
25122520

25132521
}
25142522
kfree(updownreaders);
@@ -2524,10 +2532,13 @@ static void rcu_torture_updown_one(struct rcu_torture_one_read_state_updown *rto
25242532

25252533
init_rcu_torture_one_read_state(&rtorsup->rtorsu_rtors, &rtorsup->rtorsu_trs);
25262534
rawidx = cur_ops->down_read();
2535+
rtorsup->rtorsu_ndowns++;
25272536
idx = (rawidx << RCUTORTURE_RDR_SHIFT_1) & RCUTORTURE_RDR_MASK_1;
25282537
rtorsup->rtorsu_rtors.readstate = idx | RCUTORTURE_RDR_UPDOWN;
25292538
rtorsup->rtorsu_rtors.rtrsp++;
25302539
if (!rcu_torture_one_read_start(&rtorsup->rtorsu_rtors, &rtorsup->rtorsu_trs, -1)) {
2540+
WARN_ONCE(rtorsup->rtorsu_nups >= rtorsup->rtorsu_ndowns, "%s: Up without matching down #%zu.\n", __func__, rtorsup - updownreaders);
2541+
rtorsup->rtorsu_nups++;
25312542
schedule_timeout_idle(HZ);
25322543
return;
25332544
}

0 commit comments

Comments
 (0)