]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - tools/perf/util/record.c
perf record: Fix crash in pipe mode
[linux.git] / tools / perf / util / record.c
index 1e97937b03a933890e7101ecad982c99e564836c..9cfc7bf165316b30b191593bcf2d27ddd37f017d 100644 (file)
@@ -5,6 +5,7 @@
 #include "parse-events.h"
 #include <errno.h>
 #include <api/fs/fs.h>
+#include <subcmd/parse-options.h>
 #include "util.h"
 #include "cloexec.h"
 
@@ -137,6 +138,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
        struct perf_evsel *evsel;
        bool use_sample_identifier = false;
        bool use_comm_exec;
+       bool sample_id = opts->sample_id;
 
        /*
         * Set the evsel leader links before we configure attributes,
@@ -163,8 +165,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
                 * match the id.
                 */
                use_sample_identifier = perf_can_sample_identifier();
-               evlist__for_each_entry(evlist, evsel)
-                       perf_evsel__set_sample_id(evsel, use_sample_identifier);
+               sample_id = true;
        } else if (evlist->nr_entries > 1) {
                struct perf_evsel *first = perf_evlist__first(evlist);
 
@@ -174,6 +175,10 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
                        use_sample_identifier = perf_can_sample_identifier();
                        break;
                }
+               sample_id = true;
+       }
+
+       if (sample_id) {
                evlist__for_each_entry(evlist, evsel)
                        perf_evsel__set_sample_id(evsel, use_sample_identifier);
        }
@@ -215,11 +220,21 @@ static int record_opts__config_freq(struct record_opts *opts)
         * User specified frequency is over current maximum.
         */
        if (user_freq && (max_rate < opts->freq)) {
-               pr_err("Maximum frequency rate (%u) reached.\n"
-                  "Please use -F freq option with lower value or consider\n"
-                  "tweaking /proc/sys/kernel/perf_event_max_sample_rate.\n",
-                  max_rate);
-               return -1;
+               if (opts->strict_freq) {
+                       pr_err("error: Maximum frequency rate (%'u Hz) exceeded.\n"
+                              "       Please use -F freq option with a lower value or consider\n"
+                              "       tweaking /proc/sys/kernel/perf_event_max_sample_rate.\n",
+                              max_rate);
+                       return -1;
+               } else {
+                       pr_warning("warning: Maximum frequency rate (%'u Hz) exceeded, throttling from %'u Hz to %'u Hz.\n"
+                                  "         The limit can be raised via /proc/sys/kernel/perf_event_max_sample_rate.\n"
+                                  "         The kernel will lower it when perf's interrupts take too long.\n"
+                                  "         Use --strict-freq to disable this throttling, refusing to record.\n",
+                                  max_rate, opts->freq, max_rate);
+
+                       opts->freq = max_rate;
+               }
        }
 
        /*
@@ -287,3 +302,25 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
        perf_evlist__delete(temp_evlist);
        return ret;
 }
+
+int record__parse_freq(const struct option *opt, const char *str, int unset __maybe_unused)
+{
+       unsigned int freq;
+       struct record_opts *opts = opt->value;
+
+       if (!str)
+               return -EINVAL;
+
+       if (strcasecmp(str, "max") == 0) {
+               if (get_max_rate(&freq)) {
+                       pr_err("couldn't read /proc/sys/kernel/perf_event_max_sample_rate\n");
+                       return -1;
+               }
+               pr_info("info: Using a maximum frequency rate of %'d Hz\n", freq);
+       } else {
+               freq = atoi(str);
+       }
+
+       opts->user_freq = freq;
+       return 0;
+}