1 // SPDX-License-Identifier: GPL-2.0 2 #include "../perf.h" 3 #include "util.h" 4 #include "debug.h" 5 #include "namespaces.h" 6 #include <api/fs/fs.h> 7 #include <sys/mman.h> 8 #include <sys/stat.h> 9 #include <sys/utsname.h> 10 #include <dirent.h> 11 #include <fcntl.h> 12 #include <inttypes.h> 13 #include <signal.h> 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include <errno.h> 18 #include <limits.h> 19 #include <linux/kernel.h> 20 #include <linux/log2.h> 21 #include <linux/time64.h> 22 #include <unistd.h> 23 #include "strlist.h" 24 #include "string2.h" 25 26 /* 27 * XXX We need to find a better place for these things... 28 */ 29 30 bool perf_singlethreaded = true; 31 32 void perf_set_singlethreaded(void) 33 { 34 perf_singlethreaded = true; 35 } 36 37 void perf_set_multithreaded(void) 38 { 39 perf_singlethreaded = false; 40 } 41 42 unsigned int page_size; 43 44 #ifdef _SC_LEVEL1_DCACHE_LINESIZE 45 #define cache_line_size(cacheline_sizep) *cacheline_sizep = sysconf(_SC_LEVEL1_DCACHE_LINESIZE) 46 #else 47 static void cache_line_size(int *cacheline_sizep) 48 { 49 if (sysfs__read_int("devices/system/cpu/cpu0/cache/index0/coherency_line_size", cacheline_sizep)) 50 pr_debug("cannot determine cache line size"); 51 } 52 #endif 53 54 int cacheline_size(void) 55 { 56 static int size; 57 58 if (!size) 59 cache_line_size(&size); 60 61 return size; 62 } 63 64 int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH; 65 int sysctl_perf_event_max_contexts_per_stack = PERF_MAX_CONTEXTS_PER_STACK; 66 67 int sysctl__max_stack(void) 68 { 69 int value; 70 71 if (sysctl__read_int("kernel/perf_event_max_stack", &value) == 0) 72 sysctl_perf_event_max_stack = value; 73 74 if (sysctl__read_int("kernel/perf_event_max_contexts_per_stack", &value) == 0) 75 sysctl_perf_event_max_contexts_per_stack = value; 76 77 return sysctl_perf_event_max_stack; 78 } 79 80 bool test_attr__enabled; 81 82 bool perf_host = true; 83 bool perf_guest = false; 84 85 void event_attr_init(struct perf_event_attr *attr) 86 { 87 if (!perf_host) 88 attr->exclude_host = 1; 89 if (!perf_guest) 90 attr->exclude_guest = 1; 91 /* to capture ABI version */ 92 attr->size = sizeof(*attr); 93 } 94 95 int mkdir_p(char *path, mode_t mode) 96 { 97 struct stat st; 98 int err; 99 char *d = path; 100 101 if (*d != '/') 102 return -1; 103 104 if (stat(path, &st) == 0) 105 return 0; 106 107 while (*++d == '/'); 108 109 while ((d = strchr(d, '/'))) { 110 *d = '\0'; 111 err = stat(path, &st) && mkdir(path, mode); 112 *d++ = '/'; 113 if (err) 114 return -1; 115 while (*d == '/') 116 ++d; 117 } 118 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0; 119 } 120 121 static bool match_pat(char *file, const char **pat) 122 { 123 int i = 0; 124 125 if (!pat) 126 return true; 127 128 while (pat[i]) { 129 if (strglobmatch(file, pat[i])) 130 return true; 131 132 i++; 133 } 134 135 return false; 136 } 137 138 /* 139 * The depth specify how deep the removal will go. 140 * 0 - will remove only files under the 'path' directory 141 * 1 .. x - will dive in x-level deep under the 'path' directory 142 * 143 * If specified the pat is array of string patterns ended with NULL, 144 * which are checked upon every file/directory found. Only matching 145 * ones are removed. 146 * 147 * The function returns: 148 * 0 on success 149 * -1 on removal failure with errno set 150 * -2 on pattern failure 151 */ 152 static int rm_rf_depth_pat(const char *path, int depth, const char **pat) 153 { 154 DIR *dir; 155 int ret; 156 struct dirent *d; 157 char namebuf[PATH_MAX]; 158 struct stat statbuf; 159 160 /* Do not fail if there's no file. */ 161 ret = lstat(path, &statbuf); 162 if (ret) 163 return 0; 164 165 /* Try to remove any file we get. */ 166 if (!(statbuf.st_mode & S_IFDIR)) 167 return unlink(path); 168 169 /* We have directory in path. */ 170 dir = opendir(path); 171 if (dir == NULL) 172 return -1; 173 174 while ((d = readdir(dir)) != NULL && !ret) { 175 176 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) 177 continue; 178 179 if (!match_pat(d->d_name, pat)) 180 return -2; 181 182 scnprintf(namebuf, sizeof(namebuf), "%s/%s", 183 path, d->d_name); 184 185 /* We have to check symbolic link itself */ 186 ret = lstat(namebuf, &statbuf); 187 if (ret < 0) { 188 pr_debug("stat failed: %s\n", namebuf); 189 break; 190 } 191 192 if (S_ISDIR(statbuf.st_mode)) 193 ret = depth ? rm_rf_depth_pat(namebuf, depth - 1, pat) : 0; 194 else 195 ret = unlink(namebuf); 196 } 197 closedir(dir); 198 199 if (ret < 0) 200 return ret; 201 202 return rmdir(path); 203 } 204 205 int rm_rf_perf_data(const char *path) 206 { 207 const char *pat[] = { 208 "header", 209 "data.*", 210 NULL, 211 }; 212 213 return rm_rf_depth_pat(path, 0, pat); 214 } 215 216 int rm_rf(const char *path) 217 { 218 return rm_rf_depth_pat(path, INT_MAX, NULL); 219 } 220 221 /* A filter which removes dot files */ 222 bool lsdir_no_dot_filter(const char *name __maybe_unused, struct dirent *d) 223 { 224 return d->d_name[0] != '.'; 225 } 226 227 /* lsdir reads a directory and store it in strlist */ 228 struct strlist *lsdir(const char *name, 229 bool (*filter)(const char *, struct dirent *)) 230 { 231 struct strlist *list = NULL; 232 DIR *dir; 233 struct dirent *d; 234 235 dir = opendir(name); 236 if (!dir) 237 return NULL; 238 239 list = strlist__new(NULL, NULL); 240 if (!list) { 241 errno = ENOMEM; 242 goto out; 243 } 244 245 while ((d = readdir(dir)) != NULL) { 246 if (!filter || filter(name, d)) 247 strlist__add(list, d->d_name); 248 } 249 250 out: 251 closedir(dir); 252 return list; 253 } 254 255 static int slow_copyfile(const char *from, const char *to, struct nsinfo *nsi) 256 { 257 int err = -1; 258 char *line = NULL; 259 size_t n; 260 FILE *from_fp, *to_fp; 261 struct nscookie nsc; 262 263 nsinfo__mountns_enter(nsi, &nsc); 264 from_fp = fopen(from, "r"); 265 nsinfo__mountns_exit(&nsc); 266 if (from_fp == NULL) 267 goto out; 268 269 to_fp = fopen(to, "w"); 270 if (to_fp == NULL) 271 goto out_fclose_from; 272 273 while (getline(&line, &n, from_fp) > 0) 274 if (fputs(line, to_fp) == EOF) 275 goto out_fclose_to; 276 err = 0; 277 out_fclose_to: 278 fclose(to_fp); 279 free(line); 280 out_fclose_from: 281 fclose(from_fp); 282 out: 283 return err; 284 } 285 286 int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size) 287 { 288 void *ptr; 289 loff_t pgoff; 290 291 pgoff = off_in & ~(page_size - 1); 292 off_in -= pgoff; 293 294 ptr = mmap(NULL, off_in + size, PROT_READ, MAP_PRIVATE, ifd, pgoff); 295 if (ptr == MAP_FAILED) 296 return -1; 297 298 while (size) { 299 ssize_t ret = pwrite(ofd, ptr + off_in, size, off_out); 300 if (ret < 0 && errno == EINTR) 301 continue; 302 if (ret <= 0) 303 break; 304 305 size -= ret; 306 off_in += ret; 307 off_out += ret; 308 } 309 munmap(ptr, off_in + size); 310 311 return size ? -1 : 0; 312 } 313 314 static int copyfile_mode_ns(const char *from, const char *to, mode_t mode, 315 struct nsinfo *nsi) 316 { 317 int fromfd, tofd; 318 struct stat st; 319 int err; 320 char *tmp = NULL, *ptr = NULL; 321 struct nscookie nsc; 322 323 nsinfo__mountns_enter(nsi, &nsc); 324 err = stat(from, &st); 325 nsinfo__mountns_exit(&nsc); 326 if (err) 327 goto out; 328 err = -1; 329 330 /* extra 'x' at the end is to reserve space for '.' */ 331 if (asprintf(&tmp, "%s.XXXXXXx", to) < 0) { 332 tmp = NULL; 333 goto out; 334 } 335 ptr = strrchr(tmp, '/'); 336 if (!ptr) 337 goto out; 338 ptr = memmove(ptr + 1, ptr, strlen(ptr) - 1); 339 *ptr = '.'; 340 341 tofd = mkstemp(tmp); 342 if (tofd < 0) 343 goto out; 344 345 if (fchmod(tofd, mode)) 346 goto out_close_to; 347 348 if (st.st_size == 0) { /* /proc? do it slowly... */ 349 err = slow_copyfile(from, tmp, nsi); 350 goto out_close_to; 351 } 352 353 nsinfo__mountns_enter(nsi, &nsc); 354 fromfd = open(from, O_RDONLY); 355 nsinfo__mountns_exit(&nsc); 356 if (fromfd < 0) 357 goto out_close_to; 358 359 err = copyfile_offset(fromfd, 0, tofd, 0, st.st_size); 360 361 close(fromfd); 362 out_close_to: 363 close(tofd); 364 if (!err) 365 err = link(tmp, to); 366 unlink(tmp); 367 out: 368 free(tmp); 369 return err; 370 } 371 372 int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi) 373 { 374 return copyfile_mode_ns(from, to, 0755, nsi); 375 } 376 377 int copyfile_mode(const char *from, const char *to, mode_t mode) 378 { 379 return copyfile_mode_ns(from, to, mode, NULL); 380 } 381 382 int copyfile(const char *from, const char *to) 383 { 384 return copyfile_mode(from, to, 0755); 385 } 386 387 static ssize_t ion(bool is_read, int fd, void *buf, size_t n) 388 { 389 void *buf_start = buf; 390 size_t left = n; 391 392 while (left) { 393 /* buf must be treated as const if !is_read. */ 394 ssize_t ret = is_read ? read(fd, buf, left) : 395 write(fd, buf, left); 396 397 if (ret < 0 && errno == EINTR) 398 continue; 399 if (ret <= 0) 400 return ret; 401 402 left -= ret; 403 buf += ret; 404 } 405 406 BUG_ON((size_t)(buf - buf_start) != n); 407 return n; 408 } 409 410 /* 411 * Read exactly 'n' bytes or return an error. 412 */ 413 ssize_t readn(int fd, void *buf, size_t n) 414 { 415 return ion(true, fd, buf, n); 416 } 417 418 /* 419 * Write exactly 'n' bytes or return an error. 420 */ 421 ssize_t writen(int fd, const void *buf, size_t n) 422 { 423 /* ion does not modify buf. */ 424 return ion(false, fd, (void *)buf, n); 425 } 426 427 size_t hex_width(u64 v) 428 { 429 size_t n = 1; 430 431 while ((v >>= 4)) 432 ++n; 433 434 return n; 435 } 436 437 /* 438 * While we find nice hex chars, build a long_val. 439 * Return number of chars processed. 440 */ 441 int hex2u64(const char *ptr, u64 *long_val) 442 { 443 char *p; 444 445 *long_val = strtoull(ptr, &p, 16); 446 447 return p - ptr; 448 } 449 450 int perf_event_paranoid(void) 451 { 452 int value; 453 454 if (sysctl__read_int("kernel/perf_event_paranoid", &value)) 455 return INT_MAX; 456 457 return value; 458 } 459 static int 460 fetch_ubuntu_kernel_version(unsigned int *puint) 461 { 462 ssize_t len; 463 size_t line_len = 0; 464 char *ptr, *line = NULL; 465 int version, patchlevel, sublevel, err; 466 FILE *vsig; 467 468 if (!puint) 469 return 0; 470 471 vsig = fopen("/proc/version_signature", "r"); 472 if (!vsig) { 473 pr_debug("Open /proc/version_signature failed: %s\n", 474 strerror(errno)); 475 return -1; 476 } 477 478 len = getline(&line, &line_len, vsig); 479 fclose(vsig); 480 err = -1; 481 if (len <= 0) { 482 pr_debug("Reading from /proc/version_signature failed: %s\n", 483 strerror(errno)); 484 goto errout; 485 } 486 487 ptr = strrchr(line, ' '); 488 if (!ptr) { 489 pr_debug("Parsing /proc/version_signature failed: %s\n", line); 490 goto errout; 491 } 492 493 err = sscanf(ptr + 1, "%d.%d.%d", 494 &version, &patchlevel, &sublevel); 495 if (err != 3) { 496 pr_debug("Unable to get kernel version from /proc/version_signature '%s'\n", 497 line); 498 goto errout; 499 } 500 501 *puint = (version << 16) + (patchlevel << 8) + sublevel; 502 err = 0; 503 errout: 504 free(line); 505 return err; 506 } 507 508 int 509 fetch_kernel_version(unsigned int *puint, char *str, 510 size_t str_size) 511 { 512 struct utsname utsname; 513 int version, patchlevel, sublevel, err; 514 bool int_ver_ready = false; 515 516 if (access("/proc/version_signature", R_OK) == 0) 517 if (!fetch_ubuntu_kernel_version(puint)) 518 int_ver_ready = true; 519 520 if (uname(&utsname)) 521 return -1; 522 523 if (str && str_size) { 524 strncpy(str, utsname.release, str_size); 525 str[str_size - 1] = '\0'; 526 } 527 528 if (!puint || int_ver_ready) 529 return 0; 530 531 err = sscanf(utsname.release, "%d.%d.%d", 532 &version, &patchlevel, &sublevel); 533 534 if (err != 3) { 535 pr_debug("Unable to get kernel version from uname '%s'\n", 536 utsname.release); 537 return -1; 538 } 539 540 *puint = (version << 16) + (patchlevel << 8) + sublevel; 541 return 0; 542 } 543 544 const char *perf_tip(const char *dirpath) 545 { 546 struct strlist *tips; 547 struct str_node *node; 548 char *tip = NULL; 549 struct strlist_config conf = { 550 .dirname = dirpath, 551 .file_only = true, 552 }; 553 554 tips = strlist__new("tips.txt", &conf); 555 if (tips == NULL) 556 return errno == ENOENT ? NULL : 557 "Tip: check path of tips.txt or get more memory! ;-p"; 558 559 if (strlist__nr_entries(tips) == 0) 560 goto out; 561 562 node = strlist__entry(tips, random() % strlist__nr_entries(tips)); 563 if (asprintf(&tip, "Tip: %s", node->s) < 0) 564 tip = (char *)"Tip: get more memory! ;-)"; 565 566 out: 567 strlist__delete(tips); 568 569 return tip; 570 } 571 572 char *perf_exe(char *buf, int len) 573 { 574 int n = readlink("/proc/self/exe", buf, len); 575 if (n > 0) { 576 buf[n] = 0; 577 return buf; 578 } 579 return strcpy(buf, "perf"); 580 } 581