aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/trace/trace.c73
-rw-r--r--kernel/trace/trace.h3
2 files changed, 39 insertions, 37 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index c232d8248a0..82ced406aac 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -400,6 +400,26 @@ static void
400trace_seq_reset(struct trace_seq *s) 400trace_seq_reset(struct trace_seq *s)
401{ 401{
402 s->len = 0; 402 s->len = 0;
403 s->readpos = 0;
404}
405
406ssize_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
405static void 425static 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
2543out: 2542out:
2544 mutex_unlock(&trace_types_lock); 2543 mutex_unlock(&trace_types_lock);
2545 2544
2546 return read; 2545 return sret;
2547} 2546}
2548 2547
2549static ssize_t 2548static ssize_t
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index ee53d706066..8845033ab49 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -155,6 +155,7 @@ struct tracer {
155struct trace_seq { 155struct trace_seq {
156 unsigned char buffer[PAGE_SIZE]; 156 unsigned char buffer[PAGE_SIZE];
157 unsigned int len; 157 unsigned int len;
158 unsigned int readpos;
158}; 159};
159 160
160/* 161/*
@@ -301,6 +302,8 @@ extern int trace_selftest_startup_sched_switch(struct tracer *trace,
301 302
302extern void *head_page(struct trace_array_cpu *data); 303extern void *head_page(struct trace_array_cpu *data);
303extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...); 304extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...);
305extern ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf,
306 size_t cnt);
304extern long ns2usecs(cycle_t nsec); 307extern long ns2usecs(cycle_t nsec);
305 308
306extern unsigned long trace_flags; 309extern unsigned long trace_flags;