[linux] 05/05: perf: Fix AUX buffer refcounting

debian-kernel at lists.debian.org debian-kernel at lists.debian.org
Sat Aug 22 17:28:12 UTC 2015


This is an automated email from the git hooks/post-receive script.

benh pushed a commit to branch sid
in repository linux.

commit 9f602f3712f34f062a50460597eefe33eb27b37d
Author: Ben Hutchings <ben at decadent.org.uk>
Date:   Sat Aug 22 19:26:40 2015 +0200

    perf: Fix AUX buffer refcounting
---
 debian/changelog                                   |   1 +
 .../all/perf-fix-aux-buffer-refcounting.patch      | 135 +++++++++++++++++++++
 .../perf-fix-double-free-of-the-aux-buffer.patch   |   2 +-
 debian/patches/series                              |   1 +
 4 files changed, 138 insertions(+), 1 deletion(-)

diff --git a/debian/changelog b/debian/changelog
index 4b14fa9..1ba9912 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -90,6 +90,7 @@ linux (4.1.6-1) UNRELEASED; urgency=medium
   [ Ben Hutchings ]
   * [i386] udeb: Make gpio_keys_polled and leds-gpio optional in input-modules
     as they are not built for the 686-pae flavour (fixes FTBFS)
+  * perf: Fix AUX buffer refcounting
 
  -- Aurelien Jarno <aurel32 at debian.org>  Tue, 18 Aug 2015 11:35:05 +0200
 
diff --git a/debian/patches/bugfix/all/perf-fix-aux-buffer-refcounting.patch b/debian/patches/bugfix/all/perf-fix-aux-buffer-refcounting.patch
new file mode 100644
index 0000000..180add8
--- /dev/null
+++ b/debian/patches/bugfix/all/perf-fix-aux-buffer-refcounting.patch
@@ -0,0 +1,135 @@
+From: Peter Zijlstra <peterz at infradead.org>
+Date: Thu, 18 Jun 2015 12:32:49 +0200
+Subject: perf: Fix AUX buffer refcounting
+Origin: https://git.kernel.org/linus/57ffc5ca679f499f4704fd9b6a372916f59930ee
+
+Its currently possible to drop the last refcount to the aux buffer
+from NMI context, which results in the expected fireworks.
+
+The refcounting needs a bigger overhaul, but to cure the immediate
+problem, delay the freeing by using an irq_work.
+
+Reviewed-and-tested-by: Alexander Shishkin <alexander.shishkin at linux.intel.com>
+Reported-by: Vince Weaver <vincent.weaver at maine.edu>
+Signed-off-by: Peter Zijlstra (Intel) <peterz at infradead.org>
+Cc: Arnaldo Carvalho de Melo <acme at kernel.org>
+Cc: Linus Torvalds <torvalds at linux-foundation.org>
+Cc: Peter Zijlstra <peterz at infradead.org>
+Cc: Stephane Eranian <eranian at gmail.com>
+Cc: Thomas Gleixner <tglx at linutronix.de>
+Link: http://lkml.kernel.org/r/20150618103249.GK19282@twins.programming.kicks-ass.net
+Signed-off-by: Ingo Molnar <mingo at kernel.org>
+---
+ kernel/events/core.c        |  8 --------
+ kernel/events/internal.h    | 10 ++++++++++
+ kernel/events/ring_buffer.c | 27 +++++++++++++++++++++++++--
+ 3 files changed, 35 insertions(+), 10 deletions(-)
+
+--- a/kernel/events/core.c
++++ b/kernel/events/core.c
+@@ -4381,14 +4381,6 @@ static void ring_buffer_wakeup(struct pe
+ 	rcu_read_unlock();
+ }
+ 
+-static void rb_free_rcu(struct rcu_head *rcu_head)
+-{
+-	struct ring_buffer *rb;
+-
+-	rb = container_of(rcu_head, struct ring_buffer, rcu_head);
+-	rb_free(rb);
+-}
+-
+ struct ring_buffer *ring_buffer_get(struct perf_event *event)
+ {
+ 	struct ring_buffer *rb;
+--- a/kernel/events/internal.h
++++ b/kernel/events/internal.h
+@@ -11,6 +11,7 @@
+ struct ring_buffer {
+ 	atomic_t			refcount;
+ 	struct rcu_head			rcu_head;
++	struct irq_work			irq_work;
+ #ifdef CONFIG_PERF_USE_VMALLOC
+ 	struct work_struct		work;
+ 	int				page_order;	/* allocation order  */
+@@ -55,6 +56,15 @@ struct ring_buffer {
+ };
+ 
+ extern void rb_free(struct ring_buffer *rb);
++
++static inline void rb_free_rcu(struct rcu_head *rcu_head)
++{
++	struct ring_buffer *rb;
++
++	rb = container_of(rcu_head, struct ring_buffer, rcu_head);
++	rb_free(rb);
++}
++
+ extern struct ring_buffer *
+ rb_alloc(int nr_pages, long watermark, int cpu, int flags);
+ extern void perf_event_wakeup(struct perf_event *event);
+--- a/kernel/events/ring_buffer.c
++++ b/kernel/events/ring_buffer.c
+@@ -221,6 +221,8 @@ void perf_output_end(struct perf_output_
+ 	rcu_read_unlock();
+ }
+ 
++static void rb_irq_work(struct irq_work *work);
++
+ static void
+ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags)
+ {
+@@ -241,6 +243,16 @@ ring_buffer_init(struct ring_buffer *rb,
+ 
+ 	INIT_LIST_HEAD(&rb->event_list);
+ 	spin_lock_init(&rb->event_lock);
++	init_irq_work(&rb->irq_work, rb_irq_work);
++}
++
++static void ring_buffer_put_async(struct ring_buffer *rb)
++{
++	if (!atomic_dec_and_test(&rb->refcount))
++		return;
++
++	rb->rcu_head.next = (void *)rb;
++	irq_work_queue(&rb->irq_work);
+ }
+ 
+ /*
+@@ -319,7 +331,7 @@ err_put:
+ 	rb_free_aux(rb);
+ 
+ err:
+-	ring_buffer_put(rb);
++	ring_buffer_put_async(rb);
+ 	handle->event = NULL;
+ 
+ 	return NULL;
+@@ -370,7 +382,7 @@ void perf_aux_output_end(struct perf_out
+ 
+ 	local_set(&rb->aux_nest, 0);
+ 	rb_free_aux(rb);
+-	ring_buffer_put(rb);
++	ring_buffer_put_async(rb);
+ }
+ 
+ /*
+@@ -557,7 +569,18 @@ static void __rb_free_aux(struct ring_bu
+ void rb_free_aux(struct ring_buffer *rb)
+ {
+ 	if (atomic_dec_and_test(&rb->aux_refcount))
++		irq_work_queue(&rb->irq_work);
++}
++
++static void rb_irq_work(struct irq_work *work)
++{
++	struct ring_buffer *rb = container_of(work, struct ring_buffer, irq_work);
++
++	if (!atomic_read(&rb->aux_refcount))
+ 		__rb_free_aux(rb);
++
++	if (rb->rcu_head.next == (void *)rb)
++		call_rcu(&rb->rcu_head, rb_free_rcu);
+ }
+ 
+ #ifndef CONFIG_PERF_USE_VMALLOC
diff --git a/debian/patches/bugfix/all/perf-fix-double-free-of-the-aux-buffer.patch b/debian/patches/bugfix/all/perf-fix-double-free-of-the-aux-buffer.patch
index 32125ae..74a1b63 100644
--- a/debian/patches/bugfix/all/perf-fix-double-free-of-the-aux-buffer.patch
+++ b/debian/patches/bugfix/all/perf-fix-double-free-of-the-aux-buffer.patch
@@ -24,7 +24,7 @@ Signed-off-by: Ingo Molnar <mingo at kernel.org>
 
 --- a/kernel/events/ring_buffer.c
 +++ b/kernel/events/ring_buffer.c
-@@ -547,11 +547,13 @@ static void __rb_free_aux(struct ring_bu
+@@ -559,11 +559,13 @@ static void __rb_free_aux(struct ring_bu
  		rb->aux_priv = NULL;
  	}
  
diff --git a/debian/patches/series b/debian/patches/series
index 60a3950..e54bbb6 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -90,4 +90,5 @@ bugfix/all/virtio-net-drop-netif_f_fraglist.patch
 bugfix/all/-ovl-don-t-traverse-automount-points.patch
 bugfix/all/ovl-allow-distributed-fs-as-lower-layer.patch
 bugfix/all/fix-a-braino-in-ovl_d_select_inode.patch
+bugfix/all/perf-fix-aux-buffer-refcounting.patch
 bugfix/all/perf-fix-double-free-of-the-aux-buffer.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/kernel/linux.git



More information about the Kernel-svn-changes mailing list