diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/perf/Documentation/perf-record.txt | 4 | ||||
| -rw-r--r-- | tools/perf/builtin-record.c | 30 | ||||
| -rw-r--r-- | tools/perf/util/data.c | 11 | ||||
| -rw-r--r-- | tools/perf/util/data.h | 2 |
4 files changed, 39 insertions, 8 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index 8f0c2be34848..8fe4dffcadd0 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt | |||
| @@ -495,6 +495,10 @@ overhead. You can still switch them on with: | |||
| 495 | 495 | ||
| 496 | --switch-output --no-no-buildid --no-no-buildid-cache | 496 | --switch-output --no-no-buildid --no-no-buildid-cache |
| 497 | 497 | ||
| 498 | --switch-max-files=N:: | ||
| 499 | |||
| 500 | When rotating perf.data with --switch-output, only keep N files. | ||
| 501 | |||
| 498 | --dry-run:: | 502 | --dry-run:: |
| 499 | Parse options then exit. --dry-run can be used to detect errors in cmdline | 503 | Parse options then exit. --dry-run can be used to detect errors in cmdline |
| 500 | options. | 504 | options. |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index a468d882e74f..02d7c40b2d10 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
| @@ -62,6 +62,9 @@ struct switch_output { | |||
| 62 | unsigned long time; | 62 | unsigned long time; |
| 63 | const char *str; | 63 | const char *str; |
| 64 | bool set; | 64 | bool set; |
| 65 | char **filenames; | ||
| 66 | int num_files; | ||
| 67 | int cur_file; | ||
| 65 | }; | 68 | }; |
| 66 | 69 | ||
| 67 | struct record { | 70 | struct record { |
| @@ -892,6 +895,7 @@ record__switch_output(struct record *rec, bool at_exit) | |||
| 892 | { | 895 | { |
| 893 | struct perf_data *data = &rec->data; | 896 | struct perf_data *data = &rec->data; |
| 894 | int fd, err; | 897 | int fd, err; |
| 898 | char *new_filename; | ||
| 895 | 899 | ||
| 896 | /* Same Size: "2015122520103046"*/ | 900 | /* Same Size: "2015122520103046"*/ |
| 897 | char timestamp[] = "InvalidTimestamp"; | 901 | char timestamp[] = "InvalidTimestamp"; |
| @@ -912,7 +916,7 @@ record__switch_output(struct record *rec, bool at_exit) | |||
| 912 | 916 | ||
| 913 | fd = perf_data__switch(data, timestamp, | 917 | fd = perf_data__switch(data, timestamp, |
| 914 | rec->session->header.data_offset, | 918 | rec->session->header.data_offset, |
| 915 | at_exit); | 919 | at_exit, &new_filename); |
| 916 | if (fd >= 0 && !at_exit) { | 920 | if (fd >= 0 && !at_exit) { |
| 917 | rec->bytes_written = 0; | 921 | rec->bytes_written = 0; |
| 918 | rec->session->header.data_size = 0; | 922 | rec->session->header.data_size = 0; |
| @@ -922,6 +926,21 @@ record__switch_output(struct record *rec, bool at_exit) | |||
| 922 | fprintf(stderr, "[ perf record: Dump %s.%s ]\n", | 926 | fprintf(stderr, "[ perf record: Dump %s.%s ]\n", |
| 923 | data->path, timestamp); | 927 | data->path, timestamp); |
| 924 | 928 | ||
| 929 | if (rec->switch_output.num_files) { | ||
| 930 | int n = rec->switch_output.cur_file + 1; | ||
| 931 | |||
| 932 | if (n >= rec->switch_output.num_files) | ||
| 933 | n = 0; | ||
| 934 | rec->switch_output.cur_file = n; | ||
| 935 | if (rec->switch_output.filenames[n]) { | ||
| 936 | remove(rec->switch_output.filenames[n]); | ||
| 937 | free(rec->switch_output.filenames[n]); | ||
| 938 | } | ||
| 939 | rec->switch_output.filenames[n] = new_filename; | ||
| 940 | } else { | ||
| 941 | free(new_filename); | ||
| 942 | } | ||
| 943 | |||
| 925 | /* Output tracking events */ | 944 | /* Output tracking events */ |
| 926 | if (!at_exit) { | 945 | if (!at_exit) { |
| 927 | record__synthesize(rec, false); | 946 | record__synthesize(rec, false); |
| @@ -1973,6 +1992,8 @@ static struct option __record_options[] = { | |||
| 1973 | &record.switch_output.set, "signal,size,time", | 1992 | &record.switch_output.set, "signal,size,time", |
| 1974 | "Switch output when receive SIGUSR2 or cross size,time threshold", | 1993 | "Switch output when receive SIGUSR2 or cross size,time threshold", |
| 1975 | "signal"), | 1994 | "signal"), |
| 1995 | OPT_INTEGER(0, "switch-max-files", &record.switch_output.num_files, | ||
| 1996 | "Limit number of switch output generated files"), | ||
| 1976 | OPT_BOOLEAN(0, "dry-run", &dry_run, | 1997 | OPT_BOOLEAN(0, "dry-run", &dry_run, |
| 1977 | "Parse options then exit"), | 1998 | "Parse options then exit"), |
| 1978 | #ifdef HAVE_AIO_SUPPORT | 1999 | #ifdef HAVE_AIO_SUPPORT |
| @@ -2059,6 +2080,13 @@ int cmd_record(int argc, const char **argv) | |||
| 2059 | alarm(rec->switch_output.time); | 2080 | alarm(rec->switch_output.time); |
| 2060 | } | 2081 | } |
| 2061 | 2082 | ||
| 2083 | if (rec->switch_output.num_files) { | ||
| 2084 | rec->switch_output.filenames = calloc(sizeof(char *), | ||
| 2085 | rec->switch_output.num_files); | ||
| 2086 | if (!rec->switch_output.filenames) | ||
| 2087 | return -EINVAL; | ||
| 2088 | } | ||
| 2089 | |||
| 2062 | /* | 2090 | /* |
| 2063 | * Allow aliases to facilitate the lookup of symbols for address | 2091 | * Allow aliases to facilitate the lookup of symbols for address |
| 2064 | * filters. Refer to auxtrace_parse_filters(). | 2092 | * filters. Refer to auxtrace_parse_filters(). |
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c index c6b67efea11a..6a64f713710d 100644 --- a/tools/perf/util/data.c +++ b/tools/perf/util/data.c | |||
| @@ -361,9 +361,9 @@ ssize_t perf_data__write(struct perf_data *data, | |||
| 361 | 361 | ||
| 362 | int perf_data__switch(struct perf_data *data, | 362 | int perf_data__switch(struct perf_data *data, |
| 363 | const char *postfix, | 363 | const char *postfix, |
| 364 | size_t pos, bool at_exit) | 364 | size_t pos, bool at_exit, |
| 365 | char **new_filepath) | ||
| 365 | { | 366 | { |
| 366 | char *new_filepath; | ||
| 367 | int ret; | 367 | int ret; |
| 368 | 368 | ||
| 369 | if (check_pipe(data)) | 369 | if (check_pipe(data)) |
| @@ -371,15 +371,15 @@ int perf_data__switch(struct perf_data *data, | |||
| 371 | if (perf_data__is_read(data)) | 371 | if (perf_data__is_read(data)) |
| 372 | return -EINVAL; | 372 | return -EINVAL; |
| 373 | 373 | ||
| 374 | if (asprintf(&new_filepath, "%s.%s", data->path, postfix) < 0) | 374 | if (asprintf(new_filepath, "%s.%s", data->path, postfix) < 0) |
| 375 | return -ENOMEM; | 375 | return -ENOMEM; |
| 376 | 376 | ||
| 377 | /* | 377 | /* |
| 378 | * Only fire a warning, don't return error, continue fill | 378 | * Only fire a warning, don't return error, continue fill |
| 379 | * original file. | 379 | * original file. |
| 380 | */ | 380 | */ |
| 381 | if (rename(data->path, new_filepath)) | 381 | if (rename(data->path, *new_filepath)) |
| 382 | pr_warning("Failed to rename %s to %s\n", data->path, new_filepath); | 382 | pr_warning("Failed to rename %s to %s\n", data->path, *new_filepath); |
| 383 | 383 | ||
| 384 | if (!at_exit) { | 384 | if (!at_exit) { |
| 385 | close(data->file.fd); | 385 | close(data->file.fd); |
| @@ -396,7 +396,6 @@ int perf_data__switch(struct perf_data *data, | |||
| 396 | } | 396 | } |
| 397 | ret = data->file.fd; | 397 | ret = data->file.fd; |
| 398 | out: | 398 | out: |
| 399 | free(new_filepath); | ||
| 400 | return ret; | 399 | return ret; |
| 401 | } | 400 | } |
| 402 | 401 | ||
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h index 6aef8746469f..259868a39019 100644 --- a/tools/perf/util/data.h +++ b/tools/perf/util/data.h | |||
| @@ -70,7 +70,7 @@ ssize_t perf_data_file__write(struct perf_data_file *file, | |||
| 70 | */ | 70 | */ |
| 71 | int perf_data__switch(struct perf_data *data, | 71 | int perf_data__switch(struct perf_data *data, |
| 72 | const char *postfix, | 72 | const char *postfix, |
| 73 | size_t pos, bool at_exit); | 73 | size_t pos, bool at_exit, char **new_filepath); |
| 74 | 74 | ||
| 75 | int perf_data__create_dir(struct perf_data *data, int nr); | 75 | int perf_data__create_dir(struct perf_data *data, int nr); |
| 76 | int perf_data__open_dir(struct perf_data *data); | 76 | int perf_data__open_dir(struct perf_data *data); |
