linux/kernel/rcu
Paul E. McKenney d7e2993396 rcu: Make rcu_barrier() understand about missing rcuo kthreads
Commit 35ce7f29a4 (rcu: Create rcuo kthreads only for onlined CPUs)
avoids creating rcuo kthreads for CPUs that never come online.  This
fixes a bug in many instances of firmware: Instead of lying about their
age, these systems instead lie about the number of CPUs that they have.
Before commit 35ce7f29a4, this could result in huge numbers of useless
rcuo kthreads being created.

It appears that experience indicates that I should have told the
people suffering from this problem to fix their broken firmware, but
I instead produced what turned out to be a partial fix.   The missing
piece supplied by this commit makes sure that rcu_barrier() knows not to
post callbacks for no-CBs CPUs that have not yet come online, because
otherwise rcu_barrier() will hang on systems having firmware that lies
about the number of CPUs.

It is tempting to simply have rcu_barrier() refuse to post a callback on
any no-CBs CPU that does not have an rcuo kthread.  This unfortunately
does not work because rcu_barrier() is required to wait for all pending
callbacks.  It is therefore required to wait even for those callbacks
that cannot possibly be invoked.  Even if doing so hangs the system.

Given that posting a callback to a no-CBs CPU that does not yet have an
rcuo kthread can hang rcu_barrier(), It is tempting to report an error
in this case.  Unfortunately, this will result in false positives at
boot time, when it is perfectly legal to post callbacks to the boot CPU
before the scheduler has started, in other words, before it is legal
to invoke rcu_barrier().

So this commit instead has rcu_barrier() avoid posting callbacks to
CPUs having neither rcuo kthread nor pending callbacks, and has it
complain bitterly if it finds CPUs having no rcuo kthread but some
pending callbacks.  And when rcu_barrier() does find CPUs having no rcuo
kthread but pending callbacks, as noted earlier, it has no choice but
to hang indefinitely.

Reported-by: Yanko Kaneti <yaneti@declera.com>
Reported-by: Jay Vosburgh <jay.vosburgh@canonical.com>
Reported-by: Meelis Roos <mroos@linux.ee>
Reported-by: Eric B Munson <emunson@akamai.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Tested-by: Eric B Munson <emunson@akamai.com>
Tested-by: Jay Vosburgh <jay.vosburgh@canonical.com>
Tested-by: Yanko Kaneti <yaneti@declera.com>
Tested-by: Kevin Fenzi <kevin@scrye.com>
Tested-by: Meelis Roos <mroos@linux.ee>
2014-10-28 13:24:13 -07:00
..
Makefile rcutorture: Abstract rcu_torture_random() 2014-02-23 09:00:58 -08:00
rcu.h rcu: Fix __rcu_reclaim() to use true/false for bool 2014-07-09 09:15:32 -07:00
rcutorture.c rcutorture: Rename rcutorture_runnable parameter 2014-09-16 13:41:44 -07:00
srcu.c rcu: Eliminate read-modify-write ACCESS_ONCE() calls 2014-07-09 09:14:49 -07:00
tiny.c Merge branch 'rcu-tasks.2014.09.10a' into HEAD 2014-09-16 10:10:44 -07:00
tiny_plugin.h rcu: Protect uses of ->jiffies_stall with ACCESS_ONCE() 2014-04-29 08:44:41 -07:00
tree.c rcu: Make rcu_barrier() understand about missing rcuo kthreads 2014-10-28 13:24:13 -07:00
tree.h rcu: Make rcu_barrier() understand about missing rcuo kthreads 2014-10-28 13:24:13 -07:00
tree_plugin.h rcu: Make rcu_barrier() understand about missing rcuo kthreads 2014-10-28 13:24:13 -07:00
tree_trace.c rcu: Stop tracking FSF's postal address 2014-02-17 15:01:37 -08:00
update.c Merge branch 'rcu-tasks.2014.09.10a' into HEAD 2014-09-16 10:10:44 -07:00