diff options
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/data_map.c | 71 | ||||
-rw-r--r-- | tools/perf/util/data_map.h | 9 | ||||
-rw-r--r-- | tools/perf/util/header.c | 28 | ||||
-rw-r--r-- | tools/perf/util/header.h | 4 | ||||
-rw-r--r-- | tools/perf/util/session.c | 80 | ||||
-rw-r--r-- | tools/perf/util/session.h | 16 |
6 files changed, 118 insertions, 90 deletions
diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c index 59b65d0..6d46dda 100644 --- a/tools/perf/util/data_map.c +++ b/tools/perf/util/data_map.c @@ -129,23 +129,16 @@ out: return err; } -int mmap_dispatch_perf_file(struct perf_header **pheader, - const char *input_name, - int force, - int full_paths, - int *cwdlen, - char **cwd) +int perf_session__process_events(struct perf_session *self, + int full_paths, int *cwdlen, char **cwd) { int err; - struct perf_header *header; unsigned long head, shift; unsigned long offset = 0; - struct stat input_stat; size_t page_size; u64 sample_type; event_t *event; uint32_t size; - int input; char *buf; if (curr_handler == NULL) { @@ -155,56 +148,19 @@ int mmap_dispatch_perf_file(struct perf_header **pheader, page_size = getpagesize(); - input = open(input_name, O_RDONLY); - if (input < 0) { - pr_err("Failed to open file: %s", input_name); - if (!strcmp(input_name, "perf.data")) - pr_err(" (try 'perf record' first)"); - pr_err("\n"); - return -errno; - } - - if (fstat(input, &input_stat) < 0) { - pr_err("failed to stat file"); - err = -errno; - goto out_close; - } - - err = -EACCES; - if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) { - pr_err("file: %s not owned by current user or root\n", - input_name); - goto out_close; - } - - if (input_stat.st_size == 0) { - pr_info("zero-sized file, nothing to do!\n"); - goto done; - } - - err = -ENOMEM; - header = perf_header__new(); - if (header == NULL) - goto out_close; - - err = perf_header__read(header, input); - if (err < 0) - goto out_delete; - *pheader = header; - head = header->data_offset; - - sample_type = perf_header__sample_type(header); + head = self->header.data_offset; + sample_type = perf_header__sample_type(&self->header); err = -EINVAL; if (curr_handler->sample_type_check && curr_handler->sample_type_check(sample_type) < 0) - goto out_delete; + goto out_err; if (!full_paths) { if (getcwd(__cwd, sizeof(__cwd)) == NULL) { pr_err("failed to get the current directory\n"); err = -errno; - goto out_delete; + goto out_err; } *cwd = __cwd; *cwdlen = strlen(*cwd); @@ -219,11 +175,11 @@ int mmap_dispatch_perf_file(struct perf_header **pheader, remap: buf = mmap(NULL, page_size * mmap_window, PROT_READ, - MAP_SHARED, input, offset); + MAP_SHARED, self->fd, offset); if (buf == MAP_FAILED) { pr_err("failed to mmap file\n"); err = -errno; - goto out_delete; + goto out_err; } more: @@ -273,19 +229,14 @@ more: head += size; - if (offset + head >= header->data_offset + header->data_size) + if (offset + head >= self->header.data_offset + self->header.data_size) goto done; - if (offset + head < (unsigned long)input_stat.st_size) + if (offset + head < self->size) goto more; done: err = 0; -out_close: - close(input); - +out_err: return err; -out_delete: - perf_header__delete(header); - goto out_close; } diff --git a/tools/perf/util/data_map.h b/tools/perf/util/data_map.h index 258a87b..98c5b82 100644 --- a/tools/perf/util/data_map.h +++ b/tools/perf/util/data_map.h @@ -3,6 +3,7 @@ #include "event.h" #include "header.h" +#include "session.h" typedef int (*event_type_handler_t)(event_t *); @@ -21,12 +22,8 @@ struct perf_file_handler { }; void register_perf_file_handler(struct perf_file_handler *handler); -int mmap_dispatch_perf_file(struct perf_header **pheader, - const char *input_name, - int force, - int full_paths, - int *cwdlen, - char **cwd); +int perf_session__process_events(struct perf_session *self, + int full_paths, int *cwdlen, char **cwd); int perf_header__read_build_ids(int input, u64 offset, u64 file_size); #endif diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 59a9c0b..f2e8d87 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -58,35 +58,19 @@ int perf_header_attr__add_id(struct perf_header_attr *self, u64 id) return 0; } -/* - * Create new perf.data header: - */ -struct perf_header *perf_header__new(void) +int perf_header__init(struct perf_header *self) { - struct perf_header *self = zalloc(sizeof(*self)); - - if (self != NULL) { - self->size = 1; - self->attr = malloc(sizeof(void *)); - - if (self->attr == NULL) { - free(self); - self = NULL; - } - } - - return self; + self->size = 1; + self->attr = malloc(sizeof(void *)); + return self->attr == NULL ? -ENOMEM : 0; } -void perf_header__delete(struct perf_header *self) +void perf_header__exit(struct perf_header *self) { int i; - for (i = 0; i < self->attrs; ++i) - perf_header_attr__delete(self->attr[i]); - + perf_header_attr__delete(self->attr[i]); free(self->attr); - free(self); } int perf_header__add_attr(struct perf_header *self, diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index d1dbe2b..d118d05 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -55,8 +55,8 @@ struct perf_header { DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); }; -struct perf_header *perf_header__new(void); -void perf_header__delete(struct perf_header *self); +int perf_header__init(struct perf_header *self); +void perf_header__exit(struct perf_header *self); int perf_header__read(struct perf_header *self, int fd); int perf_header__write(struct perf_header *self, int fd, bool at_exit); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c new file mode 100644 index 0000000..707ce1c --- /dev/null +++ b/tools/perf/util/session.c @@ -0,0 +1,80 @@ +#include <linux/kernel.h> + +#include <unistd.h> +#include <sys/types.h> + +#include "session.h" +#include "util.h" + +static int perf_session__open(struct perf_session *self, bool force) +{ + struct stat input_stat; + + self->fd = open(self->filename, O_RDONLY); + if (self->fd < 0) { + pr_err("failed to open file: %s", self->filename); + if (!strcmp(self->filename, "perf.data")) + pr_err(" (try 'perf record' first)"); + pr_err("\n"); + return -errno; + } + + if (fstat(self->fd, &input_stat) < 0) + goto out_close; + + if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) { + pr_err("file %s not owned by current user or root\n", + self->filename); + goto out_close; + } + + if (!input_stat.st_size) { + pr_info("zero-sized file (%s), nothing to do!\n", + self->filename); + goto out_close; + } + + if (perf_header__read(&self->header, self->fd) < 0) { + pr_err("incompatible file format"); + goto out_close; + } + + self->size = input_stat.st_size; + return 0; + +out_close: + close(self->fd); + self->fd = -1; + return -1; +} + +struct perf_session *perf_session__new(const char *filename, int mode, bool force) +{ + size_t len = strlen(filename) + 1; + struct perf_session *self = zalloc(sizeof(*self) + len); + + if (self == NULL) + goto out; + + if (perf_header__init(&self->header) < 0) + goto out_delete; + + memcpy(self->filename, filename, len); + + if (mode == O_RDONLY && perf_session__open(self, force) < 0) { + perf_session__delete(self); + self = NULL; + } +out: + return self; +out_delete: + free(self); + return NULL; +} + +void perf_session__delete(struct perf_session *self) +{ + perf_header__exit(&self->header); + close(self->fd); + free(self); +} diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h new file mode 100644 index 0000000..f3699c8 --- /dev/null +++ b/tools/perf/util/session.h @@ -0,0 +1,16 @@ +#ifndef __PERF_SESSION_H +#define __PERF_SESSION_H + +#include "header.h" + +struct perf_session { + struct perf_header header; + unsigned long size; + int fd; + char filename[0]; +}; + +struct perf_session *perf_session__new(const char *filename, int mode, bool force); +void perf_session__delete(struct perf_session *self); + +#endif /* __PERF_SESSION_H */ |