aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/builtin-report.c5
-rw-r--r--tools/perf/util/compress.h11
-rw-r--r--tools/perf/util/session.c116
-rw-r--r--tools/perf/util/session.h10
-rw-r--r--tools/perf/util/zstd.c41
5 files changed, 181 insertions, 2 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 91e27ac297c2..1ca533f06a4c 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -1258,6 +1258,9 @@ repeat:
1258 if (session == NULL) 1258 if (session == NULL)
1259 return -1; 1259 return -1;
1260 1260
1261 if (zstd_init(&(session->zstd_data), 0) < 0)
1262 pr_warning("Decompression initialization failed. Reported data may be incomplete.\n");
1263
1261 if (report.queue_size) { 1264 if (report.queue_size) {
1262 ordered_events__set_alloc_size(&session->ordered_events, 1265 ordered_events__set_alloc_size(&session->ordered_events,
1263 report.queue_size); 1266 report.queue_size);
@@ -1448,7 +1451,7 @@ repeat:
1448error: 1451error:
1449 if (report.ptime_range) 1452 if (report.ptime_range)
1450 zfree(&report.ptime_range); 1453 zfree(&report.ptime_range);
1451 1454 zstd_fini(&(session->zstd_data));
1452 perf_session__delete(session); 1455 perf_session__delete(session);
1453 return ret; 1456 return ret;
1454} 1457}
diff --git a/tools/perf/util/compress.h b/tools/perf/util/compress.h
index 1041a4fd81e2..0cd3369af2a4 100644
--- a/tools/perf/util/compress.h
+++ b/tools/perf/util/compress.h
@@ -20,6 +20,7 @@ bool lzma_is_compressed(const char *input);
20struct zstd_data { 20struct zstd_data {
21#ifdef HAVE_ZSTD_SUPPORT 21#ifdef HAVE_ZSTD_SUPPORT
22 ZSTD_CStream *cstream; 22 ZSTD_CStream *cstream;
23 ZSTD_DStream *dstream;
23#endif 24#endif
24}; 25};
25 26
@@ -31,6 +32,9 @@ int zstd_fini(struct zstd_data *data);
31size_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_t dst_size, 32size_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_t dst_size,
32 void *src, size_t src_size, size_t max_record_size, 33 void *src, size_t src_size, size_t max_record_size,
33 size_t process_header(void *record, size_t increment)); 34 size_t process_header(void *record, size_t increment));
35
36size_t zstd_decompress_stream(struct zstd_data *data, void *src, size_t src_size,
37 void *dst, size_t dst_size);
34#else /* !HAVE_ZSTD_SUPPORT */ 38#else /* !HAVE_ZSTD_SUPPORT */
35 39
36static inline int zstd_init(struct zstd_data *data __maybe_unused, int level __maybe_unused) 40static inline int zstd_init(struct zstd_data *data __maybe_unused, int level __maybe_unused)
@@ -52,6 +56,13 @@ size_t zstd_compress_stream_to_records(struct zstd_data *data __maybe_unused,
52{ 56{
53 return 0; 57 return 0;
54} 58}
59
60static inline size_t zstd_decompress_stream(struct zstd_data *data __maybe_unused, void *src __maybe_unused,
61 size_t src_size __maybe_unused, void *dst __maybe_unused,
62 size_t dst_size __maybe_unused)
63{
64 return 0;
65}
55#endif 66#endif
56 67
57#endif /* PERF_COMPRESS_H */ 68#endif /* PERF_COMPRESS_H */
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
33static 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
32static int perf_session__deliver_event(struct perf_session *session, 87static 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
255static 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
200void perf_session__delete(struct perf_session *session) 270void 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
445static void swap_sample_id_all(union perf_event *event, void *data) 516static 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
1726volatile int session_done; 1797volatile int session_done;
1727 1798
1799static int __perf_session__process_decomp_events(struct perf_session *session);
1800
1728static int __perf_session__process_pipe_events(struct perf_session *session) 1801static 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;
1810done: 1887done:
@@ -1853,6 +1930,39 @@ fetch_mmaped_event(struct perf_session *session,
1853 return event; 1930 return event;
1854} 1931}
1855 1932
1933static 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())
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 6c984c895924..dd8920b745bc 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -39,6 +39,16 @@ struct perf_session {
39 u64 bytes_transferred; 39 u64 bytes_transferred;
40 u64 bytes_compressed; 40 u64 bytes_compressed;
41 struct zstd_data zstd_data; 41 struct zstd_data zstd_data;
42 struct decomp *decomp;
43 struct decomp *decomp_last;
44};
45
46struct decomp {
47 struct decomp *next;
48 u64 file_pos;
49 u64 head;
50 size_t size;
51 char data[];
42}; 52};
43 53
44struct perf_tool; 54struct perf_tool;
diff --git a/tools/perf/util/zstd.c b/tools/perf/util/zstd.c
index 359ec9a9d306..23bdb9884576 100644
--- a/tools/perf/util/zstd.c
+++ b/tools/perf/util/zstd.c
@@ -9,6 +9,21 @@ int zstd_init(struct zstd_data *data, int level)
9{ 9{
10 size_t ret; 10 size_t ret;
11 11
12 data->dstream = ZSTD_createDStream();
13 if (data->dstream == NULL) {
14 pr_err("Couldn't create decompression stream.\n");
15 return -1;
16 }
17
18 ret = ZSTD_initDStream(data->dstream);
19 if (ZSTD_isError(ret)) {
20 pr_err("Failed to initialize decompression stream: %s\n", ZSTD_getErrorName(ret));
21 return -1;
22 }
23
24 if (!level)
25 return 0;
26
12 data->cstream = ZSTD_createCStream(); 27 data->cstream = ZSTD_createCStream();
13 if (data->cstream == NULL) { 28 if (data->cstream == NULL) {
14 pr_err("Couldn't create compression stream.\n"); 29 pr_err("Couldn't create compression stream.\n");
@@ -26,6 +41,11 @@ int zstd_init(struct zstd_data *data, int level)
26 41
27int zstd_fini(struct zstd_data *data) 42int zstd_fini(struct zstd_data *data)
28{ 43{
44 if (data->dstream) {
45 ZSTD_freeDStream(data->dstream);
46 data->dstream = NULL;
47 }
48
29 if (data->cstream) { 49 if (data->cstream) {
30 ZSTD_freeCStream(data->cstream); 50 ZSTD_freeCStream(data->cstream);
31 data->cstream = NULL; 51 data->cstream = NULL;
@@ -68,3 +88,24 @@ size_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_t
68 88
69 return compressed; 89 return compressed;
70} 90}
91
92size_t zstd_decompress_stream(struct zstd_data *data, void *src, size_t src_size,
93 void *dst, size_t dst_size)
94{
95 size_t ret;
96 ZSTD_inBuffer input = { src, src_size, 0 };
97 ZSTD_outBuffer output = { dst, dst_size, 0 };
98
99 while (input.pos < input.size) {
100 ret = ZSTD_decompressStream(data->dstream, &output, &input);
101 if (ZSTD_isError(ret)) {
102 pr_err("failed to decompress (B): %ld -> %ld : %s\n",
103 src_size, output.size, ZSTD_getErrorName(ret));
104 break;
105 }
106 output.dst = dst + output.pos;
107 output.size = dst_size - output.pos;
108 }
109
110 return output.pos;
111}