diff options
| author | Peter Zijlstra <peterz@infradead.org> | 2018-09-25 11:58:35 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2018-10-02 03:37:56 -0400 |
| commit | a9f9772114c8b07ae75bcb3654bd017461248095 (patch) | |
| tree | af2008edb00495276c182e7d77f8c334ab502ef1 | |
| parent | 291d0e5d81e101392379217b06251fe8c27f1f80 (diff) | |
perf/core: Fix perf_pmu_unregister() locking
When we unregister a PMU, we fail to serialize the @pmu_idr properly.
Fix that by doing the entire thing under pmu_lock.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Fixes: 2e80a82a49c4 ("perf: Dynamic pmu types")
Signed-off-by: Ingo Molnar <mingo@kernel.org>
| -rw-r--r-- | kernel/events/core.c | 9 |
1 files changed, 2 insertions, 7 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c index dcb093e7b377..dfb1d951789e 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
| @@ -9431,9 +9431,7 @@ static void free_pmu_context(struct pmu *pmu) | |||
| 9431 | if (pmu->task_ctx_nr > perf_invalid_context) | 9431 | if (pmu->task_ctx_nr > perf_invalid_context) |
| 9432 | return; | 9432 | return; |
| 9433 | 9433 | ||
| 9434 | mutex_lock(&pmus_lock); | ||
| 9435 | free_percpu(pmu->pmu_cpu_context); | 9434 | free_percpu(pmu->pmu_cpu_context); |
| 9436 | mutex_unlock(&pmus_lock); | ||
| 9437 | } | 9435 | } |
| 9438 | 9436 | ||
| 9439 | /* | 9437 | /* |
| @@ -9689,12 +9687,8 @@ EXPORT_SYMBOL_GPL(perf_pmu_register); | |||
| 9689 | 9687 | ||
| 9690 | void perf_pmu_unregister(struct pmu *pmu) | 9688 | void perf_pmu_unregister(struct pmu *pmu) |
| 9691 | { | 9689 | { |
| 9692 | int remove_device; | ||
| 9693 | |||
| 9694 | mutex_lock(&pmus_lock); | 9690 | mutex_lock(&pmus_lock); |
| 9695 | remove_device = pmu_bus_running; | ||
| 9696 | list_del_rcu(&pmu->entry); | 9691 | list_del_rcu(&pmu->entry); |
| 9697 | mutex_unlock(&pmus_lock); | ||
| 9698 | 9692 | ||
| 9699 | /* | 9693 | /* |
| 9700 | * We dereference the pmu list under both SRCU and regular RCU, so | 9694 | * We dereference the pmu list under both SRCU and regular RCU, so |
| @@ -9706,13 +9700,14 @@ void perf_pmu_unregister(struct pmu *pmu) | |||
| 9706 | free_percpu(pmu->pmu_disable_count); | 9700 | free_percpu(pmu->pmu_disable_count); |
| 9707 | if (pmu->type >= PERF_TYPE_MAX) | 9701 | if (pmu->type >= PERF_TYPE_MAX) |
| 9708 | idr_remove(&pmu_idr, pmu->type); | 9702 | idr_remove(&pmu_idr, pmu->type); |
| 9709 | if (remove_device) { | 9703 | if (pmu_bus_running) { |
| 9710 | if (pmu->nr_addr_filters) | 9704 | if (pmu->nr_addr_filters) |
| 9711 | device_remove_file(pmu->dev, &dev_attr_nr_addr_filters); | 9705 | device_remove_file(pmu->dev, &dev_attr_nr_addr_filters); |
| 9712 | device_del(pmu->dev); | 9706 | device_del(pmu->dev); |
| 9713 | put_device(pmu->dev); | 9707 | put_device(pmu->dev); |
| 9714 | } | 9708 | } |
| 9715 | free_pmu_context(pmu); | 9709 | free_pmu_context(pmu); |
| 9710 | mutex_unlock(&pmus_lock); | ||
| 9716 | } | 9711 | } |
| 9717 | EXPORT_SYMBOL_GPL(perf_pmu_unregister); | 9712 | EXPORT_SYMBOL_GPL(perf_pmu_unregister); |
| 9718 | 9713 | ||
