Skip to content

Commit 3e0bf9f

Browse files
James-A-Clarknamhyung
authored andcommitted
perf pmu: Restore full PMU name wildcard support
Commit b2b9d3a ("perf pmu: Support wildcards on pmu name in dynamic pmu events") gives the following example for wildcarding a subset of PMUs: E.g., in a system with the following dynamic pmus: mypmu_0 mypmu_1 mypmu_2 mypmu_4 perf stat -e mypmu_[01]/<config>/ Since commit f91fa2a ("perf pmu: Refactor perf_pmu__match()"), only "*" has been supported, removing the ability to subset PMUs, even though parse-events.l still supports ? and [] characters. Fix it by using fnmatch() when any glob character is detected and add a test which covers that and other scenarios of perf_pmu__match_ignoring_suffix(). Fixes: f91fa2a ("perf pmu: Refactor perf_pmu__match()") Signed-off-by: James Clark <[email protected]> Reviewed-by: Ian Rogers <[email protected]> Cc: [email protected] Signed-off-by: Namhyung Kim <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 4553c43 commit 3e0bf9f

File tree

2 files changed

+79
-1
lines changed

2 files changed

+79
-1
lines changed

tools/perf/tests/pmu.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,12 +453,90 @@ static int test__name_cmp(struct test_suite *test __maybe_unused, int subtest __
453453
return TEST_OK;
454454
}
455455

456+
/**
457+
* Test perf_pmu__match() that's used to search for a PMU given a name passed
458+
* on the command line. The name that's passed may also be a filename type glob
459+
* match.
460+
*/
461+
static int test__pmu_match(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
462+
{
463+
struct perf_pmu test_pmu;
464+
465+
test_pmu.name = "pmuname";
466+
TEST_ASSERT_EQUAL("Exact match", perf_pmu__match(&test_pmu, "pmuname"), true);
467+
TEST_ASSERT_EQUAL("Longer token", perf_pmu__match(&test_pmu, "longertoken"), false);
468+
TEST_ASSERT_EQUAL("Shorter token", perf_pmu__match(&test_pmu, "pmu"), false);
469+
470+
test_pmu.name = "pmuname_10";
471+
TEST_ASSERT_EQUAL("Diff suffix_", perf_pmu__match(&test_pmu, "pmuname_2"), false);
472+
TEST_ASSERT_EQUAL("Sub suffix_", perf_pmu__match(&test_pmu, "pmuname_1"), true);
473+
TEST_ASSERT_EQUAL("Same suffix_", perf_pmu__match(&test_pmu, "pmuname_10"), true);
474+
TEST_ASSERT_EQUAL("No suffix_", perf_pmu__match(&test_pmu, "pmuname"), true);
475+
TEST_ASSERT_EQUAL("Underscore_", perf_pmu__match(&test_pmu, "pmuname_"), true);
476+
TEST_ASSERT_EQUAL("Substring_", perf_pmu__match(&test_pmu, "pmuna"), false);
477+
478+
test_pmu.name = "pmuname_ab23";
479+
TEST_ASSERT_EQUAL("Diff suffix hex_", perf_pmu__match(&test_pmu, "pmuname_2"), false);
480+
TEST_ASSERT_EQUAL("Sub suffix hex_", perf_pmu__match(&test_pmu, "pmuname_ab"), true);
481+
TEST_ASSERT_EQUAL("Same suffix hex_", perf_pmu__match(&test_pmu, "pmuname_ab23"), true);
482+
TEST_ASSERT_EQUAL("No suffix hex_", perf_pmu__match(&test_pmu, "pmuname"), true);
483+
TEST_ASSERT_EQUAL("Underscore hex_", perf_pmu__match(&test_pmu, "pmuname_"), true);
484+
TEST_ASSERT_EQUAL("Substring hex_", perf_pmu__match(&test_pmu, "pmuna"), false);
485+
486+
test_pmu.name = "pmuname10";
487+
TEST_ASSERT_EQUAL("Diff suffix", perf_pmu__match(&test_pmu, "pmuname2"), false);
488+
TEST_ASSERT_EQUAL("Sub suffix", perf_pmu__match(&test_pmu, "pmuname1"), true);
489+
TEST_ASSERT_EQUAL("Same suffix", perf_pmu__match(&test_pmu, "pmuname10"), true);
490+
TEST_ASSERT_EQUAL("No suffix", perf_pmu__match(&test_pmu, "pmuname"), true);
491+
TEST_ASSERT_EQUAL("Underscore", perf_pmu__match(&test_pmu, "pmuname_"), false);
492+
TEST_ASSERT_EQUAL("Substring", perf_pmu__match(&test_pmu, "pmuna"), false);
493+
494+
test_pmu.name = "pmunameab23";
495+
TEST_ASSERT_EQUAL("Diff suffix hex", perf_pmu__match(&test_pmu, "pmuname2"), false);
496+
TEST_ASSERT_EQUAL("Sub suffix hex", perf_pmu__match(&test_pmu, "pmunameab"), true);
497+
TEST_ASSERT_EQUAL("Same suffix hex", perf_pmu__match(&test_pmu, "pmunameab23"), true);
498+
TEST_ASSERT_EQUAL("No suffix hex", perf_pmu__match(&test_pmu, "pmuname"), true);
499+
TEST_ASSERT_EQUAL("Underscore hex", perf_pmu__match(&test_pmu, "pmuname_"), false);
500+
TEST_ASSERT_EQUAL("Substring hex", perf_pmu__match(&test_pmu, "pmuna"), false);
501+
502+
/*
503+
* 2 hex chars or less are not considered suffixes so it shouldn't be
504+
* possible to wildcard by skipping the suffix. Therefore there are more
505+
* false results here than above.
506+
*/
507+
test_pmu.name = "pmuname_a3";
508+
TEST_ASSERT_EQUAL("Diff suffix 2 hex_", perf_pmu__match(&test_pmu, "pmuname_2"), false);
509+
/*
510+
* This one should be false, but because pmuname_a3 ends in 3 which is
511+
* decimal, it's not possible to determine if it's a short hex suffix or
512+
* a normal decimal suffix following text. And we want to match on any
513+
* length of decimal suffix. Run the test anyway and expect the wrong
514+
* result. And slightly fuzzy matching shouldn't do too much harm.
515+
*/
516+
TEST_ASSERT_EQUAL("Sub suffix 2 hex_", perf_pmu__match(&test_pmu, "pmuname_a"), true);
517+
TEST_ASSERT_EQUAL("Same suffix 2 hex_", perf_pmu__match(&test_pmu, "pmuname_a3"), true);
518+
TEST_ASSERT_EQUAL("No suffix 2 hex_", perf_pmu__match(&test_pmu, "pmuname"), false);
519+
TEST_ASSERT_EQUAL("Underscore 2 hex_", perf_pmu__match(&test_pmu, "pmuname_"), false);
520+
TEST_ASSERT_EQUAL("Substring 2 hex_", perf_pmu__match(&test_pmu, "pmuna"), false);
521+
522+
test_pmu.name = "pmuname_5";
523+
TEST_ASSERT_EQUAL("Glob 1", perf_pmu__match(&test_pmu, "pmu*"), true);
524+
TEST_ASSERT_EQUAL("Glob 2", perf_pmu__match(&test_pmu, "nomatch*"), false);
525+
TEST_ASSERT_EQUAL("Seq 1", perf_pmu__match(&test_pmu, "pmuname_[12345]"), true);
526+
TEST_ASSERT_EQUAL("Seq 2", perf_pmu__match(&test_pmu, "pmuname_[67890]"), false);
527+
TEST_ASSERT_EQUAL("? 1", perf_pmu__match(&test_pmu, "pmuname_?"), true);
528+
TEST_ASSERT_EQUAL("? 2", perf_pmu__match(&test_pmu, "pmuname_1?"), false);
529+
530+
return TEST_OK;
531+
}
532+
456533
static struct test_case tests__pmu[] = {
457534
TEST_CASE("Parsing with PMU format directory", pmu_format),
458535
TEST_CASE("Parsing with PMU event", pmu_events),
459536
TEST_CASE("PMU event names", pmu_event_names),
460537
TEST_CASE("PMU name combining", name_len),
461538
TEST_CASE("PMU name comparison", name_cmp),
539+
TEST_CASE("PMU cmdline match", pmu_match),
462540
{ .name = NULL, }
463541
};
464542

tools/perf/util/pmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2150,7 +2150,7 @@ void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config,
21502150
bool perf_pmu__match(const struct perf_pmu *pmu, const char *tok)
21512151
{
21522152
const char *name = pmu->name;
2153-
bool need_fnmatch = strchr(tok, '*') != NULL;
2153+
bool need_fnmatch = strisglob(tok);
21542154

21552155
if (!strncmp(tok, "uncore_", 7))
21562156
tok += 7;

0 commit comments

Comments
 (0)