diff mbox

[1/5] perf core: Introduce new ioctl options to pause and resume ring buffer

Message ID 1457949585-191064-2-git-send-email-wangnan0@huawei.com
State Superseded
Headers show

Commit Message

Wang Nan March 14, 2016, 9:59 a.m. UTC
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 <wangnan0@huawei.com>

Cc: He Kuang <hekuang@huawei.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Zefan Li <lizefan@huawei.com>
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

Comments

Wang Nan March 23, 2016, 9:33 a.m. UTC | #1
On 2016/3/23 17:16, Peter Zijlstra wrote:
> On Mon, Mar 14, 2016 at 09:59:41AM +0000, Wang Nan wrote:

>> 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.

>> 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)


Glad to see you start to look at this patchset.



> Can you also do a patch to the man-pages?

>

>    http://man7.org/linux/man-pages/man2/perf_event_open.2.html


Sure.

I think I need to provide a patch for:

  http://git.kernel.org/cgit/docs/man-pages/man-pages.git

But which one should be the first? Shall we update man pages before
this patch be merged by upstream? Or Michael and Vince will consider
this problem?

Thank you.
Michael Kerrisk (man-pages) Oct. 21, 2016, 7:06 a.m. UTC | #2
Hello Wangnan,

The patch below seems to have landed in Linux 4.7,
commit 86e7972f690c1017fd086cdfe53d8524e68c661c

Could you draft a man-pages patch for this interface
change, please? Or, failing that, a plain-text 
description that we can integrate into the man-page.

Thanks,

Michael

On 03/23/2016 10:33 AM, Wangnan (F) wrote:
> 

> 

> On 2016/3/23 17:16, Peter Zijlstra wrote:

>> On Mon, Mar 14, 2016 at 09:59:41AM +0000, Wang Nan wrote:

>>> 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.

>>> 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)

> 

> Glad to see you start to look at this patchset.

> 

> 

> 

>> Can you also do a patch to the man-pages?

>>

>>    http://man7.org/linux/man-pages/man2/perf_event_open.2.html

> 

> Sure.

> 

> I think I need to provide a patch for:

> 

>   http://git.kernel.org/cgit/docs/man-pages/man-pages.git

> 

> But which one should be the first? Shall we update man pages before

> this patch be merged by upstream? Or Michael and Vince will consider

> this problem?

> 

> Thank you.

> 

> 

> 



-- 
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
Wang Nan Oct. 21, 2016, 7:13 a.m. UTC | #3
On 2016/10/21 15:06, Michael Kerrisk (man-pages) wrote:
> Hello Wangnan,

>

> The patch below seems to have landed in Linux 4.7,

> commit 86e7972f690c1017fd086cdfe53d8524e68c661c

>

> Could you draft a man-pages patch for this interface

> change, please? Or, failing that, a plain-text

> description that we can integrate into the man-page.


I sent man-pages patches at March:

https://patchwork.kernel.org/patch/8678861/
http://www.spinics.net/lists/linux-man/msg10177.html

Let me resend them again.

Thank you.
Michael Kerrisk (man-pages) Oct. 21, 2016, 8:55 a.m. UTC | #4
Hi Wangnan

On 10/21/2016 09:13 AM, Wangnan (F) wrote:
> 

> 

> On 2016/10/21 15:06, Michael Kerrisk (man-pages) wrote:

>> Hello Wangnan,

>>

>> The patch below seems to have landed in Linux 4.7,

>> commit 86e7972f690c1017fd086cdfe53d8524e68c661c

>>

>> Could you draft a man-pages patch for this interface

>> change, please? Or, failing that, a plain-text

>> description that we can integrate into the man-page.

> 

> I sent man-pages patches at March:

> 

> https://patchwork.kernel.org/patch/8678861/

> http://www.spinics.net/lists/linux-man/msg10177.html

> 

> Let me resend them again.



Ahhh -- my apologies. I found these now.

Cheers,

Michael



-- 
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
diff mbox

Patch

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 b723149..1a1312e 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4306,6 +4306,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)