aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/trace.h10
-rw-r--r--kernel/trace/trace_events.c3
-rw-r--r--kernel/trace/trace_events_filter.c107
3 files changed, 74 insertions, 46 deletions
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 7d55bcf50e49..1fb7d6ccadf4 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -731,12 +731,16 @@ struct ftrace_event_field {
731 int size; 731 int size;
732}; 732};
733 733
734struct event_filter {
735 int n_preds;
736 struct filter_pred **preds;
737};
738
734struct event_subsystem { 739struct event_subsystem {
735 struct list_head list; 740 struct list_head list;
736 const char *name; 741 const char *name;
737 struct dentry *entry; 742 struct dentry *entry;
738 int n_preds; 743 void *filter;
739 struct filter_pred **preds;
740}; 744};
741 745
742struct filter_pred; 746struct filter_pred;
@@ -774,7 +778,7 @@ filter_check_discard(struct ftrace_event_call *call, void *rec,
774 struct ring_buffer *buffer, 778 struct ring_buffer *buffer,
775 struct ring_buffer_event *event) 779 struct ring_buffer_event *event)
776{ 780{
777 if (unlikely(call->n_preds) && !filter_match_preds(call, rec)) { 781 if (unlikely(call->filter_active) && !filter_match_preds(call, rec)) {
778 ring_buffer_discard_commit(buffer, event); 782 ring_buffer_discard_commit(buffer, event);
779 return 1; 783 return 1;
780 } 784 }
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index be4d3a437c17..1cd1f37373dd 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -757,8 +757,7 @@ event_subsystem_dir(const char *name, struct dentry *d_events)
757 757
758 list_add(&system->list, &event_subsystems); 758 list_add(&system->list, &event_subsystems);
759 759
760 system->preds = NULL; 760 system->filter = NULL;
761 system->n_preds = 0;
762 761
763 entry = debugfs_create_file("filter", 0644, system->entry, system, 762 entry = debugfs_create_file("filter", 0644, system->entry, system,
764 &ftrace_subsystem_filter_fops); 763 &ftrace_subsystem_filter_fops);
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 65418288f957..1e861eca3d02 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -93,11 +93,12 @@ static int filter_pred_none(struct filter_pred *pred, void *event)
93/* return 1 if event matches, 0 otherwise (discard) */ 93/* return 1 if event matches, 0 otherwise (discard) */
94int filter_match_preds(struct ftrace_event_call *call, void *rec) 94int filter_match_preds(struct ftrace_event_call *call, void *rec)
95{ 95{
96 struct event_filter *filter = call->filter;
96 int i, matched, and_failed = 0; 97 int i, matched, and_failed = 0;
97 struct filter_pred *pred; 98 struct filter_pred *pred;
98 99
99 for (i = 0; i < call->n_preds; i++) { 100 for (i = 0; i < filter->n_preds; i++) {
100 pred = call->preds[i]; 101 pred = filter->preds[i];
101 if (and_failed && !pred->or) 102 if (and_failed && !pred->or)
102 continue; 103 continue;
103 matched = pred->fn(pred, rec); 104 matched = pred->fn(pred, rec);
@@ -115,20 +116,20 @@ int filter_match_preds(struct ftrace_event_call *call, void *rec)
115} 116}
116EXPORT_SYMBOL_GPL(filter_match_preds); 117EXPORT_SYMBOL_GPL(filter_match_preds);
117 118
118static void __filter_print_preds(struct filter_pred **preds, int n_preds, 119static void __filter_print_preds(struct event_filter *filter,
119 struct trace_seq *s) 120 struct trace_seq *s)
120{ 121{
121 char *field_name;
122 struct filter_pred *pred; 122 struct filter_pred *pred;
123 char *field_name;
123 int i; 124 int i;
124 125
125 if (!n_preds) { 126 if (!filter || !filter->n_preds) {
126 trace_seq_printf(s, "none\n"); 127 trace_seq_printf(s, "none\n");
127 return; 128 return;
128 } 129 }
129 130
130 for (i = 0; i < n_preds; i++) { 131 for (i = 0; i < filter->n_preds; i++) {
131 pred = preds[i]; 132 pred = filter->preds[i];
132 field_name = pred->field_name; 133 field_name = pred->field_name;
133 if (i) 134 if (i)
134 trace_seq_printf(s, pred->or ? "|| " : "&& "); 135 trace_seq_printf(s, pred->or ? "|| " : "&& ");
@@ -144,7 +145,7 @@ static void __filter_print_preds(struct filter_pred **preds, int n_preds,
144void filter_print_preds(struct ftrace_event_call *call, struct trace_seq *s) 145void filter_print_preds(struct ftrace_event_call *call, struct trace_seq *s)
145{ 146{
146 mutex_lock(&filter_mutex); 147 mutex_lock(&filter_mutex);
147 __filter_print_preds(call->preds, call->n_preds, s); 148 __filter_print_preds(call->filter, s);
148 mutex_unlock(&filter_mutex); 149 mutex_unlock(&filter_mutex);
149} 150}
150 151
@@ -152,7 +153,7 @@ void filter_print_subsystem_preds(struct event_subsystem *system,
152 struct trace_seq *s) 153 struct trace_seq *s)
153{ 154{
154 mutex_lock(&filter_mutex); 155 mutex_lock(&filter_mutex);
155 __filter_print_preds(system->preds, system->n_preds, s); 156 __filter_print_preds(system->filter, s);
156 mutex_unlock(&filter_mutex); 157 mutex_unlock(&filter_mutex);
157} 158}
158 159
@@ -200,12 +201,14 @@ static int filter_set_pred(struct filter_pred *dest,
200 201
201static void __filter_disable_preds(struct ftrace_event_call *call) 202static void __filter_disable_preds(struct ftrace_event_call *call)
202{ 203{
204 struct event_filter *filter = call->filter;
203 int i; 205 int i;
204 206
205 call->n_preds = 0; 207 call->filter_active = 0;
208 filter->n_preds = 0;
206 209
207 for (i = 0; i < MAX_FILTER_PRED; i++) 210 for (i = 0; i < MAX_FILTER_PRED; i++)
208 call->preds[i]->fn = filter_pred_none; 211 filter->preds[i]->fn = filter_pred_none;
209} 212}
210 213
211void filter_disable_preds(struct ftrace_event_call *call) 214void filter_disable_preds(struct ftrace_event_call *call)
@@ -217,32 +220,39 @@ void filter_disable_preds(struct ftrace_event_call *call)
217 220
218int init_preds(struct ftrace_event_call *call) 221int init_preds(struct ftrace_event_call *call)
219{ 222{
223 struct event_filter *filter;
220 struct filter_pred *pred; 224 struct filter_pred *pred;
221 int i; 225 int i;
222 226
223 call->n_preds = 0; 227 filter = call->filter = kzalloc(sizeof(*filter), GFP_KERNEL);
224 228 if (!call->filter)
225 call->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred), GFP_KERNEL);
226 if (!call->preds)
227 return -ENOMEM; 229 return -ENOMEM;
228 230
231 call->filter_active = 0;
232 filter->n_preds = 0;
233
234 filter->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred), GFP_KERNEL);
235 if (!filter->preds)
236 goto oom;
237
229 for (i = 0; i < MAX_FILTER_PRED; i++) { 238 for (i = 0; i < MAX_FILTER_PRED; i++) {
230 pred = kzalloc(sizeof(*pred), GFP_KERNEL); 239 pred = kzalloc(sizeof(*pred), GFP_KERNEL);
231 if (!pred) 240 if (!pred)
232 goto oom; 241 goto oom;
233 pred->fn = filter_pred_none; 242 pred->fn = filter_pred_none;
234 call->preds[i] = pred; 243 filter->preds[i] = pred;
235 } 244 }
236 245
237 return 0; 246 return 0;
238 247
239oom: 248oom:
240 for (i = 0; i < MAX_FILTER_PRED; i++) { 249 for (i = 0; i < MAX_FILTER_PRED; i++) {
241 if (call->preds[i]) 250 if (filter->preds[i])
242 filter_free_pred(call->preds[i]); 251 filter_free_pred(filter->preds[i]);
243 } 252 }
244 kfree(call->preds); 253 kfree(filter->preds);
245 call->preds = NULL; 254 kfree(call->filter);
255 call->filter = NULL;
246 256
247 return -ENOMEM; 257 return -ENOMEM;
248} 258}
@@ -250,15 +260,16 @@ EXPORT_SYMBOL_GPL(init_preds);
250 260
251static void __filter_free_subsystem_preds(struct event_subsystem *system) 261static void __filter_free_subsystem_preds(struct event_subsystem *system)
252{ 262{
263 struct event_filter *filter = system->filter;
253 struct ftrace_event_call *call; 264 struct ftrace_event_call *call;
254 int i; 265 int i;
255 266
256 if (system->n_preds) { 267 if (filter && filter->n_preds) {
257 for (i = 0; i < system->n_preds; i++) 268 for (i = 0; i < filter->n_preds; i++)
258 filter_free_pred(system->preds[i]); 269 filter_free_pred(filter->preds[i]);
259 kfree(system->preds); 270 kfree(filter->preds);
260 system->preds = NULL; 271 kfree(filter);
261 system->n_preds = 0; 272 system->filter = NULL;
262 } 273 }
263 274
264 list_for_each_entry(call, &ftrace_events, list) { 275 list_for_each_entry(call, &ftrace_events, list) {
@@ -281,21 +292,23 @@ static int filter_add_pred_fn(struct ftrace_event_call *call,
281 struct filter_pred *pred, 292 struct filter_pred *pred,
282 filter_pred_fn_t fn) 293 filter_pred_fn_t fn)
283{ 294{
295 struct event_filter *filter = call->filter;
284 int idx, err; 296 int idx, err;
285 297
286 if (call->n_preds && !pred->compound) 298 if (filter->n_preds && !pred->compound)
287 __filter_disable_preds(call); 299 __filter_disable_preds(call);
288 300
289 if (call->n_preds == MAX_FILTER_PRED) 301 if (filter->n_preds == MAX_FILTER_PRED)
290 return -ENOSPC; 302 return -ENOSPC;
291 303
292 idx = call->n_preds; 304 idx = filter->n_preds;
293 filter_clear_pred(call->preds[idx]); 305 filter_clear_pred(filter->preds[idx]);
294 err = filter_set_pred(call->preds[idx], pred, fn); 306 err = filter_set_pred(filter->preds[idx], pred, fn);
295 if (err) 307 if (err)
296 return err; 308 return err;
297 309
298 call->n_preds++; 310 filter->n_preds++;
311 call->filter_active = 1;
299 312
300 return 0; 313 return 0;
301} 314}
@@ -366,29 +379,41 @@ int filter_add_pred(struct ftrace_event_call *call, struct filter_pred *pred)
366int filter_add_subsystem_pred(struct event_subsystem *system, 379int filter_add_subsystem_pred(struct event_subsystem *system,
367 struct filter_pred *pred) 380 struct filter_pred *pred)
368{ 381{
382 struct event_filter *filter = system->filter;
369 struct ftrace_event_call *call; 383 struct ftrace_event_call *call;
370 384
371 mutex_lock(&filter_mutex); 385 mutex_lock(&filter_mutex);
372 386
373 if (system->n_preds && !pred->compound) 387 if (filter && filter->n_preds && !pred->compound) {
374 __filter_free_subsystem_preds(system); 388 __filter_free_subsystem_preds(system);
389 filter = NULL;
390 }
375 391
376 if (!system->n_preds) { 392 if (!filter) {
377 system->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred), 393 system->filter = kzalloc(sizeof(*filter), GFP_KERNEL);
394 if (!system->filter) {
395 mutex_unlock(&filter_mutex);
396 return -ENOMEM;
397 }
398 filter = system->filter;
399 filter->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred),
378 GFP_KERNEL); 400 GFP_KERNEL);
379 if (!system->preds) { 401
402 if (!filter->preds) {
403 kfree(system->filter);
404 system->filter = NULL;
380 mutex_unlock(&filter_mutex); 405 mutex_unlock(&filter_mutex);
381 return -ENOMEM; 406 return -ENOMEM;
382 } 407 }
383 } 408 }
384 409
385 if (system->n_preds == MAX_FILTER_PRED) { 410 if (filter->n_preds == MAX_FILTER_PRED) {
386 mutex_unlock(&filter_mutex); 411 mutex_unlock(&filter_mutex);
387 return -ENOSPC; 412 return -ENOSPC;
388 } 413 }
389 414
390 system->preds[system->n_preds] = pred; 415 filter->preds[filter->n_preds] = pred;
391 system->n_preds++; 416 filter->n_preds++;
392 417
393 list_for_each_entry(call, &ftrace_events, list) { 418 list_for_each_entry(call, &ftrace_events, list) {
394 int err; 419 int err;
@@ -401,8 +426,8 @@ int filter_add_subsystem_pred(struct event_subsystem *system,
401 426
402 err = __filter_add_pred(call, pred); 427 err = __filter_add_pred(call, pred);
403 if (err == -ENOMEM) { 428 if (err == -ENOMEM) {
404 system->preds[system->n_preds] = NULL; 429 filter->preds[filter->n_preds] = NULL;
405 system->n_preds--; 430 filter->n_preds--;
406 mutex_unlock(&filter_mutex); 431 mutex_unlock(&filter_mutex);
407 return err; 432 return err;
408 } 433 }