diff options
Diffstat (limited to 'kernel/rcu/srcutree.c')
| -rw-r--r-- | kernel/rcu/srcutree.c | 13 | 
1 files changed, 8 insertions, 5 deletions
| diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c index bc4b58b0204e..b24db425f16d 100644 --- a/kernel/rcu/srcutree.c +++ b/kernel/rcu/srcutree.c @@ -667,7 +667,10 @@ void cleanup_srcu_struct(struct srcu_struct *ssp)  		pr_info("%s: Active srcu_struct %p read state: %d gp state: %lu/%lu\n",  			__func__, ssp, rcu_seq_state(READ_ONCE(sup->srcu_gp_seq)),  			rcu_seq_current(&sup->srcu_gp_seq), sup->srcu_gp_seq_needed); -		return; /* Caller forgot to stop doing call_srcu()? */ +		return; // Caller forgot to stop doing call_srcu()? +			// Or caller invoked start_poll_synchronize_srcu() +			// and then cleanup_srcu_struct() before that grace +			// period ended?  	}  	kfree(sup->node);  	sup->node = NULL; @@ -845,7 +848,6 @@ static void srcu_gp_end(struct srcu_struct *ssp)  	bool cbs;  	bool last_lvl;  	int cpu; -	unsigned long flags;  	unsigned long gpseq;  	int idx;  	unsigned long mask; @@ -907,12 +909,12 @@ static void srcu_gp_end(struct srcu_struct *ssp)  	if (!(gpseq & counter_wrap_check))  		for_each_possible_cpu(cpu) {  			sdp = per_cpu_ptr(ssp->sda, cpu); -			spin_lock_irqsave_rcu_node(sdp, flags); +			spin_lock_irq_rcu_node(sdp);  			if (ULONG_CMP_GE(gpseq, sdp->srcu_gp_seq_needed + 100))  				sdp->srcu_gp_seq_needed = gpseq;  			if (ULONG_CMP_GE(gpseq, sdp->srcu_gp_seq_needed_exp + 100))  				sdp->srcu_gp_seq_needed_exp = gpseq; -			spin_unlock_irqrestore_rcu_node(sdp, flags); +			spin_unlock_irq_rcu_node(sdp);  		}  	/* Callback initiation done, allow grace periods after next. */ @@ -1540,7 +1542,8 @@ EXPORT_SYMBOL_GPL(start_poll_synchronize_srcu);   */  bool poll_state_synchronize_srcu(struct srcu_struct *ssp, unsigned long cookie)  { -	if (!rcu_seq_done(&ssp->srcu_sup->srcu_gp_seq, cookie)) +	if (cookie != SRCU_GET_STATE_COMPLETED && +	    !rcu_seq_done(&ssp->srcu_sup->srcu_gp_seq, cookie))  		return false;  	// Ensure that the end of the SRCU grace period happens before  	// any subsequent code that the caller might execute. |