Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f9ec2e6f authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf tooling fixes from Ingo Molnar:
 "This contains five tooling fixes:

   - fix a remaining mmap2 assumption which resulted in perf top output
     breakage
   - fix mmap ring-buffer processing bug that corrupts data
   - fix for a severe python scripting memory leak
   - fix broken (and user-visible) -g option handling
   - fix stdio output

  The diffstat size is larger than what we'd like to see this late :-/"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  perf tools: Fixup mmap event consumption
  perf top: Split -G and --call-graph
  perf record: Split -g and --call-graph
  perf hists: Add color overhead for stdio output buffer
  perf tools: Fix up /proc/PID/maps parsing
  perf script python: Fix mem leak due to missing Py_DECREFs on dict entries
parents 2a999aa0 cd657187
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -90,8 +90,20 @@ OPTIONS
	Number of mmap data pages. Must be a power of two.

-g::
	Enables call-graph (stack chain/backtrace) recording.

--call-graph::
	Do call-graph (stack chain/backtrace) recording.
	Setup and enable call-graph (stack chain/backtrace) recording,
	implies -g.

	Allows specifying "fp" (frame pointer) or "dwarf"
	(DWARF's CFI - Call Frame Information) as the method to collect
	the information used to show the call graphs.

	In some systems, where binaries are build with gcc
	--fomit-frame-pointer, using the "fp" method will produce bogus
	call graphs, using "dwarf", if available (perf tools linked to
	the libunwind library) should be used instead.

-q::
--quiet::
+5 −13
Original line number Diff line number Diff line
@@ -140,20 +140,12 @@ Default is to monitor all CPUS.
--asm-raw::
	Show raw instruction encoding of assembly instructions.

-G [type,min,order]::
-G::
	Enables call-graph (stack chain/backtrace) recording.

--call-graph::
        Display call chains using type, min percent threshold and order.
	type can be either:
	- flat: single column, linear exposure of call chains.
	- graph: use a graph tree, displaying absolute overhead rates.
	- fractal: like graph, but displays relative rates. Each branch of
		 the tree is considered as a new profiled object.

	order can be either:
	- callee: callee based call graph.
	- caller: inverted caller based call graph.

	Default: fractal,0.5,callee.
	Setup and enable call-graph (stack chain/backtrace) recording,
	implies -G.

--ignore-callees=<regex>::
        Ignore callees of the function(s) matching the given regex.
+7 −0
Original line number Diff line number Diff line
@@ -888,11 +888,18 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
	while ((event = perf_evlist__mmap_read(kvm->evlist, idx)) != NULL) {
		err = perf_evlist__parse_sample(kvm->evlist, event, &sample);
		if (err) {
			perf_evlist__mmap_consume(kvm->evlist, idx);
			pr_err("Failed to parse sample\n");
			return -1;
		}

		err = perf_session_queue_event(kvm->session, event, &sample, 0);
		/*
		 * FIXME: Here we can't consume the event, as perf_session_queue_event will
		 *        point to it, and it'll get possibly overwritten by the kernel.
		 */
		perf_evlist__mmap_consume(kvm->evlist, idx);

		if (err) {
			pr_err("Failed to enqueue sample: %d\n", err);
			return -1;
+51 −22
Original line number Diff line number Diff line
@@ -712,21 +712,12 @@ static int get_stack_size(char *str, unsigned long *_size)
}
#endif /* LIBUNWIND_SUPPORT */

int record_parse_callchain_opt(const struct option *opt,
			       const char *arg, int unset)
int record_parse_callchain(const char *arg, struct perf_record_opts *opts)
{
	struct perf_record_opts *opts = opt->value;
	char *tok, *name, *saveptr = NULL;
	char *buf;
	int ret = -1;

	/* --no-call-graph */
	if (unset)
		return 0;

	/* We specified default option if none is provided. */
	BUG_ON(!arg);

	/* We need buffer that we know we can write to. */
	buf = malloc(strlen(arg) + 1);
	if (!buf)
@@ -764,13 +755,9 @@ int record_parse_callchain_opt(const struct option *opt,
				ret = get_stack_size(tok, &size);
				opts->stack_dump_size = size;
			}

			if (!ret)
				pr_debug("callchain: stack dump size %d\n",
					 opts->stack_dump_size);
#endif /* LIBUNWIND_SUPPORT */
		} else {
			pr_err("callchain: Unknown -g option "
			pr_err("callchain: Unknown --call-graph option "
			       "value: %s\n", arg);
			break;
		}
@@ -778,13 +765,52 @@ int record_parse_callchain_opt(const struct option *opt,
	} while (0);

	free(buf);
	return ret;
}

	if (!ret)
static void callchain_debug(struct perf_record_opts *opts)
{
	pr_debug("callchain: type %d\n", opts->call_graph);

	if (opts->call_graph == CALLCHAIN_DWARF)
		pr_debug("callchain: stack dump size %d\n",
			 opts->stack_dump_size);
}

int record_parse_callchain_opt(const struct option *opt,
			       const char *arg,
			       int unset)
{
	struct perf_record_opts *opts = opt->value;
	int ret;

	/* --no-call-graph */
	if (unset) {
		opts->call_graph = CALLCHAIN_NONE;
		pr_debug("callchain: disabled\n");
		return 0;
	}

	ret = record_parse_callchain(arg, opts);
	if (!ret)
		callchain_debug(opts);

	return ret;
}

int record_callchain_opt(const struct option *opt,
			 const char *arg __maybe_unused,
			 int unset __maybe_unused)
{
	struct perf_record_opts *opts = opt->value;

	if (opts->call_graph == CALLCHAIN_NONE)
		opts->call_graph = CALLCHAIN_FP;

	callchain_debug(opts);
	return 0;
}

static const char * const record_usage[] = {
	"perf record [<options>] [<command>]",
	"perf record [<options>] -- <command> [<options>]",
@@ -813,12 +839,12 @@ static struct perf_record record = {
	},
};

#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: "

#ifdef LIBUNWIND_SUPPORT
const char record_callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf";
#else
const char record_callchain_help[] = CALLCHAIN_HELP "[fp]";
const char record_callchain_help[] = CALLCHAIN_HELP "fp";
#endif

/*
@@ -858,9 +884,12 @@ const struct option record_options[] = {
		     "number of mmap data pages"),
	OPT_BOOLEAN(0, "group", &record.opts.group,
		    "put the counters into a counter group"),
	OPT_CALLBACK_DEFAULT('g', "call-graph", &record.opts,
	OPT_CALLBACK_NOOPT('g', NULL, &record.opts,
			   NULL, "enables call-graph recording" ,
			   &record_callchain_opt),
	OPT_CALLBACK(0, "call-graph", &record.opts,
		     "mode[,dump_size]", record_callchain_help,
			     &record_parse_callchain_opt, "fp"),
		     &record_parse_callchain_opt),
	OPT_INCR('v', "verbose", &verbose,
		    "be more verbose (show counter open errors, etc)"),
	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
+19 −14
Original line number Diff line number Diff line
@@ -810,7 +810,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
		ret = perf_evlist__parse_sample(top->evlist, event, &sample);
		if (ret) {
			pr_err("Can't parse sample, err = %d\n", ret);
			continue;
			goto next_event;
		}

		evsel = perf_evlist__id2evsel(session->evlist, sample.id);
@@ -825,13 +825,13 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
		case PERF_RECORD_MISC_USER:
			++top->us_samples;
			if (top->hide_user_symbols)
				continue;
				goto next_event;
			machine = &session->machines.host;
			break;
		case PERF_RECORD_MISC_KERNEL:
			++top->kernel_samples;
			if (top->hide_kernel_symbols)
				continue;
				goto next_event;
			machine = &session->machines.host;
			break;
		case PERF_RECORD_MISC_GUEST_KERNEL:
@@ -847,7 +847,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
			 */
			/* Fall thru */
		default:
			continue;
			goto next_event;
		}


@@ -859,6 +859,8 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
			machine__process_event(machine, event);
		} else
			++session->stats.nr_unknown_events;
next_event:
		perf_evlist__mmap_consume(top->evlist, idx);
	}
}

@@ -1016,16 +1018,16 @@ static int __cmd_top(struct perf_top *top)
}

static int
parse_callchain_opt(const struct option *opt, const char *arg, int unset)
callchain_opt(const struct option *opt, const char *arg, int unset)
{
	/*
	 * --no-call-graph
	 */
	if (unset)
		return 0;

	symbol_conf.use_callchain = true;
	return record_callchain_opt(opt, arg, unset);
}

static int
parse_callchain_opt(const struct option *opt, const char *arg, int unset)
{
	symbol_conf.use_callchain = true;
	return record_parse_callchain_opt(opt, arg, unset);
}

@@ -1106,9 +1108,12 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
		   "sort by key(s): pid, comm, dso, symbol, parent, weight, local_weight"),
	OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
		    "Show a column with the number of samples"),
	OPT_CALLBACK_DEFAULT('G', "call-graph", &top.record_opts,
	OPT_CALLBACK_NOOPT('G', NULL, &top.record_opts,
			   NULL, "enables call-graph recording",
			   &callchain_opt),
	OPT_CALLBACK(0, "call-graph", &top.record_opts,
		     "mode[,dump_size]", record_callchain_help,
			     &parse_callchain_opt, "fp"),
		     &parse_callchain_opt),
	OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
		   "ignore callees of these functions in call graphs",
		   report_parse_ignore_callees_opt),
Loading