diff options
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/blktrace.c | 7 | ||||
-rw-r--r-- | kernel/trace/ftrace.c | 52 | ||||
-rw-r--r-- | kernel/trace/trace_kprobe.c | 111 |
3 files changed, 158 insertions, 12 deletions
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index 153562d0b93c..d95721f33702 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c | |||
@@ -138,6 +138,13 @@ void __trace_note_message(struct blk_trace *bt, const char *fmt, ...) | |||
138 | !blk_tracer_enabled)) | 138 | !blk_tracer_enabled)) |
139 | return; | 139 | return; |
140 | 140 | ||
141 | /* | ||
142 | * If the BLK_TC_NOTIFY action mask isn't set, don't send any note | ||
143 | * message to the trace. | ||
144 | */ | ||
145 | if (!(bt->act_mask & BLK_TC_NOTIFY)) | ||
146 | return; | ||
147 | |||
141 | local_irq_save(flags); | 148 | local_irq_save(flags); |
142 | buf = per_cpu_ptr(bt->msg_data, smp_processor_id()); | 149 | buf = per_cpu_ptr(bt->msg_data, smp_processor_id()); |
143 | va_start(args, fmt); | 150 | va_start(args, fmt); |
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index f3dadae83883..888b611897d3 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
@@ -3328,7 +3328,7 @@ static int start_graph_tracing(void) | |||
3328 | /* The cpu_boot init_task->ret_stack will never be freed */ | 3328 | /* The cpu_boot init_task->ret_stack will never be freed */ |
3329 | for_each_online_cpu(cpu) { | 3329 | for_each_online_cpu(cpu) { |
3330 | if (!idle_task(cpu)->ret_stack) | 3330 | if (!idle_task(cpu)->ret_stack) |
3331 | ftrace_graph_init_task(idle_task(cpu)); | 3331 | ftrace_graph_init_idle_task(idle_task(cpu), cpu); |
3332 | } | 3332 | } |
3333 | 3333 | ||
3334 | do { | 3334 | do { |
@@ -3418,6 +3418,49 @@ void unregister_ftrace_graph(void) | |||
3418 | mutex_unlock(&ftrace_lock); | 3418 | mutex_unlock(&ftrace_lock); |
3419 | } | 3419 | } |
3420 | 3420 | ||
3421 | static DEFINE_PER_CPU(struct ftrace_ret_stack *, idle_ret_stack); | ||
3422 | |||
3423 | static void | ||
3424 | graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack) | ||
3425 | { | ||
3426 | atomic_set(&t->tracing_graph_pause, 0); | ||
3427 | atomic_set(&t->trace_overrun, 0); | ||
3428 | t->ftrace_timestamp = 0; | ||
3429 | /* make curr_ret_stack visable before we add the ret_stack */ | ||
3430 | smp_wmb(); | ||
3431 | t->ret_stack = ret_stack; | ||
3432 | } | ||
3433 | |||
3434 | /* | ||
3435 | * Allocate a return stack for the idle task. May be the first | ||
3436 | * time through, or it may be done by CPU hotplug online. | ||
3437 | */ | ||
3438 | void ftrace_graph_init_idle_task(struct task_struct *t, int cpu) | ||
3439 | { | ||
3440 | t->curr_ret_stack = -1; | ||
3441 | /* | ||
3442 | * The idle task has no parent, it either has its own | ||
3443 | * stack or no stack at all. | ||
3444 | */ | ||
3445 | if (t->ret_stack) | ||
3446 | WARN_ON(t->ret_stack != per_cpu(idle_ret_stack, cpu)); | ||
3447 | |||
3448 | if (ftrace_graph_active) { | ||
3449 | struct ftrace_ret_stack *ret_stack; | ||
3450 | |||
3451 | ret_stack = per_cpu(idle_ret_stack, cpu); | ||
3452 | if (!ret_stack) { | ||
3453 | ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH | ||
3454 | * sizeof(struct ftrace_ret_stack), | ||
3455 | GFP_KERNEL); | ||
3456 | if (!ret_stack) | ||
3457 | return; | ||
3458 | per_cpu(idle_ret_stack, cpu) = ret_stack; | ||
3459 | } | ||
3460 | graph_init_task(t, ret_stack); | ||
3461 | } | ||
3462 | } | ||
3463 | |||
3421 | /* Allocate a return stack for newly created task */ | 3464 | /* Allocate a return stack for newly created task */ |
3422 | void ftrace_graph_init_task(struct task_struct *t) | 3465 | void ftrace_graph_init_task(struct task_struct *t) |
3423 | { | 3466 | { |
@@ -3433,12 +3476,7 @@ void ftrace_graph_init_task(struct task_struct *t) | |||
3433 | GFP_KERNEL); | 3476 | GFP_KERNEL); |
3434 | if (!ret_stack) | 3477 | if (!ret_stack) |
3435 | return; | 3478 | return; |
3436 | atomic_set(&t->tracing_graph_pause, 0); | 3479 | graph_init_task(t, ret_stack); |
3437 | atomic_set(&t->trace_overrun, 0); | ||
3438 | t->ftrace_timestamp = 0; | ||
3439 | /* make curr_ret_stack visable before we add the ret_stack */ | ||
3440 | smp_wmb(); | ||
3441 | t->ret_stack = ret_stack; | ||
3442 | } | 3480 | } |
3443 | } | 3481 | } |
3444 | 3482 | ||
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 2dec9bcde8b4..8435b43b1782 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -353,6 +353,43 @@ static __kprobes void free_deref_fetch_param(struct deref_fetch_param *data) | |||
353 | kfree(data); | 353 | kfree(data); |
354 | } | 354 | } |
355 | 355 | ||
356 | /* Bitfield fetch function */ | ||
357 | struct bitfield_fetch_param { | ||
358 | struct fetch_param orig; | ||
359 | unsigned char hi_shift; | ||
360 | unsigned char low_shift; | ||
361 | }; | ||
362 | |||
363 | #define DEFINE_FETCH_bitfield(type) \ | ||
364 | static __kprobes void FETCH_FUNC_NAME(bitfield, type)(struct pt_regs *regs,\ | ||
365 | void *data, void *dest) \ | ||
366 | { \ | ||
367 | struct bitfield_fetch_param *bprm = data; \ | ||
368 | type buf = 0; \ | ||
369 | call_fetch(&bprm->orig, regs, &buf); \ | ||
370 | if (buf) { \ | ||
371 | buf <<= bprm->hi_shift; \ | ||
372 | buf >>= bprm->low_shift; \ | ||
373 | } \ | ||
374 | *(type *)dest = buf; \ | ||
375 | } | ||
376 | DEFINE_BASIC_FETCH_FUNCS(bitfield) | ||
377 | #define fetch_bitfield_string NULL | ||
378 | #define fetch_bitfield_string_size NULL | ||
379 | |||
380 | static __kprobes void | ||
381 | free_bitfield_fetch_param(struct bitfield_fetch_param *data) | ||
382 | { | ||
383 | /* | ||
384 | * Don't check the bitfield itself, because this must be the | ||
385 | * last fetch function. | ||
386 | */ | ||
387 | if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) | ||
388 | free_deref_fetch_param(data->orig.data); | ||
389 | else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) | ||
390 | free_symbol_cache(data->orig.data); | ||
391 | kfree(data); | ||
392 | } | ||
356 | /* Default (unsigned long) fetch type */ | 393 | /* Default (unsigned long) fetch type */ |
357 | #define __DEFAULT_FETCH_TYPE(t) u##t | 394 | #define __DEFAULT_FETCH_TYPE(t) u##t |
358 | #define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t) | 395 | #define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t) |
@@ -367,6 +404,7 @@ enum { | |||
367 | FETCH_MTD_memory, | 404 | FETCH_MTD_memory, |
368 | FETCH_MTD_symbol, | 405 | FETCH_MTD_symbol, |
369 | FETCH_MTD_deref, | 406 | FETCH_MTD_deref, |
407 | FETCH_MTD_bitfield, | ||
370 | FETCH_MTD_END, | 408 | FETCH_MTD_END, |
371 | }; | 409 | }; |
372 | 410 | ||
@@ -387,6 +425,7 @@ ASSIGN_FETCH_FUNC(retval, ftype), \ | |||
387 | ASSIGN_FETCH_FUNC(memory, ftype), \ | 425 | ASSIGN_FETCH_FUNC(memory, ftype), \ |
388 | ASSIGN_FETCH_FUNC(symbol, ftype), \ | 426 | ASSIGN_FETCH_FUNC(symbol, ftype), \ |
389 | ASSIGN_FETCH_FUNC(deref, ftype), \ | 427 | ASSIGN_FETCH_FUNC(deref, ftype), \ |
428 | ASSIGN_FETCH_FUNC(bitfield, ftype), \ | ||
390 | } \ | 429 | } \ |
391 | } | 430 | } |
392 | 431 | ||
@@ -430,9 +469,33 @@ static const struct fetch_type *find_fetch_type(const char *type) | |||
430 | if (!type) | 469 | if (!type) |
431 | type = DEFAULT_FETCH_TYPE_STR; | 470 | type = DEFAULT_FETCH_TYPE_STR; |
432 | 471 | ||
472 | /* Special case: bitfield */ | ||
473 | if (*type == 'b') { | ||
474 | unsigned long bs; | ||
475 | type = strchr(type, '/'); | ||
476 | if (!type) | ||
477 | goto fail; | ||
478 | type++; | ||
479 | if (strict_strtoul(type, 0, &bs)) | ||
480 | goto fail; | ||
481 | switch (bs) { | ||
482 | case 8: | ||
483 | return find_fetch_type("u8"); | ||
484 | case 16: | ||
485 | return find_fetch_type("u16"); | ||
486 | case 32: | ||
487 | return find_fetch_type("u32"); | ||
488 | case 64: | ||
489 | return find_fetch_type("u64"); | ||
490 | default: | ||
491 | goto fail; | ||
492 | } | ||
493 | } | ||
494 | |||
433 | for (i = 0; i < ARRAY_SIZE(fetch_type_table); i++) | 495 | for (i = 0; i < ARRAY_SIZE(fetch_type_table); i++) |
434 | if (strcmp(type, fetch_type_table[i].name) == 0) | 496 | if (strcmp(type, fetch_type_table[i].name) == 0) |
435 | return &fetch_type_table[i]; | 497 | return &fetch_type_table[i]; |
498 | fail: | ||
436 | return NULL; | 499 | return NULL; |
437 | } | 500 | } |
438 | 501 | ||
@@ -586,7 +649,9 @@ error: | |||
586 | 649 | ||
587 | static void free_probe_arg(struct probe_arg *arg) | 650 | static void free_probe_arg(struct probe_arg *arg) |
588 | { | 651 | { |
589 | if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn)) | 652 | if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn)) |
653 | free_bitfield_fetch_param(arg->fetch.data); | ||
654 | else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn)) | ||
590 | free_deref_fetch_param(arg->fetch.data); | 655 | free_deref_fetch_param(arg->fetch.data); |
591 | else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn)) | 656 | else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn)) |
592 | free_symbol_cache(arg->fetch.data); | 657 | free_symbol_cache(arg->fetch.data); |
@@ -767,16 +832,15 @@ static int __parse_probe_arg(char *arg, const struct fetch_type *t, | |||
767 | } | 832 | } |
768 | break; | 833 | break; |
769 | case '+': /* deref memory */ | 834 | case '+': /* deref memory */ |
835 | arg++; /* Skip '+', because strict_strtol() rejects it. */ | ||
770 | case '-': | 836 | case '-': |
771 | tmp = strchr(arg, '('); | 837 | tmp = strchr(arg, '('); |
772 | if (!tmp) | 838 | if (!tmp) |
773 | break; | 839 | break; |
774 | *tmp = '\0'; | 840 | *tmp = '\0'; |
775 | ret = strict_strtol(arg + 1, 0, &offset); | 841 | ret = strict_strtol(arg, 0, &offset); |
776 | if (ret) | 842 | if (ret) |
777 | break; | 843 | break; |
778 | if (arg[0] == '-') | ||
779 | offset = -offset; | ||
780 | arg = tmp + 1; | 844 | arg = tmp + 1; |
781 | tmp = strrchr(arg, ')'); | 845 | tmp = strrchr(arg, ')'); |
782 | if (tmp) { | 846 | if (tmp) { |
@@ -807,6 +871,41 @@ static int __parse_probe_arg(char *arg, const struct fetch_type *t, | |||
807 | return ret; | 871 | return ret; |
808 | } | 872 | } |
809 | 873 | ||
874 | #define BYTES_TO_BITS(nb) ((BITS_PER_LONG * (nb)) / sizeof(long)) | ||
875 | |||
876 | /* Bitfield type needs to be parsed into a fetch function */ | ||
877 | static int __parse_bitfield_probe_arg(const char *bf, | ||
878 | const struct fetch_type *t, | ||
879 | struct fetch_param *f) | ||
880 | { | ||
881 | struct bitfield_fetch_param *bprm; | ||
882 | unsigned long bw, bo; | ||
883 | char *tail; | ||
884 | |||
885 | if (*bf != 'b') | ||
886 | return 0; | ||
887 | |||
888 | bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); | ||
889 | if (!bprm) | ||
890 | return -ENOMEM; | ||
891 | bprm->orig = *f; | ||
892 | f->fn = t->fetch[FETCH_MTD_bitfield]; | ||
893 | f->data = (void *)bprm; | ||
894 | |||
895 | bw = simple_strtoul(bf + 1, &tail, 0); /* Use simple one */ | ||
896 | if (bw == 0 || *tail != '@') | ||
897 | return -EINVAL; | ||
898 | |||
899 | bf = tail + 1; | ||
900 | bo = simple_strtoul(bf, &tail, 0); | ||
901 | if (tail == bf || *tail != '/') | ||
902 | return -EINVAL; | ||
903 | |||
904 | bprm->hi_shift = BYTES_TO_BITS(t->size) - (bw + bo); | ||
905 | bprm->low_shift = bprm->hi_shift + bo; | ||
906 | return (BYTES_TO_BITS(t->size) < (bw + bo)) ? -EINVAL : 0; | ||
907 | } | ||
908 | |||
810 | /* String length checking wrapper */ | 909 | /* String length checking wrapper */ |
811 | static int parse_probe_arg(char *arg, struct trace_probe *tp, | 910 | static int parse_probe_arg(char *arg, struct trace_probe *tp, |
812 | struct probe_arg *parg, int is_return) | 911 | struct probe_arg *parg, int is_return) |
@@ -836,6 +935,8 @@ static int parse_probe_arg(char *arg, struct trace_probe *tp, | |||
836 | parg->offset = tp->size; | 935 | parg->offset = tp->size; |
837 | tp->size += parg->type->size; | 936 | tp->size += parg->type->size; |
838 | ret = __parse_probe_arg(arg, parg->type, &parg->fetch, is_return); | 937 | ret = __parse_probe_arg(arg, parg->type, &parg->fetch, is_return); |
938 | if (ret >= 0 && t != NULL) | ||
939 | ret = __parse_bitfield_probe_arg(t, parg->type, &parg->fetch); | ||
839 | if (ret >= 0) { | 940 | if (ret >= 0) { |
840 | parg->fetch_size.fn = get_fetch_size_function(parg->type, | 941 | parg->fetch_size.fn = get_fetch_size_function(parg->type, |
841 | parg->fetch.fn); | 942 | parg->fetch.fn); |
@@ -1130,7 +1231,7 @@ static int command_trace_probe(const char *buf) | |||
1130 | return ret; | 1231 | return ret; |
1131 | } | 1232 | } |
1132 | 1233 | ||
1133 | #define WRITE_BUFSIZE 128 | 1234 | #define WRITE_BUFSIZE 4096 |
1134 | 1235 | ||
1135 | static ssize_t probes_write(struct file *file, const char __user *buffer, | 1236 | static ssize_t probes_write(struct file *file, const char __user *buffer, |
1136 | size_t count, loff_t *ppos) | 1237 | size_t count, loff_t *ppos) |