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