1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/compiler.h> 3 #include <linux/kernel.h> 4 #include <linux/string.h> 5 #include <linux/zalloc.h> 6 #include <linux/err.h> 7 #include <sys/types.h> 8 #include <sys/stat.h> 9 #include <errno.h> 10 #include <fcntl.h> 11 #include <unistd.h> 12 #include <string.h> 13 #include <asm/bug.h> 14 #include <dirent.h> 15 16 #include "data.h" 17 #include "util.h" // rm_rf_perf_data() 18 #include "debug.h" 19 #include "header.h" 20 #include "rlimit.h" 21 #include <internal/lib.h> 22 23 static void close_dir(struct perf_data_file *files, int nr) 24 { 25 while (--nr >= 0) { 26 close(files[nr].fd); 27 zfree(&files[nr].path); 28 } 29 free(files); 30 } 31 32 void perf_data__close_dir(struct perf_data *data) 33 { 34 close_dir(data->dir.files, data->dir.nr); 35 } 36 37 int perf_data__create_dir(struct perf_data *data, int nr) 38 { 39 enum rlimit_action set_rlimit = NO_CHANGE; 40 struct perf_data_file *files = NULL; 41 int i, ret; 42 43 if (WARN_ON(!data->is_dir)) 44 return -EINVAL; 45 46 files = zalloc(nr * sizeof(*files)); 47 if (!files) 48 return -ENOMEM; 49 50 for (i = 0; i < nr; i++) { 51 struct perf_data_file *file = &files[i]; 52 53 ret = asprintf(&file->path, "%s/data.%d", data->path, i); 54 if (ret < 0) { 55 ret = -ENOMEM; 56 goto out_err; 57 } 58 59 retry_open: 60 ret = open(file->path, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR); 61 if (ret < 0) { 62 /* 63 * If using parallel threads to collect data, 64 * perf record needs at least 6 fds per CPU. 65 * When we run out of them try to increase the limits. 66 */ 67 if (errno == EMFILE && rlimit__increase_nofile(&set_rlimit)) 68 goto retry_open; 69 70 ret = -errno; 71 goto out_err; 72 } 73 set_rlimit = NO_CHANGE; 74 75 file->fd = ret; 76 } 77 78 data->dir.version = PERF_DIR_VERSION; 79 data->dir.files = files; 80 data->dir.nr = nr; 81 return 0; 82 83 out_err: 84 close_dir(files, i); 85 return ret; 86 } 87 88 int perf_data__open_dir(struct perf_data *data) 89 { 90 struct perf_data_file *files = NULL; 91 struct dirent *dent; 92 int ret = -1; 93 DIR *dir; 94 int nr = 0; 95 96 /* 97 * Directory containing a single regular perf data file which is already 98 * open, means there is nothing more to do here. 99 */ 100 if (perf_data__is_single_file(data)) 101 return 0; 102 103 if (WARN_ON(!data->is_dir)) 104 return -EINVAL; 105 106 /* The version is provided by DIR_FORMAT feature. */ 107 if (WARN_ON(data->dir.version != PERF_DIR_VERSION)) 108 return -1; 109 110 dir = opendir(data->path); 111 if (!dir) 112 return -EINVAL; 113 114 while ((dent = readdir(dir)) != NULL) { 115 struct perf_data_file *file; 116 char path[PATH_MAX]; 117 struct stat st; 118 119 snprintf(path, sizeof(path), "%s/%s", data->path, dent->d_name); 120 if (stat(path, &st)) 121 continue; 122 123 if (!S_ISREG(st.st_mode) || strncmp(dent->d_name, "data.", 5)) 124 continue; 125 126 ret = -ENOMEM; 127 128 file = realloc(files, (nr + 1) * sizeof(*files)); 129 if (!file) 130 goto out_err; 131 132 files = file; 133 file = &files[nr++]; 134 135 file->path = strdup(path); 136 if (!file->path) 137 goto out_err; 138 139 ret = open(file->path, O_RDONLY); 140 if (ret < 0) 141 goto out_err; 142 143 file->fd = ret; 144 file->size = st.st_size; 145 } 146 147 closedir(dir); 148 if (!files) 149 return -EINVAL; 150 151 data->dir.files = files; 152 data->dir.nr = nr; 153 return 0; 154 155 out_err: 156 closedir(dir); 157 close_dir(files, nr); 158 return ret; 159 } 160 161 static bool check_pipe(struct perf_data *data) 162 { 163 struct stat st; 164 bool is_pipe = false; 165 int fd = perf_data__is_read(data) ? 166 STDIN_FILENO : STDOUT_FILENO; 167 168 if (!data->path) { 169 if (!fstat(fd, &st) && S_ISFIFO(st.st_mode)) 170 is_pipe = true; 171 } else { 172 if (!strcmp(data->path, "-")) 173 is_pipe = true; 174 } 175 176 if (is_pipe) { 177 if (data->use_stdio) { 178 const char *mode; 179 180 mode = perf_data__is_read(data) ? "r" : "w"; 181 data->file.fptr = fdopen(fd, mode); 182 183 if (data->file.fptr == NULL) { 184 data->file.fd = fd; 185 data->use_stdio = false; 186 } 187 188 /* 189 * When is_pipe and data->file.fd is given, use given fd 190 * instead of STDIN_FILENO or STDOUT_FILENO 191 */ 192 } else if (data->file.fd <= 0) { 193 data->file.fd = fd; 194 } 195 } 196 197 return data->is_pipe = is_pipe; 198 } 199 200 static int check_backup(struct perf_data *data) 201 { 202 struct stat st; 203 204 if (perf_data__is_read(data)) 205 return 0; 206 207 if (!stat(data->path, &st) && st.st_size) { 208 char oldname[PATH_MAX]; 209 int ret; 210 211 snprintf(oldname, sizeof(oldname), "%s.old", 212 data->path); 213 214 ret = rm_rf_perf_data(oldname); 215 if (ret) { 216 if (ret == -2) 217 pr_err("Can't remove old data: Unknown file found (%s)\n", oldname); 218 else 219 pr_err("Can't remove old data: %m (%s)\n", oldname); 220 return -1; 221 } 222 223 if (rename(data->path, oldname)) { 224 pr_err("Can't move data: %m (%s to %s)\n", data->path, oldname); 225 return -1; 226 } 227 } 228 229 return 0; 230 } 231 232 static bool is_dir(struct perf_data *data) 233 { 234 struct stat st; 235 236 if (stat(data->path, &st)) 237 return false; 238 239 return (st.st_mode & S_IFMT) == S_IFDIR; 240 } 241 242 static int open_file_read(struct perf_data *data) 243 { 244 int flags = data->in_place_update ? O_RDWR : O_RDONLY; 245 struct stat st; 246 int fd; 247 248 fd = open(data->file.path, flags); 249 if (fd < 0) { 250 int err = errno; 251 252 pr_err("failed to open %s: %m", data->file.path); 253 if (err == ENOENT && !strcmp(data->file.path, "perf.data")) 254 pr_err(" (try 'perf record' first)"); 255 pr_err("\n"); 256 return -err; 257 } 258 259 if (fstat(fd, &st) < 0) 260 goto out_close; 261 262 if (!data->force && st.st_uid && (st.st_uid != geteuid())) { 263 pr_err("File %s not owned by current user or root (use -f to override)\n", 264 data->file.path); 265 goto out_close; 266 } 267 268 if (!st.st_size) { 269 pr_info("zero-sized data (%s), nothing to do!\n", 270 data->file.path); 271 goto out_close; 272 } 273 274 data->file.size = st.st_size; 275 return fd; 276 277 out_close: 278 close(fd); 279 return -1; 280 } 281 282 static int open_file_write(struct perf_data *data) 283 { 284 int fd = open(data->file.path, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, S_IRUSR|S_IWUSR); 285 286 if (fd < 0) 287 pr_err("failed to open %s : %m\n", data->file.path); 288 289 return fd; 290 } 291 292 static int open_file(struct perf_data *data) 293 { 294 int fd; 295 296 fd = perf_data__is_read(data) ? 297 open_file_read(data) : open_file_write(data); 298 299 if (fd < 0) { 300 zfree(&data->file.path); 301 return -1; 302 } 303 304 data->file.fd = fd; 305 return 0; 306 } 307 308 static int open_file_dup(struct perf_data *data) 309 { 310 data->file.path = strdup(data->path); 311 if (!data->file.path) 312 return -ENOMEM; 313 314 return open_file(data); 315 } 316 317 static int open_dir(struct perf_data *data) 318 { 319 int ret; 320 321 /* 322 * So far we open only the header, so we can read the data version and 323 * layout. 324 */ 325 if (asprintf(&data->file.path, "%s/data", data->path) < 0) 326 return -1; 327 328 if (perf_data__is_write(data) && 329 mkdir(data->path, S_IRWXU) < 0) 330 return -1; 331 332 ret = open_file(data); 333 334 /* Cleanup whatever we managed to create so far. */ 335 if (ret && perf_data__is_write(data)) 336 rm_rf_perf_data(data->path); 337 338 return ret; 339 } 340 341 int perf_data__open(struct perf_data *data) 342 { 343 if (check_pipe(data)) 344 return 0; 345 346 /* currently it allows stdio for pipe only */ 347 data->use_stdio = false; 348 349 if (!data->path) 350 data->path = "perf.data"; 351 352 if (check_backup(data)) 353 return -1; 354 355 if (perf_data__is_read(data)) 356 data->is_dir = is_dir(data); 357 358 return perf_data__is_dir(data) ? 359 open_dir(data) : open_file_dup(data); 360 } 361 362 void perf_data__close(struct perf_data *data) 363 { 364 if (perf_data__is_dir(data)) 365 perf_data__close_dir(data); 366 367 zfree(&data->file.path); 368 369 if (data->use_stdio) 370 fclose(data->file.fptr); 371 else 372 close(data->file.fd); 373 } 374 375 ssize_t perf_data__read(struct perf_data *data, void *buf, size_t size) 376 { 377 if (data->use_stdio) { 378 if (fread(buf, size, 1, data->file.fptr) == 1) 379 return size; 380 return feof(data->file.fptr) ? 0 : -1; 381 } 382 return readn(data->file.fd, buf, size); 383 } 384 385 ssize_t perf_data_file__write(struct perf_data_file *file, 386 void *buf, size_t size) 387 { 388 return writen(file->fd, buf, size); 389 } 390 391 ssize_t perf_data__write(struct perf_data *data, 392 void *buf, size_t size) 393 { 394 if (data->use_stdio) { 395 if (fwrite(buf, size, 1, data->file.fptr) == 1) 396 return size; 397 return -1; 398 } 399 return perf_data_file__write(&data->file, buf, size); 400 } 401 402 int perf_data__switch(struct perf_data *data, 403 const char *postfix, 404 size_t pos, bool at_exit, 405 char **new_filepath) 406 { 407 int ret; 408 409 if (perf_data__is_read(data)) 410 return -EINVAL; 411 412 if (asprintf(new_filepath, "%s.%s", data->path, postfix) < 0) 413 return -ENOMEM; 414 415 /* 416 * Only fire a warning, don't return error, continue fill 417 * original file. 418 */ 419 if (rename(data->path, *new_filepath)) 420 pr_warning("Failed to rename %s to %s\n", data->path, *new_filepath); 421 422 if (!at_exit) { 423 close(data->file.fd); 424 ret = perf_data__open(data); 425 if (ret < 0) 426 goto out; 427 428 if (lseek(data->file.fd, pos, SEEK_SET) == (off_t)-1) { 429 ret = -errno; 430 pr_debug("Failed to lseek to %zu: %m\n", 431 pos); 432 goto out; 433 } 434 } 435 ret = data->file.fd; 436 out: 437 return ret; 438 } 439 440 unsigned long perf_data__size(struct perf_data *data) 441 { 442 u64 size = data->file.size; 443 int i; 444 445 if (perf_data__is_single_file(data)) 446 return size; 447 448 for (i = 0; i < data->dir.nr; i++) { 449 struct perf_data_file *file = &data->dir.files[i]; 450 451 size += file->size; 452 } 453 454 return size; 455 } 456 457 int perf_data__make_kcore_dir(struct perf_data *data, char *buf, size_t buf_sz) 458 { 459 int ret; 460 461 if (!data->is_dir) 462 return -1; 463 464 ret = snprintf(buf, buf_sz, "%s/kcore_dir", data->path); 465 if (ret < 0 || (size_t)ret >= buf_sz) 466 return -1; 467 468 return mkdir(buf, S_IRWXU); 469 } 470 471 bool has_kcore_dir(const char *path) 472 { 473 struct dirent *d = ERR_PTR(-EINVAL); 474 const char *name = "kcore_dir"; 475 DIR *dir = opendir(path); 476 size_t n = strlen(name); 477 bool result = false; 478 479 if (dir) { 480 while (d && !result) { 481 d = readdir(dir); 482 result = d ? strncmp(d->d_name, name, n) : false; 483 } 484 closedir(dir); 485 } 486 487 return result; 488 } 489 490 char *perf_data__kallsyms_name(struct perf_data *data) 491 { 492 char *kallsyms_name; 493 struct stat st; 494 495 if (!data->is_dir) 496 return NULL; 497 498 if (asprintf(&kallsyms_name, "%s/kcore_dir/kallsyms", data->path) < 0) 499 return NULL; 500 501 if (stat(kallsyms_name, &st)) { 502 free(kallsyms_name); 503 return NULL; 504 } 505 506 return kallsyms_name; 507 } 508 509 char *perf_data__guest_kallsyms_name(struct perf_data *data, pid_t machine_pid) 510 { 511 char *kallsyms_name; 512 struct stat st; 513 514 if (!data->is_dir) 515 return NULL; 516 517 if (asprintf(&kallsyms_name, "%s/kcore_dir__%d/kallsyms", data->path, machine_pid) < 0) 518 return NULL; 519 520 if (stat(kallsyms_name, &st)) { 521 free(kallsyms_name); 522 return NULL; 523 } 524 525 return kallsyms_name; 526 } 527 528 bool is_perf_data(const char *path) 529 { 530 bool ret = false; 531 FILE *file; 532 u64 magic; 533 534 file = fopen(path, "r"); 535 if (!file) 536 return false; 537 538 if (fread(&magic, 1, 8, file) < 8) 539 goto out; 540 541 ret = is_perf_magic(magic); 542 out: 543 fclose(file); 544 return ret; 545 } 546