1 #include "../perf.h" 2 #include "util.h" 3 #include "debug.h" 4 #include <api/fs/fs.h> 5 #include <sys/mman.h> 6 #include <sys/stat.h> 7 #include <sys/utsname.h> 8 #include <dirent.h> 9 #include <inttypes.h> 10 #include <signal.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <errno.h> 15 #include <limits.h> 16 #include <linux/kernel.h> 17 #include <linux/log2.h> 18 #include <linux/time64.h> 19 #include <unistd.h> 20 #include "strlist.h" 21 22 /* 23 * XXX We need to find a better place for these things... 24 */ 25 unsigned int page_size; 26 int cacheline_size; 27 28 int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH; 29 int sysctl_perf_event_max_contexts_per_stack = PERF_MAX_CONTEXTS_PER_STACK; 30 31 bool test_attr__enabled; 32 33 bool perf_host = true; 34 bool perf_guest = false; 35 36 void event_attr_init(struct perf_event_attr *attr) 37 { 38 if (!perf_host) 39 attr->exclude_host = 1; 40 if (!perf_guest) 41 attr->exclude_guest = 1; 42 /* to capture ABI version */ 43 attr->size = sizeof(*attr); 44 } 45 46 int mkdir_p(char *path, mode_t mode) 47 { 48 struct stat st; 49 int err; 50 char *d = path; 51 52 if (*d != '/') 53 return -1; 54 55 if (stat(path, &st) == 0) 56 return 0; 57 58 while (*++d == '/'); 59 60 while ((d = strchr(d, '/'))) { 61 *d = '\0'; 62 err = stat(path, &st) && mkdir(path, mode); 63 *d++ = '/'; 64 if (err) 65 return -1; 66 while (*d == '/') 67 ++d; 68 } 69 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0; 70 } 71 72 int rm_rf(const char *path) 73 { 74 DIR *dir; 75 int ret = 0; 76 struct dirent *d; 77 char namebuf[PATH_MAX]; 78 79 dir = opendir(path); 80 if (dir == NULL) 81 return 0; 82 83 while ((d = readdir(dir)) != NULL && !ret) { 84 struct stat statbuf; 85 86 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) 87 continue; 88 89 scnprintf(namebuf, sizeof(namebuf), "%s/%s", 90 path, d->d_name); 91 92 /* We have to check symbolic link itself */ 93 ret = lstat(namebuf, &statbuf); 94 if (ret < 0) { 95 pr_debug("stat failed: %s\n", namebuf); 96 break; 97 } 98 99 if (S_ISDIR(statbuf.st_mode)) 100 ret = rm_rf(namebuf); 101 else 102 ret = unlink(namebuf); 103 } 104 closedir(dir); 105 106 if (ret < 0) 107 return ret; 108 109 return rmdir(path); 110 } 111 112 /* A filter which removes dot files */ 113 bool lsdir_no_dot_filter(const char *name __maybe_unused, struct dirent *d) 114 { 115 return d->d_name[0] != '.'; 116 } 117 118 /* lsdir reads a directory and store it in strlist */ 119 struct strlist *lsdir(const char *name, 120 bool (*filter)(const char *, struct dirent *)) 121 { 122 struct strlist *list = NULL; 123 DIR *dir; 124 struct dirent *d; 125 126 dir = opendir(name); 127 if (!dir) 128 return NULL; 129 130 list = strlist__new(NULL, NULL); 131 if (!list) { 132 errno = ENOMEM; 133 goto out; 134 } 135 136 while ((d = readdir(dir)) != NULL) { 137 if (!filter || filter(name, d)) 138 strlist__add(list, d->d_name); 139 } 140 141 out: 142 closedir(dir); 143 return list; 144 } 145 146 static int slow_copyfile(const char *from, const char *to) 147 { 148 int err = -1; 149 char *line = NULL; 150 size_t n; 151 FILE *from_fp = fopen(from, "r"), *to_fp; 152 153 if (from_fp == NULL) 154 goto out; 155 156 to_fp = fopen(to, "w"); 157 if (to_fp == NULL) 158 goto out_fclose_from; 159 160 while (getline(&line, &n, from_fp) > 0) 161 if (fputs(line, to_fp) == EOF) 162 goto out_fclose_to; 163 err = 0; 164 out_fclose_to: 165 fclose(to_fp); 166 free(line); 167 out_fclose_from: 168 fclose(from_fp); 169 out: 170 return err; 171 } 172 173 int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size) 174 { 175 void *ptr; 176 loff_t pgoff; 177 178 pgoff = off_in & ~(page_size - 1); 179 off_in -= pgoff; 180 181 ptr = mmap(NULL, off_in + size, PROT_READ, MAP_PRIVATE, ifd, pgoff); 182 if (ptr == MAP_FAILED) 183 return -1; 184 185 while (size) { 186 ssize_t ret = pwrite(ofd, ptr + off_in, size, off_out); 187 if (ret < 0 && errno == EINTR) 188 continue; 189 if (ret <= 0) 190 break; 191 192 size -= ret; 193 off_in += ret; 194 off_out -= ret; 195 } 196 munmap(ptr, off_in + size); 197 198 return size ? -1 : 0; 199 } 200 201 int copyfile_mode(const char *from, const char *to, mode_t mode) 202 { 203 int fromfd, tofd; 204 struct stat st; 205 int err = -1; 206 char *tmp = NULL, *ptr = NULL; 207 208 if (stat(from, &st)) 209 goto out; 210 211 /* extra 'x' at the end is to reserve space for '.' */ 212 if (asprintf(&tmp, "%s.XXXXXXx", to) < 0) { 213 tmp = NULL; 214 goto out; 215 } 216 ptr = strrchr(tmp, '/'); 217 if (!ptr) 218 goto out; 219 ptr = memmove(ptr + 1, ptr, strlen(ptr) - 1); 220 *ptr = '.'; 221 222 tofd = mkstemp(tmp); 223 if (tofd < 0) 224 goto out; 225 226 if (fchmod(tofd, mode)) 227 goto out_close_to; 228 229 if (st.st_size == 0) { /* /proc? do it slowly... */ 230 err = slow_copyfile(from, tmp); 231 goto out_close_to; 232 } 233 234 fromfd = open(from, O_RDONLY); 235 if (fromfd < 0) 236 goto out_close_to; 237 238 err = copyfile_offset(fromfd, 0, tofd, 0, st.st_size); 239 240 close(fromfd); 241 out_close_to: 242 close(tofd); 243 if (!err) 244 err = link(tmp, to); 245 unlink(tmp); 246 out: 247 free(tmp); 248 return err; 249 } 250 251 int copyfile(const char *from, const char *to) 252 { 253 return copyfile_mode(from, to, 0755); 254 } 255 256 static ssize_t ion(bool is_read, int fd, void *buf, size_t n) 257 { 258 void *buf_start = buf; 259 size_t left = n; 260 261 while (left) { 262 ssize_t ret = is_read ? read(fd, buf, left) : 263 write(fd, buf, left); 264 265 if (ret < 0 && errno == EINTR) 266 continue; 267 if (ret <= 0) 268 return ret; 269 270 left -= ret; 271 buf += ret; 272 } 273 274 BUG_ON((size_t)(buf - buf_start) != n); 275 return n; 276 } 277 278 /* 279 * Read exactly 'n' bytes or return an error. 280 */ 281 ssize_t readn(int fd, void *buf, size_t n) 282 { 283 return ion(true, fd, buf, n); 284 } 285 286 /* 287 * Write exactly 'n' bytes or return an error. 288 */ 289 ssize_t writen(int fd, void *buf, size_t n) 290 { 291 return ion(false, fd, buf, n); 292 } 293 294 size_t hex_width(u64 v) 295 { 296 size_t n = 1; 297 298 while ((v >>= 4)) 299 ++n; 300 301 return n; 302 } 303 304 static int hex(char ch) 305 { 306 if ((ch >= '0') && (ch <= '9')) 307 return ch - '0'; 308 if ((ch >= 'a') && (ch <= 'f')) 309 return ch - 'a' + 10; 310 if ((ch >= 'A') && (ch <= 'F')) 311 return ch - 'A' + 10; 312 return -1; 313 } 314 315 /* 316 * While we find nice hex chars, build a long_val. 317 * Return number of chars processed. 318 */ 319 int hex2u64(const char *ptr, u64 *long_val) 320 { 321 const char *p = ptr; 322 *long_val = 0; 323 324 while (*p) { 325 const int hex_val = hex(*p); 326 327 if (hex_val < 0) 328 break; 329 330 *long_val = (*long_val << 4) | hex_val; 331 p++; 332 } 333 334 return p - ptr; 335 } 336 337 int perf_event_paranoid(void) 338 { 339 int value; 340 341 if (sysctl__read_int("kernel/perf_event_paranoid", &value)) 342 return INT_MAX; 343 344 return value; 345 } 346 static int 347 fetch_ubuntu_kernel_version(unsigned int *puint) 348 { 349 ssize_t len; 350 size_t line_len = 0; 351 char *ptr, *line = NULL; 352 int version, patchlevel, sublevel, err; 353 FILE *vsig; 354 355 if (!puint) 356 return 0; 357 358 vsig = fopen("/proc/version_signature", "r"); 359 if (!vsig) { 360 pr_debug("Open /proc/version_signature failed: %s\n", 361 strerror(errno)); 362 return -1; 363 } 364 365 len = getline(&line, &line_len, vsig); 366 fclose(vsig); 367 err = -1; 368 if (len <= 0) { 369 pr_debug("Reading from /proc/version_signature failed: %s\n", 370 strerror(errno)); 371 goto errout; 372 } 373 374 ptr = strrchr(line, ' '); 375 if (!ptr) { 376 pr_debug("Parsing /proc/version_signature failed: %s\n", line); 377 goto errout; 378 } 379 380 err = sscanf(ptr + 1, "%d.%d.%d", 381 &version, &patchlevel, &sublevel); 382 if (err != 3) { 383 pr_debug("Unable to get kernel version from /proc/version_signature '%s'\n", 384 line); 385 goto errout; 386 } 387 388 *puint = (version << 16) + (patchlevel << 8) + sublevel; 389 err = 0; 390 errout: 391 free(line); 392 return err; 393 } 394 395 int 396 fetch_kernel_version(unsigned int *puint, char *str, 397 size_t str_size) 398 { 399 struct utsname utsname; 400 int version, patchlevel, sublevel, err; 401 bool int_ver_ready = false; 402 403 if (access("/proc/version_signature", R_OK) == 0) 404 if (!fetch_ubuntu_kernel_version(puint)) 405 int_ver_ready = true; 406 407 if (uname(&utsname)) 408 return -1; 409 410 if (str && str_size) { 411 strncpy(str, utsname.release, str_size); 412 str[str_size - 1] = '\0'; 413 } 414 415 if (!puint || int_ver_ready) 416 return 0; 417 418 err = sscanf(utsname.release, "%d.%d.%d", 419 &version, &patchlevel, &sublevel); 420 421 if (err != 3) { 422 pr_debug("Unable to get kernel version from uname '%s'\n", 423 utsname.release); 424 return -1; 425 } 426 427 *puint = (version << 16) + (patchlevel << 8) + sublevel; 428 return 0; 429 } 430 431 const char *perf_tip(const char *dirpath) 432 { 433 struct strlist *tips; 434 struct str_node *node; 435 char *tip = NULL; 436 struct strlist_config conf = { 437 .dirname = dirpath, 438 .file_only = true, 439 }; 440 441 tips = strlist__new("tips.txt", &conf); 442 if (tips == NULL) 443 return errno == ENOENT ? NULL : 444 "Tip: check path of tips.txt or get more memory! ;-p"; 445 446 if (strlist__nr_entries(tips) == 0) 447 goto out; 448 449 node = strlist__entry(tips, random() % strlist__nr_entries(tips)); 450 if (asprintf(&tip, "Tip: %s", node->s) < 0) 451 tip = (char *)"Tip: get more memory! ;-)"; 452 453 out: 454 strlist__delete(tips); 455 456 return tip; 457 } 458