diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-13 14:31:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-13 14:31:28 -0400 |
commit | 8255309b887fcac11f791913a2d1d0b966a40d32 (patch) | |
tree | ae2d43366b946ab0968762a2b68cc862983db372 /kernel | |
parent | bf20753c0cdf842c5c65af688c2cefd1eafa7630 (diff) | |
parent | 44e9c8b7adc52079f0535f9de0c2c2477831389b (diff) |
Merge branch 'tracing-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'tracing-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
tracing/filters: return proper error code when writing filter file
tracing/filters: allow user input integer to be oct or hex
tracing/filters: fix NULL pointer dereference
tracing/filters: NIL-terminate user input filter
ftrace: Output REC->var instead of __entry->var for trace format
Make __stringify support variable argument macros too
tracing: fix document references
tracing: fix splice return too large
tracing: update file->f_pos when splice(2) it
tracing: allocate page when needed
tracing: disable seeking for trace_pipe_raw
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/trace/Kconfig | 4 | ||||
-rw-r--r-- | kernel/trace/trace.c | 36 | ||||
-rw-r--r-- | kernel/trace/trace_events.c | 12 | ||||
-rw-r--r-- | kernel/trace/trace_events_filter.c | 14 | ||||
-rw-r--r-- | kernel/trace/trace_events_stage_2.h | 4 |
5 files changed, 43 insertions, 27 deletions
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 2246141bda4d..417d1985e299 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig | |||
@@ -312,7 +312,7 @@ config KMEMTRACE | |||
312 | and profile kernel code. | 312 | and profile kernel code. |
313 | 313 | ||
314 | This requires an userspace application to use. See | 314 | This requires an userspace application to use. See |
315 | Documentation/vm/kmemtrace.txt for more information. | 315 | Documentation/trace/kmemtrace.txt for more information. |
316 | 316 | ||
317 | Saying Y will make the kernel somewhat larger and slower. However, | 317 | Saying Y will make the kernel somewhat larger and slower. However, |
318 | if you disable kmemtrace at run-time or boot-time, the performance | 318 | if you disable kmemtrace at run-time or boot-time, the performance |
@@ -403,7 +403,7 @@ config MMIOTRACE | |||
403 | implementation and works via page faults. Tracing is disabled by | 403 | implementation and works via page faults. Tracing is disabled by |
404 | default and can be enabled at run-time. | 404 | default and can be enabled at run-time. |
405 | 405 | ||
406 | See Documentation/tracers/mmiotrace.txt. | 406 | See Documentation/trace/mmiotrace.txt. |
407 | If you are not helping to develop drivers, say N. | 407 | If you are not helping to develop drivers, say N. |
408 | 408 | ||
409 | config MMIOTRACE_TEST | 409 | config MMIOTRACE_TEST |
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 9d28476a9851..1ce5dc6372b8 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -3277,19 +3277,13 @@ static int tracing_buffers_open(struct inode *inode, struct file *filp) | |||
3277 | 3277 | ||
3278 | info->tr = &global_trace; | 3278 | info->tr = &global_trace; |
3279 | info->cpu = cpu; | 3279 | info->cpu = cpu; |
3280 | info->spare = ring_buffer_alloc_read_page(info->tr->buffer); | 3280 | info->spare = NULL; |
3281 | /* Force reading ring buffer for first read */ | 3281 | /* Force reading ring buffer for first read */ |
3282 | info->read = (unsigned int)-1; | 3282 | info->read = (unsigned int)-1; |
3283 | if (!info->spare) | ||
3284 | goto out; | ||
3285 | 3283 | ||
3286 | filp->private_data = info; | 3284 | filp->private_data = info; |
3287 | 3285 | ||
3288 | return 0; | 3286 | return nonseekable_open(inode, filp); |
3289 | |||
3290 | out: | ||
3291 | kfree(info); | ||
3292 | return -ENOMEM; | ||
3293 | } | 3287 | } |
3294 | 3288 | ||
3295 | static ssize_t | 3289 | static ssize_t |
@@ -3304,6 +3298,11 @@ tracing_buffers_read(struct file *filp, char __user *ubuf, | |||
3304 | if (!count) | 3298 | if (!count) |
3305 | return 0; | 3299 | return 0; |
3306 | 3300 | ||
3301 | if (!info->spare) | ||
3302 | info->spare = ring_buffer_alloc_read_page(info->tr->buffer); | ||
3303 | if (!info->spare) | ||
3304 | return -ENOMEM; | ||
3305 | |||
3307 | /* Do we have previous read data to read? */ | 3306 | /* Do we have previous read data to read? */ |
3308 | if (info->read < PAGE_SIZE) | 3307 | if (info->read < PAGE_SIZE) |
3309 | goto read; | 3308 | goto read; |
@@ -3342,7 +3341,8 @@ static int tracing_buffers_release(struct inode *inode, struct file *file) | |||
3342 | { | 3341 | { |
3343 | struct ftrace_buffer_info *info = file->private_data; | 3342 | struct ftrace_buffer_info *info = file->private_data; |
3344 | 3343 | ||
3345 | ring_buffer_free_read_page(info->tr->buffer, info->spare); | 3344 | if (info->spare) |
3345 | ring_buffer_free_read_page(info->tr->buffer, info->spare); | ||
3346 | kfree(info); | 3346 | kfree(info); |
3347 | 3347 | ||
3348 | return 0; | 3348 | return 0; |
@@ -3428,14 +3428,19 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, | |||
3428 | int size, i; | 3428 | int size, i; |
3429 | size_t ret; | 3429 | size_t ret; |
3430 | 3430 | ||
3431 | /* | 3431 | if (*ppos & (PAGE_SIZE - 1)) { |
3432 | * We can't seek on a buffer input | 3432 | WARN_ONCE(1, "Ftrace: previous read must page-align\n"); |
3433 | */ | 3433 | return -EINVAL; |
3434 | if (unlikely(*ppos)) | 3434 | } |
3435 | return -ESPIPE; | ||
3436 | 3435 | ||
3436 | if (len & (PAGE_SIZE - 1)) { | ||
3437 | WARN_ONCE(1, "Ftrace: splice_read should page-align\n"); | ||
3438 | if (len < PAGE_SIZE) | ||
3439 | return -EINVAL; | ||
3440 | len &= PAGE_MASK; | ||
3441 | } | ||
3437 | 3442 | ||
3438 | for (i = 0; i < PIPE_BUFFERS && len; i++, len -= size) { | 3443 | for (i = 0; i < PIPE_BUFFERS && len; i++, len -= PAGE_SIZE) { |
3439 | struct page *page; | 3444 | struct page *page; |
3440 | int r; | 3445 | int r; |
3441 | 3446 | ||
@@ -3474,6 +3479,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, | |||
3474 | spd.partial[i].offset = 0; | 3479 | spd.partial[i].offset = 0; |
3475 | spd.partial[i].private = (unsigned long)ref; | 3480 | spd.partial[i].private = (unsigned long)ref; |
3476 | spd.nr_pages++; | 3481 | spd.nr_pages++; |
3482 | *ppos += PAGE_SIZE; | ||
3477 | } | 3483 | } |
3478 | 3484 | ||
3479 | spd.nr_pages = i; | 3485 | spd.nr_pages = i; |
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 64ec4d278ffb..576f4fa2af0d 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
@@ -503,6 +503,7 @@ event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt, | |||
503 | 503 | ||
504 | if (copy_from_user(&buf, ubuf, cnt)) | 504 | if (copy_from_user(&buf, ubuf, cnt)) |
505 | return -EFAULT; | 505 | return -EFAULT; |
506 | buf[cnt] = '\0'; | ||
506 | 507 | ||
507 | pred = kzalloc(sizeof(*pred), GFP_KERNEL); | 508 | pred = kzalloc(sizeof(*pred), GFP_KERNEL); |
508 | if (!pred) | 509 | if (!pred) |
@@ -520,9 +521,10 @@ event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt, | |||
520 | return cnt; | 521 | return cnt; |
521 | } | 522 | } |
522 | 523 | ||
523 | if (filter_add_pred(call, pred)) { | 524 | err = filter_add_pred(call, pred); |
525 | if (err < 0) { | ||
524 | filter_free_pred(pred); | 526 | filter_free_pred(pred); |
525 | return -EINVAL; | 527 | return err; |
526 | } | 528 | } |
527 | 529 | ||
528 | *ppos += cnt; | 530 | *ppos += cnt; |
@@ -569,6 +571,7 @@ subsystem_filter_write(struct file *filp, const char __user *ubuf, size_t cnt, | |||
569 | 571 | ||
570 | if (copy_from_user(&buf, ubuf, cnt)) | 572 | if (copy_from_user(&buf, ubuf, cnt)) |
571 | return -EFAULT; | 573 | return -EFAULT; |
574 | buf[cnt] = '\0'; | ||
572 | 575 | ||
573 | pred = kzalloc(sizeof(*pred), GFP_KERNEL); | 576 | pred = kzalloc(sizeof(*pred), GFP_KERNEL); |
574 | if (!pred) | 577 | if (!pred) |
@@ -586,10 +589,11 @@ subsystem_filter_write(struct file *filp, const char __user *ubuf, size_t cnt, | |||
586 | return cnt; | 589 | return cnt; |
587 | } | 590 | } |
588 | 591 | ||
589 | if (filter_add_subsystem_pred(system, pred)) { | 592 | err = filter_add_subsystem_pred(system, pred); |
593 | if (err < 0) { | ||
590 | filter_free_subsystem_preds(system); | 594 | filter_free_subsystem_preds(system); |
591 | filter_free_pred(pred); | 595 | filter_free_pred(pred); |
592 | return -EINVAL; | 596 | return err; |
593 | } | 597 | } |
594 | 598 | ||
595 | *ppos += cnt; | 599 | *ppos += cnt; |
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 026be412f356..e03cbf1e38f3 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c | |||
@@ -215,7 +215,7 @@ static int __filter_add_pred(struct ftrace_event_call *call, | |||
215 | } | 215 | } |
216 | } | 216 | } |
217 | 217 | ||
218 | return -ENOMEM; | 218 | return -ENOSPC; |
219 | } | 219 | } |
220 | 220 | ||
221 | static int is_string_field(const char *type) | 221 | static int is_string_field(const char *type) |
@@ -319,7 +319,7 @@ int filter_add_subsystem_pred(struct event_subsystem *system, | |||
319 | } | 319 | } |
320 | 320 | ||
321 | if (i == MAX_FILTER_PRED) | 321 | if (i == MAX_FILTER_PRED) |
322 | return -EINVAL; | 322 | return -ENOSPC; |
323 | 323 | ||
324 | events_for_each(call) { | 324 | events_for_each(call) { |
325 | int err; | 325 | int err; |
@@ -410,16 +410,22 @@ int filter_parse(char **pbuf, struct filter_pred *pred) | |||
410 | } | 410 | } |
411 | } | 411 | } |
412 | 412 | ||
413 | if (!val_str) { | ||
414 | pred->field_name = NULL; | ||
415 | return -EINVAL; | ||
416 | } | ||
417 | |||
413 | pred->field_name = kstrdup(pred->field_name, GFP_KERNEL); | 418 | pred->field_name = kstrdup(pred->field_name, GFP_KERNEL); |
414 | if (!pred->field_name) | 419 | if (!pred->field_name) |
415 | return -ENOMEM; | 420 | return -ENOMEM; |
416 | 421 | ||
417 | pred->val = simple_strtoull(val_str, &tmp, 10); | 422 | pred->val = simple_strtoull(val_str, &tmp, 0); |
418 | if (tmp == val_str) { | 423 | if (tmp == val_str) { |
419 | pred->str_val = kstrdup(val_str, GFP_KERNEL); | 424 | pred->str_val = kstrdup(val_str, GFP_KERNEL); |
420 | if (!pred->str_val) | 425 | if (!pred->str_val) |
421 | return -ENOMEM; | 426 | return -ENOMEM; |
422 | } | 427 | } else if (*tmp != '\0') |
428 | return -EINVAL; | ||
423 | 429 | ||
424 | return 0; | 430 | return 0; |
425 | } | 431 | } |
diff --git a/kernel/trace/trace_events_stage_2.h b/kernel/trace/trace_events_stage_2.h index 30743f7d4110..d363c6672c6c 100644 --- a/kernel/trace/trace_events_stage_2.h +++ b/kernel/trace/trace_events_stage_2.h | |||
@@ -105,10 +105,10 @@ ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \ | |||
105 | return 0; | 105 | return 0; |
106 | 106 | ||
107 | #undef __entry | 107 | #undef __entry |
108 | #define __entry "REC" | 108 | #define __entry REC |
109 | 109 | ||
110 | #undef TP_printk | 110 | #undef TP_printk |
111 | #define TP_printk(fmt, args...) "%s, %s\n", #fmt, #args | 111 | #define TP_printk(fmt, args...) "%s, %s\n", #fmt, __stringify(args) |
112 | 112 | ||
113 | #undef TP_fast_assign | 113 | #undef TP_fast_assign |
114 | #define TP_fast_assign(args...) args | 114 | #define TP_fast_assign(args...) args |