Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf test pmu: Test all sysfs PMU event names are the same case

Being either lower or upper case means event name probes can avoid
scanning the directory doing case insensitive comparisons, just the
lower or upper case version of the name can be checked for
existence.

For the majority of PMUs event names are all lower case, upper case
names are present on S390.

Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Thomas Richter <tmricht@linux.ibm.com>
Link: https://lore.kernel.org/r/20240502213507.2339733-6-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
6debc5aa 18eb2ca8

+90
+90
tools/perf/tests/pmu.c
··· 5 5 #include "pmu.h" 6 6 #include "tests.h" 7 7 #include "debug.h" 8 + #include "fncache.h" 9 + #include <api/fs/fs.h> 10 + #include <ctype.h> 11 + #include <dirent.h> 8 12 #include <errno.h> 9 13 #include <fcntl.h> 10 14 #include <stdio.h> 11 15 #include <stdlib.h> 12 16 #include <unistd.h> 13 17 #include <sys/stat.h> 18 + #include <sys/types.h> 14 19 15 20 /* Fake PMUs created in temp directory. */ 16 21 static LIST_HEAD(test_pmus); ··· 256 251 return ret; 257 252 } 258 253 254 + static bool permitted_event_name(const char *name) 255 + { 256 + bool has_lower = false, has_upper = false; 257 + 258 + for (size_t i = 0; i < strlen(name); i++) { 259 + char c = name[i]; 260 + 261 + if (islower(c)) { 262 + if (has_upper) 263 + return false; 264 + has_lower = true; 265 + continue; 266 + } 267 + if (isupper(c)) { 268 + if (has_lower) 269 + return false; 270 + has_upper = true; 271 + continue; 272 + } 273 + if (!isdigit(c) && c != '.' && c != '_' && c != '-') 274 + return false; 275 + } 276 + return true; 277 + } 278 + 279 + static int test__pmu_event_names(struct test_suite *test __maybe_unused, 280 + int subtest __maybe_unused) 281 + { 282 + char path[PATH_MAX]; 283 + DIR *pmu_dir, *event_dir; 284 + struct dirent *pmu_dent, *event_dent; 285 + const char *sysfs = sysfs__mountpoint(); 286 + int ret = TEST_OK; 287 + 288 + if (!sysfs) { 289 + pr_err("Sysfs not mounted\n"); 290 + return TEST_FAIL; 291 + } 292 + 293 + snprintf(path, sizeof(path), "%s/bus/event_source/devices/", sysfs); 294 + pmu_dir = opendir(path); 295 + if (!pmu_dir) { 296 + pr_err("Error opening \"%s\"\n", path); 297 + return TEST_FAIL; 298 + } 299 + while ((pmu_dent = readdir(pmu_dir))) { 300 + if (!strcmp(pmu_dent->d_name, ".") || 301 + !strcmp(pmu_dent->d_name, "..")) 302 + continue; 303 + 304 + snprintf(path, sizeof(path), "%s/bus/event_source/devices/%s/type", 305 + sysfs, pmu_dent->d_name); 306 + 307 + /* Does it look like a PMU? */ 308 + if (!file_available(path)) 309 + continue; 310 + 311 + /* Process events. */ 312 + snprintf(path, sizeof(path), "%s/bus/event_source/devices/%s/events", 313 + sysfs, pmu_dent->d_name); 314 + 315 + event_dir = opendir(path); 316 + if (!event_dir) { 317 + pr_debug("Skipping as no event directory \"%s\"\n", path); 318 + continue; 319 + } 320 + while ((event_dent = readdir(event_dir))) { 321 + const char *event_name = event_dent->d_name; 322 + 323 + if (!strcmp(event_name, ".") || !strcmp(event_name, "..")) 324 + continue; 325 + 326 + if (!permitted_event_name(event_name)) { 327 + pr_err("Invalid sysfs event name: %s/%s\n", 328 + pmu_dent->d_name, event_name); 329 + ret = TEST_FAIL; 330 + } 331 + } 332 + closedir(event_dir); 333 + } 334 + closedir(pmu_dir); 335 + return ret; 336 + } 337 + 259 338 static struct test_case tests__pmu[] = { 260 339 TEST_CASE("Parsing with PMU format directory", pmu_format), 261 340 TEST_CASE("Parsing with PMU event", pmu_events), 341 + TEST_CASE("PMU event names", pmu_event_names), 262 342 { .name = NULL, } 263 343 }; 264 344