ring-buffer: Check if buffer exists before polling
[platform/adaptation/renesas_rcar/renesas_kernel.git] / kernel / trace / trace.c
index 815c878..922657f 100644 (file)
@@ -1091,13 +1091,13 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
 }
 #endif /* CONFIG_TRACER_MAX_TRACE */
 
-static void default_wait_pipe(struct trace_iterator *iter)
+static int default_wait_pipe(struct trace_iterator *iter)
 {
        /* Iterators are static, they should be filled or empty */
        if (trace_buffer_iter(iter, iter->cpu_file))
-               return;
+               return 0;
 
-       ring_buffer_wait(iter->trace_buffer->buffer, iter->cpu_file);
+       return ring_buffer_wait(iter->trace_buffer->buffer, iter->cpu_file);
 }
 
 #ifdef CONFIG_FTRACE_STARTUP_TEST
@@ -1355,7 +1355,6 @@ void tracing_start(void)
 
        arch_spin_unlock(&ftrace_max_lock);
 
-       ftrace_start();
  out:
        raw_spin_unlock_irqrestore(&global_trace.start_lock, flags);
 }
@@ -1402,7 +1401,6 @@ void tracing_stop(void)
        struct ring_buffer *buffer;
        unsigned long flags;
 
-       ftrace_stop();
        raw_spin_lock_irqsave(&global_trace.start_lock, flags);
        if (global_trace.stop_count++)
                goto out;
@@ -1449,12 +1447,12 @@ static void tracing_stop_tr(struct trace_array *tr)
 
 void trace_stop_cmdline_recording(void);
 
-static void trace_save_cmdline(struct task_struct *tsk)
+static int trace_save_cmdline(struct task_struct *tsk)
 {
        unsigned pid, idx;
 
        if (!tsk->pid || unlikely(tsk->pid > PID_MAX_DEFAULT))
-               return;
+               return 0;
 
        /*
         * It's not the end of the world if we don't get
@@ -1463,7 +1461,7 @@ static void trace_save_cmdline(struct task_struct *tsk)
         * so if we miss here, then better luck next time.
         */
        if (!arch_spin_trylock(&trace_cmdline_lock))
-               return;
+               return 0;
 
        idx = map_pid_to_cmdline[tsk->pid];
        if (idx == NO_CMDLINE_MAP) {
@@ -1488,6 +1486,8 @@ static void trace_save_cmdline(struct task_struct *tsk)
        memcpy(&saved_cmdlines[idx], tsk->comm, TASK_COMM_LEN);
 
        arch_spin_unlock(&trace_cmdline_lock);
+
+       return 1;
 }
 
 void trace_find_cmdline(int pid, char comm[])
@@ -1529,9 +1529,8 @@ void tracing_record_cmdline(struct task_struct *tsk)
        if (!__this_cpu_read(trace_cmdline_save))
                return;
 
-       __this_cpu_write(trace_cmdline_save, false);
-
-       trace_save_cmdline(tsk);
+       if (trace_save_cmdline(tsk))
+               __this_cpu_write(trace_cmdline_save, false);
 }
 
 void
@@ -1600,15 +1599,31 @@ void trace_buffer_unlock_commit(struct ring_buffer *buffer,
 }
 EXPORT_SYMBOL_GPL(trace_buffer_unlock_commit);
 
+static struct ring_buffer *temp_buffer;
+
 struct ring_buffer_event *
 trace_event_buffer_lock_reserve(struct ring_buffer **current_rb,
                          struct ftrace_event_file *ftrace_file,
                          int type, unsigned long len,
                          unsigned long flags, int pc)
 {
+       struct ring_buffer_event *entry;
+
        *current_rb = ftrace_file->tr->trace_buffer.buffer;
-       return trace_buffer_lock_reserve(*current_rb,
+       entry = trace_buffer_lock_reserve(*current_rb,
                                         type, len, flags, pc);
+       /*
+        * If tracing is off, but we have triggers enabled
+        * we still need to look at the event data. Use the temp_buffer
+        * to store the trace event for the tigger to use. It's recusive
+        * safe and will not be recorded anywhere.
+        */
+       if (!entry && ftrace_file->flags & FTRACE_EVENT_FL_TRIGGER_COND) {
+               *current_rb = temp_buffer;
+               entry = trace_buffer_lock_reserve(*current_rb,
+                                                 type, len, flags, pc);
+       }
+       return entry;
 }
 EXPORT_SYMBOL_GPL(trace_event_buffer_lock_reserve);
 
@@ -4145,17 +4160,19 @@ tracing_poll_pipe(struct file *filp, poll_table *poll_table)
  *
  *     Anyway, this is really very primitive wakeup.
  */
-void poll_wait_pipe(struct trace_iterator *iter)
+int poll_wait_pipe(struct trace_iterator *iter)
 {
        set_current_state(TASK_INTERRUPTIBLE);
        /* sleep for 100 msecs, and try again. */
        schedule_timeout(HZ / 10);
+       return 0;
 }
 
 /* Must be called with trace_types_lock mutex held. */
 static int tracing_wait_pipe(struct file *filp)
 {
        struct trace_iterator *iter = filp->private_data;
+       int ret;
 
        while (trace_empty(iter)) {
 
@@ -4165,10 +4182,13 @@ static int tracing_wait_pipe(struct file *filp)
 
                mutex_unlock(&iter->mutex);
 
-               iter->trace->wait_pipe(iter);
+               ret = iter->trace->wait_pipe(iter);
 
                mutex_lock(&iter->mutex);
 
+               if (ret)
+                       return ret;
+
                if (signal_pending(current))
                        return -EINTR;
 
@@ -5096,8 +5116,12 @@ tracing_buffers_read(struct file *filp, char __user *ubuf,
                                goto out_unlock;
                        }
                        mutex_unlock(&trace_types_lock);
-                       iter->trace->wait_pipe(iter);
+                       ret = iter->trace->wait_pipe(iter);
                        mutex_lock(&trace_types_lock);
+                       if (ret) {
+                               size = ret;
+                               goto out_unlock;
+                       }
                        if (signal_pending(current)) {
                                size = -EINTR;
                                goto out_unlock;
@@ -5309,8 +5333,10 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
                        goto out;
                }
                mutex_unlock(&trace_types_lock);
-               iter->trace->wait_pipe(iter);
+               ret = iter->trace->wait_pipe(iter);
                mutex_lock(&trace_types_lock);
+               if (ret)
+                       goto out;
                if (signal_pending(current)) {
                        ret = -EINTR;
                        goto out;
@@ -6494,11 +6520,16 @@ __init static int tracer_alloc_buffers(void)
 
        raw_spin_lock_init(&global_trace.start_lock);
 
+       /* Used for event triggers */
+       temp_buffer = ring_buffer_alloc(PAGE_SIZE, RB_FL_OVERWRITE);
+       if (!temp_buffer)
+               goto out_free_cpumask;
+
        /* TODO: make the number of buffers hot pluggable with CPUS */
        if (allocate_trace_buffers(&global_trace, ring_buf_size) < 0) {
                printk(KERN_ERR "tracer: failed to allocate ring buffer!\n");
                WARN_ON(1);
-               goto out_free_cpumask;
+               goto out_free_temp_buffer;
        }
 
        if (global_trace.buffer_disabled)
@@ -6540,6 +6571,8 @@ __init static int tracer_alloc_buffers(void)
 
        return 0;
 
+out_free_temp_buffer:
+       ring_buffer_free(temp_buffer);
 out_free_cpumask:
        free_percpu(global_trace.trace_buffer.data);
 #ifdef CONFIG_TRACER_MAX_TRACE