xref: /linux/kernel/tracepoint.c (revision 127cafbb276266b1b8da967bfe25a062ab1d42ab)
197e1c18eSMathieu Desnoyers /*
297e1c18eSMathieu Desnoyers  * Copyright (C) 2008 Mathieu Desnoyers
397e1c18eSMathieu Desnoyers  *
497e1c18eSMathieu Desnoyers  * This program is free software; you can redistribute it and/or modify
597e1c18eSMathieu Desnoyers  * it under the terms of the GNU General Public License as published by
697e1c18eSMathieu Desnoyers  * the Free Software Foundation; either version 2 of the License, or
797e1c18eSMathieu Desnoyers  * (at your option) any later version.
897e1c18eSMathieu Desnoyers  *
997e1c18eSMathieu Desnoyers  * This program is distributed in the hope that it will be useful,
1097e1c18eSMathieu Desnoyers  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1197e1c18eSMathieu Desnoyers  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1297e1c18eSMathieu Desnoyers  * GNU General Public License for more details.
1397e1c18eSMathieu Desnoyers  *
1497e1c18eSMathieu Desnoyers  * You should have received a copy of the GNU General Public License
1597e1c18eSMathieu Desnoyers  * along with this program; if not, write to the Free Software
1697e1c18eSMathieu Desnoyers  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1797e1c18eSMathieu Desnoyers  */
1897e1c18eSMathieu Desnoyers #include <linux/module.h>
1997e1c18eSMathieu Desnoyers #include <linux/mutex.h>
2097e1c18eSMathieu Desnoyers #include <linux/types.h>
2197e1c18eSMathieu Desnoyers #include <linux/jhash.h>
2297e1c18eSMathieu Desnoyers #include <linux/list.h>
2397e1c18eSMathieu Desnoyers #include <linux/rcupdate.h>
2497e1c18eSMathieu Desnoyers #include <linux/tracepoint.h>
2597e1c18eSMathieu Desnoyers #include <linux/err.h>
2697e1c18eSMathieu Desnoyers #include <linux/slab.h>
2797e1c18eSMathieu Desnoyers 
2897e1c18eSMathieu Desnoyers extern struct tracepoint __start___tracepoints[];
2997e1c18eSMathieu Desnoyers extern struct tracepoint __stop___tracepoints[];
3097e1c18eSMathieu Desnoyers 
3197e1c18eSMathieu Desnoyers /* Set to 1 to enable tracepoint debug output */
3297e1c18eSMathieu Desnoyers static const int tracepoint_debug;
3397e1c18eSMathieu Desnoyers 
3497e1c18eSMathieu Desnoyers /*
3597e1c18eSMathieu Desnoyers  * tracepoints_mutex nests inside module_mutex. Tracepoints mutex protects the
3697e1c18eSMathieu Desnoyers  * builtin and module tracepoints and the hash table.
3797e1c18eSMathieu Desnoyers  */
3897e1c18eSMathieu Desnoyers static DEFINE_MUTEX(tracepoints_mutex);
3997e1c18eSMathieu Desnoyers 
4097e1c18eSMathieu Desnoyers /*
4197e1c18eSMathieu Desnoyers  * Tracepoint hash table, containing the active tracepoints.
4297e1c18eSMathieu Desnoyers  * Protected by tracepoints_mutex.
4397e1c18eSMathieu Desnoyers  */
4497e1c18eSMathieu Desnoyers #define TRACEPOINT_HASH_BITS 6
4597e1c18eSMathieu Desnoyers #define TRACEPOINT_TABLE_SIZE (1 << TRACEPOINT_HASH_BITS)
4619dba33cSLai Jiangshan static struct hlist_head tracepoint_table[TRACEPOINT_TABLE_SIZE];
4797e1c18eSMathieu Desnoyers 
4897e1c18eSMathieu Desnoyers /*
4997e1c18eSMathieu Desnoyers  * Note about RCU :
5097e1c18eSMathieu Desnoyers  * It is used to to delay the free of multiple probes array until a quiescent
5197e1c18eSMathieu Desnoyers  * state is reached.
5297e1c18eSMathieu Desnoyers  * Tracepoint entries modifications are protected by the tracepoints_mutex.
5397e1c18eSMathieu Desnoyers  */
5497e1c18eSMathieu Desnoyers struct tracepoint_entry {
5597e1c18eSMathieu Desnoyers 	struct hlist_node hlist;
5697e1c18eSMathieu Desnoyers 	void **funcs;
5797e1c18eSMathieu Desnoyers 	int refcount;	/* Number of times armed. 0 if disarmed. */
5897e1c18eSMathieu Desnoyers 	char name[0];
5997e1c18eSMathieu Desnoyers };
6097e1c18eSMathieu Desnoyers 
6119dba33cSLai Jiangshan struct tp_probes {
62*127cafbbSLai Jiangshan 	union {
6319dba33cSLai Jiangshan 		struct rcu_head rcu;
64*127cafbbSLai Jiangshan 		struct list_head list;
65*127cafbbSLai Jiangshan 	} u;
6619dba33cSLai Jiangshan 	void *probes[0];
6719dba33cSLai Jiangshan };
6897e1c18eSMathieu Desnoyers 
6919dba33cSLai Jiangshan static inline void *allocate_probes(int count)
7097e1c18eSMathieu Desnoyers {
7119dba33cSLai Jiangshan 	struct tp_probes *p  = kmalloc(count * sizeof(void *)
7219dba33cSLai Jiangshan 			+ sizeof(struct tp_probes), GFP_KERNEL);
7319dba33cSLai Jiangshan 	return p == NULL ? NULL : p->probes;
7497e1c18eSMathieu Desnoyers }
7597e1c18eSMathieu Desnoyers 
7619dba33cSLai Jiangshan static void rcu_free_old_probes(struct rcu_head *head)
7797e1c18eSMathieu Desnoyers {
78*127cafbbSLai Jiangshan 	kfree(container_of(head, struct tp_probes, u.rcu));
7919dba33cSLai Jiangshan }
8019dba33cSLai Jiangshan 
8119dba33cSLai Jiangshan static inline void release_probes(void *old)
8219dba33cSLai Jiangshan {
8319dba33cSLai Jiangshan 	if (old) {
8419dba33cSLai Jiangshan 		struct tp_probes *tp_probes = container_of(old,
8519dba33cSLai Jiangshan 			struct tp_probes, probes[0]);
86*127cafbbSLai Jiangshan 		call_rcu_sched(&tp_probes->u.rcu, rcu_free_old_probes);
8719dba33cSLai Jiangshan 	}
8897e1c18eSMathieu Desnoyers }
8997e1c18eSMathieu Desnoyers 
9097e1c18eSMathieu Desnoyers static void debug_print_probes(struct tracepoint_entry *entry)
9197e1c18eSMathieu Desnoyers {
9297e1c18eSMathieu Desnoyers 	int i;
9397e1c18eSMathieu Desnoyers 
9419dba33cSLai Jiangshan 	if (!tracepoint_debug || !entry->funcs)
9597e1c18eSMathieu Desnoyers 		return;
9697e1c18eSMathieu Desnoyers 
9797e1c18eSMathieu Desnoyers 	for (i = 0; entry->funcs[i]; i++)
9897e1c18eSMathieu Desnoyers 		printk(KERN_DEBUG "Probe %d : %p\n", i, entry->funcs[i]);
9997e1c18eSMathieu Desnoyers }
10097e1c18eSMathieu Desnoyers 
10197e1c18eSMathieu Desnoyers static void *
10297e1c18eSMathieu Desnoyers tracepoint_entry_add_probe(struct tracepoint_entry *entry, void *probe)
10397e1c18eSMathieu Desnoyers {
10497e1c18eSMathieu Desnoyers 	int nr_probes = 0;
10597e1c18eSMathieu Desnoyers 	void **old, **new;
10697e1c18eSMathieu Desnoyers 
10797e1c18eSMathieu Desnoyers 	WARN_ON(!probe);
10897e1c18eSMathieu Desnoyers 
10997e1c18eSMathieu Desnoyers 	debug_print_probes(entry);
11097e1c18eSMathieu Desnoyers 	old = entry->funcs;
11197e1c18eSMathieu Desnoyers 	if (old) {
11297e1c18eSMathieu Desnoyers 		/* (N -> N+1), (N != 0, 1) probes */
11397e1c18eSMathieu Desnoyers 		for (nr_probes = 0; old[nr_probes]; nr_probes++)
11497e1c18eSMathieu Desnoyers 			if (old[nr_probes] == probe)
11597e1c18eSMathieu Desnoyers 				return ERR_PTR(-EEXIST);
11697e1c18eSMathieu Desnoyers 	}
11797e1c18eSMathieu Desnoyers 	/* + 2 : one for new probe, one for NULL func */
11819dba33cSLai Jiangshan 	new = allocate_probes(nr_probes + 2);
11997e1c18eSMathieu Desnoyers 	if (new == NULL)
12097e1c18eSMathieu Desnoyers 		return ERR_PTR(-ENOMEM);
12197e1c18eSMathieu Desnoyers 	if (old)
12297e1c18eSMathieu Desnoyers 		memcpy(new, old, nr_probes * sizeof(void *));
12397e1c18eSMathieu Desnoyers 	new[nr_probes] = probe;
12419dba33cSLai Jiangshan 	new[nr_probes + 1] = NULL;
12597e1c18eSMathieu Desnoyers 	entry->refcount = nr_probes + 1;
12697e1c18eSMathieu Desnoyers 	entry->funcs = new;
12797e1c18eSMathieu Desnoyers 	debug_print_probes(entry);
12897e1c18eSMathieu Desnoyers 	return old;
12997e1c18eSMathieu Desnoyers }
13097e1c18eSMathieu Desnoyers 
13197e1c18eSMathieu Desnoyers static void *
13297e1c18eSMathieu Desnoyers tracepoint_entry_remove_probe(struct tracepoint_entry *entry, void *probe)
13397e1c18eSMathieu Desnoyers {
13497e1c18eSMathieu Desnoyers 	int nr_probes = 0, nr_del = 0, i;
13597e1c18eSMathieu Desnoyers 	void **old, **new;
13697e1c18eSMathieu Desnoyers 
13797e1c18eSMathieu Desnoyers 	old = entry->funcs;
13897e1c18eSMathieu Desnoyers 
139f66af459SFrederic Weisbecker 	if (!old)
14019dba33cSLai Jiangshan 		return ERR_PTR(-ENOENT);
141f66af459SFrederic Weisbecker 
14297e1c18eSMathieu Desnoyers 	debug_print_probes(entry);
14397e1c18eSMathieu Desnoyers 	/* (N -> M), (N > 1, M >= 0) probes */
14497e1c18eSMathieu Desnoyers 	for (nr_probes = 0; old[nr_probes]; nr_probes++) {
14597e1c18eSMathieu Desnoyers 		if ((!probe || old[nr_probes] == probe))
14697e1c18eSMathieu Desnoyers 			nr_del++;
14797e1c18eSMathieu Desnoyers 	}
14897e1c18eSMathieu Desnoyers 
14997e1c18eSMathieu Desnoyers 	if (nr_probes - nr_del == 0) {
15097e1c18eSMathieu Desnoyers 		/* N -> 0, (N > 1) */
15197e1c18eSMathieu Desnoyers 		entry->funcs = NULL;
15297e1c18eSMathieu Desnoyers 		entry->refcount = 0;
15397e1c18eSMathieu Desnoyers 		debug_print_probes(entry);
15497e1c18eSMathieu Desnoyers 		return old;
15597e1c18eSMathieu Desnoyers 	} else {
15697e1c18eSMathieu Desnoyers 		int j = 0;
15797e1c18eSMathieu Desnoyers 		/* N -> M, (N > 1, M > 0) */
15897e1c18eSMathieu Desnoyers 		/* + 1 for NULL */
15919dba33cSLai Jiangshan 		new = allocate_probes(nr_probes - nr_del + 1);
16097e1c18eSMathieu Desnoyers 		if (new == NULL)
16197e1c18eSMathieu Desnoyers 			return ERR_PTR(-ENOMEM);
16297e1c18eSMathieu Desnoyers 		for (i = 0; old[i]; i++)
16397e1c18eSMathieu Desnoyers 			if ((probe && old[i] != probe))
16497e1c18eSMathieu Desnoyers 				new[j++] = old[i];
16519dba33cSLai Jiangshan 		new[nr_probes - nr_del] = NULL;
16697e1c18eSMathieu Desnoyers 		entry->refcount = nr_probes - nr_del;
16797e1c18eSMathieu Desnoyers 		entry->funcs = new;
16897e1c18eSMathieu Desnoyers 	}
16997e1c18eSMathieu Desnoyers 	debug_print_probes(entry);
17097e1c18eSMathieu Desnoyers 	return old;
17197e1c18eSMathieu Desnoyers }
17297e1c18eSMathieu Desnoyers 
17397e1c18eSMathieu Desnoyers /*
17497e1c18eSMathieu Desnoyers  * Get tracepoint if the tracepoint is present in the tracepoint hash table.
17597e1c18eSMathieu Desnoyers  * Must be called with tracepoints_mutex held.
17697e1c18eSMathieu Desnoyers  * Returns NULL if not present.
17797e1c18eSMathieu Desnoyers  */
17897e1c18eSMathieu Desnoyers static struct tracepoint_entry *get_tracepoint(const char *name)
17997e1c18eSMathieu Desnoyers {
18097e1c18eSMathieu Desnoyers 	struct hlist_head *head;
18197e1c18eSMathieu Desnoyers 	struct hlist_node *node;
18297e1c18eSMathieu Desnoyers 	struct tracepoint_entry *e;
18397e1c18eSMathieu Desnoyers 	u32 hash = jhash(name, strlen(name), 0);
18497e1c18eSMathieu Desnoyers 
1859795302aSMathieu Desnoyers 	head = &tracepoint_table[hash & (TRACEPOINT_TABLE_SIZE - 1)];
18697e1c18eSMathieu Desnoyers 	hlist_for_each_entry(e, node, head, hlist) {
18797e1c18eSMathieu Desnoyers 		if (!strcmp(name, e->name))
18897e1c18eSMathieu Desnoyers 			return e;
18997e1c18eSMathieu Desnoyers 	}
19097e1c18eSMathieu Desnoyers 	return NULL;
19197e1c18eSMathieu Desnoyers }
19297e1c18eSMathieu Desnoyers 
19397e1c18eSMathieu Desnoyers /*
19497e1c18eSMathieu Desnoyers  * Add the tracepoint to the tracepoint hash table. Must be called with
19597e1c18eSMathieu Desnoyers  * tracepoints_mutex held.
19697e1c18eSMathieu Desnoyers  */
19797e1c18eSMathieu Desnoyers static struct tracepoint_entry *add_tracepoint(const char *name)
19897e1c18eSMathieu Desnoyers {
19997e1c18eSMathieu Desnoyers 	struct hlist_head *head;
20097e1c18eSMathieu Desnoyers 	struct hlist_node *node;
20197e1c18eSMathieu Desnoyers 	struct tracepoint_entry *e;
20297e1c18eSMathieu Desnoyers 	size_t name_len = strlen(name) + 1;
20397e1c18eSMathieu Desnoyers 	u32 hash = jhash(name, name_len-1, 0);
20497e1c18eSMathieu Desnoyers 
2059795302aSMathieu Desnoyers 	head = &tracepoint_table[hash & (TRACEPOINT_TABLE_SIZE - 1)];
20697e1c18eSMathieu Desnoyers 	hlist_for_each_entry(e, node, head, hlist) {
20797e1c18eSMathieu Desnoyers 		if (!strcmp(name, e->name)) {
20897e1c18eSMathieu Desnoyers 			printk(KERN_NOTICE
20997e1c18eSMathieu Desnoyers 				"tracepoint %s busy\n", name);
21097e1c18eSMathieu Desnoyers 			return ERR_PTR(-EEXIST);	/* Already there */
21197e1c18eSMathieu Desnoyers 		}
21297e1c18eSMathieu Desnoyers 	}
21397e1c18eSMathieu Desnoyers 	/*
21497e1c18eSMathieu Desnoyers 	 * Using kmalloc here to allocate a variable length element. Could
21597e1c18eSMathieu Desnoyers 	 * cause some memory fragmentation if overused.
21697e1c18eSMathieu Desnoyers 	 */
21797e1c18eSMathieu Desnoyers 	e = kmalloc(sizeof(struct tracepoint_entry) + name_len, GFP_KERNEL);
21897e1c18eSMathieu Desnoyers 	if (!e)
21997e1c18eSMathieu Desnoyers 		return ERR_PTR(-ENOMEM);
22097e1c18eSMathieu Desnoyers 	memcpy(&e->name[0], name, name_len);
22197e1c18eSMathieu Desnoyers 	e->funcs = NULL;
22297e1c18eSMathieu Desnoyers 	e->refcount = 0;
22397e1c18eSMathieu Desnoyers 	hlist_add_head(&e->hlist, head);
22497e1c18eSMathieu Desnoyers 	return e;
22597e1c18eSMathieu Desnoyers }
22697e1c18eSMathieu Desnoyers 
22797e1c18eSMathieu Desnoyers /*
22897e1c18eSMathieu Desnoyers  * Remove the tracepoint from the tracepoint hash table. Must be called with
22997e1c18eSMathieu Desnoyers  * mutex_lock held.
23097e1c18eSMathieu Desnoyers  */
23119dba33cSLai Jiangshan static inline void remove_tracepoint(struct tracepoint_entry *e)
23297e1c18eSMathieu Desnoyers {
23397e1c18eSMathieu Desnoyers 	hlist_del(&e->hlist);
23497e1c18eSMathieu Desnoyers 	kfree(e);
23597e1c18eSMathieu Desnoyers }
23697e1c18eSMathieu Desnoyers 
23797e1c18eSMathieu Desnoyers /*
23897e1c18eSMathieu Desnoyers  * Sets the probe callback corresponding to one tracepoint.
23997e1c18eSMathieu Desnoyers  */
24097e1c18eSMathieu Desnoyers static void set_tracepoint(struct tracepoint_entry **entry,
24197e1c18eSMathieu Desnoyers 	struct tracepoint *elem, int active)
24297e1c18eSMathieu Desnoyers {
24397e1c18eSMathieu Desnoyers 	WARN_ON(strcmp((*entry)->name, elem->name) != 0);
24497e1c18eSMathieu Desnoyers 
24597e1c18eSMathieu Desnoyers 	/*
24697e1c18eSMathieu Desnoyers 	 * rcu_assign_pointer has a smp_wmb() which makes sure that the new
24797e1c18eSMathieu Desnoyers 	 * probe callbacks array is consistent before setting a pointer to it.
24897e1c18eSMathieu Desnoyers 	 * This array is referenced by __DO_TRACE from
24997e1c18eSMathieu Desnoyers 	 * include/linux/tracepoints.h. A matching smp_read_barrier_depends()
25097e1c18eSMathieu Desnoyers 	 * is used.
25197e1c18eSMathieu Desnoyers 	 */
25297e1c18eSMathieu Desnoyers 	rcu_assign_pointer(elem->funcs, (*entry)->funcs);
25397e1c18eSMathieu Desnoyers 	elem->state = active;
25497e1c18eSMathieu Desnoyers }
25597e1c18eSMathieu Desnoyers 
25697e1c18eSMathieu Desnoyers /*
25797e1c18eSMathieu Desnoyers  * Disable a tracepoint and its probe callback.
25897e1c18eSMathieu Desnoyers  * Note: only waiting an RCU period after setting elem->call to the empty
25997e1c18eSMathieu Desnoyers  * function insures that the original callback is not used anymore. This insured
26097e1c18eSMathieu Desnoyers  * by preempt_disable around the call site.
26197e1c18eSMathieu Desnoyers  */
26297e1c18eSMathieu Desnoyers static void disable_tracepoint(struct tracepoint *elem)
26397e1c18eSMathieu Desnoyers {
26497e1c18eSMathieu Desnoyers 	elem->state = 0;
26597e1c18eSMathieu Desnoyers }
26697e1c18eSMathieu Desnoyers 
26797e1c18eSMathieu Desnoyers /**
26897e1c18eSMathieu Desnoyers  * tracepoint_update_probe_range - Update a probe range
26997e1c18eSMathieu Desnoyers  * @begin: beginning of the range
27097e1c18eSMathieu Desnoyers  * @end: end of the range
27197e1c18eSMathieu Desnoyers  *
27297e1c18eSMathieu Desnoyers  * Updates the probe callback corresponding to a range of tracepoints.
27397e1c18eSMathieu Desnoyers  */
27497e1c18eSMathieu Desnoyers void tracepoint_update_probe_range(struct tracepoint *begin,
27597e1c18eSMathieu Desnoyers 	struct tracepoint *end)
27697e1c18eSMathieu Desnoyers {
27797e1c18eSMathieu Desnoyers 	struct tracepoint *iter;
27897e1c18eSMathieu Desnoyers 	struct tracepoint_entry *mark_entry;
27997e1c18eSMathieu Desnoyers 
28097e1c18eSMathieu Desnoyers 	mutex_lock(&tracepoints_mutex);
28197e1c18eSMathieu Desnoyers 	for (iter = begin; iter < end; iter++) {
28297e1c18eSMathieu Desnoyers 		mark_entry = get_tracepoint(iter->name);
28397e1c18eSMathieu Desnoyers 		if (mark_entry) {
28497e1c18eSMathieu Desnoyers 			set_tracepoint(&mark_entry, iter,
28597e1c18eSMathieu Desnoyers 					!!mark_entry->refcount);
28697e1c18eSMathieu Desnoyers 		} else {
28797e1c18eSMathieu Desnoyers 			disable_tracepoint(iter);
28897e1c18eSMathieu Desnoyers 		}
28997e1c18eSMathieu Desnoyers 	}
29097e1c18eSMathieu Desnoyers 	mutex_unlock(&tracepoints_mutex);
29197e1c18eSMathieu Desnoyers }
29297e1c18eSMathieu Desnoyers 
29397e1c18eSMathieu Desnoyers /*
29497e1c18eSMathieu Desnoyers  * Update probes, removing the faulty probes.
29597e1c18eSMathieu Desnoyers  */
29697e1c18eSMathieu Desnoyers static void tracepoint_update_probes(void)
29797e1c18eSMathieu Desnoyers {
29897e1c18eSMathieu Desnoyers 	/* Core kernel tracepoints */
29997e1c18eSMathieu Desnoyers 	tracepoint_update_probe_range(__start___tracepoints,
30097e1c18eSMathieu Desnoyers 		__stop___tracepoints);
30197e1c18eSMathieu Desnoyers 	/* tracepoints in modules. */
30297e1c18eSMathieu Desnoyers 	module_update_tracepoints();
30397e1c18eSMathieu Desnoyers }
30497e1c18eSMathieu Desnoyers 
305*127cafbbSLai Jiangshan static void *tracepoint_add_probe(const char *name, void *probe)
306*127cafbbSLai Jiangshan {
307*127cafbbSLai Jiangshan 	struct tracepoint_entry *entry;
308*127cafbbSLai Jiangshan 	void *old;
309*127cafbbSLai Jiangshan 
310*127cafbbSLai Jiangshan 	entry = get_tracepoint(name);
311*127cafbbSLai Jiangshan 	if (!entry) {
312*127cafbbSLai Jiangshan 		entry = add_tracepoint(name);
313*127cafbbSLai Jiangshan 		if (IS_ERR(entry))
314*127cafbbSLai Jiangshan 			return entry;
315*127cafbbSLai Jiangshan 	}
316*127cafbbSLai Jiangshan 	old = tracepoint_entry_add_probe(entry, probe);
317*127cafbbSLai Jiangshan 	if (IS_ERR(old) && !entry->refcount)
318*127cafbbSLai Jiangshan 		remove_tracepoint(entry);
319*127cafbbSLai Jiangshan 	return old;
320*127cafbbSLai Jiangshan }
321*127cafbbSLai Jiangshan 
32297e1c18eSMathieu Desnoyers /**
32397e1c18eSMathieu Desnoyers  * tracepoint_probe_register -  Connect a probe to a tracepoint
32497e1c18eSMathieu Desnoyers  * @name: tracepoint name
32597e1c18eSMathieu Desnoyers  * @probe: probe handler
32697e1c18eSMathieu Desnoyers  *
32797e1c18eSMathieu Desnoyers  * Returns 0 if ok, error value on error.
32897e1c18eSMathieu Desnoyers  * The probe address must at least be aligned on the architecture pointer size.
32997e1c18eSMathieu Desnoyers  */
33097e1c18eSMathieu Desnoyers int tracepoint_probe_register(const char *name, void *probe)
33197e1c18eSMathieu Desnoyers {
33297e1c18eSMathieu Desnoyers 	void *old;
33397e1c18eSMathieu Desnoyers 
33497e1c18eSMathieu Desnoyers 	mutex_lock(&tracepoints_mutex);
335*127cafbbSLai Jiangshan 	old = tracepoint_add_probe(name, probe);
33697e1c18eSMathieu Desnoyers 	mutex_unlock(&tracepoints_mutex);
337*127cafbbSLai Jiangshan 	if (IS_ERR(old))
338*127cafbbSLai Jiangshan 		return PTR_ERR(old);
339*127cafbbSLai Jiangshan 
34097e1c18eSMathieu Desnoyers 	tracepoint_update_probes();		/* may update entry */
34119dba33cSLai Jiangshan 	release_probes(old);
34219dba33cSLai Jiangshan 	return 0;
34397e1c18eSMathieu Desnoyers }
34497e1c18eSMathieu Desnoyers EXPORT_SYMBOL_GPL(tracepoint_probe_register);
34597e1c18eSMathieu Desnoyers 
346*127cafbbSLai Jiangshan static void *tracepoint_remove_probe(const char *name, void *probe)
347*127cafbbSLai Jiangshan {
348*127cafbbSLai Jiangshan 	struct tracepoint_entry *entry;
349*127cafbbSLai Jiangshan 	void *old;
350*127cafbbSLai Jiangshan 
351*127cafbbSLai Jiangshan 	entry = get_tracepoint(name);
352*127cafbbSLai Jiangshan 	if (!entry)
353*127cafbbSLai Jiangshan 		return ERR_PTR(-ENOENT);
354*127cafbbSLai Jiangshan 	old = tracepoint_entry_remove_probe(entry, probe);
355*127cafbbSLai Jiangshan 	if (IS_ERR(old))
356*127cafbbSLai Jiangshan 		return old;
357*127cafbbSLai Jiangshan 	if (!entry->refcount)
358*127cafbbSLai Jiangshan 		remove_tracepoint(entry);
359*127cafbbSLai Jiangshan 	return old;
360*127cafbbSLai Jiangshan }
361*127cafbbSLai Jiangshan 
36297e1c18eSMathieu Desnoyers /**
36397e1c18eSMathieu Desnoyers  * tracepoint_probe_unregister -  Disconnect a probe from a tracepoint
36497e1c18eSMathieu Desnoyers  * @name: tracepoint name
36597e1c18eSMathieu Desnoyers  * @probe: probe function pointer
36697e1c18eSMathieu Desnoyers  *
36797e1c18eSMathieu Desnoyers  * We do not need to call a synchronize_sched to make sure the probes have
36897e1c18eSMathieu Desnoyers  * finished running before doing a module unload, because the module unload
36997e1c18eSMathieu Desnoyers  * itself uses stop_machine(), which insures that every preempt disabled section
37097e1c18eSMathieu Desnoyers  * have finished.
37197e1c18eSMathieu Desnoyers  */
37297e1c18eSMathieu Desnoyers int tracepoint_probe_unregister(const char *name, void *probe)
37397e1c18eSMathieu Desnoyers {
37497e1c18eSMathieu Desnoyers 	void *old;
37597e1c18eSMathieu Desnoyers 
37697e1c18eSMathieu Desnoyers 	mutex_lock(&tracepoints_mutex);
377*127cafbbSLai Jiangshan 	old = tracepoint_remove_probe(name, probe);
37897e1c18eSMathieu Desnoyers 	mutex_unlock(&tracepoints_mutex);
379*127cafbbSLai Jiangshan 	if (IS_ERR(old))
380*127cafbbSLai Jiangshan 		return PTR_ERR(old);
381*127cafbbSLai Jiangshan 
38297e1c18eSMathieu Desnoyers 	tracepoint_update_probes();		/* may update entry */
38319dba33cSLai Jiangshan 	release_probes(old);
38419dba33cSLai Jiangshan 	return 0;
38597e1c18eSMathieu Desnoyers }
38697e1c18eSMathieu Desnoyers EXPORT_SYMBOL_GPL(tracepoint_probe_unregister);
38797e1c18eSMathieu Desnoyers 
388*127cafbbSLai Jiangshan static LIST_HEAD(old_probes);
389*127cafbbSLai Jiangshan static int need_update;
390*127cafbbSLai Jiangshan 
391*127cafbbSLai Jiangshan static void tracepoint_add_old_probes(void *old)
392*127cafbbSLai Jiangshan {
393*127cafbbSLai Jiangshan 	need_update = 1;
394*127cafbbSLai Jiangshan 	if (old) {
395*127cafbbSLai Jiangshan 		struct tp_probes *tp_probes = container_of(old,
396*127cafbbSLai Jiangshan 			struct tp_probes, probes[0]);
397*127cafbbSLai Jiangshan 		list_add(&tp_probes->u.list, &old_probes);
398*127cafbbSLai Jiangshan 	}
399*127cafbbSLai Jiangshan }
400*127cafbbSLai Jiangshan 
401*127cafbbSLai Jiangshan /**
402*127cafbbSLai Jiangshan  * tracepoint_probe_register_noupdate -  register a probe but not connect
403*127cafbbSLai Jiangshan  * @name: tracepoint name
404*127cafbbSLai Jiangshan  * @probe: probe handler
405*127cafbbSLai Jiangshan  *
406*127cafbbSLai Jiangshan  * caller must call tracepoint_probe_update_all()
407*127cafbbSLai Jiangshan  */
408*127cafbbSLai Jiangshan int tracepoint_probe_register_noupdate(const char *name, void *probe)
409*127cafbbSLai Jiangshan {
410*127cafbbSLai Jiangshan 	void *old;
411*127cafbbSLai Jiangshan 
412*127cafbbSLai Jiangshan 	mutex_lock(&tracepoints_mutex);
413*127cafbbSLai Jiangshan 	old = tracepoint_add_probe(name, probe);
414*127cafbbSLai Jiangshan 	if (IS_ERR(old)) {
415*127cafbbSLai Jiangshan 		mutex_unlock(&tracepoints_mutex);
416*127cafbbSLai Jiangshan 		return PTR_ERR(old);
417*127cafbbSLai Jiangshan 	}
418*127cafbbSLai Jiangshan 	tracepoint_add_old_probes(old);
419*127cafbbSLai Jiangshan 	mutex_unlock(&tracepoints_mutex);
420*127cafbbSLai Jiangshan 	return 0;
421*127cafbbSLai Jiangshan }
422*127cafbbSLai Jiangshan EXPORT_SYMBOL_GPL(tracepoint_probe_register_noupdate);
423*127cafbbSLai Jiangshan 
424*127cafbbSLai Jiangshan /**
425*127cafbbSLai Jiangshan  * tracepoint_probe_unregister_noupdate -  remove a probe but not disconnect
426*127cafbbSLai Jiangshan  * @name: tracepoint name
427*127cafbbSLai Jiangshan  * @probe: probe function pointer
428*127cafbbSLai Jiangshan  *
429*127cafbbSLai Jiangshan  * caller must call tracepoint_probe_update_all()
430*127cafbbSLai Jiangshan  */
431*127cafbbSLai Jiangshan int tracepoint_probe_unregister_noupdate(const char *name, void *probe)
432*127cafbbSLai Jiangshan {
433*127cafbbSLai Jiangshan 	void *old;
434*127cafbbSLai Jiangshan 
435*127cafbbSLai Jiangshan 	mutex_lock(&tracepoints_mutex);
436*127cafbbSLai Jiangshan 	old = tracepoint_remove_probe(name, probe);
437*127cafbbSLai Jiangshan 	if (IS_ERR(old)) {
438*127cafbbSLai Jiangshan 		mutex_unlock(&tracepoints_mutex);
439*127cafbbSLai Jiangshan 		return PTR_ERR(old);
440*127cafbbSLai Jiangshan 	}
441*127cafbbSLai Jiangshan 	tracepoint_add_old_probes(old);
442*127cafbbSLai Jiangshan 	mutex_unlock(&tracepoints_mutex);
443*127cafbbSLai Jiangshan 	return 0;
444*127cafbbSLai Jiangshan }
445*127cafbbSLai Jiangshan EXPORT_SYMBOL_GPL(tracepoint_probe_unregister_noupdate);
446*127cafbbSLai Jiangshan 
447*127cafbbSLai Jiangshan /**
448*127cafbbSLai Jiangshan  * tracepoint_probe_update_all -  update tracepoints
449*127cafbbSLai Jiangshan  */
450*127cafbbSLai Jiangshan void tracepoint_probe_update_all(void)
451*127cafbbSLai Jiangshan {
452*127cafbbSLai Jiangshan 	LIST_HEAD(release_probes);
453*127cafbbSLai Jiangshan 	struct tp_probes *pos, *next;
454*127cafbbSLai Jiangshan 
455*127cafbbSLai Jiangshan 	mutex_lock(&tracepoints_mutex);
456*127cafbbSLai Jiangshan 	if (!need_update) {
457*127cafbbSLai Jiangshan 		mutex_unlock(&tracepoints_mutex);
458*127cafbbSLai Jiangshan 		return;
459*127cafbbSLai Jiangshan 	}
460*127cafbbSLai Jiangshan 	if (!list_empty(&old_probes))
461*127cafbbSLai Jiangshan 		list_replace_init(&old_probes, &release_probes);
462*127cafbbSLai Jiangshan 	need_update = 0;
463*127cafbbSLai Jiangshan 	mutex_unlock(&tracepoints_mutex);
464*127cafbbSLai Jiangshan 
465*127cafbbSLai Jiangshan 	tracepoint_update_probes();
466*127cafbbSLai Jiangshan 	list_for_each_entry_safe(pos, next, &release_probes, u.list) {
467*127cafbbSLai Jiangshan 		list_del(&pos->u.list);
468*127cafbbSLai Jiangshan 		call_rcu_sched(&pos->u.rcu, rcu_free_old_probes);
469*127cafbbSLai Jiangshan 	}
470*127cafbbSLai Jiangshan }
471*127cafbbSLai Jiangshan EXPORT_SYMBOL_GPL(tracepoint_probe_update_all);
472*127cafbbSLai Jiangshan 
47397e1c18eSMathieu Desnoyers /**
47497e1c18eSMathieu Desnoyers  * tracepoint_get_iter_range - Get a next tracepoint iterator given a range.
47597e1c18eSMathieu Desnoyers  * @tracepoint: current tracepoints (in), next tracepoint (out)
47697e1c18eSMathieu Desnoyers  * @begin: beginning of the range
47797e1c18eSMathieu Desnoyers  * @end: end of the range
47897e1c18eSMathieu Desnoyers  *
47997e1c18eSMathieu Desnoyers  * Returns whether a next tracepoint has been found (1) or not (0).
48097e1c18eSMathieu Desnoyers  * Will return the first tracepoint in the range if the input tracepoint is
48197e1c18eSMathieu Desnoyers  * NULL.
48297e1c18eSMathieu Desnoyers  */
48397e1c18eSMathieu Desnoyers int tracepoint_get_iter_range(struct tracepoint **tracepoint,
48497e1c18eSMathieu Desnoyers 	struct tracepoint *begin, struct tracepoint *end)
48597e1c18eSMathieu Desnoyers {
48697e1c18eSMathieu Desnoyers 	if (!*tracepoint && begin != end) {
48797e1c18eSMathieu Desnoyers 		*tracepoint = begin;
48897e1c18eSMathieu Desnoyers 		return 1;
48997e1c18eSMathieu Desnoyers 	}
49097e1c18eSMathieu Desnoyers 	if (*tracepoint >= begin && *tracepoint < end)
49197e1c18eSMathieu Desnoyers 		return 1;
49297e1c18eSMathieu Desnoyers 	return 0;
49397e1c18eSMathieu Desnoyers }
49497e1c18eSMathieu Desnoyers EXPORT_SYMBOL_GPL(tracepoint_get_iter_range);
49597e1c18eSMathieu Desnoyers 
49697e1c18eSMathieu Desnoyers static void tracepoint_get_iter(struct tracepoint_iter *iter)
49797e1c18eSMathieu Desnoyers {
49897e1c18eSMathieu Desnoyers 	int found = 0;
49997e1c18eSMathieu Desnoyers 
50097e1c18eSMathieu Desnoyers 	/* Core kernel tracepoints */
50197e1c18eSMathieu Desnoyers 	if (!iter->module) {
50297e1c18eSMathieu Desnoyers 		found = tracepoint_get_iter_range(&iter->tracepoint,
50397e1c18eSMathieu Desnoyers 				__start___tracepoints, __stop___tracepoints);
50497e1c18eSMathieu Desnoyers 		if (found)
50597e1c18eSMathieu Desnoyers 			goto end;
50697e1c18eSMathieu Desnoyers 	}
50797e1c18eSMathieu Desnoyers 	/* tracepoints in modules. */
50897e1c18eSMathieu Desnoyers 	found = module_get_iter_tracepoints(iter);
50997e1c18eSMathieu Desnoyers end:
51097e1c18eSMathieu Desnoyers 	if (!found)
51197e1c18eSMathieu Desnoyers 		tracepoint_iter_reset(iter);
51297e1c18eSMathieu Desnoyers }
51397e1c18eSMathieu Desnoyers 
51497e1c18eSMathieu Desnoyers void tracepoint_iter_start(struct tracepoint_iter *iter)
51597e1c18eSMathieu Desnoyers {
51697e1c18eSMathieu Desnoyers 	tracepoint_get_iter(iter);
51797e1c18eSMathieu Desnoyers }
51897e1c18eSMathieu Desnoyers EXPORT_SYMBOL_GPL(tracepoint_iter_start);
51997e1c18eSMathieu Desnoyers 
52097e1c18eSMathieu Desnoyers void tracepoint_iter_next(struct tracepoint_iter *iter)
52197e1c18eSMathieu Desnoyers {
52297e1c18eSMathieu Desnoyers 	iter->tracepoint++;
52397e1c18eSMathieu Desnoyers 	/*
52497e1c18eSMathieu Desnoyers 	 * iter->tracepoint may be invalid because we blindly incremented it.
52597e1c18eSMathieu Desnoyers 	 * Make sure it is valid by marshalling on the tracepoints, getting the
52697e1c18eSMathieu Desnoyers 	 * tracepoints from following modules if necessary.
52797e1c18eSMathieu Desnoyers 	 */
52897e1c18eSMathieu Desnoyers 	tracepoint_get_iter(iter);
52997e1c18eSMathieu Desnoyers }
53097e1c18eSMathieu Desnoyers EXPORT_SYMBOL_GPL(tracepoint_iter_next);
53197e1c18eSMathieu Desnoyers 
53297e1c18eSMathieu Desnoyers void tracepoint_iter_stop(struct tracepoint_iter *iter)
53397e1c18eSMathieu Desnoyers {
53497e1c18eSMathieu Desnoyers }
53597e1c18eSMathieu Desnoyers EXPORT_SYMBOL_GPL(tracepoint_iter_stop);
53697e1c18eSMathieu Desnoyers 
53797e1c18eSMathieu Desnoyers void tracepoint_iter_reset(struct tracepoint_iter *iter)
53897e1c18eSMathieu Desnoyers {
53997e1c18eSMathieu Desnoyers 	iter->module = NULL;
54097e1c18eSMathieu Desnoyers 	iter->tracepoint = NULL;
54197e1c18eSMathieu Desnoyers }
54297e1c18eSMathieu Desnoyers EXPORT_SYMBOL_GPL(tracepoint_iter_reset);
543