提交 8d3eca20 编写于 作者: D David Ahern 提交者: Arnaldo Carvalho de Melo

perf record: Remove use of die/exit

Allows perf to clean up properly on exit. If perf-record is exiting due
to failure, the on_exit should not run as the session has been deleted.
Signed-off-by: NDavid Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1346005487-62961-8-git-send-email-dsahern@gmail.comSigned-off-by: NArnaldo Carvalho de Melo <acme@redhat.com>
上级 d54b1a9e
...@@ -71,19 +71,23 @@ static void advance_output(struct perf_record *rec, size_t size) ...@@ -71,19 +71,23 @@ static void advance_output(struct perf_record *rec, size_t size)
rec->bytes_written += size; rec->bytes_written += size;
} }
static void write_output(struct perf_record *rec, void *buf, size_t size) static int write_output(struct perf_record *rec, void *buf, size_t size)
{ {
while (size) { while (size) {
int ret = write(rec->output, buf, size); int ret = write(rec->output, buf, size);
if (ret < 0) if (ret < 0) {
die("failed to write"); pr_err("failed to write\n");
return -1;
}
size -= ret; size -= ret;
buf += ret; buf += ret;
rec->bytes_written += ret; rec->bytes_written += ret;
} }
return 0;
} }
static int process_synthesized_event(struct perf_tool *tool, static int process_synthesized_event(struct perf_tool *tool,
...@@ -92,11 +96,13 @@ static int process_synthesized_event(struct perf_tool *tool, ...@@ -92,11 +96,13 @@ static int process_synthesized_event(struct perf_tool *tool,
struct machine *machine __used) struct machine *machine __used)
{ {
struct perf_record *rec = container_of(tool, struct perf_record, tool); struct perf_record *rec = container_of(tool, struct perf_record, tool);
write_output(rec, event, event->header.size); if (write_output(rec, event, event->header.size) < 0)
return -1;
return 0; return 0;
} }
static void perf_record__mmap_read(struct perf_record *rec, static int perf_record__mmap_read(struct perf_record *rec,
struct perf_mmap *md) struct perf_mmap *md)
{ {
unsigned int head = perf_mmap__read_head(md); unsigned int head = perf_mmap__read_head(md);
...@@ -104,9 +110,10 @@ static void perf_record__mmap_read(struct perf_record *rec, ...@@ -104,9 +110,10 @@ static void perf_record__mmap_read(struct perf_record *rec,
unsigned char *data = md->base + rec->page_size; unsigned char *data = md->base + rec->page_size;
unsigned long size; unsigned long size;
void *buf; void *buf;
int rc = 0;
if (old == head) if (old == head)
return; return 0;
rec->samples++; rec->samples++;
...@@ -117,17 +124,26 @@ static void perf_record__mmap_read(struct perf_record *rec, ...@@ -117,17 +124,26 @@ static void perf_record__mmap_read(struct perf_record *rec,
size = md->mask + 1 - (old & md->mask); size = md->mask + 1 - (old & md->mask);
old += size; old += size;
write_output(rec, buf, size); if (write_output(rec, buf, size) < 0) {
rc = -1;
goto out;
}
} }
buf = &data[old & md->mask]; buf = &data[old & md->mask];
size = head - old; size = head - old;
old += size; old += size;
write_output(rec, buf, size); if (write_output(rec, buf, size) < 0) {
rc = -1;
goto out;
}
md->prev = old; md->prev = old;
perf_mmap__write_tail(md, old); perf_mmap__write_tail(md, old);
out:
return rc;
} }
static volatile int done = 0; static volatile int done = 0;
...@@ -183,12 +199,13 @@ static bool perf_evlist__equal(struct perf_evlist *evlist, ...@@ -183,12 +199,13 @@ static bool perf_evlist__equal(struct perf_evlist *evlist,
return true; return true;
} }
static void perf_record__open(struct perf_record *rec) static int perf_record__open(struct perf_record *rec)
{ {
struct perf_evsel *pos; struct perf_evsel *pos;
struct perf_evlist *evlist = rec->evlist; struct perf_evlist *evlist = rec->evlist;
struct perf_session *session = rec->session; struct perf_session *session = rec->session;
struct perf_record_opts *opts = &rec->opts; struct perf_record_opts *opts = &rec->opts;
int rc = 0;
perf_evlist__config_attrs(evlist, opts); perf_evlist__config_attrs(evlist, opts);
...@@ -222,10 +239,13 @@ static void perf_record__open(struct perf_record *rec) ...@@ -222,10 +239,13 @@ static void perf_record__open(struct perf_record *rec)
if (err == EPERM || err == EACCES) { if (err == EPERM || err == EACCES) {
ui__error_paranoid(); ui__error_paranoid();
exit(EXIT_FAILURE); rc = -err;
goto out;
} else if (err == ENODEV && opts->target.cpu_list) { } else if (err == ENODEV && opts->target.cpu_list) {
die("No such device - did you specify" pr_err("No such device - did you specify"
" an out-of-range profile CPU?\n"); " an out-of-range profile CPU?\n");
rc = -err;
goto out;
} else if (err == EINVAL) { } else if (err == EINVAL) {
if (!opts->exclude_guest_missing && if (!opts->exclude_guest_missing &&
(attr->exclude_guest || attr->exclude_host)) { (attr->exclude_guest || attr->exclude_host)) {
...@@ -272,7 +292,8 @@ static void perf_record__open(struct perf_record *rec) ...@@ -272,7 +292,8 @@ static void perf_record__open(struct perf_record *rec)
if (err == ENOENT) { if (err == ENOENT) {
ui__error("The %s event is not supported.\n", ui__error("The %s event is not supported.\n",
perf_evsel__name(pos)); perf_evsel__name(pos));
exit(EXIT_FAILURE); rc = -err;
goto out;
} }
printf("\n"); printf("\n");
...@@ -280,34 +301,46 @@ static void perf_record__open(struct perf_record *rec) ...@@ -280,34 +301,46 @@ static void perf_record__open(struct perf_record *rec)
err, strerror(err)); err, strerror(err));
#if defined(__i386__) || defined(__x86_64__) #if defined(__i386__) || defined(__x86_64__)
if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) if (attr->type == PERF_TYPE_HARDWARE &&
die("No hardware sampling interrupt available." err == EOPNOTSUPP) {
" No APIC? If so then you can boot the kernel" pr_err("No hardware sampling interrupt available."
" with the \"lapic\" boot parameter to" " No APIC? If so then you can boot the kernel"
" force-enable it.\n"); " with the \"lapic\" boot parameter to"
" force-enable it.\n");
rc = -err;
goto out;
}
#endif #endif
die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); pr_err("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
rc = -err;
goto out;
} }
} }
if (perf_evlist__set_filters(evlist)) { if (perf_evlist__set_filters(evlist)) {
error("failed to set filter with %d (%s)\n", errno, error("failed to set filter with %d (%s)\n", errno,
strerror(errno)); strerror(errno));
exit(-1); rc = -1;
goto out;
} }
if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
if (errno == EPERM) if (errno == EPERM) {
die("Permission error mapping pages.\n" pr_err("Permission error mapping pages.\n"
"Consider increasing " "Consider increasing "
"/proc/sys/kernel/perf_event_mlock_kb,\n" "/proc/sys/kernel/perf_event_mlock_kb,\n"
"or try again with a smaller value of -m/--mmap_pages.\n" "or try again with a smaller value of -m/--mmap_pages.\n"
"(current value: %d)\n", opts->mmap_pages); "(current value: %d)\n", opts->mmap_pages);
else if (!is_power_of_2(opts->mmap_pages)) rc = -errno;
die("--mmap_pages/-m value must be a power of two."); } else if (!is_power_of_2(opts->mmap_pages)) {
pr_err("--mmap_pages/-m value must be a power of two.");
die("failed to mmap with %d (%s)\n", errno, strerror(errno)); rc = -EINVAL;
} else {
pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno));
rc = -errno;
}
goto out;
} }
if (rec->file_new) if (rec->file_new)
...@@ -315,11 +348,14 @@ static void perf_record__open(struct perf_record *rec) ...@@ -315,11 +348,14 @@ static void perf_record__open(struct perf_record *rec)
else { else {
if (!perf_evlist__equal(session->evlist, evlist)) { if (!perf_evlist__equal(session->evlist, evlist)) {
fprintf(stderr, "incompatible append\n"); fprintf(stderr, "incompatible append\n");
exit(-1); rc = -1;
goto out;
} }
} }
perf_session__set_id_hdr_size(session); perf_session__set_id_hdr_size(session);
out:
return rc;
} }
static int process_buildids(struct perf_record *rec) static int process_buildids(struct perf_record *rec)
...@@ -335,10 +371,13 @@ static int process_buildids(struct perf_record *rec) ...@@ -335,10 +371,13 @@ static int process_buildids(struct perf_record *rec)
size, &build_id__mark_dso_hit_ops); size, &build_id__mark_dso_hit_ops);
} }
static void perf_record__exit(int status __used, void *arg) static void perf_record__exit(int status, void *arg)
{ {
struct perf_record *rec = arg; struct perf_record *rec = arg;
if (status != 0)
return;
if (!rec->opts.pipe_output) { if (!rec->opts.pipe_output) {
rec->session->header.data_size += rec->bytes_written; rec->session->header.data_size += rec->bytes_written;
...@@ -393,17 +432,26 @@ static struct perf_event_header finished_round_event = { ...@@ -393,17 +432,26 @@ static struct perf_event_header finished_round_event = {
.type = PERF_RECORD_FINISHED_ROUND, .type = PERF_RECORD_FINISHED_ROUND,
}; };
static void perf_record__mmap_read_all(struct perf_record *rec) static int perf_record__mmap_read_all(struct perf_record *rec)
{ {
int i; int i;
int rc = 0;
for (i = 0; i < rec->evlist->nr_mmaps; i++) { for (i = 0; i < rec->evlist->nr_mmaps; i++) {
if (rec->evlist->mmap[i].base) if (rec->evlist->mmap[i].base) {
perf_record__mmap_read(rec, &rec->evlist->mmap[i]); if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) {
rc = -1;
goto out;
}
}
} }
if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA)) if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA))
write_output(rec, &finished_round_event, sizeof(finished_round_event)); rc = write_output(rec, &finished_round_event,
sizeof(finished_round_event));
out:
return rc;
} }
static int __cmd_record(struct perf_record *rec, int argc, const char **argv) static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
...@@ -463,7 +511,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) ...@@ -463,7 +511,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
output = open(output_name, flags, S_IRUSR | S_IWUSR); output = open(output_name, flags, S_IRUSR | S_IWUSR);
if (output < 0) { if (output < 0) {
perror("failed to create output file"); perror("failed to create output file");
exit(-1); return -1;
} }
rec->output = output; rec->output = output;
...@@ -503,7 +551,10 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) ...@@ -503,7 +551,10 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
} }
} }
perf_record__open(rec); if (perf_record__open(rec) != 0) {
err = -1;
goto out_delete_session;
}
/* /*
* perf_session__delete(session) will be called at perf_record__exit() * perf_session__delete(session) will be called at perf_record__exit()
...@@ -513,19 +564,20 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) ...@@ -513,19 +564,20 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
if (opts->pipe_output) { if (opts->pipe_output) {
err = perf_header__write_pipe(output); err = perf_header__write_pipe(output);
if (err < 0) if (err < 0)
return err; goto out_delete_session;
} else if (rec->file_new) { } else if (rec->file_new) {
err = perf_session__write_header(session, evsel_list, err = perf_session__write_header(session, evsel_list,
output, false); output, false);
if (err < 0) if (err < 0)
return err; goto out_delete_session;
} }
if (!rec->no_buildid if (!rec->no_buildid
&& !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
pr_err("Couldn't generate buildids. " pr_err("Couldn't generate buildids. "
"Use --no-buildid to profile anyway.\n"); "Use --no-buildid to profile anyway.\n");
return -1; err = -1;
goto out_delete_session;
} }
rec->post_processing_offset = lseek(output, 0, SEEK_CUR); rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
...@@ -533,7 +585,8 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) ...@@ -533,7 +585,8 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
machine = perf_session__find_host_machine(session); machine = perf_session__find_host_machine(session);
if (!machine) { if (!machine) {
pr_err("Couldn't find native kernel information.\n"); pr_err("Couldn't find native kernel information.\n");
return -1; err = -1;
goto out_delete_session;
} }
if (opts->pipe_output) { if (opts->pipe_output) {
...@@ -541,14 +594,14 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) ...@@ -541,14 +594,14 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
process_synthesized_event); process_synthesized_event);
if (err < 0) { if (err < 0) {
pr_err("Couldn't synthesize attrs.\n"); pr_err("Couldn't synthesize attrs.\n");
return err; goto out_delete_session;
} }
err = perf_event__synthesize_event_types(tool, process_synthesized_event, err = perf_event__synthesize_event_types(tool, process_synthesized_event,
machine); machine);
if (err < 0) { if (err < 0) {
pr_err("Couldn't synthesize event_types.\n"); pr_err("Couldn't synthesize event_types.\n");
return err; goto out_delete_session;
} }
if (have_tracepoints(&evsel_list->entries)) { if (have_tracepoints(&evsel_list->entries)) {
...@@ -564,7 +617,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) ...@@ -564,7 +617,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
process_synthesized_event); process_synthesized_event);
if (err <= 0) { if (err <= 0) {
pr_err("Couldn't record tracing data.\n"); pr_err("Couldn't record tracing data.\n");
return err; goto out_delete_session;
} }
advance_output(rec, err); advance_output(rec, err);
} }
...@@ -592,20 +645,24 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) ...@@ -592,20 +645,24 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
perf_event__synthesize_guest_os); perf_event__synthesize_guest_os);
if (!opts->target.system_wide) if (!opts->target.system_wide)
perf_event__synthesize_thread_map(tool, evsel_list->threads, err = perf_event__synthesize_thread_map(tool, evsel_list->threads,
process_synthesized_event, process_synthesized_event,
machine); machine);
else else
perf_event__synthesize_threads(tool, process_synthesized_event, err = perf_event__synthesize_threads(tool, process_synthesized_event,
machine); machine);
if (err != 0)
goto out_delete_session;
if (rec->realtime_prio) { if (rec->realtime_prio) {
struct sched_param param; struct sched_param param;
param.sched_priority = rec->realtime_prio; param.sched_priority = rec->realtime_prio;
if (sched_setscheduler(0, SCHED_FIFO, &param)) { if (sched_setscheduler(0, SCHED_FIFO, &param)) {
pr_err("Could not set realtime priority.\n"); pr_err("Could not set realtime priority.\n");
exit(-1); err = -1;
goto out_delete_session;
} }
} }
...@@ -620,7 +677,10 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) ...@@ -620,7 +677,10 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
for (;;) { for (;;) {
int hits = rec->samples; int hits = rec->samples;
perf_record__mmap_read_all(rec); if (perf_record__mmap_read_all(rec) < 0) {
err = -1;
goto out_delete_session;
}
if (hits == rec->samples) { if (hits == rec->samples) {
if (done) if (done)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册