1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Test backward bit in event attribute, read ring buffer from end to 4 * beginning 5 */ 6 7 #include <evlist.h> 8 #include <sys/prctl.h> 9 #include "record.h" 10 #include "tests.h" 11 #include "debug.h" 12 #include <errno.h> 13 #include <linux/string.h> 14 15 #define NR_ITERS 111 16 17 static void testcase(void) 18 { 19 int i; 20 21 for (i = 0; i < NR_ITERS; i++) { 22 char proc_name[15]; 23 24 snprintf(proc_name, sizeof(proc_name), "p:%d\n", i); 25 prctl(PR_SET_NAME, proc_name); 26 } 27 } 28 29 static int count_samples(struct evlist *evlist, int *sample_count, 30 int *comm_count) 31 { 32 int i; 33 34 for (i = 0; i < evlist->nr_mmaps; i++) { 35 struct perf_mmap *map = &evlist->overwrite_mmap[i]; 36 union perf_event *event; 37 38 perf_mmap__read_init(map); 39 while ((event = perf_mmap__read_event(map)) != NULL) { 40 const u32 type = event->header.type; 41 42 switch (type) { 43 case PERF_RECORD_SAMPLE: 44 (*sample_count)++; 45 break; 46 case PERF_RECORD_COMM: 47 (*comm_count)++; 48 break; 49 default: 50 pr_err("Unexpected record of type %d\n", type); 51 return TEST_FAIL; 52 } 53 } 54 perf_mmap__read_done(map); 55 } 56 return TEST_OK; 57 } 58 59 static int do_test(struct evlist *evlist, int mmap_pages, 60 int *sample_count, int *comm_count) 61 { 62 int err; 63 char sbuf[STRERR_BUFSIZE]; 64 65 err = perf_evlist__mmap(evlist, mmap_pages); 66 if (err < 0) { 67 pr_debug("perf_evlist__mmap: %s\n", 68 str_error_r(errno, sbuf, sizeof(sbuf))); 69 return TEST_FAIL; 70 } 71 72 evlist__enable(evlist); 73 testcase(); 74 evlist__disable(evlist); 75 76 err = count_samples(evlist, sample_count, comm_count); 77 perf_evlist__munmap(evlist); 78 return err; 79 } 80 81 82 int test__backward_ring_buffer(struct test *test __maybe_unused, int subtest __maybe_unused) 83 { 84 int ret = TEST_SKIP, err, sample_count = 0, comm_count = 0; 85 char pid[16], sbuf[STRERR_BUFSIZE]; 86 struct evlist *evlist; 87 struct evsel *evsel __maybe_unused; 88 struct parse_events_error parse_error; 89 struct record_opts opts = { 90 .target = { 91 .uid = UINT_MAX, 92 .uses_mmap = true, 93 }, 94 .freq = 0, 95 .mmap_pages = 256, 96 .default_interval = 1, 97 }; 98 99 snprintf(pid, sizeof(pid), "%d", getpid()); 100 pid[sizeof(pid) - 1] = '\0'; 101 opts.target.tid = opts.target.pid = pid; 102 103 evlist = evlist__new(); 104 if (!evlist) { 105 pr_debug("Not enough memory to create evlist\n"); 106 return TEST_FAIL; 107 } 108 109 err = perf_evlist__create_maps(evlist, &opts.target); 110 if (err < 0) { 111 pr_debug("Not enough memory to create thread/cpu maps\n"); 112 goto out_delete_evlist; 113 } 114 115 bzero(&parse_error, sizeof(parse_error)); 116 /* 117 * Set backward bit, ring buffer should be writing from end. Record 118 * it in aux evlist 119 */ 120 err = parse_events(evlist, "syscalls:sys_enter_prctl/overwrite/", &parse_error); 121 if (err) { 122 pr_debug("Failed to parse tracepoint event, try use root\n"); 123 ret = TEST_SKIP; 124 goto out_delete_evlist; 125 } 126 127 perf_evlist__config(evlist, &opts, NULL); 128 129 err = evlist__open(evlist); 130 if (err < 0) { 131 pr_debug("perf_evlist__open: %s\n", 132 str_error_r(errno, sbuf, sizeof(sbuf))); 133 goto out_delete_evlist; 134 } 135 136 ret = TEST_FAIL; 137 err = do_test(evlist, opts.mmap_pages, &sample_count, 138 &comm_count); 139 if (err != TEST_OK) 140 goto out_delete_evlist; 141 142 if ((sample_count != NR_ITERS) || (comm_count != NR_ITERS)) { 143 pr_err("Unexpected counter: sample_count=%d, comm_count=%d\n", 144 sample_count, comm_count); 145 goto out_delete_evlist; 146 } 147 148 err = do_test(evlist, 1, &sample_count, &comm_count); 149 if (err != TEST_OK) 150 goto out_delete_evlist; 151 152 ret = TEST_OK; 153 out_delete_evlist: 154 evlist__delete(evlist); 155 return ret; 156 } 157