diff options
author | Pekka Paalanen <pq@iki.fi> | 2008-05-12 15:21:02 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2008-05-23 16:02:13 -0400 |
commit | 6c6c27969a4c6024e6c8838829546c02aaddca18 (patch) | |
tree | 95158673881e53373ec4e7d92ff0c0e0f34be30f /kernel/trace/trace.c | |
parent | 2bb6f8d6389cbfadd657e7dc069f6986abf35e4f (diff) |
ftrace: add readpos to struct trace_seq; add trace_seq_to_user()
Refactor code from tracing_read_pipe() and create trace_seq_to_user().
Moved trace_seq_reset() call before iter->trace->read() call so that
when all leftover data is returned, trace_seq is reset automatically.
Signed-off-by: Pekka Paalanen <pq@iki.fi>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r-- | kernel/trace/trace.c | 73 |
1 files changed, 36 insertions, 37 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index c232d8248a09..82ced406aacf 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -400,6 +400,26 @@ static void | |||
400 | trace_seq_reset(struct trace_seq *s) | 400 | trace_seq_reset(struct trace_seq *s) |
401 | { | 401 | { |
402 | s->len = 0; | 402 | s->len = 0; |
403 | s->readpos = 0; | ||
404 | } | ||
405 | |||
406 | ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, size_t cnt) | ||
407 | { | ||
408 | int len; | ||
409 | int ret; | ||
410 | |||
411 | if (s->len <= s->readpos) | ||
412 | return -EBUSY; | ||
413 | |||
414 | len = s->len - s->readpos; | ||
415 | if (cnt > len) | ||
416 | cnt = len; | ||
417 | ret = copy_to_user(ubuf, s->buffer + s->readpos, cnt); | ||
418 | if (ret) | ||
419 | return -EFAULT; | ||
420 | |||
421 | s->readpos += len; | ||
422 | return cnt; | ||
403 | } | 423 | } |
404 | 424 | ||
405 | static void | 425 | static void |
@@ -2361,46 +2381,32 @@ tracing_read_pipe(struct file *filp, char __user *ubuf, | |||
2361 | struct trace_iterator *iter = filp->private_data; | 2381 | struct trace_iterator *iter = filp->private_data; |
2362 | struct trace_array_cpu *data; | 2382 | struct trace_array_cpu *data; |
2363 | static cpumask_t mask; | 2383 | static cpumask_t mask; |
2364 | static int start; | ||
2365 | unsigned long flags; | 2384 | unsigned long flags; |
2366 | #ifdef CONFIG_FTRACE | 2385 | #ifdef CONFIG_FTRACE |
2367 | int ftrace_save; | 2386 | int ftrace_save; |
2368 | #endif | 2387 | #endif |
2369 | int read = 0; | ||
2370 | int cpu; | 2388 | int cpu; |
2371 | int len; | 2389 | ssize_t sret; |
2372 | int ret; | ||
2373 | 2390 | ||
2374 | /* return any leftover data */ | 2391 | /* return any leftover data */ |
2375 | if (iter->seq.len > start) { | 2392 | sret = trace_seq_to_user(&iter->seq, ubuf, cnt); |
2376 | len = iter->seq.len - start; | 2393 | if (sret != -EBUSY) |
2377 | if (cnt > len) | 2394 | return sret; |
2378 | cnt = len; | 2395 | sret = 0; |
2379 | ret = copy_to_user(ubuf, iter->seq.buffer + start, cnt); | ||
2380 | if (ret) | ||
2381 | cnt = -EFAULT; | ||
2382 | |||
2383 | start += len; | ||
2384 | 2396 | ||
2385 | return cnt; | 2397 | trace_seq_reset(&iter->seq); |
2386 | } | ||
2387 | 2398 | ||
2388 | mutex_lock(&trace_types_lock); | 2399 | mutex_lock(&trace_types_lock); |
2389 | if (iter->trace->read) { | 2400 | if (iter->trace->read) { |
2390 | ret = iter->trace->read(iter, filp, ubuf, cnt, ppos); | 2401 | sret = iter->trace->read(iter, filp, ubuf, cnt, ppos); |
2391 | if (ret) { | 2402 | if (sret) |
2392 | read = ret; | ||
2393 | goto out; | 2403 | goto out; |
2394 | } | ||
2395 | } | 2404 | } |
2396 | 2405 | ||
2397 | trace_seq_reset(&iter->seq); | ||
2398 | start = 0; | ||
2399 | |||
2400 | while (trace_empty(iter)) { | 2406 | while (trace_empty(iter)) { |
2401 | 2407 | ||
2402 | if ((filp->f_flags & O_NONBLOCK)) { | 2408 | if ((filp->f_flags & O_NONBLOCK)) { |
2403 | read = -EAGAIN; | 2409 | sret = -EAGAIN; |
2404 | goto out; | 2410 | goto out; |
2405 | } | 2411 | } |
2406 | 2412 | ||
@@ -2426,7 +2432,7 @@ tracing_read_pipe(struct file *filp, char __user *ubuf, | |||
2426 | iter->tr->waiter = NULL; | 2432 | iter->tr->waiter = NULL; |
2427 | 2433 | ||
2428 | if (signal_pending(current)) { | 2434 | if (signal_pending(current)) { |
2429 | read = -EINTR; | 2435 | sret = -EINTR; |
2430 | goto out; | 2436 | goto out; |
2431 | } | 2437 | } |
2432 | 2438 | ||
@@ -2496,6 +2502,7 @@ tracing_read_pipe(struct file *filp, char __user *ubuf, | |||
2496 | } | 2502 | } |
2497 | 2503 | ||
2498 | while (find_next_entry_inc(iter) != NULL) { | 2504 | while (find_next_entry_inc(iter) != NULL) { |
2505 | int ret; | ||
2499 | int len = iter->seq.len; | 2506 | int len = iter->seq.len; |
2500 | 2507 | ||
2501 | ret = print_trace_line(iter); | 2508 | ret = print_trace_line(iter); |
@@ -2526,24 +2533,16 @@ tracing_read_pipe(struct file *filp, char __user *ubuf, | |||
2526 | local_irq_restore(flags); | 2533 | local_irq_restore(flags); |
2527 | 2534 | ||
2528 | /* Now copy what we have to the user */ | 2535 | /* Now copy what we have to the user */ |
2529 | read = iter->seq.len; | 2536 | sret = trace_seq_to_user(&iter->seq, ubuf, cnt); |
2530 | if (read > cnt) | 2537 | if (iter->seq.readpos >= iter->seq.len) |
2531 | read = cnt; | ||
2532 | |||
2533 | ret = copy_to_user(ubuf, iter->seq.buffer, read); | ||
2534 | |||
2535 | if (read < iter->seq.len) | ||
2536 | start = read; | ||
2537 | else | ||
2538 | trace_seq_reset(&iter->seq); | 2538 | trace_seq_reset(&iter->seq); |
2539 | 2539 | if (sret == -EBUSY) | |
2540 | if (ret) | 2540 | sret = 0; |
2541 | read = -EFAULT; | ||
2542 | 2541 | ||
2543 | out: | 2542 | out: |
2544 | mutex_unlock(&trace_types_lock); | 2543 | mutex_unlock(&trace_types_lock); |
2545 | 2544 | ||
2546 | return read; | 2545 | return sret; |
2547 | } | 2546 | } |
2548 | 2547 | ||
2549 | static ssize_t | 2548 | static ssize_t |