From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754488AbaHTMsE (ORCPT ); Wed, 20 Aug 2014 08:48:04 -0400 Received: from mga09.intel.com ([134.134.136.24]:29855 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753211AbaHTMsA (ORCPT ); Wed, 20 Aug 2014 08:48:00 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.01,902,1400050800"; d="scan'208";a="561072611" From: Alexander Shishkin To: Peter Zijlstra Cc: Ingo Molnar , linux-kernel@vger.kernel.org, Robert Richter , Frederic Weisbecker , Mike Galbraith , Paul Mackerras , Stephane Eranian , Andi Kleen , kan.liang@intel.com, Alexander Shishkin Subject: [PATCH v4 20/22] perf: Allocate ring buffers for inherited per-task kernel events Date: Wed, 20 Aug 2014 15:36:17 +0300 Message-Id: <1408538179-792-21-git-send-email-alexander.shishkin@linux.intel.com> X-Mailer: git-send-email 1.9.0 In-Reply-To: <1408538179-792-1-git-send-email-alexander.shishkin@linux.intel.com> References: <1408538179-792-1-git-send-email-alexander.shishkin@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org When a new event is inherited from a per-task kernel event that has a ring buffer, allocate a new buffer for this event so that data from the child task is collected and can later be retrieved for sample annotation or whatnot. Signed-off-by: Alexander Shishkin --- kernel/events/core.c | 9 +++++++++ kernel/events/internal.h | 11 +++++++++++ 2 files changed, 20 insertions(+) diff --git a/kernel/events/core.c b/kernel/events/core.c index 3b1550fd0e..9d7f6086d5 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -8230,6 +8230,15 @@ inherit_event(struct perf_event *parent_event, (void)perf_event_set_output(child_event, parent_event); /* + * For per-task kernel events with ring buffers, set_output doesn't + * make sense, but we can allocate a new buffer here. + */ + if (parent_event->cpu == -1 && kernel_rb_event(parent_event)) { + (void)rb_alloc_kernel(child_event, parent_event->rb->nr_pages, + parent_event->rb->aux_nr_pages); + } + + /* * Precalculate sample_data sizes */ perf_event__header_size(child_event); diff --git a/kernel/events/internal.h b/kernel/events/internal.h index bb035dd645..b306bc9307 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h @@ -120,6 +120,17 @@ static inline unsigned long perf_aux_size(struct ring_buffer *rb) return rb->aux_nr_pages << PAGE_SHIFT; } +static inline bool kernel_rb_event(struct perf_event *event) +{ + /* + * Having a ring buffer and not being on any ring buffers' wakeup + * list means it was attached by rb_alloc_kernel() and not + * ring_buffer_attach(). It's the only case when these two + * conditions take place at the same time. + */ + return event->rb && list_empty(&event->rb_entry); +} + #define DEFINE_OUTPUT_COPY(func_name, memcpy_func) \ static inline unsigned long \ func_name(struct perf_output_handle *handle, \ -- 2.1.0