Commit 2b73b07ab8a44ce171e07a328439f311481a7ea7

Authored by Steffen Klassert
Committed by Herbert Xu
1 parent d46a5ac7a7

padata: Flush the padata queues actively

yield was used to wait until all references of the internal control
structure in use are dropped before it is freed. This patch implements
padata_flush_queues which actively flushes the padata percpu queues
in this case.

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

Showing 1 changed file with 25 additions and 8 deletions Side-by-side Diff

... ... @@ -417,6 +417,29 @@
417 417 kfree(pd);
418 418 }
419 419  
  420 +static void padata_flush_queues(struct parallel_data *pd)
  421 +{
  422 + int cpu;
  423 + struct padata_queue *queue;
  424 +
  425 + for_each_cpu(cpu, pd->cpumask) {
  426 + queue = per_cpu_ptr(pd->queue, cpu);
  427 + flush_work(&queue->pwork);
  428 + }
  429 +
  430 + del_timer_sync(&pd->timer);
  431 +
  432 + if (atomic_read(&pd->reorder_objects))
  433 + padata_reorder(pd);
  434 +
  435 + for_each_cpu(cpu, pd->cpumask) {
  436 + queue = per_cpu_ptr(pd->queue, cpu);
  437 + flush_work(&queue->swork);
  438 + }
  439 +
  440 + BUG_ON(atomic_read(&pd->refcnt) != 0);
  441 +}
  442 +
420 443 static void padata_replace(struct padata_instance *pinst,
421 444 struct parallel_data *pd_new)
422 445 {
... ... @@ -428,11 +451,7 @@
428 451  
429 452 synchronize_rcu();
430 453  
431   - while (atomic_read(&pd_old->refcnt) != 0)
432   - yield();
433   -
434   - flush_workqueue(pinst->wq);
435   -
  454 + padata_flush_queues(pd_old);
436 455 padata_free_pd(pd_old);
437 456  
438 457 pinst->flags &= ~PADATA_RESET;
439 458  
... ... @@ -695,12 +714,10 @@
695 714  
696 715 synchronize_rcu();
697 716  
698   - while (atomic_read(&pinst->pd->refcnt) != 0)
699   - yield();
700   -
701 717 #ifdef CONFIG_HOTPLUG_CPU
702 718 unregister_hotcpu_notifier(&pinst->cpu_notifier);
703 719 #endif
  720 + padata_flush_queues(pinst->pd);
704 721 padata_free_pd(pinst->pd);
705 722 free_cpumask_var(pinst->cpumask);
706 723 kfree(pinst);