aboutsummaryrefslogtreecommitdiff
path: root/tools/perf/util
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/data_map.c71
-rw-r--r--tools/perf/util/data_map.h9
-rw-r--r--tools/perf/util/header.c28
-rw-r--r--tools/perf/util/header.h4
-rw-r--r--tools/perf/util/session.c80
-rw-r--r--tools/perf/util/session.h16
6 files changed, 118 insertions, 90 deletions
diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c
index 59b65d0bd7c..6d46dda53a2 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 258a87bcc4f..98c5b823388 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 59a9c0b3033..f2e8d871511 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 d1dbe2b79c4..d118d05d3ab 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 00000000000..707ce1cb162
--- /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 00000000000..f3699c8c8ed
--- /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 */