From patchwork Fri Feb 5 14:01:44 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wang Nan X-Patchwork-Id: 61323 Delivered-To: patch@linaro.org Received: by 10.112.43.199 with SMTP id y7csp1121505lbl; Fri, 5 Feb 2016 06:23:02 -0800 (PST) X-Received: by 10.67.3.134 with SMTP id bw6mr19957776pad.154.1454682182261; Fri, 05 Feb 2016 06:23:02 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id tj1si24225733pab.206.2016.02.05.06.23.01; Fri, 05 Feb 2016 06:23:02 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752385AbcBEOWq (ORCPT + 30 others); Fri, 5 Feb 2016 09:22:46 -0500 Received: from szxga01-in.huawei.com ([58.251.152.64]:13316 "EHLO szxga01-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753541AbcBEOEa (ORCPT ); Fri, 5 Feb 2016 09:04:30 -0500 Received: from 172.24.1.47 (EHLO SZXEML429-HUB.china.huawei.com) ([172.24.1.47]) by szxrg01-dlp.huawei.com (MOS 4.3.7-GA FastPath queued) with ESMTP id DEF55832; Fri, 05 Feb 2016 22:03:15 +0800 (CST) Received: from linux-4hy3.site (10.107.193.248) by SZXEML429-HUB.china.huawei.com (10.82.67.184) with Microsoft SMTP Server id 14.3.235.1; Fri, 5 Feb 2016 22:03:05 +0800 From: Wang Nan To: Alexei Starovoitov , Arnaldo Carvalho de Melo , Arnaldo Carvalho de Melo , Brendan Gregg CC: Adrian Hunter , Cody P Schafer , "David S. Miller" , He Kuang , =?UTF-8?q?J=C3=A9r=C3=A9mie=20Galarneau?= , Jiri Olsa , Kirill Smelkov , Li Zefan , Masami Hiramatsu , Namhyung Kim , Peter Zijlstra , , Wang Nan , Subject: [PATCH 19/54] perf core: Introduce new ioctl options to pause and resume ring buffer Date: Fri, 5 Feb 2016 14:01:44 +0000 Message-ID: <1454680939-24963-20-git-send-email-wangnan0@huawei.com> X-Mailer: git-send-email 1.8.3.4 In-Reply-To: <1454680939-24963-1-git-send-email-wangnan0@huawei.com> References: <1454680939-24963-1-git-send-email-wangnan0@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.107.193.248] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020203.56B4ABA4.00B6, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0, so=2013-06-18 04:22:30, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 4abe18675acde26c1e4284297db11c2e Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add new ioctl() to pause/resume ring-buffer output. In some situations we want to read from ring buffer only when we ensure nothing can write to the ring buffer during reading. Without this patch we have to turn off all events attached to this ring buffer to achieve this. This patch is for supporting overwrite ring buffer. Following commits will introduce new methods support reading from overwrite ring buffer. Before reading caller must ensure the ring buffer is frozen, or the reading is unreliable. Signed-off-by: Wang Nan Cc: He Kuang Cc: Alexei Starovoitov Cc: Arnaldo Carvalho de Melo Cc: Brendan Gregg Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Zefan Li Cc: pi3orama@163.com --- include/uapi/linux/perf_event.h | 1 + kernel/events/core.c | 13 +++++++++++++ kernel/events/internal.h | 11 +++++++++++ kernel/events/ring_buffer.c | 7 ++++++- 4 files changed, 31 insertions(+), 1 deletion(-) -- 1.8.3.4 diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h index 1afe962..a3c1903 100644 --- a/include/uapi/linux/perf_event.h +++ b/include/uapi/linux/perf_event.h @@ -401,6 +401,7 @@ struct perf_event_attr { #define PERF_EVENT_IOC_SET_FILTER _IOW('$', 6, char *) #define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *) #define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32) +#define PERF_EVENT_IOC_PAUSE_OUTPUT _IOW('$', 9, __u32) enum perf_event_ioc_flags { PERF_IOC_FLAG_GROUP = 1U << 0, diff --git a/kernel/events/core.c b/kernel/events/core.c index 5946460..3e6a3ad 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4231,6 +4231,19 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon case PERF_EVENT_IOC_SET_BPF: return perf_event_set_bpf_prog(event, arg); + case PERF_EVENT_IOC_PAUSE_OUTPUT: { + struct ring_buffer *rb; + + rcu_read_lock(); + rb = rcu_dereference(event->rb); + if (!event->rb) { + rcu_read_unlock(); + return -EINVAL; + } + rb_toggle_paused(rb, !!arg); + rcu_read_unlock(); + return 0; + } default: return -ENOTTY; } diff --git a/kernel/events/internal.h b/kernel/events/internal.h index 2bbad9c..6a93d1b 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h @@ -18,6 +18,7 @@ struct ring_buffer { #endif int nr_pages; /* nr of data pages */ int overwrite; /* can overwrite itself */ + int paused; /* can write into ring buffer */ atomic_t poll; /* POLL_ for wakeups */ @@ -65,6 +66,16 @@ static inline void rb_free_rcu(struct rcu_head *rcu_head) rb_free(rb); } +static inline void +rb_toggle_paused(struct ring_buffer *rb, + bool pause) +{ + if (!pause && rb->nr_pages) + rb->paused = 0; + else + rb->paused = 1; +} + extern struct ring_buffer * rb_alloc(int nr_pages, long watermark, int cpu, int flags); extern void perf_event_wakeup(struct perf_event *event); diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index 1faad2c..22e1a47 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c @@ -125,8 +125,11 @@ int perf_output_begin(struct perf_output_handle *handle, if (unlikely(!rb)) goto out; - if (unlikely(!rb->nr_pages)) + if (unlikely(rb->paused)) { + if (rb->nr_pages) + local_inc(&rb->lost); goto out; + } handle->rb = rb; handle->event = event; @@ -244,6 +247,8 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags) INIT_LIST_HEAD(&rb->event_list); spin_lock_init(&rb->event_lock); init_irq_work(&rb->irq_work, rb_irq_work); + + rb->paused = rb->nr_pages ? 0 : 1; } static void ring_buffer_put_async(struct ring_buffer *rb)