int perf_data__create_dir(struct perf_data *data, int nr)
{ enum rlimit_action set_rlimit = NO_CHANGE; struct perf_data_file *files = NULL; int i, ret;
if (WARN_ON(!data->is_dir)) return -EINVAL;
files = zalloc(nr * sizeof(*files)); if (!files) return -ENOMEM;
for (i = 0; i < nr; i++) { struct perf_data_file *file = &files[i];
ret = asprintf(&file->path, "%s/data.%d", data->path, i); if (ret < 0) {
ret = -ENOMEM; goto out_err;
}
retry_open:
ret = open(file->path, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR); if (ret < 0) { /* * If using parallel threads to collect data, * perf record needs at least 6 fds per CPU. * When we run out of them try to increase the limits.
*/ if (errno == EMFILE && rlimit__increase_nofile(&set_rlimit)) goto retry_open;
ret = -errno; goto out_err;
}
set_rlimit = NO_CHANGE;
int perf_data__open_dir(struct perf_data *data)
{ struct perf_data_file *files = NULL; struct dirent *dent; int ret = -1;
DIR *dir; int nr = 0;
/* * Directory containing a single regular perf data file which is already * open, means there is nothing more to do here.
*/ if (perf_data__is_single_file(data)) return 0;
if (WARN_ON(!data->is_dir)) return -EINVAL;
/* The version is provided by DIR_FORMAT feature. */ if (WARN_ON(data->dir.version != PERF_DIR_VERSION)) return -1;
dir = opendir(data->path); if (!dir) return -EINVAL;
while ((dent = readdir(dir)) != NULL) { struct perf_data_file *file; char path[PATH_MAX]; struct stat st;
snprintf(path, sizeof(path), "%s/%s", data->path, dent->d_name); if (stat(path, &st)) continue;
if (!S_ISREG(st.st_mode) || strncmp(dent->d_name, "data.", 5)) continue;
/* * When is_pipe and data->file.fd is given, use given fd * instead of STDIN_FILENO or STDOUT_FILENO
*/
} elseif (data->file.fd <= 0) {
data->file.fd = fd;
}
}
return data->is_pipe = is_pipe;
}
staticint check_backup(struct perf_data *data)
{ struct stat st;
if (perf_data__is_read(data)) return 0;
if (!stat(data->path, &st) && st.st_size) { char oldname[PATH_MAX]; int ret;
ret = rm_rf_perf_data(oldname); if (ret) {
pr_err("Can't remove old data: %s (%s)\n",
ret == -2 ? "Unknown file found" : strerror(errno),
oldname); return -1;
}
if (rename(data->path, oldname)) {
pr_err("Can't move data: %s (%s to %s)\n",
strerror(errno),
data->path, oldname); return -1;
}
}
return 0;
}
staticbool is_dir(struct perf_data *data)
{ struct stat st;
if (stat(data->path, &st)) returnfalse;
return (st.st_mode & S_IFMT) == S_IFDIR;
}
staticint open_file_read(struct perf_data *data)
{ int flags = data->in_place_update ? O_RDWR : O_RDONLY; struct stat st; int fd; char sbuf[STRERR_BUFSIZE];
fd = open(data->file.path, flags); if (fd < 0) { int err = errno;
pr_err("failed to open %s: %s", data->file.path,
str_error_r(err, sbuf, sizeof(sbuf))); if (err == ENOENT && !strcmp(data->file.path, "perf.data"))
pr_err(" (try 'perf record' first)");
pr_err("\n"); return -err;
}
if (fstat(fd, &st) < 0) goto out_close;
if (!data->force && st.st_uid && (st.st_uid != geteuid())) {
pr_err("File %s not owned by current user or root (use -f to override)\n",
data->file.path); goto out_close;
}
if (!st.st_size) {
pr_info("zero-sized data (%s), nothing to do!\n",
data->file.path); goto out_close;
}
data->file.size = st.st_size; return fd;
out_close:
close(fd); return -1;
}
staticint open_file_write(struct perf_data *data)
{ int fd; char sbuf[STRERR_BUFSIZE];
staticint open_dir(struct perf_data *data)
{ int ret;
/* * So far we open only the header, so we can read the data version and * layout.
*/ if (asprintf(&data->file.path, "%s/data", data->path) < 0) return -1;
if (perf_data__is_write(data) &&
mkdir(data->path, S_IRWXU) < 0) return -1;
ret = open_file(data);
/* Cleanup whatever we managed to create so far. */ if (ret && perf_data__is_write(data))
rm_rf_perf_data(data->path);
return ret;
}
int perf_data__open(struct perf_data *data)
{ if (check_pipe(data)) return 0;
/* currently it allows stdio for pipe only */
data->use_stdio = false;
if (!data->path)
data->path = "perf.data";
if (check_backup(data)) return -1;
if (perf_data__is_read(data))
data->is_dir = is_dir(data);
int perf_data__switch(struct perf_data *data, constchar *postfix,
size_t pos, bool at_exit, char **new_filepath)
{ int ret;
if (perf_data__is_read(data)) return -EINVAL;
if (asprintf(new_filepath, "%s.%s", data->path, postfix) < 0) return -ENOMEM;
/* * Only fire a warning, don't return error, continue fill * original file.
*/ if (rename(data->path, *new_filepath))
pr_warning("Failed to rename %s to %s\n", data->path, *new_filepath);
if (!at_exit) {
close(data->file.fd);
ret = perf_data__open(data); if (ret < 0) goto out;
if (lseek(data->file.fd, pos, SEEK_SET) == (off_t)-1) {
ret = -errno;
pr_debug("Failed to lseek to %zu: %s",
pos, strerror(errno)); goto out;
}
}
ret = data->file.fd;
out: return ret;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.