Merge tag 'trace-v5.15-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 9 Sep 2021 20:11:15 +0000 (13:11 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 9 Sep 2021 20:11:15 +0000 (13:11 -0700)
Pull more tracing updates from Steven Rostedt:

 - Add migrate-disable counter to tracing header

 - Fix error handling in event probes

 - Fix missed unlock in osnoise in error path

 - Fix merge issue with tools/bootconfig

 - Clean up bootconfig data when init memory is removed

 - Fix bootconfig to loop only on subkeys

 - Have kernel command lines override bootconfig options

 - Increase field counts for synthetic events

 - Have histograms dynamic allocate event elements to save space

 - Fixes in testing and documentation

* tag 'trace-v5.15-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace:
  tracing/boot: Fix to loop on only subkeys
  selftests/ftrace: Exclude "(fault)" in testing add/remove eprobe events
  tracing: Dynamically allocate the per-elt hist_elt_data array
  tracing: synth events: increase max fields count
  tools/bootconfig: Show whole test command for each test case
  bootconfig: Fix missing return check of xbc_node_compose_key function
  tools/bootconfig: Fix tracing_on option checking in ftrace2bconf.sh
  docs: bootconfig: Add how to use bootconfig for kernel parameters
  init/bootconfig: Reorder init parameter from bootconfig and cmdline
  init: bootconfig: Remove all bootconfig data when the init memory is removed
  tracing/osnoise: Fix missed cpus_read_unlock() in start_per_cpu_kthreads()
  tracing: Fix some alloc_event_probe() error handling bugs
  tracing: Add migrate-disabled counter to tracing output.

14 files changed:
Documentation/admin-guide/bootconfig.rst
init/main.c
kernel/trace/trace.c
kernel/trace/trace_boot.c
kernel/trace/trace_eprobe.c
kernel/trace/trace_events.c
kernel/trace/trace_events_hist.c
kernel/trace/trace_osnoise.c
kernel/trace/trace_output.c
kernel/trace/trace_synth.h
tools/bootconfig/main.c
tools/bootconfig/scripts/ftrace2bconf.sh
tools/bootconfig/test-bootconfig.sh
tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc

index 6a79f2e..a1860fc 100644 (file)
@@ -178,7 +178,7 @@ update the boot loader and the kernel image itself as long as the boot
 loader passes the correct initrd file size. If by any chance, the boot
 loader passes a longer size, the kernel fails to find the bootconfig data.
 
-To do this operation, Linux kernel provides "bootconfig" command under
+To do this operation, Linux kernel provides ``bootconfig`` command under
 tools/bootconfig, which allows admin to apply or delete the config file
 to/from initrd image. You can build it by the following command::
 
@@ -196,6 +196,43 @@ To remove the config from the image, you can use -d option as below::
 Then add "bootconfig" on the normal kernel command line to tell the
 kernel to look for the bootconfig at the end of the initrd file.
 
+
+Kernel parameters via Boot Config
+=================================
+
+In addition to the kernel command line, the boot config can be used for
+passing the kernel parameters. All the key-value pairs under ``kernel``
+key will be passed to kernel cmdline directly. Moreover, the key-value
+pairs under ``init`` will be passed to init process via the cmdline.
+The parameters are concatinated with user-given kernel cmdline string
+as the following order, so that the command line parameter can override
+bootconfig parameters (this depends on how the subsystem handles parameters
+but in general, earlier parameter will be overwritten by later one.)::
+
+ [bootconfig params][cmdline params] -- [bootconfig init params][cmdline init params]
+
+Here is an example of the bootconfig file for kernel/init parameters.::
+
+ kernel {
+   root = 01234567-89ab-cdef-0123-456789abcd
+ }
+ init {
+  splash
+ }
+
+This will be copied into the kernel cmdline string as the following::
+
+ root="01234567-89ab-cdef-0123-456789abcd" -- splash
+
+If user gives some other command line like,::
+
+ ro bootconfig -- quiet
+
+The final kernel cmdline will be the following::
+
+ root="01234567-89ab-cdef-0123-456789abcd" ro bootconfig -- splash quiet
+
+
 Config File Limitation
 ======================
 
index 733e147..5c9a48d 100644 (file)
@@ -153,10 +153,10 @@ static char *extra_init_args;
 #ifdef CONFIG_BOOT_CONFIG
 /* Is bootconfig on command line? */
 static bool bootconfig_found;
-static bool initargs_found;
+static size_t initargs_offs;
 #else
 # define bootconfig_found false
-# define initargs_found false
+# define initargs_offs 0
 #endif
 
 static char *execute_command;
@@ -422,9 +422,9 @@ static void __init setup_boot_config(void)
        if (IS_ERR(err) || !bootconfig_found)
                return;
 
-       /* parse_args() stops at '--' and returns an address */
+       /* parse_args() stops at the next param of '--' and returns an address */
        if (err)
-               initargs_found = true;
+               initargs_offs = err - tmp_cmdline;
 
        if (!data) {
                pr_err("'bootconfig' found on command line, but no bootconfig found\n");
@@ -468,7 +468,12 @@ static void __init setup_boot_config(void)
        return;
 }
 
-#else
+static void __init exit_boot_config(void)
+{
+       xbc_destroy_all();
+}
+
+#else  /* !CONFIG_BOOT_CONFIG */
 
 static void __init setup_boot_config(void)
 {
@@ -481,7 +486,11 @@ static int __init warn_bootconfig(char *str)
        pr_warn("WARNING: 'bootconfig' found on the kernel command line but CONFIG_BOOT_CONFIG is not set.\n");
        return 0;
 }
-#endif
+
+#define exit_boot_config()     do {} while (0)
+
+#endif /* CONFIG_BOOT_CONFIG */
+
 early_param("bootconfig", warn_bootconfig);
 
 /* Change NUL term back to "=", to make "param" the whole string. */
@@ -646,16 +655,21 @@ static void __init setup_command_line(char *command_line)
                 * Append supplemental init boot args to saved_command_line
                 * so that user can check what command line options passed
                 * to init.
+                * The order should always be
+                * " -- "[bootconfig init-param][cmdline init-param]
                 */
-               len = strlen(saved_command_line);
-               if (initargs_found) {
-                       saved_command_line[len++] = ' ';
+               if (initargs_offs) {
+                       len = xlen + initargs_offs;
+                       strcpy(saved_command_line + len, extra_init_args);
+                       len += ilen - 4;        /* strlen(extra_init_args) */
+                       strcpy(saved_command_line + len,
+                               boot_command_line + initargs_offs - 1);
                } else {
+                       len = strlen(saved_command_line);
                        strcpy(saved_command_line + len, " -- ");
                        len += 4;
+                       strcpy(saved_command_line + len, extra_init_args);
                }
-
-               strcpy(saved_command_line + len, extra_init_args);
        }
 }
 
@@ -1494,6 +1508,7 @@ static int __ref kernel_init(void *unused)
        kprobe_free_init_mem();
        ftrace_free_init_mem();
        kgdb_free_init_mem();
+       exit_boot_config();
        free_initmem();
        mark_readonly();
 
index 2dbf797..7896d30 100644 (file)
@@ -2603,6 +2603,15 @@ enum print_line_t trace_handle_return(struct trace_seq *s)
 }
 EXPORT_SYMBOL_GPL(trace_handle_return);
 
+static unsigned short migration_disable_value(void)
+{
+#if defined(CONFIG_SMP)
+       return current->migration_disabled;
+#else
+       return 0;
+#endif
+}
+
 unsigned int tracing_gen_ctx_irq_test(unsigned int irqs_status)
 {
        unsigned int trace_flags = irqs_status;
@@ -2621,7 +2630,8 @@ unsigned int tracing_gen_ctx_irq_test(unsigned int irqs_status)
                trace_flags |= TRACE_FLAG_NEED_RESCHED;
        if (test_preempt_need_resched())
                trace_flags |= TRACE_FLAG_PREEMPT_RESCHED;
-       return (trace_flags << 16) | (pc & 0xff);
+       return (trace_flags << 16) | (min_t(unsigned int, pc & 0xff, 0xf)) |
+               (min_t(unsigned int, migration_disable_value(), 0xf)) << 4;
 }
 
 struct ring_buffer_event *
@@ -4189,9 +4199,10 @@ static void print_lat_help_header(struct seq_file *m)
                    "#                  | / _----=> need-resched    \n"
                    "#                  || / _---=> hardirq/softirq \n"
                    "#                  ||| / _--=> preempt-depth   \n"
-                   "#                  |||| /     delay            \n"
-                   "#  cmd     pid     ||||| time  |   caller      \n"
-                   "#     \\   /        |||||  \\    |   /         \n");
+                   "#                  |||| / _-=> migrate-disable \n"
+                   "#                  ||||| /     delay           \n"
+                   "#  cmd     pid     |||||| time  |   caller     \n"
+                   "#     \\   /        ||||||  \\    |    /       \n");
 }
 
 static void print_event_info(struct array_buffer *buf, struct seq_file *m)
@@ -4229,9 +4240,10 @@ static void print_func_help_header_irq(struct array_buffer *buf, struct seq_file
        seq_printf(m, "#                            %.*s / _----=> need-resched\n", prec, space);
        seq_printf(m, "#                            %.*s| / _---=> hardirq/softirq\n", prec, space);
        seq_printf(m, "#                            %.*s|| / _--=> preempt-depth\n", prec, space);
-       seq_printf(m, "#                            %.*s||| /     delay\n", prec, space);
-       seq_printf(m, "#           TASK-PID  %.*s CPU#  ||||   TIMESTAMP  FUNCTION\n", prec, "     TGID   ");
-       seq_printf(m, "#              | |    %.*s   |   ||||      |         |\n", prec, "       |    ");
+       seq_printf(m, "#                            %.*s||| / _-=> migrate-disable\n", prec, space);
+       seq_printf(m, "#                            %.*s|||| /     delay\n", prec, space);
+       seq_printf(m, "#           TASK-PID  %.*s CPU#  |||||  TIMESTAMP  FUNCTION\n", prec, "     TGID   ");
+       seq_printf(m, "#              | |    %.*s   |   |||||     |         |\n", prec, "       |    ");
 }
 
 void
index 1060b04..388e65d 100644 (file)
@@ -522,14 +522,14 @@ trace_boot_init_events(struct trace_array *tr, struct xbc_node *node)
        if (!node)
                return;
        /* per-event key starts with "event.GROUP.EVENT" */
-       xbc_node_for_each_child(node, gnode) {
+       xbc_node_for_each_subkey(node, gnode) {
                data = xbc_node_get_data(gnode);
                if (!strcmp(data, "enable")) {
                        enable_all = true;
                        continue;
                }
                enable = false;
-               xbc_node_for_each_child(gnode, enode) {
+               xbc_node_for_each_subkey(gnode, enode) {
                        data = xbc_node_get_data(enode);
                        if (!strcmp(data, "enable")) {
                                enable = true;
@@ -625,7 +625,7 @@ trace_boot_init_instances(struct xbc_node *node)
        if (!node)
                return;
 
-       xbc_node_for_each_child(node, inode) {
+       xbc_node_for_each_subkey(node, inode) {
                p = xbc_node_get_data(inode);
                if (!p || *p == '\0')
                        continue;
index 56a96e9..3044b76 100644 (file)
@@ -151,7 +151,7 @@ static struct trace_eprobe *alloc_event_probe(const char *group,
 
        ep = kzalloc(struct_size(ep, tp.args, nargs), GFP_KERNEL);
        if (!ep) {
-               trace_event_put_ref(ep->event);
+               trace_event_put_ref(event);
                goto error;
        }
        ep->event = event;
@@ -851,7 +851,8 @@ static int __trace_eprobe_create(int argc, const char *argv[])
                ret = PTR_ERR(ep);
                /* This must return -ENOMEM, else there is a bug */
                WARN_ON_ONCE(ret != -ENOMEM);
-               goto error;     /* We know ep is not allocated */
+               ep = NULL;
+               goto error;
        }
 
        argc -= 2; argv += 2;
index 1349b6d..830b3b9 100644 (file)
@@ -181,6 +181,7 @@ static int trace_define_common_fields(void)
 
        __common_field(unsigned short, type);
        __common_field(unsigned char, flags);
+       /* Holds both preempt_count and migrate_disable */
        __common_field(unsigned char, preempt_count);
        __common_field(int, pid);
 
index 9d91b1c..a6061a6 100644 (file)
@@ -508,7 +508,8 @@ struct track_data {
 struct hist_elt_data {
        char *comm;
        u64 *var_ref_vals;
-       char *field_var_str[SYNTH_FIELDS_MAX];
+       char **field_var_str;
+       int n_field_var_str;
 };
 
 struct snapshot_context {
@@ -1401,9 +1402,11 @@ static void hist_elt_data_free(struct hist_elt_data *elt_data)
 {
        unsigned int i;
 
-       for (i = 0; i < SYNTH_FIELDS_MAX; i++)
+       for (i = 0; i < elt_data->n_field_var_str; i++)
                kfree(elt_data->field_var_str[i]);
 
+       kfree(elt_data->field_var_str);
+
        kfree(elt_data->comm);
        kfree(elt_data);
 }
@@ -1451,6 +1454,13 @@ static int hist_trigger_elt_data_alloc(struct tracing_map_elt *elt)
 
        size = STR_VAR_LEN_MAX;
 
+       elt_data->field_var_str = kcalloc(n_str, sizeof(char *), GFP_KERNEL);
+       if (!elt_data->field_var_str) {
+               hist_elt_data_free(elt_data);
+               return -EINVAL;
+       }
+       elt_data->n_field_var_str = n_str;
+
        for (i = 0; i < n_str; i++) {
                elt_data->field_var_str[i] = kzalloc(size, GFP_KERNEL);
                if (!elt_data->field_var_str[i]) {
index 65b08b8..ce05361 100644 (file)
@@ -1548,7 +1548,7 @@ static int start_kthread(unsigned int cpu)
 static int start_per_cpu_kthreads(struct trace_array *tr)
 {
        struct cpumask *current_mask = &save_cpumask;
-       int retval;
+       int retval = 0;
        int cpu;
 
        cpus_read_lock();
@@ -1568,13 +1568,13 @@ static int start_per_cpu_kthreads(struct trace_array *tr)
                retval = start_kthread(cpu);
                if (retval) {
                        stop_per_cpu_kthreads();
-                       return retval;
+                       break;
                }
        }
 
        cpus_read_unlock();
 
-       return 0;
+       return retval;
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
index a0bf446..c2ca40e 100644 (file)
@@ -492,8 +492,13 @@ int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry)
        trace_seq_printf(s, "%c%c%c",
                         irqs_off, need_resched, hardsoft_irq);
 
-       if (entry->preempt_count)
-               trace_seq_printf(s, "%x", entry->preempt_count);
+       if (entry->preempt_count & 0xf)
+               trace_seq_printf(s, "%x", entry->preempt_count & 0xf);
+       else
+               trace_seq_putc(s, '.');
+
+       if (entry->preempt_count & 0xf0)
+               trace_seq_printf(s, "%x", entry->preempt_count >> 4);
        else
                trace_seq_putc(s, '.');
 
@@ -656,7 +661,7 @@ int trace_print_lat_context(struct trace_iterator *iter)
                trace_seq_printf(
                        s, "%16s %7d %3d %d %08x %08lx ",
                        comm, entry->pid, iter->cpu, entry->flags,
-                       entry->preempt_count, iter->idx);
+                       entry->preempt_count & 0xf, iter->idx);
        } else {
                lat_print_generic(s, entry, iter->cpu);
        }
index 4007fe9..b29595f 100644 (file)
@@ -5,7 +5,7 @@
 #include "trace_dynevent.h"
 
 #define SYNTH_SYSTEM           "synthetic"
-#define SYNTH_FIELDS_MAX       32
+#define SYNTH_FIELDS_MAX       64
 
 #define STR_VAR_LEN_MAX                MAX_FILTER_STR_VAL /* must be multiple of sizeof(u64) */
 
index f45fa99..fd67496 100644 (file)
@@ -111,9 +111,11 @@ static void xbc_show_list(void)
        char key[XBC_KEYLEN_MAX];
        struct xbc_node *leaf;
        const char *val;
+       int ret;
 
        xbc_for_each_key_value(leaf, val) {
-               if (xbc_node_compose_key(leaf, key, XBC_KEYLEN_MAX) < 0) {
+               ret = xbc_node_compose_key(leaf, key, XBC_KEYLEN_MAX);
+               if (ret < 0) {
                        fprintf(stderr, "Failed to compose key %d\n", ret);
                        break;
                }
index fbaf07d..6183b36 100755 (executable)
@@ -239,8 +239,8 @@ instance_options() { # [instance-name]
                emit_kv $PREFIX.cpumask = $val
        fi
        val=`cat $INSTANCE/tracing_on`
-       if [ `echo $val | sed -e s/f//g`x != x ]; then
-               emit_kv $PREFIX.tracing_on = $val
+       if [ "$val" = "0" ]; then
+               emit_kv $PREFIX.tracing_on = 0
        fi
 
        val=`cat $INSTANCE/current_tracer`
index baed891..f68e2e9 100755 (executable)
@@ -26,7 +26,7 @@ trap cleanup EXIT TERM
 NO=1
 
 xpass() { # pass test command
-  echo "test case $NO ($3)... "
+  echo "test case $NO ($*)... "
   if ! ($@ && echo "\t\t[OK]"); then
      echo "\t\t[NG]"; NG=$((NG + 1))
   fi
@@ -34,7 +34,7 @@ xpass() { # pass test command
 }
 
 xfail() { # fail test command
-  echo "test case $NO ($3)... "
+  echo "test case $NO ($*)... "
   if ! (! $@ && echo "\t\t[OK]"); then
      echo "\t\t[NG]"; NG=$((NG + 1))
   fi
index 25a3da4..5f5b2ba 100644 (file)
@@ -22,7 +22,7 @@ ls
 echo 0 > events/eprobes/$EPROBE/enable
 
 content=`grep '^ *ls-' trace | grep 'file='`
-nocontent=`grep '^ *ls-' trace | grep 'file=' | grep -v -e '"/' -e '"."'` || true
+nocontent=`grep '^ *ls-' trace | grep 'file=' | grep -v -e '"/' -e '"."' -e '(fault)' ` || true
 
 if [ -z "$content" ]; then
        exit_fail