aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2008-11-17 13:23:42 -0500
committerIngo Molnar <mingo@elte.hu>2008-11-18 05:10:58 -0500
commitadf9f19574334c9a29a2bc956009fcac7edf1a6b (patch)
tree644415fb8e460290a6747c5933a1c62be9a9d50f /kernel
parent5a209c2d58e70f9bc415b9cdf0e3b9aaefb70371 (diff)
tracing/ftrace: implement a set_flag callback for tracers
Impact: give a way to send specific messages to tracers The current implementation of tracing uses some flags to control the output of general tracers. But we have no way to implement custom flags handling for a specific tracer. This patch proposes a new callback for the struct tracer which called set_flag and a structure that represents a 32 bits variable flag. A tracer can implement a struct tracer_flags on which it puts the initial value of the flag integer. Than it can place a range of flags with their name and their flag mask on the flag integer. The structure that implement a single flag is called struct tracer_opt. These custom flags will be available through the trace_options file like the general tracing flags. Changing their value is done like the other general flags. For example if you have a flag that calls "foo", you can activate it by writing "foo" or "nofoo" on trace_options. Note that the set_flag callback is optional and is only needed if you want the flags changing to be signaled to your tracer and let it to accept or refuse their assignment. V2: Some arrangements in coding style.... Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Acked-by: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/trace.c92
-rw-r--r--kernel/trace/trace.h26
2 files changed, 112 insertions, 6 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 2596b5a968c4..9531fddcfb8d 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -43,6 +43,20 @@
43unsigned long __read_mostly tracing_max_latency = (cycle_t)ULONG_MAX; 43unsigned long __read_mostly tracing_max_latency = (cycle_t)ULONG_MAX;
44unsigned long __read_mostly tracing_thresh; 44unsigned long __read_mostly tracing_thresh;
45 45
46/* For tracers that don't implement custom flags */
47static struct tracer_opt dummy_tracer_opt[] = {
48 { }
49};
50
51static struct tracer_flags dummy_tracer_flags = {
52 .val = 0,
53 .opts = dummy_tracer_opt
54};
55
56static int dummy_set_flag(u32 old_flags, u32 bit, int set)
57{
58 return 0;
59}
46 60
47/* 61/*
48 * Kill all tracing for good (never come back). 62 * Kill all tracing for good (never come back).
@@ -529,6 +543,14 @@ int register_tracer(struct tracer *type)
529 } 543 }
530 } 544 }
531 545
546 if (!type->set_flag)
547 type->set_flag = &dummy_set_flag;
548 if (!type->flags)
549 type->flags = &dummy_tracer_flags;
550 else
551 if (!type->flags->opts)
552 type->flags->opts = dummy_tracer_opt;
553
532#ifdef CONFIG_FTRACE_STARTUP_TEST 554#ifdef CONFIG_FTRACE_STARTUP_TEST
533 if (type->selftest) { 555 if (type->selftest) {
534 struct tracer *saved_tracer = current_trace; 556 struct tracer *saved_tracer = current_trace;
@@ -2426,10 +2448,13 @@ static ssize_t
2426tracing_trace_options_read(struct file *filp, char __user *ubuf, 2448tracing_trace_options_read(struct file *filp, char __user *ubuf,
2427 size_t cnt, loff_t *ppos) 2449 size_t cnt, loff_t *ppos)
2428{ 2450{
2451 int i;
2429 char *buf; 2452 char *buf;
2430 int r = 0; 2453 int r = 0;
2431 int len = 0; 2454 int len = 0;
2432 int i; 2455 u32 tracer_flags = current_trace->flags->val;
2456 struct tracer_opt *trace_opts = current_trace->flags->opts;
2457
2433 2458
2434 /* calulate max size */ 2459 /* calulate max size */
2435 for (i = 0; trace_options[i]; i++) { 2460 for (i = 0; trace_options[i]; i++) {
@@ -2437,6 +2462,15 @@ tracing_trace_options_read(struct file *filp, char __user *ubuf,
2437 len += 3; /* "no" and space */ 2462 len += 3; /* "no" and space */
2438 } 2463 }
2439 2464
2465 /*
2466 * Increase the size with names of options specific
2467 * of the current tracer.
2468 */
2469 for (i = 0; trace_opts[i].name; i++) {
2470 len += strlen(trace_opts[i].name);
2471 len += 3; /* "no" and space */
2472 }
2473
2440 /* +2 for \n and \0 */ 2474 /* +2 for \n and \0 */
2441 buf = kmalloc(len + 2, GFP_KERNEL); 2475 buf = kmalloc(len + 2, GFP_KERNEL);
2442 if (!buf) 2476 if (!buf)
@@ -2449,6 +2483,15 @@ tracing_trace_options_read(struct file *filp, char __user *ubuf,
2449 r += sprintf(buf + r, "no%s ", trace_options[i]); 2483 r += sprintf(buf + r, "no%s ", trace_options[i]);
2450 } 2484 }
2451 2485
2486 for (i = 0; trace_opts[i].name; i++) {
2487 if (tracer_flags & trace_opts[i].bit)
2488 r += sprintf(buf + r, "%s ",
2489 trace_opts[i].name);
2490 else
2491 r += sprintf(buf + r, "no%s ",
2492 trace_opts[i].name);
2493 }
2494
2452 r += sprintf(buf + r, "\n"); 2495 r += sprintf(buf + r, "\n");
2453 WARN_ON(r >= len + 2); 2496 WARN_ON(r >= len + 2);
2454 2497
@@ -2459,6 +2502,40 @@ tracing_trace_options_read(struct file *filp, char __user *ubuf,
2459 return r; 2502 return r;
2460} 2503}
2461 2504
2505/* Try to assign a tracer specific option */
2506static int set_tracer_option(struct tracer *trace, char *cmp, int neg)
2507{
2508 struct tracer_flags *trace_flags = trace->flags;
2509 struct tracer_opt *opts = NULL;
2510 int ret = 0, i = 0;
2511 int len;
2512
2513 for (i = 0; trace_flags->opts[i].name; i++) {
2514 opts = &trace_flags->opts[i];
2515 len = strlen(opts->name);
2516
2517 if (strncmp(cmp, opts->name, len) == 0) {
2518 ret = trace->set_flag(trace_flags->val,
2519 opts->bit, !neg);
2520 break;
2521 }
2522 }
2523 /* Not found */
2524 if (!trace_flags->opts[i].name)
2525 return -EINVAL;
2526
2527 /* Refused to handle */
2528 if (ret)
2529 return ret;
2530
2531 if (neg)
2532 trace_flags->val &= ~opts->bit;
2533 else
2534 trace_flags->val |= opts->bit;
2535
2536 return 0;
2537}
2538
2462static ssize_t 2539static ssize_t
2463tracing_trace_options_write(struct file *filp, const char __user *ubuf, 2540tracing_trace_options_write(struct file *filp, const char __user *ubuf,
2464 size_t cnt, loff_t *ppos) 2541 size_t cnt, loff_t *ppos)
@@ -2466,6 +2543,7 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
2466 char buf[64]; 2543 char buf[64];
2467 char *cmp = buf; 2544 char *cmp = buf;
2468 int neg = 0; 2545 int neg = 0;
2546 int ret;
2469 int i; 2547 int i;
2470 2548
2471 if (cnt >= sizeof(buf)) 2549 if (cnt >= sizeof(buf))
@@ -2492,11 +2570,13 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
2492 break; 2570 break;
2493 } 2571 }
2494 } 2572 }
2495 /* 2573
2496 * If no option could be set, return an error: 2574 /* If no option could be set, test the specific tracer options */
2497 */ 2575 if (!trace_options[i]) {
2498 if (!trace_options[i]) 2576 ret = set_tracer_option(current_trace, cmp, neg);
2499 return -EINVAL; 2577 if (ret)
2578 return ret;
2579 }
2500 2580
2501 filp->f_pos += cnt; 2581 filp->f_pos += cnt;
2502 2582
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 37947f6b92bf..9d22618bf99f 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -259,6 +259,29 @@ enum print_line_t {
259 TRACE_TYPE_UNHANDLED = 2 /* Relay to other output functions */ 259 TRACE_TYPE_UNHANDLED = 2 /* Relay to other output functions */
260}; 260};
261 261
262
263/*
264 * An option specific to a tracer. This is a boolean value.
265 * The bit is the bit index that sets its value on the
266 * flags value in struct tracer_flags.
267 */
268struct tracer_opt {
269 const char *name; /* Will appear on the trace_options file */
270 u32 bit; /* Mask assigned in val field in tracer_flags */
271};
272
273/*
274 * The set of specific options for a tracer. Your tracer
275 * have to set the initial value of the flags val.
276 */
277struct tracer_flags {
278 u32 val;
279 struct tracer_opt *opts;
280};
281
282/* Makes more easy to define a tracer opt */
283#define TRACER_OPT(s, b) .name = #s, .bit = b
284
262/* 285/*
263 * A specific tracer, represented by methods that operate on a trace array: 286 * A specific tracer, represented by methods that operate on a trace array:
264 */ 287 */
@@ -280,8 +303,11 @@ struct tracer {
280 struct trace_array *tr); 303 struct trace_array *tr);
281#endif 304#endif
282 enum print_line_t (*print_line)(struct trace_iterator *iter); 305 enum print_line_t (*print_line)(struct trace_iterator *iter);
306 /* If you handled the flag setting, return 0 */
307 int (*set_flag)(u32 old_flags, u32 bit, int set);
283 struct tracer *next; 308 struct tracer *next;
284 int print_max; 309 int print_max;
310 struct tracer_flags *flags;
285}; 311};
286 312
287struct trace_seq { 313struct trace_seq {