Commit 27569620c748ec13f801b4683b448a2ac2adaae4

Authored by Paul E. McKenney
Committed by Ingo Molnar
1 parent fa08661af8

rcu: Split hierarchical RCU initialization into boot-time and CPU-online pieces

This patch divides the rcutree initialization into boot-time
and hotplug-time components, so that the tree data structures
are guaranteed to be fully linked at boot time regardless of
what might happen in CPU hotplug operations.

This makes RCU more resilient against CPU hotplug misbehavior
(and vice versa), but more importantly, does a better job of
compartmentalizing the code.

Reported-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: laijs@cn.fujitsu.com
Cc: dipankar@in.ibm.com
Cc: josht@linux.vnet.ibm.com
Cc: akpm@linux-foundation.org
Cc: mathieu.desnoyers@polymtl.ca
Cc: dvhltc@us.ibm.com
Cc: niv@us.ibm.com
Cc: peterz@infradead.org
Cc: rostedt@goodmis.org
Cc: hugh.dickins@tiscali.co.uk
Cc: benh@kernel.crashing.org
LKML-Reference: <1250355231152-git-send-email->
Signed-off-by: Ingo Molnar <mingo@elte.hu>

Showing 1 changed file with 33 additions and 20 deletions Side-by-side Diff

... ... @@ -1325,22 +1325,40 @@
1325 1325 }
1326 1326  
1327 1327 /*
1328   - * Initialize a CPU's per-CPU RCU data. We take this "scorched earth"
1329   - * approach so that we don't have to worry about how long the CPU has
1330   - * been gone, or whether it ever was online previously. We do trust the
1331   - * ->mynode field, as it is constant for a given struct rcu_data and
1332   - * initialized during early boot.
1333   - *
1334   - * Note that only one online or offline event can be happening at a given
1335   - * time. Note also that we can accept some slop in the rsp->completed
1336   - * access due to the fact that this CPU cannot possibly have any RCU
1337   - * callbacks in flight yet.
  1328 + * Do boot-time initialization of a CPU's per-CPU RCU data.
1338 1329 */
  1330 +static void __init
  1331 +rcu_boot_init_percpu_data(int cpu, struct rcu_state *rsp)
  1332 +{
  1333 + unsigned long flags;
  1334 + int i;
  1335 + struct rcu_data *rdp = rsp->rda[cpu];
  1336 + struct rcu_node *rnp = rcu_get_root(rsp);
  1337 +
  1338 + /* Set up local state, ensuring consistent view of global state. */
  1339 + spin_lock_irqsave(&rnp->lock, flags);
  1340 + rdp->grpmask = 1UL << (cpu - rdp->mynode->grplo);
  1341 + rdp->nxtlist = NULL;
  1342 + for (i = 0; i < RCU_NEXT_SIZE; i++)
  1343 + rdp->nxttail[i] = &rdp->nxtlist;
  1344 + rdp->qlen = 0;
  1345 +#ifdef CONFIG_NO_HZ
  1346 + rdp->dynticks = &per_cpu(rcu_dynticks, cpu);
  1347 +#endif /* #ifdef CONFIG_NO_HZ */
  1348 + rdp->cpu = cpu;
  1349 + spin_unlock_irqrestore(&rnp->lock, flags);
  1350 +}
  1351 +
  1352 +/*
  1353 + * Initialize a CPU's per-CPU RCU data. Note that only one online or
  1354 + * offline event can be happening at a given time. Note also that we
  1355 + * can accept some slop in the rsp->completed access due to the fact
  1356 + * that this CPU cannot possibly have any RCU callbacks in flight yet.
  1357 + */
1339 1358 static void __cpuinit
1340 1359 rcu_init_percpu_data(int cpu, struct rcu_state *rsp)
1341 1360 {
1342 1361 unsigned long flags;
1343   - int i;
1344 1362 long lastcomp;
1345 1363 unsigned long mask;
1346 1364 struct rcu_data *rdp = rsp->rda[cpu];
1347 1365  
... ... @@ -1355,16 +1373,7 @@
1355 1373 rdp->qs_pending = 1; /* so set up to respond to current GP. */
1356 1374 rdp->beenonline = 1; /* We have now been online. */
1357 1375 rdp->passed_quiesc_completed = lastcomp - 1;
1358   - rdp->grpmask = 1UL << (cpu - rdp->mynode->grplo);
1359   - rdp->nxtlist = NULL;
1360   - for (i = 0; i < RCU_NEXT_SIZE; i++)
1361   - rdp->nxttail[i] = &rdp->nxtlist;
1362   - rdp->qlen = 0;
1363 1376 rdp->blimit = blimit;
1364   -#ifdef CONFIG_NO_HZ
1365   - rdp->dynticks = &per_cpu(rcu_dynticks, cpu);
1366   -#endif /* #ifdef CONFIG_NO_HZ */
1367   - rdp->cpu = cpu;
1368 1377 spin_unlock(&rnp->lock); /* irqs remain disabled. */
1369 1378  
1370 1379 /*
1371 1380  
... ... @@ -1539,8 +1548,12 @@
1539 1548 #endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
1540 1549 rcu_init_one(&rcu_state);
1541 1550 RCU_DATA_PTR_INIT(&rcu_state, rcu_data);
  1551 + for_each_possible_cpu(i)
  1552 + rcu_boot_init_percpu_data(i, &rcu_state);
1542 1553 rcu_init_one(&rcu_bh_state);
1543 1554 RCU_DATA_PTR_INIT(&rcu_bh_state, rcu_bh_data);
  1555 + for_each_possible_cpu(i)
  1556 + rcu_boot_init_percpu_data(i, &rcu_bh_state);
1544 1557  
1545 1558 for_each_online_cpu(i)
1546 1559 rcu_cpu_notify(&rcu_nb, CPU_UP_PREPARE, (void *)(long)i);