0001
0002 #include <linux/compiler.h>
0003 #include <linux/kernel.h>
0004 #include <linux/string.h>
0005 #include <linux/zalloc.h>
0006 #include <linux/err.h>
0007 #include <sys/types.h>
0008 #include <sys/stat.h>
0009 #include <errno.h>
0010 #include <fcntl.h>
0011 #include <unistd.h>
0012 #include <string.h>
0013 #include <asm/bug.h>
0014 #include <dirent.h>
0015
0016 #include "data.h"
0017 #include "util.h" // rm_rf_perf_data()
0018 #include "debug.h"
0019 #include "header.h"
0020 #include <internal/lib.h>
0021
0022 static void close_dir(struct perf_data_file *files, int nr)
0023 {
0024 while (--nr >= 0) {
0025 close(files[nr].fd);
0026 zfree(&files[nr].path);
0027 }
0028 free(files);
0029 }
0030
0031 void perf_data__close_dir(struct perf_data *data)
0032 {
0033 close_dir(data->dir.files, data->dir.nr);
0034 }
0035
0036 int perf_data__create_dir(struct perf_data *data, int nr)
0037 {
0038 struct perf_data_file *files = NULL;
0039 int i, ret;
0040
0041 if (WARN_ON(!data->is_dir))
0042 return -EINVAL;
0043
0044 files = zalloc(nr * sizeof(*files));
0045 if (!files)
0046 return -ENOMEM;
0047
0048 for (i = 0; i < nr; i++) {
0049 struct perf_data_file *file = &files[i];
0050
0051 ret = asprintf(&file->path, "%s/data.%d", data->path, i);
0052 if (ret < 0) {
0053 ret = -ENOMEM;
0054 goto out_err;
0055 }
0056
0057 ret = open(file->path, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
0058 if (ret < 0) {
0059 ret = -errno;
0060 goto out_err;
0061 }
0062
0063 file->fd = ret;
0064 }
0065
0066 data->dir.version = PERF_DIR_VERSION;
0067 data->dir.files = files;
0068 data->dir.nr = nr;
0069 return 0;
0070
0071 out_err:
0072 close_dir(files, i);
0073 return ret;
0074 }
0075
0076 int perf_data__open_dir(struct perf_data *data)
0077 {
0078 struct perf_data_file *files = NULL;
0079 struct dirent *dent;
0080 int ret = -1;
0081 DIR *dir;
0082 int nr = 0;
0083
0084
0085
0086
0087
0088 if (perf_data__is_single_file(data))
0089 return 0;
0090
0091 if (WARN_ON(!data->is_dir))
0092 return -EINVAL;
0093
0094
0095 if (WARN_ON(data->dir.version != PERF_DIR_VERSION))
0096 return -1;
0097
0098 dir = opendir(data->path);
0099 if (!dir)
0100 return -EINVAL;
0101
0102 while ((dent = readdir(dir)) != NULL) {
0103 struct perf_data_file *file;
0104 char path[PATH_MAX];
0105 struct stat st;
0106
0107 snprintf(path, sizeof(path), "%s/%s", data->path, dent->d_name);
0108 if (stat(path, &st))
0109 continue;
0110
0111 if (!S_ISREG(st.st_mode) || strncmp(dent->d_name, "data.", 5))
0112 continue;
0113
0114 ret = -ENOMEM;
0115
0116 file = realloc(files, (nr + 1) * sizeof(*files));
0117 if (!file)
0118 goto out_err;
0119
0120 files = file;
0121 file = &files[nr++];
0122
0123 file->path = strdup(path);
0124 if (!file->path)
0125 goto out_err;
0126
0127 ret = open(file->path, O_RDONLY);
0128 if (ret < 0)
0129 goto out_err;
0130
0131 file->fd = ret;
0132 file->size = st.st_size;
0133 }
0134
0135 if (!files)
0136 return -EINVAL;
0137
0138 data->dir.files = files;
0139 data->dir.nr = nr;
0140 return 0;
0141
0142 out_err:
0143 close_dir(files, nr);
0144 return ret;
0145 }
0146
0147 int perf_data__update_dir(struct perf_data *data)
0148 {
0149 int i;
0150
0151 if (WARN_ON(!data->is_dir))
0152 return -EINVAL;
0153
0154 for (i = 0; i < data->dir.nr; i++) {
0155 struct perf_data_file *file = &data->dir.files[i];
0156 struct stat st;
0157
0158 if (fstat(file->fd, &st))
0159 return -1;
0160
0161 file->size = st.st_size;
0162 }
0163
0164 return 0;
0165 }
0166
0167 static bool check_pipe(struct perf_data *data)
0168 {
0169 struct stat st;
0170 bool is_pipe = false;
0171 int fd = perf_data__is_read(data) ?
0172 STDIN_FILENO : STDOUT_FILENO;
0173
0174 if (!data->path) {
0175 if (!fstat(fd, &st) && S_ISFIFO(st.st_mode))
0176 is_pipe = true;
0177 } else {
0178 if (!strcmp(data->path, "-"))
0179 is_pipe = true;
0180 }
0181
0182 if (is_pipe) {
0183 if (data->use_stdio) {
0184 const char *mode;
0185
0186 mode = perf_data__is_read(data) ? "r" : "w";
0187 data->file.fptr = fdopen(fd, mode);
0188
0189 if (data->file.fptr == NULL) {
0190 data->file.fd = fd;
0191 data->use_stdio = false;
0192 }
0193 } else {
0194 data->file.fd = fd;
0195 }
0196 }
0197
0198 return data->is_pipe = is_pipe;
0199 }
0200
0201 static int check_backup(struct perf_data *data)
0202 {
0203 struct stat st;
0204
0205 if (perf_data__is_read(data))
0206 return 0;
0207
0208 if (!stat(data->path, &st) && st.st_size) {
0209 char oldname[PATH_MAX];
0210 int ret;
0211
0212 snprintf(oldname, sizeof(oldname), "%s.old",
0213 data->path);
0214
0215 ret = rm_rf_perf_data(oldname);
0216 if (ret) {
0217 pr_err("Can't remove old data: %s (%s)\n",
0218 ret == -2 ?
0219 "Unknown file found" : strerror(errno),
0220 oldname);
0221 return -1;
0222 }
0223
0224 if (rename(data->path, oldname)) {
0225 pr_err("Can't move data: %s (%s to %s)\n",
0226 strerror(errno),
0227 data->path, oldname);
0228 return -1;
0229 }
0230 }
0231
0232 return 0;
0233 }
0234
0235 static bool is_dir(struct perf_data *data)
0236 {
0237 struct stat st;
0238
0239 if (stat(data->path, &st))
0240 return false;
0241
0242 return (st.st_mode & S_IFMT) == S_IFDIR;
0243 }
0244
0245 static int open_file_read(struct perf_data *data)
0246 {
0247 int flags = data->in_place_update ? O_RDWR : O_RDONLY;
0248 struct stat st;
0249 int fd;
0250 char sbuf[STRERR_BUFSIZE];
0251
0252 fd = open(data->file.path, flags);
0253 if (fd < 0) {
0254 int err = errno;
0255
0256 pr_err("failed to open %s: %s", data->file.path,
0257 str_error_r(err, sbuf, sizeof(sbuf)));
0258 if (err == ENOENT && !strcmp(data->file.path, "perf.data"))
0259 pr_err(" (try 'perf record' first)");
0260 pr_err("\n");
0261 return -err;
0262 }
0263
0264 if (fstat(fd, &st) < 0)
0265 goto out_close;
0266
0267 if (!data->force && st.st_uid && (st.st_uid != geteuid())) {
0268 pr_err("File %s not owned by current user or root (use -f to override)\n",
0269 data->file.path);
0270 goto out_close;
0271 }
0272
0273 if (!st.st_size) {
0274 pr_info("zero-sized data (%s), nothing to do!\n",
0275 data->file.path);
0276 goto out_close;
0277 }
0278
0279 data->file.size = st.st_size;
0280 return fd;
0281
0282 out_close:
0283 close(fd);
0284 return -1;
0285 }
0286
0287 static int open_file_write(struct perf_data *data)
0288 {
0289 int fd;
0290 char sbuf[STRERR_BUFSIZE];
0291
0292 fd = open(data->file.path, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC,
0293 S_IRUSR|S_IWUSR);
0294
0295 if (fd < 0)
0296 pr_err("failed to open %s : %s\n", data->file.path,
0297 str_error_r(errno, sbuf, sizeof(sbuf)));
0298
0299 return fd;
0300 }
0301
0302 static int open_file(struct perf_data *data)
0303 {
0304 int fd;
0305
0306 fd = perf_data__is_read(data) ?
0307 open_file_read(data) : open_file_write(data);
0308
0309 if (fd < 0) {
0310 zfree(&data->file.path);
0311 return -1;
0312 }
0313
0314 data->file.fd = fd;
0315 return 0;
0316 }
0317
0318 static int open_file_dup(struct perf_data *data)
0319 {
0320 data->file.path = strdup(data->path);
0321 if (!data->file.path)
0322 return -ENOMEM;
0323
0324 return open_file(data);
0325 }
0326
0327 static int open_dir(struct perf_data *data)
0328 {
0329 int ret;
0330
0331
0332
0333
0334
0335 if (asprintf(&data->file.path, "%s/data", data->path) < 0)
0336 return -1;
0337
0338 if (perf_data__is_write(data) &&
0339 mkdir(data->path, S_IRWXU) < 0)
0340 return -1;
0341
0342 ret = open_file(data);
0343
0344
0345 if (ret && perf_data__is_write(data))
0346 rm_rf_perf_data(data->path);
0347
0348 return ret;
0349 }
0350
0351 int perf_data__open(struct perf_data *data)
0352 {
0353 if (check_pipe(data))
0354 return 0;
0355
0356
0357 data->use_stdio = false;
0358
0359 if (!data->path)
0360 data->path = "perf.data";
0361
0362 if (check_backup(data))
0363 return -1;
0364
0365 if (perf_data__is_read(data))
0366 data->is_dir = is_dir(data);
0367
0368 return perf_data__is_dir(data) ?
0369 open_dir(data) : open_file_dup(data);
0370 }
0371
0372 void perf_data__close(struct perf_data *data)
0373 {
0374 if (perf_data__is_dir(data))
0375 perf_data__close_dir(data);
0376
0377 zfree(&data->file.path);
0378
0379 if (data->use_stdio)
0380 fclose(data->file.fptr);
0381 else
0382 close(data->file.fd);
0383 }
0384
0385 ssize_t perf_data__read(struct perf_data *data, void *buf, size_t size)
0386 {
0387 if (data->use_stdio) {
0388 if (fread(buf, size, 1, data->file.fptr) == 1)
0389 return size;
0390 return feof(data->file.fptr) ? 0 : -1;
0391 }
0392 return readn(data->file.fd, buf, size);
0393 }
0394
0395 ssize_t perf_data_file__write(struct perf_data_file *file,
0396 void *buf, size_t size)
0397 {
0398 return writen(file->fd, buf, size);
0399 }
0400
0401 ssize_t perf_data__write(struct perf_data *data,
0402 void *buf, size_t size)
0403 {
0404 if (data->use_stdio) {
0405 if (fwrite(buf, size, 1, data->file.fptr) == 1)
0406 return size;
0407 return -1;
0408 }
0409 return perf_data_file__write(&data->file, buf, size);
0410 }
0411
0412 int perf_data__switch(struct perf_data *data,
0413 const char *postfix,
0414 size_t pos, bool at_exit,
0415 char **new_filepath)
0416 {
0417 int ret;
0418
0419 if (check_pipe(data))
0420 return -EINVAL;
0421 if (perf_data__is_read(data))
0422 return -EINVAL;
0423
0424 if (asprintf(new_filepath, "%s.%s", data->path, postfix) < 0)
0425 return -ENOMEM;
0426
0427
0428
0429
0430
0431 if (rename(data->path, *new_filepath))
0432 pr_warning("Failed to rename %s to %s\n", data->path, *new_filepath);
0433
0434 if (!at_exit) {
0435 close(data->file.fd);
0436 ret = perf_data__open(data);
0437 if (ret < 0)
0438 goto out;
0439
0440 if (lseek(data->file.fd, pos, SEEK_SET) == (off_t)-1) {
0441 ret = -errno;
0442 pr_debug("Failed to lseek to %zu: %s",
0443 pos, strerror(errno));
0444 goto out;
0445 }
0446 }
0447 ret = data->file.fd;
0448 out:
0449 return ret;
0450 }
0451
0452 unsigned long perf_data__size(struct perf_data *data)
0453 {
0454 u64 size = data->file.size;
0455 int i;
0456
0457 if (perf_data__is_single_file(data))
0458 return size;
0459
0460 for (i = 0; i < data->dir.nr; i++) {
0461 struct perf_data_file *file = &data->dir.files[i];
0462
0463 size += file->size;
0464 }
0465
0466 return size;
0467 }
0468
0469 int perf_data__make_kcore_dir(struct perf_data *data, char *buf, size_t buf_sz)
0470 {
0471 int ret;
0472
0473 if (!data->is_dir)
0474 return -1;
0475
0476 ret = snprintf(buf, buf_sz, "%s/kcore_dir", data->path);
0477 if (ret < 0 || (size_t)ret >= buf_sz)
0478 return -1;
0479
0480 return mkdir(buf, S_IRWXU);
0481 }
0482
0483 bool has_kcore_dir(const char *path)
0484 {
0485 struct dirent *d = ERR_PTR(-EINVAL);
0486 const char *name = "kcore_dir";
0487 DIR *dir = opendir(path);
0488 size_t n = strlen(name);
0489 bool result = false;
0490
0491 if (dir) {
0492 while (d && !result) {
0493 d = readdir(dir);
0494 result = d ? strncmp(d->d_name, name, n) : false;
0495 }
0496 closedir(dir);
0497 }
0498
0499 return result;
0500 }
0501
0502 char *perf_data__kallsyms_name(struct perf_data *data)
0503 {
0504 char *kallsyms_name;
0505 struct stat st;
0506
0507 if (!data->is_dir)
0508 return NULL;
0509
0510 if (asprintf(&kallsyms_name, "%s/kcore_dir/kallsyms", data->path) < 0)
0511 return NULL;
0512
0513 if (stat(kallsyms_name, &st)) {
0514 free(kallsyms_name);
0515 return NULL;
0516 }
0517
0518 return kallsyms_name;
0519 }
0520
0521 char *perf_data__guest_kallsyms_name(struct perf_data *data, pid_t machine_pid)
0522 {
0523 char *kallsyms_name;
0524 struct stat st;
0525
0526 if (!data->is_dir)
0527 return NULL;
0528
0529 if (asprintf(&kallsyms_name, "%s/kcore_dir__%d/kallsyms", data->path, machine_pid) < 0)
0530 return NULL;
0531
0532 if (stat(kallsyms_name, &st)) {
0533 free(kallsyms_name);
0534 return NULL;
0535 }
0536
0537 return kallsyms_name;
0538 }
0539
0540 bool is_perf_data(const char *path)
0541 {
0542 bool ret = false;
0543 FILE *file;
0544 u64 magic;
0545
0546 file = fopen(path, "r");
0547 if (!file)
0548 return false;
0549
0550 if (fread(&magic, 1, 8, file) < 8)
0551 goto out;
0552
0553 ret = is_perf_magic(magic);
0554 out:
0555 fclose(file);
0556 return ret;
0557 }