diff options
Diffstat (limited to 'kernel/rcu/srcutree.c')
-rw-r--r-- | kernel/rcu/srcutree.c | 32 |
1 files changed, 14 insertions, 18 deletions
diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c index a60b8ba9e1ac..9b761e546de8 100644 --- a/kernel/rcu/srcutree.c +++ b/kernel/rcu/srcutree.c | |||
@@ -360,8 +360,14 @@ static unsigned long srcu_get_delay(struct srcu_struct *ssp) | |||
360 | return SRCU_INTERVAL; | 360 | return SRCU_INTERVAL; |
361 | } | 361 | } |
362 | 362 | ||
363 | /* Helper for cleanup_srcu_struct() and cleanup_srcu_struct_quiesced(). */ | 363 | /** |
364 | void _cleanup_srcu_struct(struct srcu_struct *ssp, bool quiesced) | 364 | * cleanup_srcu_struct - deconstruct a sleep-RCU structure |
365 | * @ssp: structure to clean up. | ||
366 | * | ||
367 | * Must invoke this after you are finished using a given srcu_struct that | ||
368 | * was initialized via init_srcu_struct(), else you leak memory. | ||
369 | */ | ||
370 | void cleanup_srcu_struct(struct srcu_struct *ssp) | ||
365 | { | 371 | { |
366 | int cpu; | 372 | int cpu; |
367 | 373 | ||
@@ -369,24 +375,14 @@ void _cleanup_srcu_struct(struct srcu_struct *ssp, bool quiesced) | |||
369 | return; /* Just leak it! */ | 375 | return; /* Just leak it! */ |
370 | if (WARN_ON(srcu_readers_active(ssp))) | 376 | if (WARN_ON(srcu_readers_active(ssp))) |
371 | return; /* Just leak it! */ | 377 | return; /* Just leak it! */ |
372 | if (quiesced) { | 378 | flush_delayed_work(&ssp->work); |
373 | if (WARN_ON(delayed_work_pending(&ssp->work))) | ||
374 | return; /* Just leak it! */ | ||
375 | } else { | ||
376 | flush_delayed_work(&ssp->work); | ||
377 | } | ||
378 | for_each_possible_cpu(cpu) { | 379 | for_each_possible_cpu(cpu) { |
379 | struct srcu_data *sdp = per_cpu_ptr(ssp->sda, cpu); | 380 | struct srcu_data *sdp = per_cpu_ptr(ssp->sda, cpu); |
380 | 381 | ||
381 | if (quiesced) { | 382 | del_timer_sync(&sdp->delay_work); |
382 | if (WARN_ON(timer_pending(&sdp->delay_work))) | 383 | flush_work(&sdp->work); |
383 | return; /* Just leak it! */ | 384 | if (WARN_ON(rcu_segcblist_n_cbs(&sdp->srcu_cblist))) |
384 | if (WARN_ON(work_pending(&sdp->work))) | 385 | return; /* Forgot srcu_barrier(), so just leak it! */ |
385 | return; /* Just leak it! */ | ||
386 | } else { | ||
387 | del_timer_sync(&sdp->delay_work); | ||
388 | flush_work(&sdp->work); | ||
389 | } | ||
390 | } | 386 | } |
391 | if (WARN_ON(rcu_seq_state(READ_ONCE(ssp->srcu_gp_seq)) != SRCU_STATE_IDLE) || | 387 | if (WARN_ON(rcu_seq_state(READ_ONCE(ssp->srcu_gp_seq)) != SRCU_STATE_IDLE) || |
392 | WARN_ON(srcu_readers_active(ssp))) { | 388 | WARN_ON(srcu_readers_active(ssp))) { |
@@ -397,7 +393,7 @@ void _cleanup_srcu_struct(struct srcu_struct *ssp, bool quiesced) | |||
397 | free_percpu(ssp->sda); | 393 | free_percpu(ssp->sda); |
398 | ssp->sda = NULL; | 394 | ssp->sda = NULL; |
399 | } | 395 | } |
400 | EXPORT_SYMBOL_GPL(_cleanup_srcu_struct); | 396 | EXPORT_SYMBOL_GPL(cleanup_srcu_struct); |
401 | 397 | ||
402 | /* | 398 | /* |
403 | * Counts the new reader in the appropriate per-CPU element of the | 399 | * Counts the new reader in the appropriate per-CPU element of the |