linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch 0/5] Markers fixes
@ 2008-10-01 16:03 Mathieu Desnoyers
  2008-10-01 16:03 ` [patch 1/5] Markers reenable fast batch registration Mathieu Desnoyers
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Mathieu Desnoyers @ 2008-10-01 16:03 UTC (permalink / raw)
  To: Ingo Molnar, linux-kernel

Hi Ingo,

Here are the marker fixes which reenable batch markers
registration/unregistration. They apply to -tip.

Thanks,

Mathieu

-- 
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [patch 1/5] Markers reenable fast batch registration
  2008-10-01 16:03 [patch 0/5] Markers fixes Mathieu Desnoyers
@ 2008-10-01 16:03 ` Mathieu Desnoyers
  2008-10-01 16:03 ` [patch 2/5] Markers : marker_synchronize_unregister() Mathieu Desnoyers
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Mathieu Desnoyers @ 2008-10-01 16:03 UTC (permalink / raw)
  To: Ingo Molnar, linux-kernel; +Cc: Mathieu Desnoyers, Lai Jiangshan

[-- Attachment #1: markers-reenable-batch-registration.patch --]
[-- Type: text/plain, Size: 5377 bytes --]

Lai Jiangshan discovered a reentrancy issue with markers and fixed it by adding
synchronize_sched() calls at each registration/unregistraiton. It works, but it
removes the ability to do batch registration/unregistration and can cause
registration of ~100 markers to take about 30 seconds on a loaded machine
(synchronize_sched() is much slower on such workloads). This patch implements a
version of the fix which won't slow down marker batch
registration/unregistration. It also go back to the original non-synchronized
reg/unreg, and thus needs the following
markers-synchronize_marker_unregister.patch patch and friends.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
CC: Lai Jiangshan <laijs@cn.fujitsu.com>
CC: Ingo Molnar <mingo@elte.hu>
---
 kernel/marker.c |   58 ++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 52 insertions(+), 6 deletions(-)

Index: linux-2.6-lttng/kernel/marker.c
===================================================================
--- linux-2.6-lttng.orig/kernel/marker.c	2008-10-01 11:53:42.000000000 -0400
+++ linux-2.6-lttng/kernel/marker.c	2008-10-01 11:54:10.000000000 -0400
@@ -60,6 +60,9 @@ struct marker_entry {
 	struct marker_probe_closure single;
 	struct marker_probe_closure *multi;
 	int refcount;	/* Number of times armed. 0 if disarmed. */
+	struct rcu_head rcu;
+	void *oldptr;
+	unsigned char rcu_pending:1;
 	unsigned char ptype:1;
 	char name[0];	/* Contains name'\0'format'\0' */
 };
@@ -196,6 +199,16 @@ void marker_probe_cb_noarg(const struct 
 }
 EXPORT_SYMBOL_GPL(marker_probe_cb_noarg);
 
+static void free_old_closure(struct rcu_head *head)
+{
+	struct marker_entry *entry = container_of(head,
+		struct marker_entry, rcu);
+	kfree(entry->oldptr);
+	/* Make sure we free the data before setting the pending flag to 0 */
+	smp_wmb();
+	entry->rcu_pending = 0;
+}
+
 static void debug_print_probes(struct marker_entry *entry)
 {
 	int i;
@@ -404,6 +417,7 @@ static struct marker_entry *add_marker(c
 	e->multi = NULL;
 	e->ptype = 0;
 	e->refcount = 0;
+	e->rcu_pending = 0;
 	hlist_add_head(&e->hlist, head);
 	return e;
 }
@@ -433,6 +447,9 @@ static int remove_marker(const char *nam
 	if (e->single.func != __mark_empty_function)
 		return -EBUSY;
 	hlist_del(&e->hlist);
+	/* Make sure the call_rcu has been executed */
+	if (e->rcu_pending)
+		rcu_barrier_sched();
 	kfree(e);
 	return 0;
 }
@@ -462,8 +479,12 @@ static int marker_set_format(struct mark
 	e->multi = (*entry)->multi;
 	e->ptype = (*entry)->ptype;
 	e->refcount = (*entry)->refcount;
+	e->rcu_pending = 0;
 	hlist_add_before(&e->hlist, &(*entry)->hlist);
 	hlist_del(&(*entry)->hlist);
+	/* Make sure the call_rcu has been executed */
+	if ((*entry)->rcu_pending)
+		rcu_barrier_sched();
 	kfree(*entry);
 	*entry = e;
 	trace_mark(core_marker_format, "name %s format %s",
@@ -637,6 +658,12 @@ int marker_probe_register(const char *na
 			goto end;
 		}
 	}
+	/*
+	 * If we detect that a call_rcu is pending for this marker,
+	 * make sure it's executed now.
+	 */
+	if (entry->rcu_pending)
+		rcu_barrier_sched();
 	old = marker_entry_add_probe(entry, probe, probe_private);
 	if (IS_ERR(old)) {
 		ret = PTR_ERR(old);
@@ -644,11 +671,16 @@ int marker_probe_register(const char *na
 	}
 	mutex_unlock(&markers_mutex);
 	marker_update_probes();		/* may update entry */
-	synchronize_sched();
-	kfree(old);
 	mutex_lock(&markers_mutex);
 	entry = get_marker(name);
 	WARN_ON(!entry);
+	if (entry->rcu_pending)
+		rcu_barrier_sched();
+	entry->oldptr = old;
+	entry->rcu_pending = 1;
+	/* write rcu_pending before calling the RCU callback */
+	smp_wmb();
+	call_rcu_sched(&entry->rcu, free_old_closure);
 end:
 	mutex_unlock(&markers_mutex);
 	return ret;
@@ -678,15 +710,22 @@ int marker_probe_unregister(const char *
 	entry = get_marker(name);
 	if (!entry)
 		goto end;
+	if (entry->rcu_pending)
+		rcu_barrier_sched();
 	old = marker_entry_remove_probe(entry, probe, probe_private);
 	mutex_unlock(&markers_mutex);
 	marker_update_probes();		/* may update entry */
-	synchronize_sched();
-	kfree(old);
 	mutex_lock(&markers_mutex);
 	entry = get_marker(name);
 	if (!entry)
 		goto end;
+	if (entry->rcu_pending)
+		rcu_barrier_sched();
+	entry->oldptr = old;
+	entry->rcu_pending = 1;
+	/* write rcu_pending before calling the RCU callback */
+	smp_wmb();
+	call_rcu_sched(&entry->rcu, free_old_closure);
 	remove_marker(name);	/* Ignore busy error message */
 	ret = 0;
 end:
@@ -752,14 +791,21 @@ int marker_probe_unregister_private_data
 		ret = -ENOENT;
 		goto end;
 	}
+	if (entry->rcu_pending)
+		rcu_barrier_sched();
 	old = marker_entry_remove_probe(entry, NULL, probe_private);
 	mutex_unlock(&markers_mutex);
 	marker_update_probes();		/* may update entry */
-	synchronize_sched();
-	kfree(old);
 	mutex_lock(&markers_mutex);
 	entry = get_marker_from_private_data(probe, probe_private);
 	WARN_ON(!entry);
+	if (entry->rcu_pending)
+		rcu_barrier_sched();
+	entry->oldptr = old;
+	entry->rcu_pending = 1;
+	/* write rcu_pending before calling the RCU callback */
+	smp_wmb();
+	call_rcu_sched(&entry->rcu, free_old_closure);
 	remove_marker(entry->name);	/* Ignore busy error message */
 end:
 	mutex_unlock(&markers_mutex);

-- 
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [patch 2/5] Markers : marker_synchronize_unregister()
  2008-10-01 16:03 [patch 0/5] Markers fixes Mathieu Desnoyers
  2008-10-01 16:03 ` [patch 1/5] Markers reenable fast batch registration Mathieu Desnoyers
@ 2008-10-01 16:03 ` Mathieu Desnoyers
  2008-10-01 16:03 ` [patch 3/5] Markers : probe example fix teardown Mathieu Desnoyers
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Mathieu Desnoyers @ 2008-10-01 16:03 UTC (permalink / raw)
  To: Ingo Molnar, linux-kernel
  Cc: Mathieu Desnoyers, Rusty Russell, akpm, Frank Ch. Eigler

[-- Attachment #1: markers-synchronize_marker_unregister.patch --]
[-- Type: text/plain, Size: 1375 bytes --]

Create marker_synchronize_unregister() which must be called before the end of
exit() to make sure every probe callers have exited the non preemptible section
and thus are not executing the probe code anymore.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
CC: Ingo Molnar <mingo@elte.hu>
CC: Rusty Russell <rusty@rustcorp.com.au>
CC: akpm@linux-foundation.org
CC: "Frank Ch. Eigler" <fche@redhat.com>
---
 include/linux/marker.h |    7 +++++++
 1 file changed, 7 insertions(+)

Index: linux-2.6-lttng/include/linux/marker.h
===================================================================
--- linux-2.6-lttng.orig/include/linux/marker.h	2008-07-31 09:12:52.000000000 -0400
+++ linux-2.6-lttng/include/linux/marker.h	2008-07-31 09:19:31.000000000 -0400
@@ -142,4 +142,11 @@ extern int marker_probe_unregister_priva
 extern void *marker_get_private_data(const char *name, marker_probe_func *probe,
 	int num);
 
+/*
+ * marker_synchronize_unregister must be called between the last marker probe
+ * unregistration and the end of module exit to make sure there is no caller
+ * executing a probe when it is freed.
+ */
+#define marker_synchronize_unregister() synchronize_sched()
+
 #endif

-- 
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [patch 3/5] Markers : probe example fix teardown
  2008-10-01 16:03 [patch 0/5] Markers fixes Mathieu Desnoyers
  2008-10-01 16:03 ` [patch 1/5] Markers reenable fast batch registration Mathieu Desnoyers
  2008-10-01 16:03 ` [patch 2/5] Markers : marker_synchronize_unregister() Mathieu Desnoyers
@ 2008-10-01 16:03 ` Mathieu Desnoyers
  2008-10-01 16:03 ` [patch 4/5] Markers : documentation " Mathieu Desnoyers
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Mathieu Desnoyers @ 2008-10-01 16:03 UTC (permalink / raw)
  To: Ingo Molnar, linux-kernel
  Cc: Mathieu Desnoyers, Rusty Russell, akpm, Frank Ch. Eigler

[-- Attachment #1: markers-probe-example-fix-teardown.patch --]
[-- Type: text/plain, Size: 1197 bytes --]

Need a marker_synchronize_unregister() before the end of exit() to make sure
every probe callers have exited the non preemptible section and thus are not
executing the probe code anymore.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
CC: Ingo Molnar <mingo@elte.hu>
CC: Rusty Russell <rusty@rustcorp.com.au>
CC: akpm@linux-foundation.org
CC: "Frank Ch. Eigler" <fche@redhat.com>
---
 samples/markers/probe-example.c |    1 +
 1 file changed, 1 insertion(+)

Index: linux-2.6-lttng/samples/markers/probe-example.c
===================================================================
--- linux-2.6-lttng.orig/samples/markers/probe-example.c	2008-07-31 09:11:13.000000000 -0400
+++ linux-2.6-lttng/samples/markers/probe-example.c	2008-07-31 09:18:54.000000000 -0400
@@ -81,6 +81,7 @@ static void __exit probe_fini(void)
 			probe_array[i].probe_func, &probe_array[i]);
 	printk(KERN_INFO "Number of event b : %u\n",
 			atomic_read(&eventb_count));
+	marker_synchronize_unregister();
 }
 
 module_init(probe_init);

-- 
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [patch 4/5] Markers : documentation fix teardown
  2008-10-01 16:03 [patch 0/5] Markers fixes Mathieu Desnoyers
                   ` (2 preceding siblings ...)
  2008-10-01 16:03 ` [patch 3/5] Markers : probe example fix teardown Mathieu Desnoyers
@ 2008-10-01 16:03 ` Mathieu Desnoyers
  2008-10-01 16:03 ` [patch 5/5] sputrace : use marker_synchronize_unregister() Mathieu Desnoyers
  2008-10-02  8:36 ` [patch 0/5] Markers fixes Ingo Molnar
  5 siblings, 0 replies; 7+ messages in thread
From: Mathieu Desnoyers @ 2008-10-01 16:03 UTC (permalink / raw)
  To: Ingo Molnar, linux-kernel
  Cc: Mathieu Desnoyers, Rusty Russell, akpm, Frank Ch. Eigler

[-- Attachment #1: markers-documentation-probe-teardown.patch --]
[-- Type: text/plain, Size: 2121 bytes --]

Document the need for a marker_synchronize_unregister() before the end of exit()
to make sure every probe callers have exited the non preemptible section and
thus are not executing the probe code anymore.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
CC: Ingo Molnar <mingo@elte.hu>
CC: Rusty Russell <rusty@rustcorp.com.au>
CC: akpm@linux-foundation.org
CC: "Frank Ch. Eigler" <fche@redhat.com>
---
 Documentation/markers.txt |   10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

Index: linux-2.6-lttng/Documentation/markers.txt
===================================================================
--- linux-2.6-lttng.orig/Documentation/markers.txt	2008-07-31 09:11:13.000000000 -0400
+++ linux-2.6-lttng/Documentation/markers.txt	2008-07-31 09:20:57.000000000 -0400
@@ -50,10 +50,12 @@ Connecting a function (probe) to a marke
 to call) for the specific marker through marker_probe_register() and can be
 activated by calling marker_arm(). Marker deactivation can be done by calling
 marker_disarm() as many times as marker_arm() has been called. Removing a probe
-is done through marker_probe_unregister(); it will disarm the probe and make
-sure there is no caller left using the probe when it returns. Probe removal is
-preempt-safe because preemption is disabled around the probe call. See the
-"Probe example" section below for a sample probe module.
+is done through marker_probe_unregister(); it will disarm the probe.
+marker_synchronize_unregister() must be called before the end of the module exit
+function to make sure there is no caller left using the probe. This, and the
+fact that preemption is disabled around the probe call, make sure that probe
+removal and module unload are safe. See the "Probe example" section below for a
+sample probe module.
 
 The marker mechanism supports inserting multiple instances of the same marker.
 Markers can be put in inline functions, inlined static functions, and

-- 
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [patch 5/5] sputrace : use marker_synchronize_unregister()
  2008-10-01 16:03 [patch 0/5] Markers fixes Mathieu Desnoyers
                   ` (3 preceding siblings ...)
  2008-10-01 16:03 ` [patch 4/5] Markers : documentation " Mathieu Desnoyers
@ 2008-10-01 16:03 ` Mathieu Desnoyers
  2008-10-02  8:36 ` [patch 0/5] Markers fixes Ingo Molnar
  5 siblings, 0 replies; 7+ messages in thread
From: Mathieu Desnoyers @ 2008-10-01 16:03 UTC (permalink / raw)
  To: Ingo Molnar, linux-kernel
  Cc: Mathieu Desnoyers, Jeremy Kerr, linuxppc-dev, Christoph Hellwig

[-- Attachment #1: sputrace-use-marker-synchronize-unregister.patch --]
[-- Type: text/plain, Size: 1184 bytes --]

We need a marker_synchronize_unregister() before the end of exit() to make sure
every probe callers have exited the non preemptible section and thus are not
executing the probe code anymore.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
CC: Ingo Molnar <mingo@elte.hu>
CC: Jeremy Kerr <jk@ozlabs.org>
CC: linuxppc-dev@ozlabs.org
CC: Christoph Hellwig <hch@infradead.org>
---
 arch/powerpc/platforms/cell/spufs/sputrace.c |    1 +
 1 file changed, 1 insertion(+)

Index: linux-2.6-lttng/arch/powerpc/platforms/cell/spufs/sputrace.c
===================================================================
--- linux-2.6-lttng.orig/arch/powerpc/platforms/cell/spufs/sputrace.c	2008-07-31 09:34:58.000000000 -0400
+++ linux-2.6-lttng/arch/powerpc/platforms/cell/spufs/sputrace.c	2008-07-31 09:35:15.000000000 -0400
@@ -233,6 +233,7 @@ static void __exit sputrace_exit(void)
 
 	remove_proc_entry("sputrace", NULL);
 	kfree(sputrace_log);
+	marker_synchronize_unregister();
 }
 
 module_init(sputrace_init);

-- 
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [patch 0/5] Markers fixes
  2008-10-01 16:03 [patch 0/5] Markers fixes Mathieu Desnoyers
                   ` (4 preceding siblings ...)
  2008-10-01 16:03 ` [patch 5/5] sputrace : use marker_synchronize_unregister() Mathieu Desnoyers
@ 2008-10-02  8:36 ` Ingo Molnar
  5 siblings, 0 replies; 7+ messages in thread
From: Ingo Molnar @ 2008-10-02  8:36 UTC (permalink / raw)
  To: Mathieu Desnoyers; +Cc: linux-kernel


* Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> wrote:

> Hi Ingo,
> 
> Here are the marker fixes which reenable batch markers
> registration/unregistration. They apply to -tip.

hm, only the first patch applies to tip/master - the rest is already 
applied. So i applied the first patch to tip/tracing/markers:

  # a2b4a6c: markers: re-enable fast batch registration

Could you please check latest tip/master:

  http://people.redhat.com/mingo/tip.git/README

to make sure that i sorted them out correctly. Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2008-10-02  8:36 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-10-01 16:03 [patch 0/5] Markers fixes Mathieu Desnoyers
2008-10-01 16:03 ` [patch 1/5] Markers reenable fast batch registration Mathieu Desnoyers
2008-10-01 16:03 ` [patch 2/5] Markers : marker_synchronize_unregister() Mathieu Desnoyers
2008-10-01 16:03 ` [patch 3/5] Markers : probe example fix teardown Mathieu Desnoyers
2008-10-01 16:03 ` [patch 4/5] Markers : documentation " Mathieu Desnoyers
2008-10-01 16:03 ` [patch 5/5] sputrace : use marker_synchronize_unregister() Mathieu Desnoyers
2008-10-02  8:36 ` [patch 0/5] Markers fixes Ingo Molnar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).