139 lines · c
1// SPDX-License-Identifier: GPL-2.02#include <errno.h>3#include <inttypes.h>4/* For the CPU_* macros */5#include <sched.h>6 7#include <sys/types.h>8#include <sys/stat.h>9#include <fcntl.h>10#include <api/fs/fs.h>11#include <linux/err.h>12#include <linux/string.h>13#include <api/fs/tracing_path.h>14#include "evsel.h"15#include "tests.h"16#include "thread_map.h"17#include <perf/cpumap.h>18#include "debug.h"19#include "stat.h"20#include "util/counts.h"21 22static int test__openat_syscall_event_on_all_cpus(struct test_suite *test __maybe_unused,23 int subtest __maybe_unused)24{25 int err = TEST_FAIL, fd, idx;26 struct perf_cpu cpu;27 struct perf_cpu_map *cpus;28 struct evsel *evsel;29 unsigned int nr_openat_calls = 111, i;30 cpu_set_t cpu_set;31 struct perf_thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);32 char sbuf[STRERR_BUFSIZE];33 char errbuf[BUFSIZ];34 35 if (threads == NULL) {36 pr_debug("thread_map__new\n");37 return -1;38 }39 40 cpus = perf_cpu_map__new_online_cpus();41 if (cpus == NULL) {42 pr_debug("perf_cpu_map__new\n");43 goto out_thread_map_delete;44 }45 46 CPU_ZERO(&cpu_set);47 48 evsel = evsel__newtp("syscalls", "sys_enter_openat");49 if (IS_ERR(evsel)) {50 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "syscalls", "sys_enter_openat");51 pr_debug("%s\n", errbuf);52 err = TEST_SKIP;53 goto out_cpu_map_delete;54 }55 56 if (evsel__open(evsel, cpus, threads) < 0) {57 pr_debug("failed to open counter: %s, "58 "tweak /proc/sys/kernel/perf_event_paranoid?\n",59 str_error_r(errno, sbuf, sizeof(sbuf)));60 err = TEST_SKIP;61 goto out_evsel_delete;62 }63 64 perf_cpu_map__for_each_cpu(cpu, idx, cpus) {65 unsigned int ncalls = nr_openat_calls + idx;66 /*67 * XXX eventually lift this restriction in a way that68 * keeps perf building on older glibc installations69 * without CPU_ALLOC. 1024 cpus in 2010 still seems70 * a reasonable upper limit tho :-)71 */72 if (cpu.cpu >= CPU_SETSIZE) {73 pr_debug("Ignoring CPU %d\n", cpu.cpu);74 continue;75 }76 77 CPU_SET(cpu.cpu, &cpu_set);78 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {79 pr_debug("sched_setaffinity() failed on CPU %d: %s ",80 cpu.cpu,81 str_error_r(errno, sbuf, sizeof(sbuf)));82 goto out_close_fd;83 }84 for (i = 0; i < ncalls; ++i) {85 fd = openat(0, "/etc/passwd", O_RDONLY);86 close(fd);87 }88 CPU_CLR(cpu.cpu, &cpu_set);89 }90 91 evsel->core.cpus = perf_cpu_map__get(cpus);92 93 err = TEST_OK;94 95 perf_cpu_map__for_each_cpu(cpu, idx, cpus) {96 unsigned int expected;97 98 if (cpu.cpu >= CPU_SETSIZE)99 continue;100 101 if (evsel__read_on_cpu(evsel, idx, 0) < 0) {102 pr_debug("evsel__read_on_cpu\n");103 err = TEST_FAIL;104 break;105 }106 107 expected = nr_openat_calls + idx;108 if (perf_counts(evsel->counts, idx, 0)->val != expected) {109 pr_debug("evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n",110 expected, cpu.cpu, perf_counts(evsel->counts, idx, 0)->val);111 err = TEST_FAIL;112 }113 }114 115 evsel__free_counts(evsel);116out_close_fd:117 perf_evsel__close_fd(&evsel->core);118out_evsel_delete:119 evsel__delete(evsel);120out_cpu_map_delete:121 perf_cpu_map__put(cpus);122out_thread_map_delete:123 perf_thread_map__put(threads);124 return err;125}126 127 128static struct test_case tests__openat_syscall_event_on_all_cpus[] = {129 TEST_CASE_REASON("Detect openat syscall event on all cpus",130 openat_syscall_event_on_all_cpus,131 "permissions"),132 { .name = NULL, }133};134 135struct test_suite suite__openat_syscall_event_on_all_cpus = {136 .desc = "Detect openat syscall event on all cpus",137 .test_cases = tests__openat_syscall_event_on_all_cpus,138};139