Merge tag 'for-4.21/block-20190102' of git://git.kernel.dk/linux-block
[linux] / kernel / trace / trace.c
index 51612b4..c521b73 100644 (file)
@@ -1431,7 +1431,7 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
 }
 #endif /* CONFIG_TRACER_MAX_TRACE */
 
-static int wait_on_pipe(struct trace_iterator *iter, bool full)
+static int wait_on_pipe(struct trace_iterator *iter, int full)
 {
        /* Iterators are static, they should be filled or empty */
        if (trace_buffer_iter(iter, iter->cpu_file))
@@ -2452,7 +2452,7 @@ static inline void ftrace_exports_disable(void)
        static_branch_disable(&ftrace_exports_enabled);
 }
 
-void ftrace_exports(struct ring_buffer_event *event)
+static void ftrace_exports(struct ring_buffer_event *event)
 {
        struct trace_export *export;
 
@@ -4408,13 +4408,15 @@ static int trace_set_options(struct trace_array *tr, char *option)
        int neg = 0;
        int ret;
        size_t orig_len = strlen(option);
+       int len;
 
        cmp = strstrip(option);
 
-       if (strncmp(cmp, "no", 2) == 0) {
+       len = str_has_prefix(cmp, "no");
+       if (len)
                neg = 1;
-               cmp += 2;
-       }
+
+       cmp += len;
 
        mutex_lock(&trace_types_lock);
 
@@ -4604,6 +4606,10 @@ static const char readme_msg[] =
        "\t\t\t  traces\n"
 #endif
 #endif /* CONFIG_STACK_TRACER */
+#ifdef CONFIG_DYNAMIC_EVENTS
+       "  dynamic_events\t\t- Add/remove/show the generic dynamic events\n"
+       "\t\t\t  Write into this file to define/undefine new trace events.\n"
+#endif
 #ifdef CONFIG_KPROBE_EVENTS
        "  kprobe_events\t\t- Add/remove/show the kernel dynamic events\n"
        "\t\t\t  Write into this file to define/undefine new trace events.\n"
@@ -4616,6 +4622,9 @@ static const char readme_msg[] =
        "\t  accepts: event-definitions (one definition per line)\n"
        "\t   Format: p[:[<group>/]<event>] <place> [<args>]\n"
        "\t           r[maxactive][:[<group>/]<event>] <place> [<args>]\n"
+#ifdef CONFIG_HIST_TRIGGERS
+       "\t           s:[synthetic/]<event> <field> [<field>]\n"
+#endif
        "\t           -:[<group>/]<event>\n"
 #ifdef CONFIG_KPROBE_EVENTS
        "\t    place: [<module>:]<symbol>[+<offset>]|<memaddr>\n"
@@ -4634,6 +4643,11 @@ static const char readme_msg[] =
        "\t     type: s8/16/32/64, u8/16/32/64, x8/16/32/64, string, symbol,\n"
        "\t           b<bit-width>@<bit-offset>/<container-size>,\n"
        "\t           <type>\\[<array-size>\\]\n"
+#ifdef CONFIG_HIST_TRIGGERS
+       "\t    field: <stype> <name>;\n"
+       "\t    stype: u8/u16/u32/u64, s8/s16/s32/s64, pid_t,\n"
+       "\t           [unsigned] char/int/long\n"
+#endif
 #endif
        "  events/\t\t- Directory containing all trace event subsystems:\n"
        "      enable\t\t- Write 0/1 to enable/disable tracing of all events\n"
@@ -5693,7 +5707,7 @@ static int tracing_wait_pipe(struct file *filp)
 
                mutex_unlock(&iter->mutex);
 
-               ret = wait_on_pipe(iter, false);
+               ret = wait_on_pipe(iter, 0);
 
                mutex_lock(&iter->mutex);
 
@@ -6751,7 +6765,7 @@ tracing_buffers_read(struct file *filp, char __user *ubuf,
                        if ((filp->f_flags & O_NONBLOCK))
                                return -EAGAIN;
 
-                       ret = wait_on_pipe(iter, false);
+                       ret = wait_on_pipe(iter, 0);
                        if (ret)
                                return ret;
 
@@ -6948,7 +6962,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
                if ((file->f_flags & O_NONBLOCK) || (flags & SPLICE_F_NONBLOCK))
                        goto out;
 
-               ret = wait_on_pipe(iter, true);
+               ret = wait_on_pipe(iter, iter->tr->buffer_percent);
                if (ret)
                        goto out;
 
@@ -7662,6 +7676,53 @@ static const struct file_operations rb_simple_fops = {
        .llseek         = default_llseek,
 };
 
+static ssize_t
+buffer_percent_read(struct file *filp, char __user *ubuf,
+                   size_t cnt, loff_t *ppos)
+{
+       struct trace_array *tr = filp->private_data;
+       char buf[64];
+       int r;
+
+       r = tr->buffer_percent;
+       r = sprintf(buf, "%d\n", r);
+
+       return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+}
+
+static ssize_t
+buffer_percent_write(struct file *filp, const char __user *ubuf,
+                    size_t cnt, loff_t *ppos)
+{
+       struct trace_array *tr = filp->private_data;
+       unsigned long val;
+       int ret;
+
+       ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
+       if (ret)
+               return ret;
+
+       if (val > 100)
+               return -EINVAL;
+
+       if (!val)
+               val = 1;
+
+       tr->buffer_percent = val;
+
+       (*ppos)++;
+
+       return cnt;
+}
+
+static const struct file_operations buffer_percent_fops = {
+       .open           = tracing_open_generic_tr,
+       .read           = buffer_percent_read,
+       .write          = buffer_percent_write,
+       .release        = tracing_release_generic_tr,
+       .llseek         = default_llseek,
+};
+
 struct dentry *trace_instance_dir;
 
 static void
@@ -7970,6 +8031,11 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
        trace_create_file("timestamp_mode", 0444, d_tracer, tr,
                          &trace_time_stamp_mode_fops);
 
+       tr->buffer_percent = 50;
+
+       trace_create_file("buffer_percent", 0444, d_tracer,
+                       tr, &buffer_percent_fops);
+
        create_trace_options_dir(tr);
 
 #if defined(CONFIG_TRACER_MAX_TRACE) || defined(CONFIG_HWLAT_TRACER)