1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/err.h> 3 #include "perf.h" 4 #include "evlist.h" 5 #include "evsel.h" 6 #include "thread_map.h" 7 #include "tests.h" 8 #include "debug.h" 9 #include <errno.h> 10 11 #ifndef O_DIRECTORY 12 #define O_DIRECTORY 00200000 13 #endif 14 #ifndef AT_FDCWD 15 #define AT_FDCWD -100 16 #endif 17 18 int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest __maybe_unused) 19 { 20 struct record_opts opts = { 21 .target = { 22 .uid = UINT_MAX, 23 .uses_mmap = true, 24 }, 25 .no_buffering = true, 26 .freq = 1, 27 .mmap_pages = 256, 28 .raw_samples = true, 29 }; 30 const char *filename = "/etc/passwd"; 31 int flags = O_RDONLY | O_DIRECTORY; 32 struct perf_evlist *evlist = perf_evlist__new(); 33 struct perf_evsel *evsel; 34 int err = -1, i, nr_events = 0, nr_polls = 0; 35 char sbuf[STRERR_BUFSIZE]; 36 37 if (evlist == NULL) { 38 pr_debug("%s: perf_evlist__new\n", __func__); 39 goto out; 40 } 41 42 evsel = perf_evsel__newtp("syscalls", "sys_enter_openat"); 43 if (IS_ERR(evsel)) { 44 pr_debug("%s: perf_evsel__newtp\n", __func__); 45 goto out_delete_evlist; 46 } 47 48 perf_evlist__add(evlist, evsel); 49 50 err = perf_evlist__create_maps(evlist, &opts.target); 51 if (err < 0) { 52 pr_debug("%s: perf_evlist__create_maps\n", __func__); 53 goto out_delete_evlist; 54 } 55 56 perf_evsel__config(evsel, &opts, NULL); 57 58 thread_map__set_pid(evlist->threads, 0, getpid()); 59 60 err = perf_evlist__open(evlist); 61 if (err < 0) { 62 pr_debug("perf_evlist__open: %s\n", 63 str_error_r(errno, sbuf, sizeof(sbuf))); 64 goto out_delete_evlist; 65 } 66 67 err = perf_evlist__mmap(evlist, UINT_MAX, false); 68 if (err < 0) { 69 pr_debug("perf_evlist__mmap: %s\n", 70 str_error_r(errno, sbuf, sizeof(sbuf))); 71 goto out_delete_evlist; 72 } 73 74 perf_evlist__enable(evlist); 75 76 /* 77 * Generate the event: 78 */ 79 openat(AT_FDCWD, filename, flags); 80 81 while (1) { 82 int before = nr_events; 83 84 for (i = 0; i < evlist->nr_mmaps; i++) { 85 union perf_event *event; 86 87 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 88 const u32 type = event->header.type; 89 int tp_flags; 90 struct perf_sample sample; 91 92 ++nr_events; 93 94 if (type != PERF_RECORD_SAMPLE) { 95 perf_evlist__mmap_consume(evlist, i); 96 continue; 97 } 98 99 err = perf_evsel__parse_sample(evsel, event, &sample); 100 if (err) { 101 pr_debug("Can't parse sample, err = %d\n", err); 102 goto out_delete_evlist; 103 } 104 105 tp_flags = perf_evsel__intval(evsel, &sample, "flags"); 106 107 if (flags != tp_flags) { 108 pr_debug("%s: Expected flags=%#x, got %#x\n", 109 __func__, flags, tp_flags); 110 goto out_delete_evlist; 111 } 112 113 goto out_ok; 114 } 115 } 116 117 if (nr_events == before) 118 perf_evlist__poll(evlist, 10); 119 120 if (++nr_polls > 5) { 121 pr_debug("%s: no events!\n", __func__); 122 goto out_delete_evlist; 123 } 124 } 125 out_ok: 126 err = 0; 127 out_delete_evlist: 128 perf_evlist__delete(evlist); 129 out: 130 return err; 131 } 132