Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6a4d98d7 authored by Jiri Olsa's avatar Jiri Olsa Committed by Arnaldo Carvalho de Melo
Browse files

perf tools: Add perf_data_file__open interface to data object



Adding perf_data_file__open interface to data object to open the
perf.data file for both read and write.

Signed-off-by: default avatarJiri Olsa <jolsa@redhat.com>
Acked-by: default avatarNamhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1381847254-28809-3-git-send-email-jolsa@redhat.com


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent f5fc1412
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -365,6 +365,7 @@ LIB_OBJS += $(OUTPUT)util/vdso.o
LIB_OBJS += $(OUTPUT)util/stat.o
LIB_OBJS += $(OUTPUT)util/record.o
LIB_OBJS += $(OUTPUT)util/srcline.o
LIB_OBJS += $(OUTPUT)util/data.o

LIB_OBJS += $(OUTPUT)ui/setup.o
LIB_OBJS += $(OUTPUT)ui/helpline.o
+1 −33
Original line number Diff line number Diff line
@@ -345,8 +345,6 @@ static int perf_record__mmap_read_all(struct perf_record *rec)

static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
{
	struct stat st;
	int flags;
	int err, feat;
	unsigned long waking = 0;
	const bool forks = argc > 0;
@@ -355,7 +353,6 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
	struct perf_record_opts *opts = &rec->opts;
	struct perf_evlist *evsel_list = rec->evlist;
	struct perf_data_file *file = &rec->file;
	const char *output_name = file->path;
	struct perf_session *session;
	bool disabled = false;

@@ -367,35 +364,6 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
	signal(SIGUSR1, sig_handler);
	signal(SIGTERM, sig_handler);

	if (!output_name) {
		if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
			file->is_pipe = true;
		else
			file->path = output_name = "perf.data";
	}
	if (output_name) {
		if (!strcmp(output_name, "-"))
			file->is_pipe = true;
		else if (!stat(output_name, &st) && st.st_size) {
			char oldname[PATH_MAX];
			snprintf(oldname, sizeof(oldname), "%s.old",
				 output_name);
			unlink(oldname);
			rename(output_name, oldname);
		}
	}

	flags = O_CREAT|O_RDWR|O_TRUNC;

	if (file->is_pipe)
		file->fd = STDOUT_FILENO;
	else
		file->fd = open(output_name, flags, S_IRUSR | S_IWUSR);
	if (file->fd < 0) {
		perror("failed to create output file");
		return -1;
	}

	session = perf_session__new(file, false, NULL);
	if (session == NULL) {
		pr_err("Not enough memory for reading perf file header\n");
@@ -586,7 +554,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
	fprintf(stderr,
		"[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
		(double)rec->bytes_written / 1024.0 / 1024.0,
		output_name,
		file->path,
		rec->bytes_written / 24);

	return 0;
+1 −8
Original line number Diff line number Diff line
@@ -929,15 +929,8 @@ static int __cmd_top(struct perf_top *top)
	struct perf_record_opts *opts = &top->record_opts;
	pthread_t thread;
	int ret;
	struct perf_data_file file = {
		.mode = PERF_DATA_MODE_WRITE,
	};

	/*
	 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
	 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
	 */
	top->session = perf_session__new(&file, false, NULL);
	top->session = perf_session__new(NULL, false, NULL);
	if (top->session == NULL)
		return -ENOMEM;

tools/perf/util/data.c

0 → 100644
+120 −0
Original line number Diff line number Diff line
#include <linux/compiler.h>
#include <linux/kernel.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>

#include "data.h"
#include "util.h"

static bool check_pipe(struct perf_data_file *file)
{
	struct stat st;
	bool is_pipe = false;
	int fd = perf_data_file__is_read(file) ?
		 STDIN_FILENO : STDOUT_FILENO;

	if (!file->path) {
		if (!fstat(fd, &st) && S_ISFIFO(st.st_mode))
			is_pipe = true;
	} else {
		if (!strcmp(file->path, "-"))
			is_pipe = true;
	}

	if (is_pipe)
		file->fd = fd;

	return file->is_pipe = is_pipe;
}

static int check_backup(struct perf_data_file *file)
{
	struct stat st;

	if (!stat(file->path, &st) && st.st_size) {
		/* TODO check errors properly */
		char oldname[PATH_MAX];
		snprintf(oldname, sizeof(oldname), "%s.old",
			 file->path);
		unlink(oldname);
		rename(file->path, oldname);
	}

	return 0;
}

static int open_file_read(struct perf_data_file *file)
{
	struct stat st;
	int fd;

	fd = open(file->path, O_RDONLY);
	if (fd < 0) {
		int err = errno;

		pr_err("failed to open %s: %s", file->path, strerror(err));
		if (err == ENOENT && !strcmp(file->path, "perf.data"))
			pr_err("  (try 'perf record' first)");
		pr_err("\n");
		return -err;
	}

	if (fstat(fd, &st) < 0)
		goto out_close;

	if (!file->force && st.st_uid && (st.st_uid != geteuid())) {
		pr_err("file %s not owned by current user or root\n",
		       file->path);
		goto out_close;
	}

	if (!st.st_size) {
		pr_info("zero-sized file (%s), nothing to do!\n",
			file->path);
		goto out_close;
	}

	file->size = st.st_size;
	return fd;

 out_close:
	close(fd);
	return -1;
}

static int open_file_write(struct perf_data_file *file)
{
	if (check_backup(file))
		return -1;

	return open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
}

static int open_file(struct perf_data_file *file)
{
	int fd;

	fd = perf_data_file__is_read(file) ?
	     open_file_read(file) : open_file_write(file);

	file->fd = fd;
	return fd < 0 ? -1 : 0;
}

int perf_data_file__open(struct perf_data_file *file)
{
	if (check_pipe(file))
		return 0;

	if (!file->path)
		file->path = "perf.data";

	return open_file(file);
}

void perf_data_file__close(struct perf_data_file *file)
{
	close(file->fd);
}
+4 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ struct perf_data_file {
	int fd;
	bool is_pipe;
	bool force;
	unsigned long size;
	enum perf_data_mode mode;
};

@@ -26,4 +27,7 @@ static inline bool perf_data_file__is_write(struct perf_data_file *file)
	return file->mode == PERF_DATA_MODE_WRITE;
}

int perf_data_file__open(struct perf_data_file *file);
void perf_data_file__close(struct perf_data_file *file);

#endif /* __PERF_DATA_H */
Loading