Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'perf_urgent_for_v6.7_rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf fix from Borislav Petkov:

- Make sure the context refcount is transferred too when migrating perf
events

* tag 'perf_urgent_for_v6.7_rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
perf/core: Fix cpuctx refcounting

+25 -5
+8 -5
include/linux/perf_event.h
··· 843 843 }; 844 844 845 845 /* 846 - * ,-----------------------[1:n]----------------------. 847 - * V V 848 - * perf_event_context <-[1:n]-> perf_event_pmu_context <--- perf_event 849 - * ^ ^ | | 850 - * `--------[1:n]---------' `-[n:1]-> pmu <-[1:n]-' 846 + * ,-----------------------[1:n]------------------------. 847 + * V V 848 + * perf_event_context <-[1:n]-> perf_event_pmu_context <-[1:n]- perf_event 849 + * | | 850 + * `--[n:1]-> pmu <-[1:n]--' 851 851 * 852 852 * 853 853 * struct perf_event_pmu_context lifetime is refcount based and RCU freed ··· 865 865 * ctx->mutex pinning the configuration. Since we hold a reference on 866 866 * group_leader (through the filedesc) it can't go away, therefore it's 867 867 * associated pmu_ctx must exist and cannot change due to ctx->mutex. 868 + * 869 + * perf_event holds a refcount on perf_event_context 870 + * perf_event holds a refcount on perf_event_pmu_context 868 871 */ 869 872 struct perf_event_pmu_context { 870 873 struct pmu *pmu;
+17
kernel/events/core.c
··· 4828 4828 void *task_ctx_data = NULL; 4829 4829 4830 4830 if (!ctx->task) { 4831 + /* 4832 + * perf_pmu_migrate_context() / __perf_pmu_install_event() 4833 + * relies on the fact that find_get_pmu_context() cannot fail 4834 + * for CPU contexts. 4835 + */ 4831 4836 struct perf_cpu_pmu_context *cpc; 4832 4837 4833 4838 cpc = per_cpu_ptr(pmu->cpu_pmu_context, event->cpu); ··· 12894 12889 int cpu, struct perf_event *event) 12895 12890 { 12896 12891 struct perf_event_pmu_context *epc; 12892 + struct perf_event_context *old_ctx = event->ctx; 12893 + 12894 + get_ctx(ctx); /* normally find_get_context() */ 12897 12895 12898 12896 event->cpu = cpu; 12899 12897 epc = find_get_pmu_context(pmu, ctx, event); ··· 12905 12897 if (event->state >= PERF_EVENT_STATE_OFF) 12906 12898 event->state = PERF_EVENT_STATE_INACTIVE; 12907 12899 perf_install_in_context(ctx, event, cpu); 12900 + 12901 + /* 12902 + * Now that event->ctx is updated and visible, put the old ctx. 12903 + */ 12904 + put_ctx(old_ctx); 12908 12905 } 12909 12906 12910 12907 static void __perf_pmu_install(struct perf_event_context *ctx, ··· 12948 12935 struct perf_event_context *src_ctx, *dst_ctx; 12949 12936 LIST_HEAD(events); 12950 12937 12938 + /* 12939 + * Since per-cpu context is persistent, no need to grab an extra 12940 + * reference. 12941 + */ 12951 12942 src_ctx = &per_cpu_ptr(&perf_cpu_context, src_cpu)->ctx; 12952 12943 dst_ctx = &per_cpu_ptr(&perf_cpu_context, dst_cpu)->ctx; 12953 12944