Skip to content
  • Paul E. McKenney's avatar
    rcu: Avoid RCU-preempt expedited grace-period botch · 389abd48
    Paul E. McKenney authored
    
    
    Because rcu_read_unlock_special() samples rcu_preempted_readers_exp(rnp)
    after dropping rnp->lock, the following sequence of events is possible:
    
    1.	Task A exits its RCU read-side critical section, and removes
    	itself from the ->blkd_tasks list, releases rnp->lock, and is
    	then preempted.  Task B remains on the ->blkd_tasks list, and
    	blocks the current expedited grace period.
    
    2.	Task B exits from its RCU read-side critical section and removes
    	itself from the ->blkd_tasks list.  Because it is the last task
    	blocking the current expedited grace period, it ends that
    	expedited grace period.
    
    3.	Task A resumes, and samples rcu_preempted_readers_exp(rnp) which
    	of course indicates that nothing is blocking the nonexistent
    	expedited grace period. Task A is again preempted.
    
    4.	Some other CPU starts an expedited grace period.  There are several
    	tasks blocking this expedited grace period queued on the
    	same rcu_node structure that Task A was using in step 1 above.
    
    5.	Task A examines its state and incorrectly concludes that it was
    	the last task blocking the expedited grace period on the current
    	rcu_node structure.  It therefore reports completion up the
    	rcu_node tree.
    
    6.	The expedited grace period can then incorrectly complete before
    	the tasks blocked on this same rcu_node structure exit their
    	RCU read-side critical sections.  Arbitrarily bad things happen.
    
    This commit therefore takes a snapshot of rcu_preempted_readers_exp(rnp)
    prior to dropping the lock, so that only the last task thinks that it is
    the last task, thus avoiding the failure scenario laid out above.
    
    Signed-off-by: default avatarPaul E. McKenney <paulmck@linux.vnet.ibm.com>
    Reviewed-by: default avatarJosh Triplett <josh@joshtriplett.org>
    389abd48