summaryrefslogtreecommitdiff
path: root/tools/perf/util/zstd.c
AgeCommit message (Collapse)Author
2026-05-29perf zstd: Fix multi-iteration decompression and error handlingArnaldo Carvalho de Melo
zstd_decompress_stream() has two bugs in its multi-iteration loop: 1. After each ZSTD_decompressStream() call, the code advances output.dst by output.pos but doesn't reset output.pos to 0. ZSTD interprets output.pos relative to output.dst, so the next iteration writes at (dst + pos) + pos = dst + 2*pos, skipping a gap and potentially writing out of bounds. 2. On ZSTD_decompressStream() error, the loop executes break and returns output.pos (which is > 0 if some bytes were decompressed before the error). The caller checks !decomp_size and skips the error, silently accepting truncated or corrupted data. Fix both by removing the output buffer adjustment — ZSTD correctly accumulates output.pos across calls without it. Return 0 on decompression error so the caller detects it. Add a no-progress guard to prevent infinite loops if the output buffer fills before all input is consumed. Note: the compressed event data_size is validated against header.size by a subsequent patch in this series ("perf tools: Harden compressed event processing"). Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers <irogers@google.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-05-29perf zstd: Fix compression error path in zstd_compress_stream_to_records()Arnaldo Carvalho de Melo
The error fallback does memcpy(dst, src, src_size) intending to store uncompressed data when compression fails, but this has three bugs: 1. dst has been advanced past the record header (and potentially past earlier compressed records), so the copy writes to the wrong offset in the output buffer. 2. src still points to the start of the input, not to the remaining uncompressed data at src + input.pos. On a second or later iteration, previously compressed data would be duplicated. 3. No check that dst_size >= src_size — if the remaining output space is smaller, this is an out-of-bounds write. Replace with return -1 after resetting the ZSTD compression context via ZSTD_initCStream(). The -1 propagates through zstd_compress() -> record__pushfn() -> perf_mmap__push() to the recording loop, which breaks out and terminates recording. Add an out_child_no_flush label in __cmd_record() so the mmap-read failure path skips the final record__mmap_read_all() flush — retrying the same read that just failed would just fail again, and the flush is only useful when the mmap data is intact but the control path (auxtrace, switch_output) had an error. Consolidate all error paths through a single 'reset' label to ensure the compression context is always reset on failure — including the output-buffer-full path, where a bare return without resetting would leave stale stream state that corrupts output if the caller retries. Also guard against process_header() writing the event header before the buffer-full check: add a sizeof(perf_event_header) pre-check so the callback never writes past the output buffer. Guard against ZSTD making no progress: if output.pos is zero after ZSTD_compressStream(), calling process_header(record, 0) would re-trigger header initialization, double-subtracting the header size from dst_size and underflowing the unsigned counter. Also fix two pre-existing issues in the same function: - Add a dst_size guard before subtracting the record header size: if the output buffer is nearly full, the unsigned dst_size -= size underflows to a huge value, causing ZSTD_compressStream to write past the buffer boundary. - Check the ZSTD_initCStream() return value and log an error if the context reset itself fails. Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers <irogers@google.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2023-11-28perf mmap: Lazily initialize zstd streams to save memory when not using itIan Rogers
Zstd streams create dictionaries that can require significant RAM, especially when there is one per-CPU. Tools like 'perf record' won't use the streams without the -z option, and so the creation of the streams is pure overhead. Switch to creating the streams on first use. Committer notes: ssize_t comes from sys/types.h, size_t from stddef.h. This worked on glibc as stdlib.h includes both, but not on musl libc. So do what 'man size_t' says and include sys/types.h and stddef.h instead of stdlib.h Signed-off-by: Ian Rogers <irogers@google.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Athira Jajeev <atrajeev@linux.vnet.ibm.com> Cc: Changbin Du <changbin.du@huawei.com> Cc: Colin Ian King <colin.i.king@gmail.com> Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: German Gomez <german.gomez@arm.com> Cc: Huacai Chen <chenhuacai@kernel.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: James Clark <james.clark@arm.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: K Prateek Nayak <kprateek.nayak@amd.com> Cc: Kajol Jain <kjain@linux.ibm.com> Cc: Kan Liang <kan.liang@linux.intel.com> Cc: Leo Yan <leo.yan@linaro.org> Cc: Li Dong <lidong@vivo.com> Cc: Liam Howlett <liam.howlett@oracle.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Masami Hiramatsu (Google) <mhiramat@kernel.org> Cc: Miguel Ojeda <ojeda@kernel.org> Cc: Ming Wang <wangming01@loongson.cn> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Nick Terrell <terrelln@fb.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ravi Bangoria <ravi.bangoria@amd.com> Cc: Sandipan Das <sandipan.das@amd.com> Cc: Sean Christopherson <seanjc@google.com> Cc: Steinar H. Gunderson <sesse@google.com> Cc: Vincent Whitchurch <vincent.whitchurch@axis.com> Cc: Wenyu Liu <liuwenyu7@huawei.com> Cc: Yang Jihong <yangjihong1@huawei.com> Link: https://lore.kernel.org/r/20231102175735.2272696-5-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-09-01perf tools: Use %zd for size_t printf formats on 32-bitChris Wilson
A couple of trivial fixes for using %zd for size_t in the code supporting the ZSTD compression library. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Acked-by: Jiri Olsa <jolsa@redhat.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexey Budankov <alexey.budankov@linux.intel.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lore.kernel.org/lkml/20200820212501.24421-1-chris@chris-wilson.co.uk Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-23perf session: Fix loading of compressed data split across adjacent recordsAlexey Budankov
Fix decompression failure found during the loading of compressed trace collected on larger scale systems (>48 cores). The error happened due to lack of decompression space for a mmaped buffer data chunk split across adjacent PERF_RECORD_COMPRESSED records. $ perf report -i bt.16384.data --stats failed to decompress (B): 63869 -> 0 : Destination buffer is too small user stack dump failure Can't parse sample, err = -14 0x2637e436 [0x4080]: failed to process type: 9 Error: failed to process sample $ perf test 71 71: Zstd perf.data compression/decompression : Ok Signed-off-by: Alexey Budankov <alexey.budankov@linux.intel.com> Acked-by: Jiri Olsa <jolsa@kernel.org> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/4d839e1b-9c48-89c4-9702-a12217420611@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-05-15perf report: Implement perf.data record decompressionAlexey Budankov
zstd_init(, comp_level = 0) initializes decompression part of API only hat now consists of zstd_decompress_stream() function. The perf.data PERF_RECORD_COMPRESSED records are decompressed using zstd_decompress_stream() function into a linked list of mmaped memory regions of mmap_comp_len size (struct decomp). After decompression of one COMPRESSED record its content is iterated and fetched for usual processing. The mmaped memory regions with decompressed events are kept in the linked list till the tool process termination. When dumping raw records (e.g., perf report -D --header) file offsets of events from compressed records are printed as zero. Committer notes: Since now we have support for processing PERF_RECORD_COMPRESSED, we see none, in raw form, like we saw in the previous patch commiter notes, they were decompressed into the usual PERF_RECORD_{FORK,MMAP,COMM,etc} records, we only see the stats for those PERF_RECORD_COMPRESSED events, and since I used the file generated in the commiter notes for the previous patch, there they are, 2 compressed records: $ perf report --header-only | grep cmdline # cmdline : /home/acme/bin/perf record -z2 sleep 1 $ perf report -D | grep COMPRESS COMPRESSED events: 2 COMPRESSED events: 0 $ perf report --stdio # To display the perf.data header info, please use --header/--header-only options. # # # Total Lost Samples: 0 # # Samples: 15 of event 'cycles:u' # Event count (approx.): 962227 # # Overhead Command Shared Object Symbol # ........ ....... ................ ........................... # 46.99% sleep libc-2.28.so [.] _dl_addr 29.24% sleep [unknown] [k] 0xffffffffaea00a67 16.45% sleep libc-2.28.so [.] __GI__IO_un_link.part.1 5.92% sleep ld-2.28.so [.] _dl_setup_hash 1.40% sleep libc-2.28.so [.] __nanosleep 0.00% sleep [unknown] [k] 0xffffffffaea00163 # # (Tip: To see callchains in a more compact form: perf report -g folded) # $ Signed-off-by: Alexey Budankov <alexey.budankov@linux.intel.com> Reviewed-by: Jiri Olsa <jolsa@kernel.org> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/304b0a59-942c-3fe1-da02-aa749f87108b@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-05-15perf tools: Introduce Zstd streaming based compression APIAlexey Budankov
Implemented functions are based on Zstd streaming compression API. The functions are used in runtime to compress data that come from mmaped kernel buffer. zstd_init(), zstd_fini() are used for initialization and finalization to allocate and deallocate internal zstd objects. zstd_compress_stream_to_records() is used to convert parts of mmaped kernel buffer into an array of PERF_RECORD_COMPRESSED records. Signed-off-by: Alexey Budankov <alexey.budankov@linux.intel.com> Reviewed-by: Jiri Olsa <jolsa@kernel.org> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/18bf36f3-b85a-1fe2-dd83-10e0c6069568@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>