Blame view

kernel/trace/trace_events.c 36.9 KB
b77e38aa2   Steven Rostedt   tracing: add even...
1
2
3
4
5
  /*
   * event tracer
   *
   * Copyright (C) 2008 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
   *
981d081ec   Steven Rostedt   tracing: add form...
6
7
8
   *  - Added format output of fields of the trace point.
   *    This was based off of work by Tom Zanussi <tzanussi@gmail.com>.
   *
b77e38aa2   Steven Rostedt   tracing: add even...
9
   */
e6187007d   Steven Rostedt   tracing/events: a...
10
11
12
  #include <linux/workqueue.h>
  #include <linux/spinlock.h>
  #include <linux/kthread.h>
b77e38aa2   Steven Rostedt   tracing: add even...
13
14
15
16
  #include <linux/debugfs.h>
  #include <linux/uaccess.h>
  #include <linux/module.h>
  #include <linux/ctype.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
17
  #include <linux/slab.h>
e6187007d   Steven Rostedt   tracing/events: a...
18
  #include <linux/delay.h>
b77e38aa2   Steven Rostedt   tracing: add even...
19

020e5f85c   Li Zefan   tracing/events: A...
20
  #include <asm/setup.h>
91729ef96   Steven Rostedt   tracing: add ftra...
21
  #include "trace_output.h"
b77e38aa2   Steven Rostedt   tracing: add even...
22

4e5292ea1   Steven Rostedt   tracing: use the ...
23
  #undef TRACE_SYSTEM
b628b3e62   Steven Rostedt   tracing: make the...
24
  #define TRACE_SYSTEM "TRACE_SYSTEM"
20c8928ab   Li Zefan   tracing/events: f...
25
  DEFINE_MUTEX(event_mutex);
11a241a33   Steven Rostedt   tracing: add prot...
26

042957801   Steven Rostedt   tracing/events: S...
27
28
29
30
31
  DEFINE_MUTEX(event_storage_mutex);
  EXPORT_SYMBOL_GPL(event_storage_mutex);
  
  char event_storage[EVENT_STORAGE_SIZE];
  EXPORT_SYMBOL_GPL(event_storage);
a59fd6027   Steven Rostedt   tracing/events: c...
32
  LIST_HEAD(ftrace_events);
8728fe501   Li Zefan   tracing: Don't al...
33
  LIST_HEAD(ftrace_common_fields);
a59fd6027   Steven Rostedt   tracing/events: c...
34

2e33af029   Steven Rostedt   tracing: Move fie...
35
36
37
38
39
40
41
  struct list_head *
  trace_get_fields(struct ftrace_event_call *event_call)
  {
  	if (!event_call->class->get_fields)
  		return &event_call->class->fields;
  	return event_call->class->get_fields(event_call);
  }
8728fe501   Li Zefan   tracing: Don't al...
42
43
44
  static int __trace_define_field(struct list_head *head, const char *type,
  				const char *name, int offset, int size,
  				int is_signed, int filter_type)
cf027f645   Tom Zanussi   tracing: add run-...
45
46
  {
  	struct ftrace_event_field *field;
fe9f57f25   Ingo Molnar   tracing: add run-...
47
  	field = kzalloc(sizeof(*field), GFP_KERNEL);
cf027f645   Tom Zanussi   tracing: add run-...
48
49
  	if (!field)
  		goto err;
fe9f57f25   Ingo Molnar   tracing: add run-...
50

cf027f645   Tom Zanussi   tracing: add run-...
51
52
53
  	field->name = kstrdup(name, GFP_KERNEL);
  	if (!field->name)
  		goto err;
fe9f57f25   Ingo Molnar   tracing: add run-...
54

cf027f645   Tom Zanussi   tracing: add run-...
55
56
57
  	field->type = kstrdup(type, GFP_KERNEL);
  	if (!field->type)
  		goto err;
fe9f57f25   Ingo Molnar   tracing: add run-...
58

43b51ead3   Li Zefan   tracing/filters: ...
59
60
61
62
  	if (filter_type == FILTER_OTHER)
  		field->filter_type = filter_assign_type(type);
  	else
  		field->filter_type = filter_type;
cf027f645   Tom Zanussi   tracing: add run-...
63
64
  	field->offset = offset;
  	field->size = size;
a118e4d14   Tom Zanussi   tracing/filters: ...
65
  	field->is_signed = is_signed;
aa38e9fc3   Li Zefan   tracing/filters: ...
66

2e33af029   Steven Rostedt   tracing: Move fie...
67
  	list_add(&field->link, head);
cf027f645   Tom Zanussi   tracing: add run-...
68
69
  
  	return 0;
fe9f57f25   Ingo Molnar   tracing: add run-...
70

cf027f645   Tom Zanussi   tracing: add run-...
71
  err:
7b60997f7   Wenji Huang   tracing: Simplify...
72
  	if (field)
cf027f645   Tom Zanussi   tracing: add run-...
73
  		kfree(field->name);
cf027f645   Tom Zanussi   tracing: add run-...
74
  	kfree(field);
fe9f57f25   Ingo Molnar   tracing: add run-...
75

cf027f645   Tom Zanussi   tracing: add run-...
76
77
  	return -ENOMEM;
  }
8728fe501   Li Zefan   tracing: Don't al...
78
79
80
81
82
83
84
85
86
87
88
89
90
91
  
  int trace_define_field(struct ftrace_event_call *call, const char *type,
  		       const char *name, int offset, int size, int is_signed,
  		       int filter_type)
  {
  	struct list_head *head;
  
  	if (WARN_ON(!call->class))
  		return 0;
  
  	head = trace_get_fields(call);
  	return __trace_define_field(head, type, name, offset, size,
  				    is_signed, filter_type);
  }
17c873ec2   Steven Rostedt   tracing/events: a...
92
  EXPORT_SYMBOL_GPL(trace_define_field);
cf027f645   Tom Zanussi   tracing: add run-...
93

e647d6b31   Li Zefan   tracing/events: A...
94
  #define __common_field(type, item)					\
8728fe501   Li Zefan   tracing: Don't al...
95
96
97
98
99
  	ret = __trace_define_field(&ftrace_common_fields, #type,	\
  				   "common_" #item,			\
  				   offsetof(typeof(ent), item),		\
  				   sizeof(ent.item),			\
  				   is_signed_type(type), FILTER_OTHER);	\
e647d6b31   Li Zefan   tracing/events: A...
100
101
  	if (ret)							\
  		return ret;
8728fe501   Li Zefan   tracing: Don't al...
102
  static int trace_define_common_fields(void)
e647d6b31   Li Zefan   tracing/events: A...
103
104
105
106
107
108
109
110
  {
  	int ret;
  	struct trace_entry ent;
  
  	__common_field(unsigned short, type);
  	__common_field(unsigned char, flags);
  	__common_field(unsigned char, preempt_count);
  	__common_field(int, pid);
a3a4a5acd   Arjan van de Ven   Regression: parti...
111
  	__common_field(int, padding);
e647d6b31   Li Zefan   tracing/events: A...
112
113
114
  
  	return ret;
  }
bd1a5c849   Masami Hiramatsu   tracing: Ftrace d...
115
  void trace_destroy_fields(struct ftrace_event_call *call)
2df75e415   Li Zefan   tracing/events: f...
116
117
  {
  	struct ftrace_event_field *field, *next;
2e33af029   Steven Rostedt   tracing: Move fie...
118
  	struct list_head *head;
2df75e415   Li Zefan   tracing/events: f...
119

2e33af029   Steven Rostedt   tracing: Move fie...
120
121
  	head = trace_get_fields(call);
  	list_for_each_entry_safe(field, next, head, link) {
2df75e415   Li Zefan   tracing/events: f...
122
123
124
125
126
127
  		list_del(&field->link);
  		kfree(field->type);
  		kfree(field->name);
  		kfree(field);
  	}
  }
87d9b4e1c   Li Zefan   tracing: Extract ...
128
129
130
  int trace_event_raw_init(struct ftrace_event_call *call)
  {
  	int id;
80decc70a   Steven Rostedt   tracing: Move pri...
131
  	id = register_ftrace_event(&call->event);
87d9b4e1c   Li Zefan   tracing: Extract ...
132
133
  	if (!id)
  		return -ENODEV;
87d9b4e1c   Li Zefan   tracing: Extract ...
134
135
136
137
  
  	return 0;
  }
  EXPORT_SYMBOL_GPL(trace_event_raw_init);
a1d0ce821   Steven Rostedt   tracing: Use clas...
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
  int ftrace_event_reg(struct ftrace_event_call *call, enum trace_reg type)
  {
  	switch (type) {
  	case TRACE_REG_REGISTER:
  		return tracepoint_probe_register(call->name,
  						 call->class->probe,
  						 call);
  	case TRACE_REG_UNREGISTER:
  		tracepoint_probe_unregister(call->name,
  					    call->class->probe,
  					    call);
  		return 0;
  
  #ifdef CONFIG_PERF_EVENTS
  	case TRACE_REG_PERF_REGISTER:
  		return tracepoint_probe_register(call->name,
  						 call->class->perf_probe,
  						 call);
  	case TRACE_REG_PERF_UNREGISTER:
  		tracepoint_probe_unregister(call->name,
  					    call->class->perf_probe,
  					    call);
  		return 0;
  #endif
  	}
  	return 0;
  }
  EXPORT_SYMBOL_GPL(ftrace_event_reg);
e870e9a12   Li Zefan   tracing: Allow to...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
  void trace_event_enable_cmd_record(bool enable)
  {
  	struct ftrace_event_call *call;
  
  	mutex_lock(&event_mutex);
  	list_for_each_entry(call, &ftrace_events, list) {
  		if (!(call->flags & TRACE_EVENT_FL_ENABLED))
  			continue;
  
  		if (enable) {
  			tracing_start_cmdline_record();
  			call->flags |= TRACE_EVENT_FL_RECORDED_CMD;
  		} else {
  			tracing_stop_cmdline_record();
  			call->flags &= ~TRACE_EVENT_FL_RECORDED_CMD;
  		}
  	}
  	mutex_unlock(&event_mutex);
  }
3b8e42738   Li Zefan   tracing: Move a p...
185
  static int ftrace_event_enable_disable(struct ftrace_event_call *call,
fd9949898   Steven Rostedt   tracing: add raw ...
186
187
  					int enable)
  {
3b8e42738   Li Zefan   tracing: Move a p...
188
  	int ret = 0;
fd9949898   Steven Rostedt   tracing: add raw ...
189
190
  	switch (enable) {
  	case 0:
553552ce1   Steven Rostedt   tracing: Combine ...
191
192
  		if (call->flags & TRACE_EVENT_FL_ENABLED) {
  			call->flags &= ~TRACE_EVENT_FL_ENABLED;
e870e9a12   Li Zefan   tracing: Allow to...
193
194
195
196
  			if (call->flags & TRACE_EVENT_FL_RECORDED_CMD) {
  				tracing_stop_cmdline_record();
  				call->flags &= ~TRACE_EVENT_FL_RECORDED_CMD;
  			}
a1d0ce821   Steven Rostedt   tracing: Use clas...
197
  			call->class->reg(call, TRACE_REG_UNREGISTER);
fd9949898   Steven Rostedt   tracing: add raw ...
198
  		}
fd9949898   Steven Rostedt   tracing: add raw ...
199
200
  		break;
  	case 1:
553552ce1   Steven Rostedt   tracing: Combine ...
201
  		if (!(call->flags & TRACE_EVENT_FL_ENABLED)) {
e870e9a12   Li Zefan   tracing: Allow to...
202
203
204
205
  			if (trace_flags & TRACE_ITER_RECORD_CMD) {
  				tracing_start_cmdline_record();
  				call->flags |= TRACE_EVENT_FL_RECORDED_CMD;
  			}
a1d0ce821   Steven Rostedt   tracing: Use clas...
206
  			ret = call->class->reg(call, TRACE_REG_REGISTER);
3b8e42738   Li Zefan   tracing: Move a p...
207
208
209
210
211
212
213
  			if (ret) {
  				tracing_stop_cmdline_record();
  				pr_info("event trace: Could not enable event "
  					"%s
  ", call->name);
  				break;
  			}
553552ce1   Steven Rostedt   tracing: Combine ...
214
  			call->flags |= TRACE_EVENT_FL_ENABLED;
fd9949898   Steven Rostedt   tracing: add raw ...
215
  		}
fd9949898   Steven Rostedt   tracing: add raw ...
216
217
  		break;
  	}
3b8e42738   Li Zefan   tracing: Move a p...
218
219
  
  	return ret;
fd9949898   Steven Rostedt   tracing: add raw ...
220
  }
0e907c993   Zhaolei   ftrace: clean up ...
221
222
223
224
225
226
227
228
229
230
  static void ftrace_clear_events(void)
  {
  	struct ftrace_event_call *call;
  
  	mutex_lock(&event_mutex);
  	list_for_each_entry(call, &ftrace_events, list) {
  		ftrace_event_enable_disable(call, 0);
  	}
  	mutex_unlock(&event_mutex);
  }
e9dbfae53   Steven Rostedt   tracing: Fix bug ...
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
  static void __put_system(struct event_subsystem *system)
  {
  	struct event_filter *filter = system->filter;
  
  	WARN_ON_ONCE(system->ref_count == 0);
  	if (--system->ref_count)
  		return;
  
  	if (filter) {
  		kfree(filter->filter_string);
  		kfree(filter);
  	}
  	kfree(system->name);
  	kfree(system);
  }
  
  static void __get_system(struct event_subsystem *system)
  {
  	WARN_ON_ONCE(system->ref_count == 0);
  	system->ref_count++;
  }
  
  static void put_system(struct event_subsystem *system)
  {
  	mutex_lock(&event_mutex);
  	__put_system(system);
  	mutex_unlock(&event_mutex);
  }
8f31bfe53   Li Zefan   tracing/events: c...
259
260
261
262
263
  /*
   * __ftrace_set_clr_event(NULL, NULL, NULL, set) will set/unset all events.
   */
  static int __ftrace_set_clr_event(const char *match, const char *sub,
  				  const char *event, int set)
b77e38aa2   Steven Rostedt   tracing: add even...
264
  {
a59fd6027   Steven Rostedt   tracing/events: c...
265
  	struct ftrace_event_call *call;
29f93943d   Steven Rostedt   tracing: initiali...
266
  	int ret = -EINVAL;
8f31bfe53   Li Zefan   tracing/events: c...
267
268
269
  
  	mutex_lock(&event_mutex);
  	list_for_each_entry(call, &ftrace_events, list) {
a1d0ce821   Steven Rostedt   tracing: Use clas...
270
  		if (!call->name || !call->class || !call->class->reg)
8f31bfe53   Li Zefan   tracing/events: c...
271
272
273
274
  			continue;
  
  		if (match &&
  		    strcmp(match, call->name) != 0 &&
8f0820183   Steven Rostedt   tracing: Create c...
275
  		    strcmp(match, call->class->system) != 0)
8f31bfe53   Li Zefan   tracing/events: c...
276
  			continue;
8f0820183   Steven Rostedt   tracing: Create c...
277
  		if (sub && strcmp(sub, call->class->system) != 0)
8f31bfe53   Li Zefan   tracing/events: c...
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
  			continue;
  
  		if (event && strcmp(event, call->name) != 0)
  			continue;
  
  		ftrace_event_enable_disable(call, set);
  
  		ret = 0;
  	}
  	mutex_unlock(&event_mutex);
  
  	return ret;
  }
  
  static int ftrace_set_clr_event(char *buf, int set)
  {
b628b3e62   Steven Rostedt   tracing: make the...
294
  	char *event = NULL, *sub = NULL, *match;
b628b3e62   Steven Rostedt   tracing: make the...
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
  
  	/*
  	 * The buf format can be <subsystem>:<event-name>
  	 *  *:<event-name> means any event by that name.
  	 *  :<event-name> is the same.
  	 *
  	 *  <subsystem>:* means all events in that subsystem
  	 *  <subsystem>: means the same.
  	 *
  	 *  <name> (no ':') means all events in a subsystem with
  	 *  the name <name> or any event that matches <name>
  	 */
  
  	match = strsep(&buf, ":");
  	if (buf) {
  		sub = match;
  		event = buf;
  		match = NULL;
  
  		if (!strlen(sub) || strcmp(sub, "*") == 0)
  			sub = NULL;
  		if (!strlen(event) || strcmp(event, "*") == 0)
  			event = NULL;
  	}
b77e38aa2   Steven Rostedt   tracing: add even...
319

8f31bfe53   Li Zefan   tracing/events: c...
320
  	return __ftrace_set_clr_event(match, sub, event, set);
b77e38aa2   Steven Rostedt   tracing: add even...
321
  }
4671c7940   Steven Rostedt   tracing: add trac...
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
  /**
   * trace_set_clr_event - enable or disable an event
   * @system: system name to match (NULL for any system)
   * @event: event name to match (NULL for all events, within system)
   * @set: 1 to enable, 0 to disable
   *
   * This is a way for other parts of the kernel to enable or disable
   * event recording.
   *
   * Returns 0 on success, -EINVAL if the parameters do not match any
   * registered events.
   */
  int trace_set_clr_event(const char *system, const char *event, int set)
  {
  	return __ftrace_set_clr_event(NULL, system, event, set);
  }
56355b83e   Yuanhan Liu   tracing: Export t...
338
  EXPORT_SYMBOL_GPL(trace_set_clr_event);
4671c7940   Steven Rostedt   tracing: add trac...
339

b77e38aa2   Steven Rostedt   tracing: add even...
340
341
342
343
344
345
346
  /* 128 should be much more than enough */
  #define EVENT_BUF_SIZE		127
  
  static ssize_t
  ftrace_event_write(struct file *file, const char __user *ubuf,
  		   size_t cnt, loff_t *ppos)
  {
489663644   jolsa@redhat.com   tracing: trace pa...
347
  	struct trace_parser parser;
4ba7978e9   Li Zefan   tracing: Check th...
348
  	ssize_t read, ret;
b77e38aa2   Steven Rostedt   tracing: add even...
349

4ba7978e9   Li Zefan   tracing: Check th...
350
  	if (!cnt)
b77e38aa2   Steven Rostedt   tracing: add even...
351
  		return 0;
1852fcce1   Steven Rostedt   tracing: expand t...
352
353
354
  	ret = tracing_update_buffers();
  	if (ret < 0)
  		return ret;
489663644   jolsa@redhat.com   tracing: trace pa...
355
  	if (trace_parser_get_init(&parser, EVENT_BUF_SIZE + 1))
b77e38aa2   Steven Rostedt   tracing: add even...
356
  		return -ENOMEM;
489663644   jolsa@redhat.com   tracing: trace pa...
357
  	read = trace_get_user(&parser, ubuf, cnt, ppos);
4ba7978e9   Li Zefan   tracing: Check th...
358
  	if (read >= 0 && trace_parser_loaded((&parser))) {
489663644   jolsa@redhat.com   tracing: trace pa...
359
  		int set = 1;
b77e38aa2   Steven Rostedt   tracing: add even...
360

489663644   jolsa@redhat.com   tracing: trace pa...
361
  		if (*parser.buffer == '!')
b77e38aa2   Steven Rostedt   tracing: add even...
362
  			set = 0;
b77e38aa2   Steven Rostedt   tracing: add even...
363

489663644   jolsa@redhat.com   tracing: trace pa...
364
365
366
  		parser.buffer[parser.idx] = 0;
  
  		ret = ftrace_set_clr_event(parser.buffer + !set, set);
b77e38aa2   Steven Rostedt   tracing: add even...
367
  		if (ret)
489663644   jolsa@redhat.com   tracing: trace pa...
368
  			goto out_put;
b77e38aa2   Steven Rostedt   tracing: add even...
369
  	}
b77e38aa2   Steven Rostedt   tracing: add even...
370
371
  
  	ret = read;
489663644   jolsa@redhat.com   tracing: trace pa...
372
373
   out_put:
  	trace_parser_put(&parser);
b77e38aa2   Steven Rostedt   tracing: add even...
374
375
376
377
378
379
380
  
  	return ret;
  }
  
  static void *
  t_next(struct seq_file *m, void *v, loff_t *pos)
  {
30bd39cd6   Li Zefan   tracing/events: u...
381
  	struct ftrace_event_call *call = v;
b77e38aa2   Steven Rostedt   tracing: add even...
382
383
  
  	(*pos)++;
30bd39cd6   Li Zefan   tracing/events: u...
384
  	list_for_each_entry_continue(call, &ftrace_events, list) {
40e26815f   Steven Rostedt   tracing: do not a...
385
386
387
388
  		/*
  		 * The ftrace subsystem is for showing formats only.
  		 * They can not be enabled or disabled via the event files.
  		 */
a1d0ce821   Steven Rostedt   tracing: Use clas...
389
  		if (call->class && call->class->reg)
30bd39cd6   Li Zefan   tracing/events: u...
390
  			return call;
40e26815f   Steven Rostedt   tracing: do not a...
391
  	}
b77e38aa2   Steven Rostedt   tracing: add even...
392

30bd39cd6   Li Zefan   tracing/events: u...
393
  	return NULL;
b77e38aa2   Steven Rostedt   tracing: add even...
394
395
396
397
  }
  
  static void *t_start(struct seq_file *m, loff_t *pos)
  {
30bd39cd6   Li Zefan   tracing/events: u...
398
  	struct ftrace_event_call *call;
e1c7e2a6e   Li Zefan   tracing/events: D...
399
  	loff_t l;
20c8928ab   Li Zefan   tracing/events: f...
400
  	mutex_lock(&event_mutex);
e1c7e2a6e   Li Zefan   tracing/events: D...
401

30bd39cd6   Li Zefan   tracing/events: u...
402
  	call = list_entry(&ftrace_events, struct ftrace_event_call, list);
e1c7e2a6e   Li Zefan   tracing/events: D...
403
  	for (l = 0; l <= *pos; ) {
30bd39cd6   Li Zefan   tracing/events: u...
404
  		call = t_next(m, call, &l);
e1c7e2a6e   Li Zefan   tracing/events: D...
405
406
407
408
  		if (!call)
  			break;
  	}
  	return call;
b77e38aa2   Steven Rostedt   tracing: add even...
409
410
411
412
413
  }
  
  static void *
  s_next(struct seq_file *m, void *v, loff_t *pos)
  {
30bd39cd6   Li Zefan   tracing/events: u...
414
  	struct ftrace_event_call *call = v;
b77e38aa2   Steven Rostedt   tracing: add even...
415
416
  
  	(*pos)++;
30bd39cd6   Li Zefan   tracing/events: u...
417
  	list_for_each_entry_continue(call, &ftrace_events, list) {
553552ce1   Steven Rostedt   tracing: Combine ...
418
  		if (call->flags & TRACE_EVENT_FL_ENABLED)
30bd39cd6   Li Zefan   tracing/events: u...
419
  			return call;
b77e38aa2   Steven Rostedt   tracing: add even...
420
  	}
30bd39cd6   Li Zefan   tracing/events: u...
421
  	return NULL;
b77e38aa2   Steven Rostedt   tracing: add even...
422
423
424
425
  }
  
  static void *s_start(struct seq_file *m, loff_t *pos)
  {
30bd39cd6   Li Zefan   tracing/events: u...
426
  	struct ftrace_event_call *call;
e1c7e2a6e   Li Zefan   tracing/events: D...
427
  	loff_t l;
20c8928ab   Li Zefan   tracing/events: f...
428
  	mutex_lock(&event_mutex);
e1c7e2a6e   Li Zefan   tracing/events: D...
429

30bd39cd6   Li Zefan   tracing/events: u...
430
  	call = list_entry(&ftrace_events, struct ftrace_event_call, list);
e1c7e2a6e   Li Zefan   tracing/events: D...
431
  	for (l = 0; l <= *pos; ) {
30bd39cd6   Li Zefan   tracing/events: u...
432
  		call = s_next(m, call, &l);
e1c7e2a6e   Li Zefan   tracing/events: D...
433
434
435
436
  		if (!call)
  			break;
  	}
  	return call;
b77e38aa2   Steven Rostedt   tracing: add even...
437
438
439
440
441
  }
  
  static int t_show(struct seq_file *m, void *v)
  {
  	struct ftrace_event_call *call = v;
8f0820183   Steven Rostedt   tracing: Create c...
442
443
  	if (strcmp(call->class->system, TRACE_SYSTEM) != 0)
  		seq_printf(m, "%s:", call->class->system);
b77e38aa2   Steven Rostedt   tracing: add even...
444
445
446
447
448
449
450
451
  	seq_printf(m, "%s
  ", call->name);
  
  	return 0;
  }
  
  static void t_stop(struct seq_file *m, void *p)
  {
20c8928ab   Li Zefan   tracing/events: f...
452
  	mutex_unlock(&event_mutex);
b77e38aa2   Steven Rostedt   tracing: add even...
453
454
455
456
457
  }
  
  static int
  ftrace_event_seq_open(struct inode *inode, struct file *file)
  {
b77e38aa2   Steven Rostedt   tracing: add even...
458
459
460
  	const struct seq_operations *seq_ops;
  
  	if ((file->f_mode & FMODE_WRITE) &&
8650ae32e   Steven Rostedt   tracing: only tru...
461
  	    (file->f_flags & O_TRUNC))
b77e38aa2   Steven Rostedt   tracing: add even...
462
463
464
  		ftrace_clear_events();
  
  	seq_ops = inode->i_private;
20c8928ab   Li Zefan   tracing/events: f...
465
  	return seq_open(file, seq_ops);
b77e38aa2   Steven Rostedt   tracing: add even...
466
  }
1473e4417   Steven Rostedt   tracing: make eve...
467
468
469
470
471
472
  static ssize_t
  event_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
  		  loff_t *ppos)
  {
  	struct ftrace_event_call *call = filp->private_data;
  	char *buf;
553552ce1   Steven Rostedt   tracing: Combine ...
473
  	if (call->flags & TRACE_EVENT_FL_ENABLED)
1473e4417   Steven Rostedt   tracing: make eve...
474
475
476
477
478
479
480
481
482
483
484
485
486
487
  		buf = "1
  ";
  	else
  		buf = "0
  ";
  
  	return simple_read_from_buffer(ubuf, cnt, ppos, buf, 2);
  }
  
  static ssize_t
  event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
  		   loff_t *ppos)
  {
  	struct ftrace_event_call *call = filp->private_data;
1473e4417   Steven Rostedt   tracing: make eve...
488
489
  	unsigned long val;
  	int ret;
22fe9b54d   Peter Huewe   tracing: Convert ...
490
491
  	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
  	if (ret)
1473e4417   Steven Rostedt   tracing: make eve...
492
  		return ret;
1852fcce1   Steven Rostedt   tracing: expand t...
493
494
495
  	ret = tracing_update_buffers();
  	if (ret < 0)
  		return ret;
1473e4417   Steven Rostedt   tracing: make eve...
496
497
  	switch (val) {
  	case 0:
1473e4417   Steven Rostedt   tracing: make eve...
498
  	case 1:
11a241a33   Steven Rostedt   tracing: add prot...
499
  		mutex_lock(&event_mutex);
3b8e42738   Li Zefan   tracing: Move a p...
500
  		ret = ftrace_event_enable_disable(call, val);
11a241a33   Steven Rostedt   tracing: add prot...
501
  		mutex_unlock(&event_mutex);
1473e4417   Steven Rostedt   tracing: make eve...
502
503
504
505
506
507
508
  		break;
  
  	default:
  		return -EINVAL;
  	}
  
  	*ppos += cnt;
3b8e42738   Li Zefan   tracing: Move a p...
509
  	return ret ? ret : cnt;
1473e4417   Steven Rostedt   tracing: make eve...
510
  }
8ae79a138   Steven Rostedt   tracing: add hier...
511
512
513
514
  static ssize_t
  system_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
  		   loff_t *ppos)
  {
c142b15dc   Li Zefan   tracing/events: s...
515
  	const char set_to_char[4] = { '?', '0', '1', 'X' };
40ee4dfff   Steven Rostedt   tracing: Have "en...
516
  	struct event_subsystem *system = filp->private_data;
8ae79a138   Steven Rostedt   tracing: add hier...
517
518
  	struct ftrace_event_call *call;
  	char buf[2];
c142b15dc   Li Zefan   tracing/events: s...
519
  	int set = 0;
8ae79a138   Steven Rostedt   tracing: add hier...
520
  	int ret;
8ae79a138   Steven Rostedt   tracing: add hier...
521
522
  	mutex_lock(&event_mutex);
  	list_for_each_entry(call, &ftrace_events, list) {
a1d0ce821   Steven Rostedt   tracing: Use clas...
523
  		if (!call->name || !call->class || !call->class->reg)
8ae79a138   Steven Rostedt   tracing: add hier...
524
  			continue;
40ee4dfff   Steven Rostedt   tracing: Have "en...
525
  		if (system && strcmp(call->class->system, system->name) != 0)
8ae79a138   Steven Rostedt   tracing: add hier...
526
527
528
529
530
531
532
  			continue;
  
  		/*
  		 * We need to find out if all the events are set
  		 * or if all events or cleared, or if we have
  		 * a mixture.
  		 */
553552ce1   Steven Rostedt   tracing: Combine ...
533
  		set |= (1 << !!(call->flags & TRACE_EVENT_FL_ENABLED));
c142b15dc   Li Zefan   tracing/events: s...
534

8ae79a138   Steven Rostedt   tracing: add hier...
535
536
537
  		/*
  		 * If we have a mixture, no need to look further.
  		 */
c142b15dc   Li Zefan   tracing/events: s...
538
  		if (set == 3)
8ae79a138   Steven Rostedt   tracing: add hier...
539
540
541
  			break;
  	}
  	mutex_unlock(&event_mutex);
c142b15dc   Li Zefan   tracing/events: s...
542
  	buf[0] = set_to_char[set];
8ae79a138   Steven Rostedt   tracing: add hier...
543
544
  	buf[1] = '
  ';
8ae79a138   Steven Rostedt   tracing: add hier...
545
546
547
548
549
550
551
552
553
554
  
  	ret = simple_read_from_buffer(ubuf, cnt, ppos, buf, 2);
  
  	return ret;
  }
  
  static ssize_t
  system_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
  		    loff_t *ppos)
  {
40ee4dfff   Steven Rostedt   tracing: Have "en...
555
556
  	struct event_subsystem *system = filp->private_data;
  	const char *name = NULL;
8ae79a138   Steven Rostedt   tracing: add hier...
557
  	unsigned long val;
8ae79a138   Steven Rostedt   tracing: add hier...
558
  	ssize_t ret;
22fe9b54d   Peter Huewe   tracing: Convert ...
559
560
  	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
  	if (ret)
8ae79a138   Steven Rostedt   tracing: add hier...
561
562
563
564
565
  		return ret;
  
  	ret = tracing_update_buffers();
  	if (ret < 0)
  		return ret;
8f31bfe53   Li Zefan   tracing/events: c...
566
  	if (val != 0 && val != 1)
8ae79a138   Steven Rostedt   tracing: add hier...
567
  		return -EINVAL;
8ae79a138   Steven Rostedt   tracing: add hier...
568

40ee4dfff   Steven Rostedt   tracing: Have "en...
569
570
571
572
573
574
575
576
  	/*
  	 * Opening of "enable" adds a ref count to system,
  	 * so the name is safe to use.
  	 */
  	if (system)
  		name = system->name;
  
  	ret = __ftrace_set_clr_event(NULL, name, NULL, val);
8ae79a138   Steven Rostedt   tracing: add hier...
577
  	if (ret)
8f31bfe53   Li Zefan   tracing/events: c...
578
  		goto out;
8ae79a138   Steven Rostedt   tracing: add hier...
579
580
  
  	ret = cnt;
8f31bfe53   Li Zefan   tracing/events: c...
581
  out:
8ae79a138   Steven Rostedt   tracing: add hier...
582
583
584
585
  	*ppos += cnt;
  
  	return ret;
  }
2a37a3df5   Steven Rostedt   tracing/events: C...
586
587
  enum {
  	FORMAT_HEADER		= 1,
86397dc3c   Li Zefan   tracing: Clean up...
588
589
  	FORMAT_FIELD_SEPERATOR	= 2,
  	FORMAT_PRINTFMT		= 3,
2a37a3df5   Steven Rostedt   tracing/events: C...
590
591
592
  };
  
  static void *f_next(struct seq_file *m, void *v, loff_t *pos)
981d081ec   Steven Rostedt   tracing: add form...
593
  {
2a37a3df5   Steven Rostedt   tracing/events: C...
594
  	struct ftrace_event_call *call = m->private;
5a65e9562   Lai Jiangshan   tracing: Use defi...
595
  	struct ftrace_event_field *field;
86397dc3c   Li Zefan   tracing: Clean up...
596
597
  	struct list_head *common_head = &ftrace_common_fields;
  	struct list_head *head = trace_get_fields(call);
981d081ec   Steven Rostedt   tracing: add form...
598

2a37a3df5   Steven Rostedt   tracing/events: C...
599
  	(*pos)++;
5a65e9562   Lai Jiangshan   tracing: Use defi...
600

2a37a3df5   Steven Rostedt   tracing/events: C...
601
602
  	switch ((unsigned long)v) {
  	case FORMAT_HEADER:
86397dc3c   Li Zefan   tracing: Clean up...
603
604
605
606
607
608
  		if (unlikely(list_empty(common_head)))
  			return NULL;
  
  		field = list_entry(common_head->prev,
  				   struct ftrace_event_field, link);
  		return field;
5a65e9562   Lai Jiangshan   tracing: Use defi...
609

86397dc3c   Li Zefan   tracing: Clean up...
610
  	case FORMAT_FIELD_SEPERATOR:
2a37a3df5   Steven Rostedt   tracing/events: C...
611
612
  		if (unlikely(list_empty(head)))
  			return NULL;
5a65e9562   Lai Jiangshan   tracing: Use defi...
613

2a37a3df5   Steven Rostedt   tracing/events: C...
614
615
  		field = list_entry(head->prev, struct ftrace_event_field, link);
  		return field;
5a65e9562   Lai Jiangshan   tracing: Use defi...
616

2a37a3df5   Steven Rostedt   tracing/events: C...
617
618
619
  	case FORMAT_PRINTFMT:
  		/* all done */
  		return NULL;
5a65e9562   Lai Jiangshan   tracing: Use defi...
620
  	}
2a37a3df5   Steven Rostedt   tracing/events: C...
621
  	field = v;
86397dc3c   Li Zefan   tracing: Clean up...
622
623
624
  	if (field->link.prev == common_head)
  		return (void *)FORMAT_FIELD_SEPERATOR;
  	else if (field->link.prev == head)
2a37a3df5   Steven Rostedt   tracing/events: C...
625
626
627
  		return (void *)FORMAT_PRINTFMT;
  
  	field = list_entry(field->link.prev, struct ftrace_event_field, link);
2a37a3df5   Steven Rostedt   tracing/events: C...
628
  	return field;
8728fe501   Li Zefan   tracing: Don't al...
629
  }
5a65e9562   Lai Jiangshan   tracing: Use defi...
630

2a37a3df5   Steven Rostedt   tracing/events: C...
631
  static void *f_start(struct seq_file *m, loff_t *pos)
8728fe501   Li Zefan   tracing: Don't al...
632
  {
2a37a3df5   Steven Rostedt   tracing/events: C...
633
634
  	loff_t l = 0;
  	void *p;
5a65e9562   Lai Jiangshan   tracing: Use defi...
635

2a37a3df5   Steven Rostedt   tracing/events: C...
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
  	/* Start by showing the header */
  	if (!*pos)
  		return (void *)FORMAT_HEADER;
  
  	p = (void *)FORMAT_HEADER;
  	do {
  		p = f_next(m, p, &l);
  	} while (p && l < *pos);
  
  	return p;
  }
  
  static int f_show(struct seq_file *m, void *v)
  {
  	struct ftrace_event_call *call = m->private;
  	struct ftrace_event_field *field;
  	const char *array_descriptor;
  
  	switch ((unsigned long)v) {
  	case FORMAT_HEADER:
  		seq_printf(m, "name: %s
  ", call->name);
  		seq_printf(m, "ID: %d
  ", call->event.type);
  		seq_printf(m, "format:
  ");
8728fe501   Li Zefan   tracing: Don't al...
662
  		return 0;
5a65e9562   Lai Jiangshan   tracing: Use defi...
663

86397dc3c   Li Zefan   tracing: Clean up...
664
665
666
667
  	case FORMAT_FIELD_SEPERATOR:
  		seq_putc(m, '
  ');
  		return 0;
2a37a3df5   Steven Rostedt   tracing/events: C...
668
669
670
671
672
673
  	case FORMAT_PRINTFMT:
  		seq_printf(m, "
  print fmt: %s
  ",
  			   call->print_fmt);
  		return 0;
981d081ec   Steven Rostedt   tracing: add form...
674
  	}
8728fe501   Li Zefan   tracing: Don't al...
675

2a37a3df5   Steven Rostedt   tracing/events: C...
676
  	field = v;
8728fe501   Li Zefan   tracing: Don't al...
677

2a37a3df5   Steven Rostedt   tracing/events: C...
678
679
680
681
682
683
684
685
  	/*
  	 * Smartly shows the array type(except dynamic array).
  	 * Normal:
  	 *	field:TYPE VAR
  	 * If TYPE := TYPE[LEN], it is shown:
  	 *	field:TYPE VAR[LEN]
  	 */
  	array_descriptor = strchr(field->type, '[');
8728fe501   Li Zefan   tracing: Don't al...
686

2a37a3df5   Steven Rostedt   tracing/events: C...
687
688
  	if (!strncmp(field->type, "__data_loc", 10))
  		array_descriptor = NULL;
8728fe501   Li Zefan   tracing: Don't al...
689

2a37a3df5   Steven Rostedt   tracing/events: C...
690
691
692
693
694
695
696
697
698
699
700
701
  	if (!array_descriptor)
  		seq_printf(m, "\tfield:%s %s;\toffset:%u;\tsize:%u;\tsigned:%d;
  ",
  			   field->type, field->name, field->offset,
  			   field->size, !!field->is_signed);
  	else
  		seq_printf(m, "\tfield:%.*s %s%s;\toffset:%u;\tsize:%u;\tsigned:%d;
  ",
  			   (int)(array_descriptor - field->type),
  			   field->type, field->name,
  			   array_descriptor, field->offset,
  			   field->size, !!field->is_signed);
8728fe501   Li Zefan   tracing: Don't al...
702

2a37a3df5   Steven Rostedt   tracing/events: C...
703
704
  	return 0;
  }
5a65e9562   Lai Jiangshan   tracing: Use defi...
705

2a37a3df5   Steven Rostedt   tracing/events: C...
706
707
708
  static void f_stop(struct seq_file *m, void *p)
  {
  }
981d081ec   Steven Rostedt   tracing: add form...
709

2a37a3df5   Steven Rostedt   tracing/events: C...
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
  static const struct seq_operations trace_format_seq_ops = {
  	.start		= f_start,
  	.next		= f_next,
  	.stop		= f_stop,
  	.show		= f_show,
  };
  
  static int trace_format_open(struct inode *inode, struct file *file)
  {
  	struct ftrace_event_call *call = inode->i_private;
  	struct seq_file *m;
  	int ret;
  
  	ret = seq_open(file, &trace_format_seq_ops);
  	if (ret < 0)
  		return ret;
  
  	m = file->private_data;
  	m->private = call;
  
  	return 0;
981d081ec   Steven Rostedt   tracing: add form...
731
  }
23725aeea   Peter Zijlstra   ftrace: provide a...
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
  static ssize_t
  event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
  {
  	struct ftrace_event_call *call = filp->private_data;
  	struct trace_seq *s;
  	int r;
  
  	if (*ppos)
  		return 0;
  
  	s = kmalloc(sizeof(*s), GFP_KERNEL);
  	if (!s)
  		return -ENOMEM;
  
  	trace_seq_init(s);
32c0edaea   Steven Rostedt   tracing: Remove d...
747
748
  	trace_seq_printf(s, "%d
  ", call->event.type);
23725aeea   Peter Zijlstra   ftrace: provide a...
749
750
751
752
753
754
  
  	r = simple_read_from_buffer(ubuf, cnt, ppos,
  				    s->buffer, s->len);
  	kfree(s);
  	return r;
  }
7ce7e4249   Tom Zanussi   tracing: add per-...
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
  static ssize_t
  event_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
  		  loff_t *ppos)
  {
  	struct ftrace_event_call *call = filp->private_data;
  	struct trace_seq *s;
  	int r;
  
  	if (*ppos)
  		return 0;
  
  	s = kmalloc(sizeof(*s), GFP_KERNEL);
  	if (!s)
  		return -ENOMEM;
  
  	trace_seq_init(s);
8b3725621   Tom Zanussi   tracing/filters: ...
771
  	print_event_filter(call, s);
4bda2d517   Tom Zanussi   tracing/filters: ...
772
  	r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len);
7ce7e4249   Tom Zanussi   tracing: add per-...
773
774
775
776
777
778
779
780
781
782
783
  
  	kfree(s);
  
  	return r;
  }
  
  static ssize_t
  event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt,
  		   loff_t *ppos)
  {
  	struct ftrace_event_call *call = filp->private_data;
8b3725621   Tom Zanussi   tracing/filters: ...
784
  	char *buf;
7ce7e4249   Tom Zanussi   tracing: add per-...
785
  	int err;
8b3725621   Tom Zanussi   tracing/filters: ...
786
  	if (cnt >= PAGE_SIZE)
7ce7e4249   Tom Zanussi   tracing: add per-...
787
  		return -EINVAL;
8b3725621   Tom Zanussi   tracing/filters: ...
788
789
  	buf = (char *)__get_free_page(GFP_TEMPORARY);
  	if (!buf)
7ce7e4249   Tom Zanussi   tracing: add per-...
790
  		return -ENOMEM;
8b3725621   Tom Zanussi   tracing/filters: ...
791
792
793
  	if (copy_from_user(buf, ubuf, cnt)) {
  		free_page((unsigned long) buf);
  		return -EFAULT;
7ce7e4249   Tom Zanussi   tracing: add per-...
794
  	}
8b3725621   Tom Zanussi   tracing/filters: ...
795
  	buf[cnt] = '\0';
7ce7e4249   Tom Zanussi   tracing: add per-...
796

8b3725621   Tom Zanussi   tracing/filters: ...
797
798
799
  	err = apply_event_filter(call, buf);
  	free_page((unsigned long) buf);
  	if (err < 0)
44e9c8b7a   Li Zefan   tracing/filters: ...
800
  		return err;
0a19e53c1   Tom Zanussi   tracing/filters: ...
801

7ce7e4249   Tom Zanussi   tracing: add per-...
802
803
804
805
  	*ppos += cnt;
  
  	return cnt;
  }
e9dbfae53   Steven Rostedt   tracing: Fix bug ...
806
807
808
809
810
811
  static LIST_HEAD(event_subsystems);
  
  static int subsystem_open(struct inode *inode, struct file *filp)
  {
  	struct event_subsystem *system = NULL;
  	int ret;
40ee4dfff   Steven Rostedt   tracing: Have "en...
812
813
  	if (!inode->i_private)
  		goto skip_search;
e9dbfae53   Steven Rostedt   tracing: Fix bug ...
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
  	/* Make sure the system still exists */
  	mutex_lock(&event_mutex);
  	list_for_each_entry(system, &event_subsystems, list) {
  		if (system == inode->i_private) {
  			/* Don't open systems with no events */
  			if (!system->nr_events) {
  				system = NULL;
  				break;
  			}
  			__get_system(system);
  			break;
  		}
  	}
  	mutex_unlock(&event_mutex);
  
  	if (system != inode->i_private)
  		return -ENODEV;
40ee4dfff   Steven Rostedt   tracing: Have "en...
831
   skip_search:
e9dbfae53   Steven Rostedt   tracing: Fix bug ...
832
  	ret = tracing_open_generic(inode, filp);
40ee4dfff   Steven Rostedt   tracing: Have "en...
833
  	if (ret < 0 && system)
e9dbfae53   Steven Rostedt   tracing: Fix bug ...
834
835
836
837
838
839
840
841
  		put_system(system);
  
  	return ret;
  }
  
  static int subsystem_release(struct inode *inode, struct file *file)
  {
  	struct event_subsystem *system = inode->i_private;
40ee4dfff   Steven Rostedt   tracing: Have "en...
842
843
  	if (system)
  		put_system(system);
e9dbfae53   Steven Rostedt   tracing: Fix bug ...
844
845
846
  
  	return 0;
  }
cfb180f3e   Tom Zanussi   tracing: add per-...
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
  static ssize_t
  subsystem_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
  		      loff_t *ppos)
  {
  	struct event_subsystem *system = filp->private_data;
  	struct trace_seq *s;
  	int r;
  
  	if (*ppos)
  		return 0;
  
  	s = kmalloc(sizeof(*s), GFP_KERNEL);
  	if (!s)
  		return -ENOMEM;
  
  	trace_seq_init(s);
8b3725621   Tom Zanussi   tracing/filters: ...
863
  	print_subsystem_event_filter(system, s);
4bda2d517   Tom Zanussi   tracing/filters: ...
864
  	r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len);
cfb180f3e   Tom Zanussi   tracing: add per-...
865
866
867
868
869
870
871
872
873
874
875
  
  	kfree(s);
  
  	return r;
  }
  
  static ssize_t
  subsystem_filter_write(struct file *filp, const char __user *ubuf, size_t cnt,
  		       loff_t *ppos)
  {
  	struct event_subsystem *system = filp->private_data;
8b3725621   Tom Zanussi   tracing/filters: ...
876
  	char *buf;
cfb180f3e   Tom Zanussi   tracing: add per-...
877
  	int err;
8b3725621   Tom Zanussi   tracing/filters: ...
878
  	if (cnt >= PAGE_SIZE)
cfb180f3e   Tom Zanussi   tracing: add per-...
879
  		return -EINVAL;
8b3725621   Tom Zanussi   tracing/filters: ...
880
881
  	buf = (char *)__get_free_page(GFP_TEMPORARY);
  	if (!buf)
cfb180f3e   Tom Zanussi   tracing: add per-...
882
  		return -ENOMEM;
8b3725621   Tom Zanussi   tracing/filters: ...
883
884
885
  	if (copy_from_user(buf, ubuf, cnt)) {
  		free_page((unsigned long) buf);
  		return -EFAULT;
cfb180f3e   Tom Zanussi   tracing: add per-...
886
  	}
8b3725621   Tom Zanussi   tracing/filters: ...
887
  	buf[cnt] = '\0';
cfb180f3e   Tom Zanussi   tracing: add per-...
888

8b3725621   Tom Zanussi   tracing/filters: ...
889
890
891
  	err = apply_subsystem_event_filter(system, buf);
  	free_page((unsigned long) buf);
  	if (err < 0)
44e9c8b7a   Li Zefan   tracing/filters: ...
892
  		return err;
cfb180f3e   Tom Zanussi   tracing: add per-...
893
894
895
896
897
  
  	*ppos += cnt;
  
  	return cnt;
  }
d1b182a8d   Steven Rostedt   tracing/events/ri...
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
  static ssize_t
  show_header(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
  {
  	int (*func)(struct trace_seq *s) = filp->private_data;
  	struct trace_seq *s;
  	int r;
  
  	if (*ppos)
  		return 0;
  
  	s = kmalloc(sizeof(*s), GFP_KERNEL);
  	if (!s)
  		return -ENOMEM;
  
  	trace_seq_init(s);
  
  	func(s);
  	r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len);
  
  	kfree(s);
  
  	return r;
  }
b77e38aa2   Steven Rostedt   tracing: add even...
921
922
923
924
925
926
927
928
929
930
931
932
933
  static const struct seq_operations show_event_seq_ops = {
  	.start = t_start,
  	.next = t_next,
  	.show = t_show,
  	.stop = t_stop,
  };
  
  static const struct seq_operations show_set_event_seq_ops = {
  	.start = s_start,
  	.next = s_next,
  	.show = t_show,
  	.stop = t_stop,
  };
2314c4ae1   Steven Rostedt   tracing: add back...
934
935
936
937
938
939
  static const struct file_operations ftrace_avail_fops = {
  	.open = ftrace_event_seq_open,
  	.read = seq_read,
  	.llseek = seq_lseek,
  	.release = seq_release,
  };
b77e38aa2   Steven Rostedt   tracing: add even...
940
941
942
943
944
945
946
  static const struct file_operations ftrace_set_event_fops = {
  	.open = ftrace_event_seq_open,
  	.read = seq_read,
  	.write = ftrace_event_write,
  	.llseek = seq_lseek,
  	.release = seq_release,
  };
1473e4417   Steven Rostedt   tracing: make eve...
947
948
949
950
  static const struct file_operations ftrace_enable_fops = {
  	.open = tracing_open_generic,
  	.read = event_enable_read,
  	.write = event_enable_write,
6038f373a   Arnd Bergmann   llseek: automatic...
951
  	.llseek = default_llseek,
1473e4417   Steven Rostedt   tracing: make eve...
952
  };
981d081ec   Steven Rostedt   tracing: add form...
953
  static const struct file_operations ftrace_event_format_fops = {
2a37a3df5   Steven Rostedt   tracing/events: C...
954
955
956
957
  	.open = trace_format_open,
  	.read = seq_read,
  	.llseek = seq_lseek,
  	.release = seq_release,
981d081ec   Steven Rostedt   tracing: add form...
958
  };
23725aeea   Peter Zijlstra   ftrace: provide a...
959
960
961
  static const struct file_operations ftrace_event_id_fops = {
  	.open = tracing_open_generic,
  	.read = event_id_read,
6038f373a   Arnd Bergmann   llseek: automatic...
962
  	.llseek = default_llseek,
23725aeea   Peter Zijlstra   ftrace: provide a...
963
  };
7ce7e4249   Tom Zanussi   tracing: add per-...
964
965
966
967
  static const struct file_operations ftrace_event_filter_fops = {
  	.open = tracing_open_generic,
  	.read = event_filter_read,
  	.write = event_filter_write,
6038f373a   Arnd Bergmann   llseek: automatic...
968
  	.llseek = default_llseek,
7ce7e4249   Tom Zanussi   tracing: add per-...
969
  };
cfb180f3e   Tom Zanussi   tracing: add per-...
970
  static const struct file_operations ftrace_subsystem_filter_fops = {
e9dbfae53   Steven Rostedt   tracing: Fix bug ...
971
  	.open = subsystem_open,
cfb180f3e   Tom Zanussi   tracing: add per-...
972
973
  	.read = subsystem_filter_read,
  	.write = subsystem_filter_write,
6038f373a   Arnd Bergmann   llseek: automatic...
974
  	.llseek = default_llseek,
e9dbfae53   Steven Rostedt   tracing: Fix bug ...
975
  	.release = subsystem_release,
cfb180f3e   Tom Zanussi   tracing: add per-...
976
  };
8ae79a138   Steven Rostedt   tracing: add hier...
977
  static const struct file_operations ftrace_system_enable_fops = {
40ee4dfff   Steven Rostedt   tracing: Have "en...
978
  	.open = subsystem_open,
8ae79a138   Steven Rostedt   tracing: add hier...
979
980
  	.read = system_enable_read,
  	.write = system_enable_write,
6038f373a   Arnd Bergmann   llseek: automatic...
981
  	.llseek = default_llseek,
40ee4dfff   Steven Rostedt   tracing: Have "en...
982
  	.release = subsystem_release,
8ae79a138   Steven Rostedt   tracing: add hier...
983
  };
d1b182a8d   Steven Rostedt   tracing/events/ri...
984
985
986
  static const struct file_operations ftrace_show_header_fops = {
  	.open = tracing_open_generic,
  	.read = show_header,
6038f373a   Arnd Bergmann   llseek: automatic...
987
  	.llseek = default_llseek,
d1b182a8d   Steven Rostedt   tracing/events/ri...
988
  };
1473e4417   Steven Rostedt   tracing: make eve...
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
  static struct dentry *event_trace_events_dir(void)
  {
  	static struct dentry *d_tracer;
  	static struct dentry *d_events;
  
  	if (d_events)
  		return d_events;
  
  	d_tracer = tracing_init_dentry();
  	if (!d_tracer)
  		return NULL;
  
  	d_events = debugfs_create_dir("events", d_tracer);
  	if (!d_events)
  		pr_warning("Could not create debugfs "
  			   "'events' directory
  ");
  
  	return d_events;
  }
6ecc2d1ca   Steven Rostedt   tracing: add subs...
1009
1010
1011
1012
  static struct dentry *
  event_subsystem_dir(const char *name, struct dentry *d_events)
  {
  	struct event_subsystem *system;
e1112b4d9   Tom Zanussi   tracing/filters: ...
1013
  	struct dentry *entry;
6ecc2d1ca   Steven Rostedt   tracing: add subs...
1014
1015
1016
  
  	/* First see if we did not already create this dir */
  	list_for_each_entry(system, &event_subsystems, list) {
dc82ec98a   Xiao Guangrong   tracing/filter: R...
1017
1018
  		if (strcmp(system->name, name) == 0) {
  			system->nr_events++;
6ecc2d1ca   Steven Rostedt   tracing: add subs...
1019
  			return system->entry;
dc82ec98a   Xiao Guangrong   tracing/filter: R...
1020
  		}
6ecc2d1ca   Steven Rostedt   tracing: add subs...
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
  	}
  
  	/* need to create new entry */
  	system = kmalloc(sizeof(*system), GFP_KERNEL);
  	if (!system) {
  		pr_warning("No memory to create event subsystem %s
  ",
  			   name);
  		return d_events;
  	}
  
  	system->entry = debugfs_create_dir(name, d_events);
  	if (!system->entry) {
  		pr_warning("Could not create event subsystem %s
  ",
  			   name);
  		kfree(system);
  		return d_events;
  	}
dc82ec98a   Xiao Guangrong   tracing/filter: R...
1040
  	system->nr_events = 1;
e9dbfae53   Steven Rostedt   tracing: Fix bug ...
1041
  	system->ref_count = 1;
6d723736e   Steven Rostedt   tracing/events: a...
1042
1043
1044
1045
1046
1047
  	system->name = kstrdup(name, GFP_KERNEL);
  	if (!system->name) {
  		debugfs_remove(system->entry);
  		kfree(system);
  		return d_events;
  	}
6ecc2d1ca   Steven Rostedt   tracing: add subs...
1048
  	list_add(&system->list, &event_subsystems);
30e673b23   Tom Zanussi   tracing/filters: ...
1049
  	system->filter = NULL;
cfb180f3e   Tom Zanussi   tracing: add per-...
1050

8b3725621   Tom Zanussi   tracing/filters: ...
1051
1052
1053
1054
1055
1056
1057
  	system->filter = kzalloc(sizeof(struct event_filter), GFP_KERNEL);
  	if (!system->filter) {
  		pr_warning("Could not allocate filter for subsystem "
  			   "'%s'
  ", name);
  		return system->entry;
  	}
e1112b4d9   Tom Zanussi   tracing/filters: ...
1058
1059
  	entry = debugfs_create_file("filter", 0644, system->entry, system,
  				    &ftrace_subsystem_filter_fops);
8b3725621   Tom Zanussi   tracing/filters: ...
1060
1061
1062
  	if (!entry) {
  		kfree(system->filter);
  		system->filter = NULL;
e1112b4d9   Tom Zanussi   tracing/filters: ...
1063
1064
1065
  		pr_warning("Could not create debugfs "
  			   "'%s/filter' entry
  ", name);
8b3725621   Tom Zanussi   tracing/filters: ...
1066
  	}
e1112b4d9   Tom Zanussi   tracing/filters: ...
1067

40ee4dfff   Steven Rostedt   tracing: Have "en...
1068
  	trace_create_file("enable", 0644, system->entry, system,
f3f3f0092   Frederic Weisbecker   tracing/event: Cl...
1069
  			  &ftrace_system_enable_fops);
8ae79a138   Steven Rostedt   tracing: add hier...
1070

6ecc2d1ca   Steven Rostedt   tracing: add subs...
1071
1072
  	return system->entry;
  }
1473e4417   Steven Rostedt   tracing: make eve...
1073
  static int
701970b3a   Steven Rostedt   tracing/events: m...
1074
1075
1076
1077
1078
  event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
  		 const struct file_operations *id,
  		 const struct file_operations *enable,
  		 const struct file_operations *filter,
  		 const struct file_operations *format)
1473e4417   Steven Rostedt   tracing: make eve...
1079
  {
2e33af029   Steven Rostedt   tracing: Move fie...
1080
  	struct list_head *head;
fd9949898   Steven Rostedt   tracing: add raw ...
1081
  	int ret;
1473e4417   Steven Rostedt   tracing: make eve...
1082

6ecc2d1ca   Steven Rostedt   tracing: add subs...
1083
1084
1085
1086
  	/*
  	 * If the trace point header did not define TRACE_SYSTEM
  	 * then the system would be called "TRACE_SYSTEM".
  	 */
8f0820183   Steven Rostedt   tracing: Create c...
1087
1088
  	if (strcmp(call->class->system, TRACE_SYSTEM) != 0)
  		d_events = event_subsystem_dir(call->class->system, d_events);
6ecc2d1ca   Steven Rostedt   tracing: add subs...
1089

1473e4417   Steven Rostedt   tracing: make eve...
1090
1091
1092
1093
1094
1095
1096
  	call->dir = debugfs_create_dir(call->name, d_events);
  	if (!call->dir) {
  		pr_warning("Could not create debugfs "
  			   "'%s' directory
  ", call->name);
  		return -1;
  	}
a1d0ce821   Steven Rostedt   tracing: Use clas...
1097
  	if (call->class->reg)
f3f3f0092   Frederic Weisbecker   tracing/event: Cl...
1098
1099
  		trace_create_file("enable", 0644, call->dir, call,
  				  enable);
1473e4417   Steven Rostedt   tracing: make eve...
1100

2239291ae   Steven Rostedt   tracing: Remove p...
1101
  #ifdef CONFIG_PERF_EVENTS
a1d0ce821   Steven Rostedt   tracing: Use clas...
1102
  	if (call->event.type && call->class->reg)
f3f3f0092   Frederic Weisbecker   tracing/event: Cl...
1103
1104
  		trace_create_file("id", 0444, call->dir, call,
  		 		  id);
2239291ae   Steven Rostedt   tracing: Remove p...
1105
  #endif
23725aeea   Peter Zijlstra   ftrace: provide a...
1106

c9d932cf8   Li Zefan   tracing: Remove t...
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
  	/*
  	 * Other events may have the same class. Only update
  	 * the fields if they are not already defined.
  	 */
  	head = trace_get_fields(call);
  	if (list_empty(head)) {
  		ret = call->class->define_fields(call);
  		if (ret < 0) {
  			pr_warning("Could not initialize trace point"
  				   " events/%s
  ", call->name);
  			return ret;
cf027f645   Tom Zanussi   tracing: add run-...
1119
1120
  		}
  	}
c9d932cf8   Li Zefan   tracing: Remove t...
1121
1122
  	trace_create_file("filter", 0644, call->dir, call,
  			  filter);
cf027f645   Tom Zanussi   tracing: add run-...
1123

f3f3f0092   Frederic Weisbecker   tracing/event: Cl...
1124
1125
  	trace_create_file("format", 0444, call->dir, call,
  			  format);
6d723736e   Steven Rostedt   tracing/events: a...
1126
1127
1128
  
  	return 0;
  }
67ead0a6c   Li Zefan   tracing: Remove o...
1129
1130
1131
1132
1133
1134
  static int
  __trace_add_event_call(struct ftrace_event_call *call, struct module *mod,
  		       const struct file_operations *id,
  		       const struct file_operations *enable,
  		       const struct file_operations *filter,
  		       const struct file_operations *format)
bd1a5c849   Masami Hiramatsu   tracing: Ftrace d...
1135
1136
1137
  {
  	struct dentry *d_events;
  	int ret;
6d723736e   Steven Rostedt   tracing/events: a...
1138

67ead0a6c   Li Zefan   tracing: Remove o...
1139
  	/* The linker may leave blanks */
bd1a5c849   Masami Hiramatsu   tracing: Ftrace d...
1140
1141
  	if (!call->name)
  		return -EINVAL;
701970b3a   Steven Rostedt   tracing/events: m...
1142

0405ab80a   Steven Rostedt   tracing: Move raw...
1143
1144
  	if (call->class->raw_init) {
  		ret = call->class->raw_init(call);
bd1a5c849   Masami Hiramatsu   tracing: Ftrace d...
1145
1146
  		if (ret < 0) {
  			if (ret != -ENOSYS)
67ead0a6c   Li Zefan   tracing: Remove o...
1147
1148
1149
  				pr_warning("Could not initialize trace events/%s
  ",
  					   call->name);
bd1a5c849   Masami Hiramatsu   tracing: Ftrace d...
1150
1151
1152
  			return ret;
  		}
  	}
701970b3a   Steven Rostedt   tracing/events: m...
1153

bd1a5c849   Masami Hiramatsu   tracing: Ftrace d...
1154
1155
1156
  	d_events = event_trace_events_dir();
  	if (!d_events)
  		return -ENOENT;
67ead0a6c   Li Zefan   tracing: Remove o...
1157
  	ret = event_create_dir(call, d_events, id, enable, filter, format);
88f70d759   Masami Hiramatsu   tracing/ftrace: F...
1158
1159
  	if (!ret)
  		list_add(&call->list, &ftrace_events);
67ead0a6c   Li Zefan   tracing: Remove o...
1160
  	call->mod = mod;
88f70d759   Masami Hiramatsu   tracing/ftrace: F...
1161

588bebb74   Masami Hiramatsu   ftrace: Fix trace...
1162
  	return ret;
bd1a5c849   Masami Hiramatsu   tracing: Ftrace d...
1163
1164
1165
1166
1167
1168
1169
  }
  
  /* Add an additional event_call dynamically */
  int trace_add_event_call(struct ftrace_event_call *call)
  {
  	int ret;
  	mutex_lock(&event_mutex);
67ead0a6c   Li Zefan   tracing: Remove o...
1170
1171
1172
1173
  	ret = __trace_add_event_call(call, NULL, &ftrace_event_id_fops,
  				     &ftrace_enable_fops,
  				     &ftrace_event_filter_fops,
  				     &ftrace_event_format_fops);
bd1a5c849   Masami Hiramatsu   tracing: Ftrace d...
1174
1175
1176
  	mutex_unlock(&event_mutex);
  	return ret;
  }
701970b3a   Steven Rostedt   tracing/events: m...
1177

a2ca5e03b   Frederic Weisbecker   tracing/events: O...
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
  static void remove_subsystem_dir(const char *name)
  {
  	struct event_subsystem *system;
  
  	if (strcmp(name, TRACE_SYSTEM) == 0)
  		return;
  
  	list_for_each_entry(system, &event_subsystems, list) {
  		if (strcmp(system->name, name) == 0) {
  			if (!--system->nr_events) {
a2ca5e03b   Frederic Weisbecker   tracing/events: O...
1188
1189
  				debugfs_remove_recursive(system->entry);
  				list_del(&system->list);
e9dbfae53   Steven Rostedt   tracing: Fix bug ...
1190
  				__put_system(system);
a2ca5e03b   Frederic Weisbecker   tracing/events: O...
1191
1192
1193
1194
1195
  			}
  			break;
  		}
  	}
  }
4fead8e46   Masami Hiramatsu   ftrace: Fix trace...
1196
1197
1198
  /*
   * Must be called under locking both of event_mutex and trace_event_mutex.
   */
bd1a5c849   Masami Hiramatsu   tracing: Ftrace d...
1199
1200
1201
  static void __trace_remove_event_call(struct ftrace_event_call *call)
  {
  	ftrace_event_enable_disable(call, 0);
80decc70a   Steven Rostedt   tracing: Move pri...
1202
1203
  	if (call->event.funcs)
  		__unregister_ftrace_event(&call->event);
bd1a5c849   Masami Hiramatsu   tracing: Ftrace d...
1204
1205
1206
1207
  	debugfs_remove_recursive(call->dir);
  	list_del(&call->list);
  	trace_destroy_fields(call);
  	destroy_preds(call);
8f0820183   Steven Rostedt   tracing: Create c...
1208
  	remove_subsystem_dir(call->class->system);
bd1a5c849   Masami Hiramatsu   tracing: Ftrace d...
1209
1210
1211
1212
1213
1214
  }
  
  /* Remove an event_call */
  void trace_remove_event_call(struct ftrace_event_call *call)
  {
  	mutex_lock(&event_mutex);
4fead8e46   Masami Hiramatsu   ftrace: Fix trace...
1215
  	down_write(&trace_event_mutex);
bd1a5c849   Masami Hiramatsu   tracing: Ftrace d...
1216
  	__trace_remove_event_call(call);
4fead8e46   Masami Hiramatsu   ftrace: Fix trace...
1217
  	up_write(&trace_event_mutex);
bd1a5c849   Masami Hiramatsu   tracing: Ftrace d...
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
  	mutex_unlock(&event_mutex);
  }
  
  #define for_each_event(event, start, end)			\
  	for (event = start;					\
  	     (unsigned long)event < (unsigned long)end;		\
  	     event++)
  
  #ifdef CONFIG_MODULES
  
  static LIST_HEAD(ftrace_module_file_list);
  
  /*
   * Modules must own their file_operations to keep up with
   * reference counting.
   */
  struct ftrace_module_file_ops {
  	struct list_head		list;
  	struct module			*mod;
  	struct file_operations		id;
  	struct file_operations		enable;
  	struct file_operations		format;
  	struct file_operations		filter;
  };
701970b3a   Steven Rostedt   tracing/events: m...
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
  static struct ftrace_module_file_ops *
  trace_create_file_ops(struct module *mod)
  {
  	struct ftrace_module_file_ops *file_ops;
  
  	/*
  	 * This is a bit of a PITA. To allow for correct reference
  	 * counting, modules must "own" their file_operations.
  	 * To do this, we allocate the file operations that will be
  	 * used in the event directory.
  	 */
  
  	file_ops = kmalloc(sizeof(*file_ops), GFP_KERNEL);
  	if (!file_ops)
  		return NULL;
  
  	file_ops->mod = mod;
  
  	file_ops->id = ftrace_event_id_fops;
  	file_ops->id.owner = mod;
  
  	file_ops->enable = ftrace_enable_fops;
  	file_ops->enable.owner = mod;
  
  	file_ops->filter = ftrace_event_filter_fops;
  	file_ops->filter.owner = mod;
  
  	file_ops->format = ftrace_event_format_fops;
  	file_ops->format.owner = mod;
  
  	list_add(&file_ops->list, &ftrace_module_file_list);
  
  	return file_ops;
  }
6d723736e   Steven Rostedt   tracing/events: a...
1276
1277
  static void trace_module_add_events(struct module *mod)
  {
701970b3a   Steven Rostedt   tracing/events: m...
1278
  	struct ftrace_module_file_ops *file_ops = NULL;
e4a9ea5ee   Steven Rostedt   tracing: Replace ...
1279
  	struct ftrace_event_call **call, **start, **end;
6d723736e   Steven Rostedt   tracing/events: a...
1280
1281
1282
1283
1284
1285
  
  	start = mod->trace_events;
  	end = mod->trace_events + mod->num_trace_events;
  
  	if (start == end)
  		return;
67ead0a6c   Li Zefan   tracing: Remove o...
1286
1287
  	file_ops = trace_create_file_ops(mod);
  	if (!file_ops)
6d723736e   Steven Rostedt   tracing/events: a...
1288
1289
1290
  		return;
  
  	for_each_event(call, start, end) {
e4a9ea5ee   Steven Rostedt   tracing: Replace ...
1291
  		__trace_add_event_call(*call, mod,
88f70d759   Masami Hiramatsu   tracing/ftrace: F...
1292
1293
  				       &file_ops->id, &file_ops->enable,
  				       &file_ops->filter, &file_ops->format);
6d723736e   Steven Rostedt   tracing/events: a...
1294
1295
1296
1297
1298
  	}
  }
  
  static void trace_module_remove_events(struct module *mod)
  {
701970b3a   Steven Rostedt   tracing/events: m...
1299
  	struct ftrace_module_file_ops *file_ops;
6d723736e   Steven Rostedt   tracing/events: a...
1300
  	struct ftrace_event_call *call, *p;
9456f0fa6   Steven Rostedt   tracing: reset ri...
1301
  	bool found = false;
6d723736e   Steven Rostedt   tracing/events: a...
1302

110bf2b76   Steven Rostedt   tracing: add prot...
1303
  	down_write(&trace_event_mutex);
6d723736e   Steven Rostedt   tracing/events: a...
1304
1305
  	list_for_each_entry_safe(call, p, &ftrace_events, list) {
  		if (call->mod == mod) {
9456f0fa6   Steven Rostedt   tracing: reset ri...
1306
  			found = true;
bd1a5c849   Masami Hiramatsu   tracing: Ftrace d...
1307
  			__trace_remove_event_call(call);
6d723736e   Steven Rostedt   tracing/events: a...
1308
1309
  		}
  	}
701970b3a   Steven Rostedt   tracing/events: m...
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
  
  	/* Now free the file_operations */
  	list_for_each_entry(file_ops, &ftrace_module_file_list, list) {
  		if (file_ops->mod == mod)
  			break;
  	}
  	if (&file_ops->list != &ftrace_module_file_list) {
  		list_del(&file_ops->list);
  		kfree(file_ops);
  	}
9456f0fa6   Steven Rostedt   tracing: reset ri...
1320
1321
1322
1323
1324
1325
1326
  
  	/*
  	 * It is safest to reset the ring buffer if the module being unloaded
  	 * registered any events.
  	 */
  	if (found)
  		tracing_reset_current_online_cpus();
110bf2b76   Steven Rostedt   tracing: add prot...
1327
  	up_write(&trace_event_mutex);
6d723736e   Steven Rostedt   tracing/events: a...
1328
  }
61f919a12   Steven Rostedt   tracing/events: f...
1329
1330
  static int trace_module_notify(struct notifier_block *self,
  			       unsigned long val, void *data)
6d723736e   Steven Rostedt   tracing/events: a...
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
  {
  	struct module *mod = data;
  
  	mutex_lock(&event_mutex);
  	switch (val) {
  	case MODULE_STATE_COMING:
  		trace_module_add_events(mod);
  		break;
  	case MODULE_STATE_GOING:
  		trace_module_remove_events(mod);
  		break;
  	}
  	mutex_unlock(&event_mutex);
fd9949898   Steven Rostedt   tracing: add raw ...
1344

1473e4417   Steven Rostedt   tracing: make eve...
1345
1346
  	return 0;
  }
61f919a12   Steven Rostedt   tracing/events: f...
1347
1348
1349
1350
1351
1352
1353
  #else
  static int trace_module_notify(struct notifier_block *self,
  			       unsigned long val, void *data)
  {
  	return 0;
  }
  #endif /* CONFIG_MODULES */
1473e4417   Steven Rostedt   tracing: make eve...
1354

ec827c7ec   Steven Rostedt   tracing: add stat...
1355
  static struct notifier_block trace_module_nb = {
6d723736e   Steven Rostedt   tracing/events: a...
1356
1357
1358
  	.notifier_call = trace_module_notify,
  	.priority = 0,
  };
e4a9ea5ee   Steven Rostedt   tracing: Replace ...
1359
1360
  extern struct ftrace_event_call *__start_ftrace_events[];
  extern struct ftrace_event_call *__stop_ftrace_events[];
a59fd6027   Steven Rostedt   tracing/events: c...
1361

020e5f85c   Li Zefan   tracing/events: A...
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
  static char bootup_event_buf[COMMAND_LINE_SIZE] __initdata;
  
  static __init int setup_trace_event(char *str)
  {
  	strlcpy(bootup_event_buf, str, COMMAND_LINE_SIZE);
  	ring_buffer_expanded = 1;
  	tracing_selftest_disabled = 1;
  
  	return 1;
  }
  __setup("trace_event=", setup_trace_event);
b77e38aa2   Steven Rostedt   tracing: add even...
1373
1374
  static __init int event_trace_init(void)
  {
e4a9ea5ee   Steven Rostedt   tracing: Replace ...
1375
  	struct ftrace_event_call **call;
b77e38aa2   Steven Rostedt   tracing: add even...
1376
1377
  	struct dentry *d_tracer;
  	struct dentry *entry;
1473e4417   Steven Rostedt   tracing: make eve...
1378
  	struct dentry *d_events;
6d723736e   Steven Rostedt   tracing/events: a...
1379
  	int ret;
020e5f85c   Li Zefan   tracing/events: A...
1380
1381
  	char *buf = bootup_event_buf;
  	char *token;
b77e38aa2   Steven Rostedt   tracing: add even...
1382
1383
1384
1385
  
  	d_tracer = tracing_init_dentry();
  	if (!d_tracer)
  		return 0;
2314c4ae1   Steven Rostedt   tracing: add back...
1386
1387
1388
1389
1390
1391
1392
  	entry = debugfs_create_file("available_events", 0444, d_tracer,
  				    (void *)&show_event_seq_ops,
  				    &ftrace_avail_fops);
  	if (!entry)
  		pr_warning("Could not create debugfs "
  			   "'available_events' entry
  ");
b77e38aa2   Steven Rostedt   tracing: add even...
1393
1394
1395
1396
1397
1398
1399
  	entry = debugfs_create_file("set_event", 0644, d_tracer,
  				    (void *)&show_set_event_seq_ops,
  				    &ftrace_set_event_fops);
  	if (!entry)
  		pr_warning("Could not create debugfs "
  			   "'set_event' entry
  ");
1473e4417   Steven Rostedt   tracing: make eve...
1400
1401
1402
  	d_events = event_trace_events_dir();
  	if (!d_events)
  		return 0;
d1b182a8d   Steven Rostedt   tracing/events/ri...
1403
1404
1405
1406
1407
1408
1409
1410
  	/* ring buffer internal formats */
  	trace_create_file("header_page", 0444, d_events,
  			  ring_buffer_print_page_header,
  			  &ftrace_show_header_fops);
  
  	trace_create_file("header_event", 0444, d_events,
  			  ring_buffer_print_entry_header,
  			  &ftrace_show_header_fops);
8ae79a138   Steven Rostedt   tracing: add hier...
1411
  	trace_create_file("enable", 0644, d_events,
8f31bfe53   Li Zefan   tracing/events: c...
1412
  			  NULL, &ftrace_system_enable_fops);
8ae79a138   Steven Rostedt   tracing: add hier...
1413

8728fe501   Li Zefan   tracing: Don't al...
1414
1415
  	if (trace_define_common_fields())
  		pr_warning("tracing: Failed to allocate common fields");
6d723736e   Steven Rostedt   tracing/events: a...
1416
  	for_each_event(call, __start_ftrace_events, __stop_ftrace_events) {
e4a9ea5ee   Steven Rostedt   tracing: Replace ...
1417
  		__trace_add_event_call(*call, NULL, &ftrace_event_id_fops,
88f70d759   Masami Hiramatsu   tracing/ftrace: F...
1418
1419
1420
  				       &ftrace_enable_fops,
  				       &ftrace_event_filter_fops,
  				       &ftrace_event_format_fops);
1473e4417   Steven Rostedt   tracing: make eve...
1421
  	}
020e5f85c   Li Zefan   tracing/events: A...
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
  	while (true) {
  		token = strsep(&buf, ",");
  
  		if (!token)
  			break;
  		if (!*token)
  			continue;
  
  		ret = ftrace_set_clr_event(token, 1);
  		if (ret)
  			pr_warning("Failed to enable trace event: %s
  ", token);
  	}
6d723736e   Steven Rostedt   tracing/events: a...
1435
  	ret = register_module_notifier(&trace_module_nb);
553793769   Ming Lei   ftrace: fix check...
1436
  	if (ret)
6d723736e   Steven Rostedt   tracing/events: a...
1437
1438
  		pr_warning("Failed to register trace events module notifier
  ");
b77e38aa2   Steven Rostedt   tracing: add even...
1439
1440
1441
  	return 0;
  }
  fs_initcall(event_trace_init);
e6187007d   Steven Rostedt   tracing/events: a...
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
  
  #ifdef CONFIG_FTRACE_STARTUP_TEST
  
  static DEFINE_SPINLOCK(test_spinlock);
  static DEFINE_SPINLOCK(test_spinlock_irq);
  static DEFINE_MUTEX(test_mutex);
  
  static __init void test_work(struct work_struct *dummy)
  {
  	spin_lock(&test_spinlock);
  	spin_lock_irq(&test_spinlock_irq);
  	udelay(1);
  	spin_unlock_irq(&test_spinlock_irq);
  	spin_unlock(&test_spinlock);
  
  	mutex_lock(&test_mutex);
  	msleep(1);
  	mutex_unlock(&test_mutex);
  }
  
  static __init int event_test_thread(void *unused)
  {
  	void *test_malloc;
  
  	test_malloc = kmalloc(1234, GFP_KERNEL);
  	if (!test_malloc)
  		pr_info("failed to kmalloc
  ");
  
  	schedule_on_each_cpu(test_work);
  
  	kfree(test_malloc);
  
  	set_current_state(TASK_INTERRUPTIBLE);
  	while (!kthread_should_stop())
  		schedule();
  
  	return 0;
  }
  
  /*
   * Do various things that may trigger events.
   */
  static __init void event_test_stuff(void)
  {
  	struct task_struct *test_thread;
  
  	test_thread = kthread_run(event_test_thread, NULL, "test-events");
  	msleep(1);
  	kthread_stop(test_thread);
  }
  
  /*
   * For every trace event defined, we will test each trace point separately,
   * and then by groups, and finally all trace points.
   */
9ea21c1ec   Steven Rostedt   tracing/events: p...
1498
  static __init void event_trace_self_tests(void)
e6187007d   Steven Rostedt   tracing/events: a...
1499
1500
1501
  {
  	struct ftrace_event_call *call;
  	struct event_subsystem *system;
e6187007d   Steven Rostedt   tracing/events: a...
1502
1503
1504
1505
1506
1507
  	int ret;
  
  	pr_info("Running tests on trace events:
  ");
  
  	list_for_each_entry(call, &ftrace_events, list) {
2239291ae   Steven Rostedt   tracing: Remove p...
1508
1509
  		/* Only test those that have a probe */
  		if (!call->class || !call->class->probe)
e6187007d   Steven Rostedt   tracing/events: a...
1510
  			continue;
1f5a6b454   Steven Rostedt   tracing: make tes...
1511
1512
1513
1514
1515
1516
1517
  /*
   * Testing syscall events here is pretty useless, but
   * we still do it if configured. But this is time consuming.
   * What we really need is a user thread to perform the
   * syscalls as we test.
   */
  #ifndef CONFIG_EVENT_TRACE_TEST_SYSCALLS
8f0820183   Steven Rostedt   tracing: Create c...
1518
1519
  		if (call->class->system &&
  		    strcmp(call->class->system, "syscalls") == 0)
1f5a6b454   Steven Rostedt   tracing: make tes...
1520
1521
  			continue;
  #endif
e6187007d   Steven Rostedt   tracing/events: a...
1522
1523
1524
1525
1526
1527
  		pr_info("Testing event %s: ", call->name);
  
  		/*
  		 * If an event is already enabled, someone is using
  		 * it and the self test should not be on.
  		 */
553552ce1   Steven Rostedt   tracing: Combine ...
1528
  		if (call->flags & TRACE_EVENT_FL_ENABLED) {
e6187007d   Steven Rostedt   tracing/events: a...
1529
1530
1531
1532
1533
  			pr_warning("Enabled event during self test!
  ");
  			WARN_ON_ONCE(1);
  			continue;
  		}
0e907c993   Zhaolei   ftrace: clean up ...
1534
  		ftrace_event_enable_disable(call, 1);
e6187007d   Steven Rostedt   tracing/events: a...
1535
  		event_test_stuff();
0e907c993   Zhaolei   ftrace: clean up ...
1536
  		ftrace_event_enable_disable(call, 0);
e6187007d   Steven Rostedt   tracing/events: a...
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
  
  		pr_cont("OK
  ");
  	}
  
  	/* Now test at the sub system level */
  
  	pr_info("Running tests on trace event systems:
  ");
  
  	list_for_each_entry(system, &event_subsystems, list) {
  
  		/* the ftrace system is special, skip it */
  		if (strcmp(system->name, "ftrace") == 0)
  			continue;
  
  		pr_info("Testing event system %s: ", system->name);
8f31bfe53   Li Zefan   tracing/events: c...
1554
  		ret = __ftrace_set_clr_event(NULL, system->name, NULL, 1);
e6187007d   Steven Rostedt   tracing/events: a...
1555
1556
1557
1558
1559
1560
1561
1562
  		if (WARN_ON_ONCE(ret)) {
  			pr_warning("error enabling system %s
  ",
  				   system->name);
  			continue;
  		}
  
  		event_test_stuff();
8f31bfe53   Li Zefan   tracing/events: c...
1563
  		ret = __ftrace_set_clr_event(NULL, system->name, NULL, 0);
e6187007d   Steven Rostedt   tracing/events: a...
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
  		if (WARN_ON_ONCE(ret))
  			pr_warning("error disabling system %s
  ",
  				   system->name);
  
  		pr_cont("OK
  ");
  	}
  
  	/* Test with all events enabled */
  
  	pr_info("Running tests on all trace events:
  ");
  	pr_info("Testing all events: ");
8f31bfe53   Li Zefan   tracing/events: c...
1578
  	ret = __ftrace_set_clr_event(NULL, NULL, NULL, 1);
e6187007d   Steven Rostedt   tracing/events: a...
1579
  	if (WARN_ON_ONCE(ret)) {
e6187007d   Steven Rostedt   tracing/events: a...
1580
1581
  		pr_warning("error enabling all events
  ");
9ea21c1ec   Steven Rostedt   tracing/events: p...
1582
  		return;
e6187007d   Steven Rostedt   tracing/events: a...
1583
1584
1585
1586
1587
  	}
  
  	event_test_stuff();
  
  	/* reset sysname */
8f31bfe53   Li Zefan   tracing/events: c...
1588
  	ret = __ftrace_set_clr_event(NULL, NULL, NULL, 0);
e6187007d   Steven Rostedt   tracing/events: a...
1589
1590
1591
  	if (WARN_ON_ONCE(ret)) {
  		pr_warning("error disabling all events
  ");
9ea21c1ec   Steven Rostedt   tracing/events: p...
1592
  		return;
e6187007d   Steven Rostedt   tracing/events: a...
1593
1594
1595
1596
  	}
  
  	pr_cont("OK
  ");
9ea21c1ec   Steven Rostedt   tracing/events: p...
1597
1598
1599
  }
  
  #ifdef CONFIG_FUNCTION_TRACER
245b2e70e   Tejun Heo   percpu: clean up ...
1600
  static DEFINE_PER_CPU(atomic_t, ftrace_test_event_disable);
9ea21c1ec   Steven Rostedt   tracing/events: p...
1601
1602
1603
1604
1605
  
  static void
  function_test_events_call(unsigned long ip, unsigned long parent_ip)
  {
  	struct ring_buffer_event *event;
e77405ad8   Steven Rostedt   tracing: pass aro...
1606
  	struct ring_buffer *buffer;
9ea21c1ec   Steven Rostedt   tracing/events: p...
1607
1608
1609
  	struct ftrace_entry *entry;
  	unsigned long flags;
  	long disabled;
9ea21c1ec   Steven Rostedt   tracing/events: p...
1610
1611
1612
1613
  	int cpu;
  	int pc;
  
  	pc = preempt_count();
5168ae50a   Steven Rostedt   tracing: Remove f...
1614
  	preempt_disable_notrace();
9ea21c1ec   Steven Rostedt   tracing/events: p...
1615
  	cpu = raw_smp_processor_id();
245b2e70e   Tejun Heo   percpu: clean up ...
1616
  	disabled = atomic_inc_return(&per_cpu(ftrace_test_event_disable, cpu));
9ea21c1ec   Steven Rostedt   tracing/events: p...
1617
1618
1619
1620
1621
  
  	if (disabled != 1)
  		goto out;
  
  	local_save_flags(flags);
e77405ad8   Steven Rostedt   tracing: pass aro...
1622
1623
  	event = trace_current_buffer_lock_reserve(&buffer,
  						  TRACE_FN, sizeof(*entry),
9ea21c1ec   Steven Rostedt   tracing/events: p...
1624
1625
1626
1627
1628
1629
  						  flags, pc);
  	if (!event)
  		goto out;
  	entry	= ring_buffer_event_data(event);
  	entry->ip			= ip;
  	entry->parent_ip		= parent_ip;
e77405ad8   Steven Rostedt   tracing: pass aro...
1630
  	trace_nowake_buffer_unlock_commit(buffer, event, flags, pc);
9ea21c1ec   Steven Rostedt   tracing/events: p...
1631
1632
  
   out:
245b2e70e   Tejun Heo   percpu: clean up ...
1633
  	atomic_dec(&per_cpu(ftrace_test_event_disable, cpu));
5168ae50a   Steven Rostedt   tracing: Remove f...
1634
  	preempt_enable_notrace();
9ea21c1ec   Steven Rostedt   tracing/events: p...
1635
1636
1637
1638
1639
1640
1641
1642
1643
  }
  
  static struct ftrace_ops trace_ops __initdata  =
  {
  	.func = function_test_events_call,
  };
  
  static __init void event_trace_self_test_with_function(void)
  {
17bb615ad   Steven Rostedt   tracing: Have eve...
1644
1645
1646
1647
1648
1649
1650
  	int ret;
  	ret = register_ftrace_function(&trace_ops);
  	if (WARN_ON(ret < 0)) {
  		pr_info("Failed to enable function tracer for event tests
  ");
  		return;
  	}
9ea21c1ec   Steven Rostedt   tracing/events: p...
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
  	pr_info("Running tests again, along with the function tracer
  ");
  	event_trace_self_tests();
  	unregister_ftrace_function(&trace_ops);
  }
  #else
  static __init void event_trace_self_test_with_function(void)
  {
  }
  #endif
  
  static __init int event_trace_self_tests_init(void)
  {
020e5f85c   Li Zefan   tracing/events: A...
1664
1665
1666
1667
  	if (!tracing_selftest_disabled) {
  		event_trace_self_tests();
  		event_trace_self_test_with_function();
  	}
e6187007d   Steven Rostedt   tracing/events: a...
1668
1669
1670
  
  	return 0;
  }
28d20e2d6   Steven Rostedt   tracing/events: c...
1671
  late_initcall(event_trace_self_tests_init);
e6187007d   Steven Rostedt   tracing/events: a...
1672
1673
  
  #endif