aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r--kernel/trace/trace.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 3a89496dc99b..307524d784ec 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -339,6 +339,90 @@ void tracing_on(void)
339} 339}
340EXPORT_SYMBOL_GPL(tracing_on); 340EXPORT_SYMBOL_GPL(tracing_on);
341 341
342#ifdef CONFIG_TRACER_SNAPSHOT
343/**
344 * trace_snapshot - take a snapshot of the current buffer.
345 *
346 * This causes a swap between the snapshot buffer and the current live
347 * tracing buffer. You can use this to take snapshots of the live
348 * trace when some condition is triggered, but continue to trace.
349 *
350 * Note, make sure to allocate the snapshot with either
351 * a tracing_snapshot_alloc(), or by doing it manually
352 * with: echo 1 > /sys/kernel/debug/tracing/snapshot
353 *
354 * If the snapshot buffer is not allocated, it will stop tracing.
355 * Basically making a permanent snapshot.
356 */
357void tracing_snapshot(void)
358{
359 struct trace_array *tr = &global_trace;
360 struct tracer *tracer = tr->current_trace;
361 unsigned long flags;
362
363 if (!tr->allocated_snapshot) {
364 trace_printk("*** SNAPSHOT NOT ALLOCATED ***\n");
365 trace_printk("*** stopping trace here! ***\n");
366 tracing_off();
367 return;
368 }
369
370 /* Note, snapshot can not be used when the tracer uses it */
371 if (tracer->use_max_tr) {
372 trace_printk("*** LATENCY TRACER ACTIVE ***\n");
373 trace_printk("*** Can not use snapshot (sorry) ***\n");
374 return;
375 }
376
377 local_irq_save(flags);
378 update_max_tr(tr, current, smp_processor_id());
379 local_irq_restore(flags);
380}
381
382static int resize_buffer_duplicate_size(struct trace_buffer *trace_buf,
383 struct trace_buffer *size_buf, int cpu_id);
384
385/**
386 * trace_snapshot_alloc - allocate and take a snapshot of the current buffer.
387 *
388 * This is similar to trace_snapshot(), but it will allocate the
389 * snapshot buffer if it isn't already allocated. Use this only
390 * where it is safe to sleep, as the allocation may sleep.
391 *
392 * This causes a swap between the snapshot buffer and the current live
393 * tracing buffer. You can use this to take snapshots of the live
394 * trace when some condition is triggered, but continue to trace.
395 */
396void tracing_snapshot_alloc(void)
397{
398 struct trace_array *tr = &global_trace;
399 int ret;
400
401 if (!tr->allocated_snapshot) {
402
403 /* allocate spare buffer */
404 ret = resize_buffer_duplicate_size(&tr->max_buffer,
405 &tr->trace_buffer, RING_BUFFER_ALL_CPUS);
406 if (WARN_ON(ret < 0))
407 return;
408
409 tr->allocated_snapshot = true;
410 }
411
412 tracing_snapshot();
413}
414#else
415void tracing_snapshot(void)
416{
417 WARN_ONCE(1, "Snapshot feature not enabled, but internal snapshot used");
418}
419void tracing_snapshot_alloc(void)
420{
421 /* Give warning */
422 tracing_snapshot();
423}
424#endif /* CONFIG_TRACER_SNAPSHOT */
425
342/** 426/**
343 * tracing_off - turn off tracing buffers 427 * tracing_off - turn off tracing buffers
344 * 428 *