Commit a1614851 authored by Namhyung Kim's avatar Namhyung Kim Committed by sanglipeng
Browse files

perf hists browser: Fix the number of entries for 'e' key

stable inclusion
from stable-v5.10.195
commit c6dc2a2e11c28f98ce9a0a4de67a7a47f5cab9ac
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I95JOC

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=c6dc2a2e11c28f98ce9a0a4de67a7a47f5cab9ac



--------------------------------

commit f6b8436b upstream.

The 'e' key is to toggle expand/collapse the selected entry only.  But
the current code has a bug that it only increases the number of entries
by 1 in the hierarchy mode so users cannot move under the current entry
after the key stroke.  This is due to a wrong assumption in the
hist_entry__set_folding().

The commit b33f9226 ("perf hists browser: Put hist_entry folding
logic into single function") factored out the code, but actually it
should be handled separately.  The hist_browser__set_folding() is to
update fold state for each entry so it needs to traverse all (child)
entries regardless of the current fold state.  So it increases the
number of entries by 1.

But the hist_entry__set_folding() only cares the currently selected
entry and its all children.  So it should count all unfolded child
entries.  This code is implemented in hist_browser__toggle_fold()
already so we can just call it.

Fixes: b33f9226 ("perf hists browser: Put hist_entry folding logic into single function")
Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
Tested-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20230731094934.1616495-2-namhyung@kernel.org


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarsanglipeng <sanglipeng1@jd.com>
parent 73483e6e
Loading
Loading
Loading
Loading
+24 −34
Original line number Diff line number Diff line
@@ -407,11 +407,6 @@ static bool hist_browser__selection_has_children(struct hist_browser *browser)
	return container_of(ms, struct callchain_list, ms)->has_children;
}

static bool hist_browser__he_selection_unfolded(struct hist_browser *browser)
{
	return browser->he_selection ? browser->he_selection->unfolded : false;
}

static bool hist_browser__selection_unfolded(struct hist_browser *browser)
{
	struct hist_entry *he = browser->he_selection;
@@ -584,7 +579,7 @@ static int hierarchy_set_folding(struct hist_browser *hb, struct hist_entry *he,
	return n;
}

static void __hist_entry__set_folding(struct hist_entry *he,
static void hist_entry__set_folding(struct hist_entry *he,
				    struct hist_browser *hb, bool unfold)
{
	hist_entry__init_have_children(he);
@@ -603,16 +598,25 @@ static void __hist_entry__set_folding(struct hist_entry *he,
		he->nr_rows = 0;
}

static void hist_entry__set_folding(struct hist_entry *he,
				    struct hist_browser *browser, bool unfold)
static void
__hist_browser__set_folding(struct hist_browser *browser, bool unfold)
{
	struct rb_node *nd;
	struct hist_entry *he;
	double percent;

	nd = rb_first_cached(&browser->hists->entries);
	while (nd) {
		he = rb_entry(nd, struct hist_entry, rb_node);

		/* set folding state even if it's currently folded */
		nd = __rb_hierarchy_next(nd, HMD_FORCE_CHILD);

		hist_entry__set_folding(he, browser, unfold);

		percent = hist_entry__get_percent_limit(he);
		if (he->filtered || percent < browser->min_pcnt)
		return;

	__hist_entry__set_folding(he, browser, unfold);
			continue;

		if (!he->depth || unfold)
			browser->nr_hierarchy_entries++;
@@ -625,22 +629,6 @@ static void hist_entry__set_folding(struct hist_entry *he,
		} else
			he->has_no_entry = false;
	}

static void
__hist_browser__set_folding(struct hist_browser *browser, bool unfold)
{
	struct rb_node *nd;
	struct hist_entry *he;

	nd = rb_first_cached(&browser->hists->entries);
	while (nd) {
		he = rb_entry(nd, struct hist_entry, rb_node);

		/* set folding state even if it's currently folded */
		nd = __rb_hierarchy_next(nd, HMD_FORCE_CHILD);

		hist_entry__set_folding(he, browser, unfold);
	}
}

static void hist_browser__set_folding(struct hist_browser *browser, bool unfold)
@@ -659,8 +647,10 @@ static void hist_browser__set_folding_selected(struct hist_browser *browser, boo
	if (!browser->he_selection)
		return;

	hist_entry__set_folding(browser->he_selection, browser, unfold);
	browser->b.nr_entries = hist_browser__nr_entries(browser);
	if (unfold == browser->he_selection->unfolded)
		return;

	hist_browser__toggle_fold(browser);
}

static void ui_browser__warn_lost_events(struct ui_browser *browser)
@@ -731,8 +721,8 @@ static int hist_browser__handle_hotkey(struct hist_browser *browser, bool warn_l
		hist_browser__set_folding(browser, true);
		break;
	case 'e':
		/* Expand the selected entry. */
		hist_browser__set_folding_selected(browser, !hist_browser__he_selection_unfolded(browser));
		/* Toggle expand/collapse the selected entry. */
		hist_browser__toggle_fold(browser);
		break;
	case 'H':
		browser->show_headers = !browser->show_headers;