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