diff options
Diffstat (limited to 'tools/perf/util/session.c')
| -rw-r--r-- | tools/perf/util/session.c | 116 |
1 files changed, 115 insertions, 1 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index ec1dec86d0e1..2310a1752983 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
| @@ -29,6 +29,61 @@ | |||
| 29 | #include "stat.h" | 29 | #include "stat.h" |
| 30 | #include "arch/common.h" | 30 | #include "arch/common.h" |
| 31 | 31 | ||
| 32 | #ifdef HAVE_ZSTD_SUPPORT | ||
| 33 | static int perf_session__process_compressed_event(struct perf_session *session, | ||
| 34 | union perf_event *event, u64 file_offset) | ||
| 35 | { | ||
| 36 | void *src; | ||
| 37 | size_t decomp_size, src_size; | ||
| 38 | u64 decomp_last_rem = 0; | ||
| 39 | size_t decomp_len = session->header.env.comp_mmap_len; | ||
| 40 | struct decomp *decomp, *decomp_last = session->decomp_last; | ||
| 41 | |||
| 42 | decomp = mmap(NULL, sizeof(struct decomp) + decomp_len, PROT_READ|PROT_WRITE, | ||
| 43 | MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); | ||
| 44 | if (decomp == MAP_FAILED) { | ||
| 45 | pr_err("Couldn't allocate memory for decompression\n"); | ||
| 46 | return -1; | ||
| 47 | } | ||
| 48 | |||
| 49 | decomp->file_pos = file_offset; | ||
| 50 | decomp->head = 0; | ||
| 51 | |||
| 52 | if (decomp_last) { | ||
| 53 | decomp_last_rem = decomp_last->size - decomp_last->head; | ||
| 54 | memcpy(decomp->data, &(decomp_last->data[decomp_last->head]), decomp_last_rem); | ||
| 55 | decomp->size = decomp_last_rem; | ||
| 56 | } | ||
| 57 | |||
| 58 | src = (void *)event + sizeof(struct compressed_event); | ||
| 59 | src_size = event->pack.header.size - sizeof(struct compressed_event); | ||
| 60 | |||
| 61 | decomp_size = zstd_decompress_stream(&(session->zstd_data), src, src_size, | ||
| 62 | &(decomp->data[decomp_last_rem]), decomp_len - decomp_last_rem); | ||
| 63 | if (!decomp_size) { | ||
| 64 | munmap(decomp, sizeof(struct decomp) + decomp_len); | ||
| 65 | pr_err("Couldn't decompress data\n"); | ||
| 66 | return -1; | ||
| 67 | } | ||
| 68 | |||
| 69 | decomp->size += decomp_size; | ||
| 70 | |||
| 71 | if (session->decomp == NULL) { | ||
| 72 | session->decomp = decomp; | ||
| 73 | session->decomp_last = decomp; | ||
| 74 | } else { | ||
| 75 | session->decomp_last->next = decomp; | ||
| 76 | session->decomp_last = decomp; | ||
| 77 | } | ||
| 78 | |||
| 79 | pr_debug("decomp (B): %ld to %ld\n", src_size, decomp_size); | ||
| 80 | |||
| 81 | return 0; | ||
| 82 | } | ||
| 83 | #else /* !HAVE_ZSTD_SUPPORT */ | ||
| 84 | #define perf_session__process_compressed_event perf_session__process_compressed_event_stub | ||
| 85 | #endif | ||
| 86 | |||
| 32 | static int perf_session__deliver_event(struct perf_session *session, | 87 | static int perf_session__deliver_event(struct perf_session *session, |
| 33 | union perf_event *event, | 88 | union perf_event *event, |
| 34 | struct perf_tool *tool, | 89 | struct perf_tool *tool, |
| @@ -197,6 +252,21 @@ static void perf_session__delete_threads(struct perf_session *session) | |||
| 197 | machine__delete_threads(&session->machines.host); | 252 | machine__delete_threads(&session->machines.host); |
| 198 | } | 253 | } |
| 199 | 254 | ||
| 255 | static void perf_session__release_decomp_events(struct perf_session *session) | ||
| 256 | { | ||
| 257 | struct decomp *next, *decomp; | ||
| 258 | size_t decomp_len; | ||
| 259 | next = session->decomp; | ||
| 260 | decomp_len = session->header.env.comp_mmap_len; | ||
| 261 | do { | ||
| 262 | decomp = next; | ||
| 263 | if (decomp == NULL) | ||
| 264 | break; | ||
| 265 | next = decomp->next; | ||
| 266 | munmap(decomp, decomp_len + sizeof(struct decomp)); | ||
| 267 | } while (1); | ||
| 268 | } | ||
| 269 | |||
| 200 | void perf_session__delete(struct perf_session *session) | 270 | void perf_session__delete(struct perf_session *session) |
| 201 | { | 271 | { |
| 202 | if (session == NULL) | 272 | if (session == NULL) |
| @@ -205,6 +275,7 @@ void perf_session__delete(struct perf_session *session) | |||
| 205 | auxtrace_index__free(&session->auxtrace_index); | 275 | auxtrace_index__free(&session->auxtrace_index); |
| 206 | perf_session__destroy_kernel_maps(session); | 276 | perf_session__destroy_kernel_maps(session); |
| 207 | perf_session__delete_threads(session); | 277 | perf_session__delete_threads(session); |
| 278 | perf_session__release_decomp_events(session); | ||
| 208 | perf_env__exit(&session->header.env); | 279 | perf_env__exit(&session->header.env); |
| 209 | machines__exit(&session->machines); | 280 | machines__exit(&session->machines); |
| 210 | if (session->data) | 281 | if (session->data) |
| @@ -439,7 +510,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool) | |||
| 439 | if (tool->feature == NULL) | 510 | if (tool->feature == NULL) |
| 440 | tool->feature = process_event_op2_stub; | 511 | tool->feature = process_event_op2_stub; |
| 441 | if (tool->compressed == NULL) | 512 | if (tool->compressed == NULL) |
| 442 | tool->compressed = perf_session__process_compressed_event_stub; | 513 | tool->compressed = perf_session__process_compressed_event; |
| 443 | } | 514 | } |
| 444 | 515 | ||
| 445 | static void swap_sample_id_all(union perf_event *event, void *data) | 516 | static void swap_sample_id_all(union perf_event *event, void *data) |
| @@ -1725,6 +1796,8 @@ static int perf_session__flush_thread_stacks(struct perf_session *session) | |||
| 1725 | 1796 | ||
| 1726 | volatile int session_done; | 1797 | volatile int session_done; |
| 1727 | 1798 | ||
| 1799 | static int __perf_session__process_decomp_events(struct perf_session *session); | ||
| 1800 | |||
| 1728 | static int __perf_session__process_pipe_events(struct perf_session *session) | 1801 | static int __perf_session__process_pipe_events(struct perf_session *session) |
| 1729 | { | 1802 | { |
| 1730 | struct ordered_events *oe = &session->ordered_events; | 1803 | struct ordered_events *oe = &session->ordered_events; |
| @@ -1805,6 +1878,10 @@ more: | |||
| 1805 | if (skip > 0) | 1878 | if (skip > 0) |
| 1806 | head += skip; | 1879 | head += skip; |
| 1807 | 1880 | ||
| 1881 | err = __perf_session__process_decomp_events(session); | ||
| 1882 | if (err) | ||
| 1883 | goto out_err; | ||
| 1884 | |||
| 1808 | if (!session_done()) | 1885 | if (!session_done()) |
| 1809 | goto more; | 1886 | goto more; |
| 1810 | done: | 1887 | done: |
| @@ -1853,6 +1930,39 @@ fetch_mmaped_event(struct perf_session *session, | |||
| 1853 | return event; | 1930 | return event; |
| 1854 | } | 1931 | } |
| 1855 | 1932 | ||
| 1933 | static int __perf_session__process_decomp_events(struct perf_session *session) | ||
| 1934 | { | ||
| 1935 | s64 skip; | ||
| 1936 | u64 size, file_pos = 0; | ||
| 1937 | struct decomp *decomp = session->decomp_last; | ||
| 1938 | |||
| 1939 | if (!decomp) | ||
| 1940 | return 0; | ||
| 1941 | |||
| 1942 | while (decomp->head < decomp->size && !session_done()) { | ||
| 1943 | union perf_event *event = fetch_mmaped_event(session, decomp->head, decomp->size, decomp->data); | ||
| 1944 | |||
| 1945 | if (!event) | ||
| 1946 | break; | ||
| 1947 | |||
| 1948 | size = event->header.size; | ||
| 1949 | |||
| 1950 | if (size < sizeof(struct perf_event_header) || | ||
| 1951 | (skip = perf_session__process_event(session, event, file_pos)) < 0) { | ||
| 1952 | pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", | ||
| 1953 | decomp->file_pos + decomp->head, event->header.size, event->header.type); | ||
| 1954 | return -EINVAL; | ||
| 1955 | } | ||
| 1956 | |||
| 1957 | if (skip) | ||
| 1958 | size += skip; | ||
| 1959 | |||
| 1960 | decomp->head += size; | ||
| 1961 | } | ||
| 1962 | |||
| 1963 | return 0; | ||
| 1964 | } | ||
| 1965 | |||
| 1856 | /* | 1966 | /* |
| 1857 | * On 64bit we can mmap the data file in one go. No need for tiny mmap | 1967 | * On 64bit we can mmap the data file in one go. No need for tiny mmap |
| 1858 | * slices. On 32bit we use 32MB. | 1968 | * slices. On 32bit we use 32MB. |
| @@ -1962,6 +2072,10 @@ more: | |||
| 1962 | head += size; | 2072 | head += size; |
| 1963 | file_pos += size; | 2073 | file_pos += size; |
| 1964 | 2074 | ||
| 2075 | err = __perf_session__process_decomp_events(session); | ||
| 2076 | if (err) | ||
| 2077 | goto out; | ||
| 2078 | |||
| 1965 | ui_progress__update(prog, size); | 2079 | ui_progress__update(prog, size); |
| 1966 | 2080 | ||
| 1967 | if (session_done()) | 2081 | if (session_done()) |
