openat-syscall-all-cpus.c 3.5 KB

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