Skip to content

Commit 43b39ca

Browse files
Zqiangpaulmckrcu
authored andcommitted
rcutorture: Make rcutorture support srcu double call test
This commit allows rcutorture to test double-call_srcu() when the CONFIG_DEBUG_OBJECTS_RCU_HEAD Kconfig option is enabled. The non-raw sdp structure's ->spinlock will be acquired in call_srcu(), hence this commit also removes the current IRQ and preemption disabling so as to avoid lockdep complaints. Link: https://lore.kernel.org/all/[email protected]/ Signed-off-by: Zqiang <[email protected]> Signed-off-by: Paul E. McKenney <[email protected]>
1 parent 1613e60 commit 43b39ca

File tree

1 file changed

+26
-20
lines changed

1 file changed

+26
-20
lines changed

kernel/rcu/rcutorture.c

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ struct rcu_torture_ops {
390390
int extendables;
391391
int slow_gps;
392392
int no_pi_lock;
393+
int debug_objects;
393394
const char *name;
394395
};
395396

@@ -577,6 +578,7 @@ static struct rcu_torture_ops rcu_ops = {
577578
.irq_capable = 1,
578579
.can_boost = IS_ENABLED(CONFIG_RCU_BOOST),
579580
.extendables = RCUTORTURE_MAX_EXTEND,
581+
.debug_objects = 1,
580582
.name = "rcu"
581583
};
582584

@@ -747,6 +749,7 @@ static struct rcu_torture_ops srcu_ops = {
747749
.cbflood_max = 50000,
748750
.irq_capable = 1,
749751
.no_pi_lock = IS_ENABLED(CONFIG_TINY_SRCU),
752+
.debug_objects = 1,
750753
.name = "srcu"
751754
};
752755

@@ -786,6 +789,7 @@ static struct rcu_torture_ops srcud_ops = {
786789
.cbflood_max = 50000,
787790
.irq_capable = 1,
788791
.no_pi_lock = IS_ENABLED(CONFIG_TINY_SRCU),
792+
.debug_objects = 1,
789793
.name = "srcud"
790794
};
791795

@@ -3455,7 +3459,6 @@ rcu_torture_cleanup(void)
34553459
cur_ops->gp_slow_unregister(NULL);
34563460
}
34573461

3458-
#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
34593462
static void rcu_torture_leak_cb(struct rcu_head *rhp)
34603463
{
34613464
}
@@ -3473,7 +3476,6 @@ static void rcu_torture_err_cb(struct rcu_head *rhp)
34733476
*/
34743477
pr_alert("%s: duplicated callback was invoked.\n", KBUILD_MODNAME);
34753478
}
3476-
#endif /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
34773479

34783480
/*
34793481
* Verify that double-free causes debug-objects to complain, but only
@@ -3482,39 +3484,43 @@ static void rcu_torture_err_cb(struct rcu_head *rhp)
34823484
*/
34833485
static void rcu_test_debug_objects(void)
34843486
{
3485-
#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
34863487
struct rcu_head rh1;
34873488
struct rcu_head rh2;
3489+
int idx;
3490+
3491+
if (!IS_ENABLED(CONFIG_DEBUG_OBJECTS_RCU_HEAD)) {
3492+
pr_alert("%s: !CONFIG_DEBUG_OBJECTS_RCU_HEAD, not testing duplicate call_%s()\n",
3493+
KBUILD_MODNAME, cur_ops->name);
3494+
return;
3495+
}
3496+
3497+
if (WARN_ON_ONCE(cur_ops->debug_objects &&
3498+
(!cur_ops->call || !cur_ops->cb_barrier)))
3499+
return;
3500+
34883501
struct rcu_head *rhp = kmalloc(sizeof(*rhp), GFP_KERNEL);
34893502

34903503
init_rcu_head_on_stack(&rh1);
34913504
init_rcu_head_on_stack(&rh2);
3492-
pr_alert("%s: WARN: Duplicate call_rcu() test starting.\n", KBUILD_MODNAME);
3505+
pr_alert("%s: WARN: Duplicate call_%s() test starting.\n", KBUILD_MODNAME, cur_ops->name);
34933506

34943507
/* Try to queue the rh2 pair of callbacks for the same grace period. */
3495-
preempt_disable(); /* Prevent preemption from interrupting test. */
3496-
rcu_read_lock(); /* Make it impossible to finish a grace period. */
3497-
call_rcu_hurry(&rh1, rcu_torture_leak_cb); /* Start grace period. */
3498-
local_irq_disable(); /* Make it harder to start a new grace period. */
3499-
call_rcu_hurry(&rh2, rcu_torture_leak_cb);
3500-
call_rcu_hurry(&rh2, rcu_torture_err_cb); /* Duplicate callback. */
3508+
idx = cur_ops->readlock(); /* Make it impossible to finish a grace period. */
3509+
cur_ops->call(&rh1, rcu_torture_leak_cb); /* Start grace period. */
3510+
cur_ops->call(&rh2, rcu_torture_leak_cb);
3511+
cur_ops->call(&rh2, rcu_torture_err_cb); /* Duplicate callback. */
35013512
if (rhp) {
3502-
call_rcu_hurry(rhp, rcu_torture_leak_cb);
3503-
call_rcu_hurry(rhp, rcu_torture_err_cb); /* Another duplicate callback. */
3513+
cur_ops->call(rhp, rcu_torture_leak_cb);
3514+
cur_ops->call(rhp, rcu_torture_err_cb); /* Another duplicate callback. */
35043515
}
3505-
local_irq_enable();
3506-
rcu_read_unlock();
3507-
preempt_enable();
3516+
cur_ops->readunlock(idx);
35083517

35093518
/* Wait for them all to get done so we can safely return. */
3510-
rcu_barrier();
3511-
pr_alert("%s: WARN: Duplicate call_rcu() test complete.\n", KBUILD_MODNAME);
3519+
cur_ops->cb_barrier();
3520+
pr_alert("%s: WARN: Duplicate call_%s() test complete.\n", KBUILD_MODNAME, cur_ops->name);
35123521
destroy_rcu_head_on_stack(&rh1);
35133522
destroy_rcu_head_on_stack(&rh2);
35143523
kfree(rhp);
3515-
#else /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
3516-
pr_alert("%s: !CONFIG_DEBUG_OBJECTS_RCU_HEAD, not testing duplicate call_rcu()\n", KBUILD_MODNAME);
3517-
#endif /* #else #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
35183524
}
35193525

35203526
static void rcutorture_sync(void)

0 commit comments

Comments
 (0)