trigger_error(&auxtrace_snapshot_trigger);
trigger_error(&switch_output_trigger);
err = -1;
- goto out_child;
+ goto out_child_no_flush;
}
if (auxtrace_record__snapshot_started) {
out_child:
record__stop_threads(rec);
record__mmap_read_all(rec, true);
+ goto out_free_threads;
+out_child_no_flush:
+ /* mmap read already failed — retrying would just fail again */
+ record__stop_threads(rec);
out_free_threads:
record__free_thread_data(rec);
evlist__finalize_ctlfd(rec->evlist);
// SPDX-License-Identifier: GPL-2.0
#include <string.h>
+#include <linux/perf_event.h>
#include "util/compress.h"
#include "util/debug.h"
while (input.pos < input.size) {
record = dst;
+ /* process_header writes the event header into record */
+ if (dst_size < sizeof(struct perf_event_header))
+ goto reset;
size = process_header(record, 0);
+ /* Output buffer full — cannot fit even the record header */
+ if (size > dst_size)
+ goto reset;
compressed += size;
dst += size;
dst_size -= size;
if (ZSTD_isError(ret)) {
pr_err("failed to compress %ld bytes: %s\n",
(long)src_size, ZSTD_getErrorName(ret));
- memcpy(dst, src, src_size);
- return src_size;
+ goto reset;
}
size = output.pos;
+ /*
+ * No progress: ZSTD couldn't emit any bytes into the
+ * remaining output buffer. Calling process_header
+ * with size=0 would re-trigger header initialization,
+ * double-subtracting the header size from dst_size and
+ * underflowing the unsigned counter.
+ */
+ if (size == 0)
+ goto reset;
size = process_header(record, size);
compressed += size;
dst += size;
}
return compressed;
+
+reset:
+ /* Reset so the context is usable if the caller retries */
+ ret = ZSTD_initCStream(data->cstream, data->comp_level);
+ if (ZSTD_isError(ret))
+ pr_err("failed to reset compression context: %s\n",
+ ZSTD_getErrorName(ret));
+ return -1;
}
size_t zstd_decompress_stream(struct zstd_data *data, void *src, size_t src_size,