xref: /linux/kernel/tracepoint.c (revision 97e1c18e8d17bd87e1e383b2e9d9fc740332c8e2)
1*97e1c18eSMathieu Desnoyers /*
2*97e1c18eSMathieu Desnoyers  * Copyright (C) 2008 Mathieu Desnoyers
3*97e1c18eSMathieu Desnoyers  *
4*97e1c18eSMathieu Desnoyers  * This program is free software; you can redistribute it and/or modify
5*97e1c18eSMathieu Desnoyers  * it under the terms of the GNU General Public License as published by
6*97e1c18eSMathieu Desnoyers  * the Free Software Foundation; either version 2 of the License, or
7*97e1c18eSMathieu Desnoyers  * (at your option) any later version.
8*97e1c18eSMathieu Desnoyers  *
9*97e1c18eSMathieu Desnoyers  * This program is distributed in the hope that it will be useful,
10*97e1c18eSMathieu Desnoyers  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*97e1c18eSMathieu Desnoyers  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12*97e1c18eSMathieu Desnoyers  * GNU General Public License for more details.
13*97e1c18eSMathieu Desnoyers  *
14*97e1c18eSMathieu Desnoyers  * You should have received a copy of the GNU General Public License
15*97e1c18eSMathieu Desnoyers  * along with this program; if not, write to the Free Software
16*97e1c18eSMathieu Desnoyers  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17*97e1c18eSMathieu Desnoyers  */
18*97e1c18eSMathieu Desnoyers #include <linux/module.h>
19*97e1c18eSMathieu Desnoyers #include <linux/mutex.h>
20*97e1c18eSMathieu Desnoyers #include <linux/types.h>
21*97e1c18eSMathieu Desnoyers #include <linux/jhash.h>
22*97e1c18eSMathieu Desnoyers #include <linux/list.h>
23*97e1c18eSMathieu Desnoyers #include <linux/rcupdate.h>
24*97e1c18eSMathieu Desnoyers #include <linux/tracepoint.h>
25*97e1c18eSMathieu Desnoyers #include <linux/err.h>
26*97e1c18eSMathieu Desnoyers #include <linux/slab.h>
27*97e1c18eSMathieu Desnoyers 
28*97e1c18eSMathieu Desnoyers extern struct tracepoint __start___tracepoints[];
29*97e1c18eSMathieu Desnoyers extern struct tracepoint __stop___tracepoints[];
30*97e1c18eSMathieu Desnoyers 
31*97e1c18eSMathieu Desnoyers /* Set to 1 to enable tracepoint debug output */
32*97e1c18eSMathieu Desnoyers static const int tracepoint_debug;
33*97e1c18eSMathieu Desnoyers 
34*97e1c18eSMathieu Desnoyers /*
35*97e1c18eSMathieu Desnoyers  * tracepoints_mutex nests inside module_mutex. Tracepoints mutex protects the
36*97e1c18eSMathieu Desnoyers  * builtin and module tracepoints and the hash table.
37*97e1c18eSMathieu Desnoyers  */
38*97e1c18eSMathieu Desnoyers static DEFINE_MUTEX(tracepoints_mutex);
39*97e1c18eSMathieu Desnoyers 
40*97e1c18eSMathieu Desnoyers /*
41*97e1c18eSMathieu Desnoyers  * Tracepoint hash table, containing the active tracepoints.
42*97e1c18eSMathieu Desnoyers  * Protected by tracepoints_mutex.
43*97e1c18eSMathieu Desnoyers  */
44*97e1c18eSMathieu Desnoyers #define TRACEPOINT_HASH_BITS 6
45*97e1c18eSMathieu Desnoyers #define TRACEPOINT_TABLE_SIZE (1 << TRACEPOINT_HASH_BITS)
46*97e1c18eSMathieu Desnoyers 
47*97e1c18eSMathieu Desnoyers /*
48*97e1c18eSMathieu Desnoyers  * Note about RCU :
49*97e1c18eSMathieu Desnoyers  * It is used to to delay the free of multiple probes array until a quiescent
50*97e1c18eSMathieu Desnoyers  * state is reached.
51*97e1c18eSMathieu Desnoyers  * Tracepoint entries modifications are protected by the tracepoints_mutex.
52*97e1c18eSMathieu Desnoyers  */
53*97e1c18eSMathieu Desnoyers struct tracepoint_entry {
54*97e1c18eSMathieu Desnoyers 	struct hlist_node hlist;
55*97e1c18eSMathieu Desnoyers 	void **funcs;
56*97e1c18eSMathieu Desnoyers 	int refcount;	/* Number of times armed. 0 if disarmed. */
57*97e1c18eSMathieu Desnoyers 	struct rcu_head rcu;
58*97e1c18eSMathieu Desnoyers 	void *oldptr;
59*97e1c18eSMathieu Desnoyers 	unsigned char rcu_pending:1;
60*97e1c18eSMathieu Desnoyers 	char name[0];
61*97e1c18eSMathieu Desnoyers };
62*97e1c18eSMathieu Desnoyers 
63*97e1c18eSMathieu Desnoyers static struct hlist_head tracepoint_table[TRACEPOINT_TABLE_SIZE];
64*97e1c18eSMathieu Desnoyers 
65*97e1c18eSMathieu Desnoyers static void free_old_closure(struct rcu_head *head)
66*97e1c18eSMathieu Desnoyers {
67*97e1c18eSMathieu Desnoyers 	struct tracepoint_entry *entry = container_of(head,
68*97e1c18eSMathieu Desnoyers 		struct tracepoint_entry, rcu);
69*97e1c18eSMathieu Desnoyers 	kfree(entry->oldptr);
70*97e1c18eSMathieu Desnoyers 	/* Make sure we free the data before setting the pending flag to 0 */
71*97e1c18eSMathieu Desnoyers 	smp_wmb();
72*97e1c18eSMathieu Desnoyers 	entry->rcu_pending = 0;
73*97e1c18eSMathieu Desnoyers }
74*97e1c18eSMathieu Desnoyers 
75*97e1c18eSMathieu Desnoyers static void tracepoint_entry_free_old(struct tracepoint_entry *entry, void *old)
76*97e1c18eSMathieu Desnoyers {
77*97e1c18eSMathieu Desnoyers 	if (!old)
78*97e1c18eSMathieu Desnoyers 		return;
79*97e1c18eSMathieu Desnoyers 	entry->oldptr = old;
80*97e1c18eSMathieu Desnoyers 	entry->rcu_pending = 1;
81*97e1c18eSMathieu Desnoyers 	/* write rcu_pending before calling the RCU callback */
82*97e1c18eSMathieu Desnoyers 	smp_wmb();
83*97e1c18eSMathieu Desnoyers #ifdef CONFIG_PREEMPT_RCU
84*97e1c18eSMathieu Desnoyers 	synchronize_sched();	/* Until we have the call_rcu_sched() */
85*97e1c18eSMathieu Desnoyers #endif
86*97e1c18eSMathieu Desnoyers 	call_rcu(&entry->rcu, free_old_closure);
87*97e1c18eSMathieu Desnoyers }
88*97e1c18eSMathieu Desnoyers 
89*97e1c18eSMathieu Desnoyers static void debug_print_probes(struct tracepoint_entry *entry)
90*97e1c18eSMathieu Desnoyers {
91*97e1c18eSMathieu Desnoyers 	int i;
92*97e1c18eSMathieu Desnoyers 
93*97e1c18eSMathieu Desnoyers 	if (!tracepoint_debug)
94*97e1c18eSMathieu Desnoyers 		return;
95*97e1c18eSMathieu Desnoyers 
96*97e1c18eSMathieu Desnoyers 	for (i = 0; entry->funcs[i]; i++)
97*97e1c18eSMathieu Desnoyers 		printk(KERN_DEBUG "Probe %d : %p\n", i, entry->funcs[i]);
98*97e1c18eSMathieu Desnoyers }
99*97e1c18eSMathieu Desnoyers 
100*97e1c18eSMathieu Desnoyers static void *
101*97e1c18eSMathieu Desnoyers tracepoint_entry_add_probe(struct tracepoint_entry *entry, void *probe)
102*97e1c18eSMathieu Desnoyers {
103*97e1c18eSMathieu Desnoyers 	int nr_probes = 0;
104*97e1c18eSMathieu Desnoyers 	void **old, **new;
105*97e1c18eSMathieu Desnoyers 
106*97e1c18eSMathieu Desnoyers 	WARN_ON(!probe);
107*97e1c18eSMathieu Desnoyers 
108*97e1c18eSMathieu Desnoyers 	debug_print_probes(entry);
109*97e1c18eSMathieu Desnoyers 	old = entry->funcs;
110*97e1c18eSMathieu Desnoyers 	if (old) {
111*97e1c18eSMathieu Desnoyers 		/* (N -> N+1), (N != 0, 1) probes */
112*97e1c18eSMathieu Desnoyers 		for (nr_probes = 0; old[nr_probes]; nr_probes++)
113*97e1c18eSMathieu Desnoyers 			if (old[nr_probes] == probe)
114*97e1c18eSMathieu Desnoyers 				return ERR_PTR(-EEXIST);
115*97e1c18eSMathieu Desnoyers 	}
116*97e1c18eSMathieu Desnoyers 	/* + 2 : one for new probe, one for NULL func */
117*97e1c18eSMathieu Desnoyers 	new = kzalloc((nr_probes + 2) * sizeof(void *), GFP_KERNEL);
118*97e1c18eSMathieu Desnoyers 	if (new == NULL)
119*97e1c18eSMathieu Desnoyers 		return ERR_PTR(-ENOMEM);
120*97e1c18eSMathieu Desnoyers 	if (old)
121*97e1c18eSMathieu Desnoyers 		memcpy(new, old, nr_probes * sizeof(void *));
122*97e1c18eSMathieu Desnoyers 	new[nr_probes] = probe;
123*97e1c18eSMathieu Desnoyers 	entry->refcount = nr_probes + 1;
124*97e1c18eSMathieu Desnoyers 	entry->funcs = new;
125*97e1c18eSMathieu Desnoyers 	debug_print_probes(entry);
126*97e1c18eSMathieu Desnoyers 	return old;
127*97e1c18eSMathieu Desnoyers }
128*97e1c18eSMathieu Desnoyers 
129*97e1c18eSMathieu Desnoyers static void *
130*97e1c18eSMathieu Desnoyers tracepoint_entry_remove_probe(struct tracepoint_entry *entry, void *probe)
131*97e1c18eSMathieu Desnoyers {
132*97e1c18eSMathieu Desnoyers 	int nr_probes = 0, nr_del = 0, i;
133*97e1c18eSMathieu Desnoyers 	void **old, **new;
134*97e1c18eSMathieu Desnoyers 
135*97e1c18eSMathieu Desnoyers 	old = entry->funcs;
136*97e1c18eSMathieu Desnoyers 
137*97e1c18eSMathieu Desnoyers 	debug_print_probes(entry);
138*97e1c18eSMathieu Desnoyers 	/* (N -> M), (N > 1, M >= 0) probes */
139*97e1c18eSMathieu Desnoyers 	for (nr_probes = 0; old[nr_probes]; nr_probes++) {
140*97e1c18eSMathieu Desnoyers 		if ((!probe || old[nr_probes] == probe))
141*97e1c18eSMathieu Desnoyers 			nr_del++;
142*97e1c18eSMathieu Desnoyers 	}
143*97e1c18eSMathieu Desnoyers 
144*97e1c18eSMathieu Desnoyers 	if (nr_probes - nr_del == 0) {
145*97e1c18eSMathieu Desnoyers 		/* N -> 0, (N > 1) */
146*97e1c18eSMathieu Desnoyers 		entry->funcs = NULL;
147*97e1c18eSMathieu Desnoyers 		entry->refcount = 0;
148*97e1c18eSMathieu Desnoyers 		debug_print_probes(entry);
149*97e1c18eSMathieu Desnoyers 		return old;
150*97e1c18eSMathieu Desnoyers 	} else {
151*97e1c18eSMathieu Desnoyers 		int j = 0;
152*97e1c18eSMathieu Desnoyers 		/* N -> M, (N > 1, M > 0) */
153*97e1c18eSMathieu Desnoyers 		/* + 1 for NULL */
154*97e1c18eSMathieu Desnoyers 		new = kzalloc((nr_probes - nr_del + 1)
155*97e1c18eSMathieu Desnoyers 			* sizeof(void *), GFP_KERNEL);
156*97e1c18eSMathieu Desnoyers 		if (new == NULL)
157*97e1c18eSMathieu Desnoyers 			return ERR_PTR(-ENOMEM);
158*97e1c18eSMathieu Desnoyers 		for (i = 0; old[i]; i++)
159*97e1c18eSMathieu Desnoyers 			if ((probe && old[i] != probe))
160*97e1c18eSMathieu Desnoyers 				new[j++] = old[i];
161*97e1c18eSMathieu Desnoyers 		entry->refcount = nr_probes - nr_del;
162*97e1c18eSMathieu Desnoyers 		entry->funcs = new;
163*97e1c18eSMathieu Desnoyers 	}
164*97e1c18eSMathieu Desnoyers 	debug_print_probes(entry);
165*97e1c18eSMathieu Desnoyers 	return old;
166*97e1c18eSMathieu Desnoyers }
167*97e1c18eSMathieu Desnoyers 
168*97e1c18eSMathieu Desnoyers /*
169*97e1c18eSMathieu Desnoyers  * Get tracepoint if the tracepoint is present in the tracepoint hash table.
170*97e1c18eSMathieu Desnoyers  * Must be called with tracepoints_mutex held.
171*97e1c18eSMathieu Desnoyers  * Returns NULL if not present.
172*97e1c18eSMathieu Desnoyers  */
173*97e1c18eSMathieu Desnoyers static struct tracepoint_entry *get_tracepoint(const char *name)
174*97e1c18eSMathieu Desnoyers {
175*97e1c18eSMathieu Desnoyers 	struct hlist_head *head;
176*97e1c18eSMathieu Desnoyers 	struct hlist_node *node;
177*97e1c18eSMathieu Desnoyers 	struct tracepoint_entry *e;
178*97e1c18eSMathieu Desnoyers 	u32 hash = jhash(name, strlen(name), 0);
179*97e1c18eSMathieu Desnoyers 
180*97e1c18eSMathieu Desnoyers 	head = &tracepoint_table[hash & ((1 << TRACEPOINT_HASH_BITS)-1)];
181*97e1c18eSMathieu Desnoyers 	hlist_for_each_entry(e, node, head, hlist) {
182*97e1c18eSMathieu Desnoyers 		if (!strcmp(name, e->name))
183*97e1c18eSMathieu Desnoyers 			return e;
184*97e1c18eSMathieu Desnoyers 	}
185*97e1c18eSMathieu Desnoyers 	return NULL;
186*97e1c18eSMathieu Desnoyers }
187*97e1c18eSMathieu Desnoyers 
188*97e1c18eSMathieu Desnoyers /*
189*97e1c18eSMathieu Desnoyers  * Add the tracepoint to the tracepoint hash table. Must be called with
190*97e1c18eSMathieu Desnoyers  * tracepoints_mutex held.
191*97e1c18eSMathieu Desnoyers  */
192*97e1c18eSMathieu Desnoyers static struct tracepoint_entry *add_tracepoint(const char *name)
193*97e1c18eSMathieu Desnoyers {
194*97e1c18eSMathieu Desnoyers 	struct hlist_head *head;
195*97e1c18eSMathieu Desnoyers 	struct hlist_node *node;
196*97e1c18eSMathieu Desnoyers 	struct tracepoint_entry *e;
197*97e1c18eSMathieu Desnoyers 	size_t name_len = strlen(name) + 1;
198*97e1c18eSMathieu Desnoyers 	u32 hash = jhash(name, name_len-1, 0);
199*97e1c18eSMathieu Desnoyers 
200*97e1c18eSMathieu Desnoyers 	head = &tracepoint_table[hash & ((1 << TRACEPOINT_HASH_BITS)-1)];
201*97e1c18eSMathieu Desnoyers 	hlist_for_each_entry(e, node, head, hlist) {
202*97e1c18eSMathieu Desnoyers 		if (!strcmp(name, e->name)) {
203*97e1c18eSMathieu Desnoyers 			printk(KERN_NOTICE
204*97e1c18eSMathieu Desnoyers 				"tracepoint %s busy\n", name);
205*97e1c18eSMathieu Desnoyers 			return ERR_PTR(-EEXIST);	/* Already there */
206*97e1c18eSMathieu Desnoyers 		}
207*97e1c18eSMathieu Desnoyers 	}
208*97e1c18eSMathieu Desnoyers 	/*
209*97e1c18eSMathieu Desnoyers 	 * Using kmalloc here to allocate a variable length element. Could
210*97e1c18eSMathieu Desnoyers 	 * cause some memory fragmentation if overused.
211*97e1c18eSMathieu Desnoyers 	 */
212*97e1c18eSMathieu Desnoyers 	e = kmalloc(sizeof(struct tracepoint_entry) + name_len, GFP_KERNEL);
213*97e1c18eSMathieu Desnoyers 	if (!e)
214*97e1c18eSMathieu Desnoyers 		return ERR_PTR(-ENOMEM);
215*97e1c18eSMathieu Desnoyers 	memcpy(&e->name[0], name, name_len);
216*97e1c18eSMathieu Desnoyers 	e->funcs = NULL;
217*97e1c18eSMathieu Desnoyers 	e->refcount = 0;
218*97e1c18eSMathieu Desnoyers 	e->rcu_pending = 0;
219*97e1c18eSMathieu Desnoyers 	hlist_add_head(&e->hlist, head);
220*97e1c18eSMathieu Desnoyers 	return e;
221*97e1c18eSMathieu Desnoyers }
222*97e1c18eSMathieu Desnoyers 
223*97e1c18eSMathieu Desnoyers /*
224*97e1c18eSMathieu Desnoyers  * Remove the tracepoint from the tracepoint hash table. Must be called with
225*97e1c18eSMathieu Desnoyers  * mutex_lock held.
226*97e1c18eSMathieu Desnoyers  */
227*97e1c18eSMathieu Desnoyers static int remove_tracepoint(const char *name)
228*97e1c18eSMathieu Desnoyers {
229*97e1c18eSMathieu Desnoyers 	struct hlist_head *head;
230*97e1c18eSMathieu Desnoyers 	struct hlist_node *node;
231*97e1c18eSMathieu Desnoyers 	struct tracepoint_entry *e;
232*97e1c18eSMathieu Desnoyers 	int found = 0;
233*97e1c18eSMathieu Desnoyers 	size_t len = strlen(name) + 1;
234*97e1c18eSMathieu Desnoyers 	u32 hash = jhash(name, len-1, 0);
235*97e1c18eSMathieu Desnoyers 
236*97e1c18eSMathieu Desnoyers 	head = &tracepoint_table[hash & ((1 << TRACEPOINT_HASH_BITS)-1)];
237*97e1c18eSMathieu Desnoyers 	hlist_for_each_entry(e, node, head, hlist) {
238*97e1c18eSMathieu Desnoyers 		if (!strcmp(name, e->name)) {
239*97e1c18eSMathieu Desnoyers 			found = 1;
240*97e1c18eSMathieu Desnoyers 			break;
241*97e1c18eSMathieu Desnoyers 		}
242*97e1c18eSMathieu Desnoyers 	}
243*97e1c18eSMathieu Desnoyers 	if (!found)
244*97e1c18eSMathieu Desnoyers 		return -ENOENT;
245*97e1c18eSMathieu Desnoyers 	if (e->refcount)
246*97e1c18eSMathieu Desnoyers 		return -EBUSY;
247*97e1c18eSMathieu Desnoyers 	hlist_del(&e->hlist);
248*97e1c18eSMathieu Desnoyers 	/* Make sure the call_rcu has been executed */
249*97e1c18eSMathieu Desnoyers 	if (e->rcu_pending)
250*97e1c18eSMathieu Desnoyers 		rcu_barrier();
251*97e1c18eSMathieu Desnoyers 	kfree(e);
252*97e1c18eSMathieu Desnoyers 	return 0;
253*97e1c18eSMathieu Desnoyers }
254*97e1c18eSMathieu Desnoyers 
255*97e1c18eSMathieu Desnoyers /*
256*97e1c18eSMathieu Desnoyers  * Sets the probe callback corresponding to one tracepoint.
257*97e1c18eSMathieu Desnoyers  */
258*97e1c18eSMathieu Desnoyers static void set_tracepoint(struct tracepoint_entry **entry,
259*97e1c18eSMathieu Desnoyers 	struct tracepoint *elem, int active)
260*97e1c18eSMathieu Desnoyers {
261*97e1c18eSMathieu Desnoyers 	WARN_ON(strcmp((*entry)->name, elem->name) != 0);
262*97e1c18eSMathieu Desnoyers 
263*97e1c18eSMathieu Desnoyers 	/*
264*97e1c18eSMathieu Desnoyers 	 * rcu_assign_pointer has a smp_wmb() which makes sure that the new
265*97e1c18eSMathieu Desnoyers 	 * probe callbacks array is consistent before setting a pointer to it.
266*97e1c18eSMathieu Desnoyers 	 * This array is referenced by __DO_TRACE from
267*97e1c18eSMathieu Desnoyers 	 * include/linux/tracepoints.h. A matching smp_read_barrier_depends()
268*97e1c18eSMathieu Desnoyers 	 * is used.
269*97e1c18eSMathieu Desnoyers 	 */
270*97e1c18eSMathieu Desnoyers 	rcu_assign_pointer(elem->funcs, (*entry)->funcs);
271*97e1c18eSMathieu Desnoyers 	elem->state = active;
272*97e1c18eSMathieu Desnoyers }
273*97e1c18eSMathieu Desnoyers 
274*97e1c18eSMathieu Desnoyers /*
275*97e1c18eSMathieu Desnoyers  * Disable a tracepoint and its probe callback.
276*97e1c18eSMathieu Desnoyers  * Note: only waiting an RCU period after setting elem->call to the empty
277*97e1c18eSMathieu Desnoyers  * function insures that the original callback is not used anymore. This insured
278*97e1c18eSMathieu Desnoyers  * by preempt_disable around the call site.
279*97e1c18eSMathieu Desnoyers  */
280*97e1c18eSMathieu Desnoyers static void disable_tracepoint(struct tracepoint *elem)
281*97e1c18eSMathieu Desnoyers {
282*97e1c18eSMathieu Desnoyers 	elem->state = 0;
283*97e1c18eSMathieu Desnoyers }
284*97e1c18eSMathieu Desnoyers 
285*97e1c18eSMathieu Desnoyers /**
286*97e1c18eSMathieu Desnoyers  * tracepoint_update_probe_range - Update a probe range
287*97e1c18eSMathieu Desnoyers  * @begin: beginning of the range
288*97e1c18eSMathieu Desnoyers  * @end: end of the range
289*97e1c18eSMathieu Desnoyers  *
290*97e1c18eSMathieu Desnoyers  * Updates the probe callback corresponding to a range of tracepoints.
291*97e1c18eSMathieu Desnoyers  */
292*97e1c18eSMathieu Desnoyers void tracepoint_update_probe_range(struct tracepoint *begin,
293*97e1c18eSMathieu Desnoyers 	struct tracepoint *end)
294*97e1c18eSMathieu Desnoyers {
295*97e1c18eSMathieu Desnoyers 	struct tracepoint *iter;
296*97e1c18eSMathieu Desnoyers 	struct tracepoint_entry *mark_entry;
297*97e1c18eSMathieu Desnoyers 
298*97e1c18eSMathieu Desnoyers 	mutex_lock(&tracepoints_mutex);
299*97e1c18eSMathieu Desnoyers 	for (iter = begin; iter < end; iter++) {
300*97e1c18eSMathieu Desnoyers 		mark_entry = get_tracepoint(iter->name);
301*97e1c18eSMathieu Desnoyers 		if (mark_entry) {
302*97e1c18eSMathieu Desnoyers 			set_tracepoint(&mark_entry, iter,
303*97e1c18eSMathieu Desnoyers 					!!mark_entry->refcount);
304*97e1c18eSMathieu Desnoyers 		} else {
305*97e1c18eSMathieu Desnoyers 			disable_tracepoint(iter);
306*97e1c18eSMathieu Desnoyers 		}
307*97e1c18eSMathieu Desnoyers 	}
308*97e1c18eSMathieu Desnoyers 	mutex_unlock(&tracepoints_mutex);
309*97e1c18eSMathieu Desnoyers }
310*97e1c18eSMathieu Desnoyers 
311*97e1c18eSMathieu Desnoyers /*
312*97e1c18eSMathieu Desnoyers  * Update probes, removing the faulty probes.
313*97e1c18eSMathieu Desnoyers  */
314*97e1c18eSMathieu Desnoyers static void tracepoint_update_probes(void)
315*97e1c18eSMathieu Desnoyers {
316*97e1c18eSMathieu Desnoyers 	/* Core kernel tracepoints */
317*97e1c18eSMathieu Desnoyers 	tracepoint_update_probe_range(__start___tracepoints,
318*97e1c18eSMathieu Desnoyers 		__stop___tracepoints);
319*97e1c18eSMathieu Desnoyers 	/* tracepoints in modules. */
320*97e1c18eSMathieu Desnoyers 	module_update_tracepoints();
321*97e1c18eSMathieu Desnoyers }
322*97e1c18eSMathieu Desnoyers 
323*97e1c18eSMathieu Desnoyers /**
324*97e1c18eSMathieu Desnoyers  * tracepoint_probe_register -  Connect a probe to a tracepoint
325*97e1c18eSMathieu Desnoyers  * @name: tracepoint name
326*97e1c18eSMathieu Desnoyers  * @probe: probe handler
327*97e1c18eSMathieu Desnoyers  *
328*97e1c18eSMathieu Desnoyers  * Returns 0 if ok, error value on error.
329*97e1c18eSMathieu Desnoyers  * The probe address must at least be aligned on the architecture pointer size.
330*97e1c18eSMathieu Desnoyers  */
331*97e1c18eSMathieu Desnoyers int tracepoint_probe_register(const char *name, void *probe)
332*97e1c18eSMathieu Desnoyers {
333*97e1c18eSMathieu Desnoyers 	struct tracepoint_entry *entry;
334*97e1c18eSMathieu Desnoyers 	int ret = 0;
335*97e1c18eSMathieu Desnoyers 	void *old;
336*97e1c18eSMathieu Desnoyers 
337*97e1c18eSMathieu Desnoyers 	mutex_lock(&tracepoints_mutex);
338*97e1c18eSMathieu Desnoyers 	entry = get_tracepoint(name);
339*97e1c18eSMathieu Desnoyers 	if (!entry) {
340*97e1c18eSMathieu Desnoyers 		entry = add_tracepoint(name);
341*97e1c18eSMathieu Desnoyers 		if (IS_ERR(entry)) {
342*97e1c18eSMathieu Desnoyers 			ret = PTR_ERR(entry);
343*97e1c18eSMathieu Desnoyers 			goto end;
344*97e1c18eSMathieu Desnoyers 		}
345*97e1c18eSMathieu Desnoyers 	}
346*97e1c18eSMathieu Desnoyers 	/*
347*97e1c18eSMathieu Desnoyers 	 * If we detect that a call_rcu is pending for this tracepoint,
348*97e1c18eSMathieu Desnoyers 	 * make sure it's executed now.
349*97e1c18eSMathieu Desnoyers 	 */
350*97e1c18eSMathieu Desnoyers 	if (entry->rcu_pending)
351*97e1c18eSMathieu Desnoyers 		rcu_barrier();
352*97e1c18eSMathieu Desnoyers 	old = tracepoint_entry_add_probe(entry, probe);
353*97e1c18eSMathieu Desnoyers 	if (IS_ERR(old)) {
354*97e1c18eSMathieu Desnoyers 		ret = PTR_ERR(old);
355*97e1c18eSMathieu Desnoyers 		goto end;
356*97e1c18eSMathieu Desnoyers 	}
357*97e1c18eSMathieu Desnoyers 	mutex_unlock(&tracepoints_mutex);
358*97e1c18eSMathieu Desnoyers 	tracepoint_update_probes();		/* may update entry */
359*97e1c18eSMathieu Desnoyers 	mutex_lock(&tracepoints_mutex);
360*97e1c18eSMathieu Desnoyers 	entry = get_tracepoint(name);
361*97e1c18eSMathieu Desnoyers 	WARN_ON(!entry);
362*97e1c18eSMathieu Desnoyers 	tracepoint_entry_free_old(entry, old);
363*97e1c18eSMathieu Desnoyers end:
364*97e1c18eSMathieu Desnoyers 	mutex_unlock(&tracepoints_mutex);
365*97e1c18eSMathieu Desnoyers 	return ret;
366*97e1c18eSMathieu Desnoyers }
367*97e1c18eSMathieu Desnoyers EXPORT_SYMBOL_GPL(tracepoint_probe_register);
368*97e1c18eSMathieu Desnoyers 
369*97e1c18eSMathieu Desnoyers /**
370*97e1c18eSMathieu Desnoyers  * tracepoint_probe_unregister -  Disconnect a probe from a tracepoint
371*97e1c18eSMathieu Desnoyers  * @name: tracepoint name
372*97e1c18eSMathieu Desnoyers  * @probe: probe function pointer
373*97e1c18eSMathieu Desnoyers  *
374*97e1c18eSMathieu Desnoyers  * We do not need to call a synchronize_sched to make sure the probes have
375*97e1c18eSMathieu Desnoyers  * finished running before doing a module unload, because the module unload
376*97e1c18eSMathieu Desnoyers  * itself uses stop_machine(), which insures that every preempt disabled section
377*97e1c18eSMathieu Desnoyers  * have finished.
378*97e1c18eSMathieu Desnoyers  */
379*97e1c18eSMathieu Desnoyers int tracepoint_probe_unregister(const char *name, void *probe)
380*97e1c18eSMathieu Desnoyers {
381*97e1c18eSMathieu Desnoyers 	struct tracepoint_entry *entry;
382*97e1c18eSMathieu Desnoyers 	void *old;
383*97e1c18eSMathieu Desnoyers 	int ret = -ENOENT;
384*97e1c18eSMathieu Desnoyers 
385*97e1c18eSMathieu Desnoyers 	mutex_lock(&tracepoints_mutex);
386*97e1c18eSMathieu Desnoyers 	entry = get_tracepoint(name);
387*97e1c18eSMathieu Desnoyers 	if (!entry)
388*97e1c18eSMathieu Desnoyers 		goto end;
389*97e1c18eSMathieu Desnoyers 	if (entry->rcu_pending)
390*97e1c18eSMathieu Desnoyers 		rcu_barrier();
391*97e1c18eSMathieu Desnoyers 	old = tracepoint_entry_remove_probe(entry, probe);
392*97e1c18eSMathieu Desnoyers 	mutex_unlock(&tracepoints_mutex);
393*97e1c18eSMathieu Desnoyers 	tracepoint_update_probes();		/* may update entry */
394*97e1c18eSMathieu Desnoyers 	mutex_lock(&tracepoints_mutex);
395*97e1c18eSMathieu Desnoyers 	entry = get_tracepoint(name);
396*97e1c18eSMathieu Desnoyers 	if (!entry)
397*97e1c18eSMathieu Desnoyers 		goto end;
398*97e1c18eSMathieu Desnoyers 	tracepoint_entry_free_old(entry, old);
399*97e1c18eSMathieu Desnoyers 	remove_tracepoint(name);	/* Ignore busy error message */
400*97e1c18eSMathieu Desnoyers 	ret = 0;
401*97e1c18eSMathieu Desnoyers end:
402*97e1c18eSMathieu Desnoyers 	mutex_unlock(&tracepoints_mutex);
403*97e1c18eSMathieu Desnoyers 	return ret;
404*97e1c18eSMathieu Desnoyers }
405*97e1c18eSMathieu Desnoyers EXPORT_SYMBOL_GPL(tracepoint_probe_unregister);
406*97e1c18eSMathieu Desnoyers 
407*97e1c18eSMathieu Desnoyers /**
408*97e1c18eSMathieu Desnoyers  * tracepoint_get_iter_range - Get a next tracepoint iterator given a range.
409*97e1c18eSMathieu Desnoyers  * @tracepoint: current tracepoints (in), next tracepoint (out)
410*97e1c18eSMathieu Desnoyers  * @begin: beginning of the range
411*97e1c18eSMathieu Desnoyers  * @end: end of the range
412*97e1c18eSMathieu Desnoyers  *
413*97e1c18eSMathieu Desnoyers  * Returns whether a next tracepoint has been found (1) or not (0).
414*97e1c18eSMathieu Desnoyers  * Will return the first tracepoint in the range if the input tracepoint is
415*97e1c18eSMathieu Desnoyers  * NULL.
416*97e1c18eSMathieu Desnoyers  */
417*97e1c18eSMathieu Desnoyers int tracepoint_get_iter_range(struct tracepoint **tracepoint,
418*97e1c18eSMathieu Desnoyers 	struct tracepoint *begin, struct tracepoint *end)
419*97e1c18eSMathieu Desnoyers {
420*97e1c18eSMathieu Desnoyers 	if (!*tracepoint && begin != end) {
421*97e1c18eSMathieu Desnoyers 		*tracepoint = begin;
422*97e1c18eSMathieu Desnoyers 		return 1;
423*97e1c18eSMathieu Desnoyers 	}
424*97e1c18eSMathieu Desnoyers 	if (*tracepoint >= begin && *tracepoint < end)
425*97e1c18eSMathieu Desnoyers 		return 1;
426*97e1c18eSMathieu Desnoyers 	return 0;
427*97e1c18eSMathieu Desnoyers }
428*97e1c18eSMathieu Desnoyers EXPORT_SYMBOL_GPL(tracepoint_get_iter_range);
429*97e1c18eSMathieu Desnoyers 
430*97e1c18eSMathieu Desnoyers static void tracepoint_get_iter(struct tracepoint_iter *iter)
431*97e1c18eSMathieu Desnoyers {
432*97e1c18eSMathieu Desnoyers 	int found = 0;
433*97e1c18eSMathieu Desnoyers 
434*97e1c18eSMathieu Desnoyers 	/* Core kernel tracepoints */
435*97e1c18eSMathieu Desnoyers 	if (!iter->module) {
436*97e1c18eSMathieu Desnoyers 		found = tracepoint_get_iter_range(&iter->tracepoint,
437*97e1c18eSMathieu Desnoyers 				__start___tracepoints, __stop___tracepoints);
438*97e1c18eSMathieu Desnoyers 		if (found)
439*97e1c18eSMathieu Desnoyers 			goto end;
440*97e1c18eSMathieu Desnoyers 	}
441*97e1c18eSMathieu Desnoyers 	/* tracepoints in modules. */
442*97e1c18eSMathieu Desnoyers 	found = module_get_iter_tracepoints(iter);
443*97e1c18eSMathieu Desnoyers end:
444*97e1c18eSMathieu Desnoyers 	if (!found)
445*97e1c18eSMathieu Desnoyers 		tracepoint_iter_reset(iter);
446*97e1c18eSMathieu Desnoyers }
447*97e1c18eSMathieu Desnoyers 
448*97e1c18eSMathieu Desnoyers void tracepoint_iter_start(struct tracepoint_iter *iter)
449*97e1c18eSMathieu Desnoyers {
450*97e1c18eSMathieu Desnoyers 	tracepoint_get_iter(iter);
451*97e1c18eSMathieu Desnoyers }
452*97e1c18eSMathieu Desnoyers EXPORT_SYMBOL_GPL(tracepoint_iter_start);
453*97e1c18eSMathieu Desnoyers 
454*97e1c18eSMathieu Desnoyers void tracepoint_iter_next(struct tracepoint_iter *iter)
455*97e1c18eSMathieu Desnoyers {
456*97e1c18eSMathieu Desnoyers 	iter->tracepoint++;
457*97e1c18eSMathieu Desnoyers 	/*
458*97e1c18eSMathieu Desnoyers 	 * iter->tracepoint may be invalid because we blindly incremented it.
459*97e1c18eSMathieu Desnoyers 	 * Make sure it is valid by marshalling on the tracepoints, getting the
460*97e1c18eSMathieu Desnoyers 	 * tracepoints from following modules if necessary.
461*97e1c18eSMathieu Desnoyers 	 */
462*97e1c18eSMathieu Desnoyers 	tracepoint_get_iter(iter);
463*97e1c18eSMathieu Desnoyers }
464*97e1c18eSMathieu Desnoyers EXPORT_SYMBOL_GPL(tracepoint_iter_next);
465*97e1c18eSMathieu Desnoyers 
466*97e1c18eSMathieu Desnoyers void tracepoint_iter_stop(struct tracepoint_iter *iter)
467*97e1c18eSMathieu Desnoyers {
468*97e1c18eSMathieu Desnoyers }
469*97e1c18eSMathieu Desnoyers EXPORT_SYMBOL_GPL(tracepoint_iter_stop);
470*97e1c18eSMathieu Desnoyers 
471*97e1c18eSMathieu Desnoyers void tracepoint_iter_reset(struct tracepoint_iter *iter)
472*97e1c18eSMathieu Desnoyers {
473*97e1c18eSMathieu Desnoyers 	iter->module = NULL;
474*97e1c18eSMathieu Desnoyers 	iter->tracepoint = NULL;
475*97e1c18eSMathieu Desnoyers }
476*97e1c18eSMathieu Desnoyers EXPORT_SYMBOL_GPL(tracepoint_iter_reset);
477