Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Thomas Gleixner: "This is much bigger than typical fixes, but Peter found a category of races that spurred more fixes and more debugging enhancements. Work started before the merge window, but got finished only now. Aside of that this contains the usual small fixes to perf and tools. Nothing particular exciting" * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (43 commits) perf: Remove/simplify lockdep annotation perf: Synchronously clean up child events perf: Untangle 'owner' confusion perf: Add flags argument to perf_remove_from_context() perf: Clean up sync_child_event() perf: Robustify event->owner usage and SMP ordering perf: Fix STATE_EXIT usage perf: Update locking order perf: Remove __free_event() perf/bpf: Convert perf_event_array to use struct file perf: Fix NULL deref perf/x86: De-obfuscate code perf/x86: Fix uninitialized value usage perf: Fix race in perf_event_exit_task_context() perf: Fix orphan hole perf stat: Do not clean event's private stats perf hists: Fix HISTC_MEM_DCACHELINE width setting perf annotate browser: Fix behaviour of Shift-Tab with nothing focussed perf tests: Remove wrong semicolon in while loop in CQM test perf: Synchronously free aux pages in case of allocation failure ...
Šī revīzija ir iekļauta:
@@ -291,10 +291,13 @@ static void *perf_event_fd_array_get_ptr(struct bpf_map *map, int fd)
|
||||
{
|
||||
struct perf_event *event;
|
||||
const struct perf_event_attr *attr;
|
||||
struct file *file;
|
||||
|
||||
event = perf_event_get(fd);
|
||||
if (IS_ERR(event))
|
||||
return event;
|
||||
file = perf_event_get(fd);
|
||||
if (IS_ERR(file))
|
||||
return file;
|
||||
|
||||
event = file->private_data;
|
||||
|
||||
attr = perf_event_attrs(event);
|
||||
if (IS_ERR(attr))
|
||||
@@ -304,24 +307,22 @@ static void *perf_event_fd_array_get_ptr(struct bpf_map *map, int fd)
|
||||
goto err;
|
||||
|
||||
if (attr->type == PERF_TYPE_RAW)
|
||||
return event;
|
||||
return file;
|
||||
|
||||
if (attr->type == PERF_TYPE_HARDWARE)
|
||||
return event;
|
||||
return file;
|
||||
|
||||
if (attr->type == PERF_TYPE_SOFTWARE &&
|
||||
attr->config == PERF_COUNT_SW_BPF_OUTPUT)
|
||||
return event;
|
||||
return file;
|
||||
err:
|
||||
perf_event_release_kernel(event);
|
||||
fput(file);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static void perf_event_fd_array_put_ptr(void *ptr)
|
||||
{
|
||||
struct perf_event *event = ptr;
|
||||
|
||||
perf_event_release_kernel(event);
|
||||
fput((struct file *)ptr);
|
||||
}
|
||||
|
||||
static const struct bpf_map_ops perf_event_array_ops = {
|
||||
|
1211
kernel/events/core.c
1211
kernel/events/core.c
Failā izmaiņas netiks attēlotas, jo tās ir par lielu
Ielādēt izmaiņas
@@ -444,7 +444,7 @@ int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *att
|
||||
* current task.
|
||||
*/
|
||||
if (irqs_disabled() && bp->ctx && bp->ctx->task == current)
|
||||
__perf_event_disable(bp);
|
||||
perf_event_disable_local(bp);
|
||||
else
|
||||
perf_event_disable(bp);
|
||||
|
||||
|
@@ -459,6 +459,25 @@ static void rb_free_aux_page(struct ring_buffer *rb, int idx)
|
||||
__free_page(page);
|
||||
}
|
||||
|
||||
static void __rb_free_aux(struct ring_buffer *rb)
|
||||
{
|
||||
int pg;
|
||||
|
||||
if (rb->aux_priv) {
|
||||
rb->free_aux(rb->aux_priv);
|
||||
rb->free_aux = NULL;
|
||||
rb->aux_priv = NULL;
|
||||
}
|
||||
|
||||
if (rb->aux_nr_pages) {
|
||||
for (pg = 0; pg < rb->aux_nr_pages; pg++)
|
||||
rb_free_aux_page(rb, pg);
|
||||
|
||||
kfree(rb->aux_pages);
|
||||
rb->aux_nr_pages = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int rb_alloc_aux(struct ring_buffer *rb, struct perf_event *event,
|
||||
pgoff_t pgoff, int nr_pages, long watermark, int flags)
|
||||
{
|
||||
@@ -547,30 +566,11 @@ out:
|
||||
if (!ret)
|
||||
rb->aux_pgoff = pgoff;
|
||||
else
|
||||
rb_free_aux(rb);
|
||||
__rb_free_aux(rb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __rb_free_aux(struct ring_buffer *rb)
|
||||
{
|
||||
int pg;
|
||||
|
||||
if (rb->aux_priv) {
|
||||
rb->free_aux(rb->aux_priv);
|
||||
rb->free_aux = NULL;
|
||||
rb->aux_priv = NULL;
|
||||
}
|
||||
|
||||
if (rb->aux_nr_pages) {
|
||||
for (pg = 0; pg < rb->aux_nr_pages; pg++)
|
||||
rb_free_aux_page(rb, pg);
|
||||
|
||||
kfree(rb->aux_pages);
|
||||
rb->aux_nr_pages = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void rb_free_aux(struct ring_buffer *rb)
|
||||
{
|
||||
if (atomic_dec_and_test(&rb->aux_refcount))
|
||||
|
@@ -191,14 +191,17 @@ static u64 bpf_perf_event_read(u64 r1, u64 index, u64 r3, u64 r4, u64 r5)
|
||||
struct bpf_map *map = (struct bpf_map *) (unsigned long) r1;
|
||||
struct bpf_array *array = container_of(map, struct bpf_array, map);
|
||||
struct perf_event *event;
|
||||
struct file *file;
|
||||
|
||||
if (unlikely(index >= array->map.max_entries))
|
||||
return -E2BIG;
|
||||
|
||||
event = (struct perf_event *)array->ptrs[index];
|
||||
if (!event)
|
||||
file = (struct file *)array->ptrs[index];
|
||||
if (unlikely(!file))
|
||||
return -ENOENT;
|
||||
|
||||
event = file->private_data;
|
||||
|
||||
/* make sure event is local and doesn't have pmu::count */
|
||||
if (event->oncpu != smp_processor_id() ||
|
||||
event->pmu->count)
|
||||
@@ -228,6 +231,7 @@ static u64 bpf_perf_event_output(u64 r1, u64 r2, u64 index, u64 r4, u64 size)
|
||||
void *data = (void *) (long) r4;
|
||||
struct perf_sample_data sample_data;
|
||||
struct perf_event *event;
|
||||
struct file *file;
|
||||
struct perf_raw_record raw = {
|
||||
.size = size,
|
||||
.data = data,
|
||||
@@ -236,10 +240,12 @@ static u64 bpf_perf_event_output(u64 r1, u64 r2, u64 index, u64 r4, u64 size)
|
||||
if (unlikely(index >= array->map.max_entries))
|
||||
return -E2BIG;
|
||||
|
||||
event = (struct perf_event *)array->ptrs[index];
|
||||
if (unlikely(!event))
|
||||
file = (struct file *)array->ptrs[index];
|
||||
if (unlikely(!file))
|
||||
return -ENOENT;
|
||||
|
||||
event = file->private_data;
|
||||
|
||||
if (unlikely(event->attr.type != PERF_TYPE_SOFTWARE ||
|
||||
event->attr.config != PERF_COUNT_SW_BPF_OUTPUT))
|
||||
return -EINVAL;
|
||||
|
Atsaukties uz šo jaunā problēmā
Block a user