Linux Perf Users
 help / color / mirror / Atom feed
* [PATCH 0/4] perf: support zstd-compressed kernel modules
@ 2026-10-14 17:34 Ivan Shapovalov
  2026-10-14 17:34 ` [PATCH 1/4] perf: zstd: zstd_decompress_stream -> zstd_decompress_buffer Ivan Shapovalov
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Ivan Shapovalov @ 2026-10-14 17:34 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, James Clark, Nick Terrell,
	David Sterba
  Cc: linux-perf-users, linux-kernel, Ivan Shapovalov

This extends in-perf zstd code to add an interface for streaming
decompression of an entire file, and uses that interface in dso.c to
support handling of zstd-compressed DSOs (e.g., zstd-compressed kernel
modules, as shipped by various distros including Arch).

Signed-off-by: Ivan Shapovalov <intelfx@intelfx.name>
---
Ivan Shapovalov (4):
      perf: zstd: zstd_decompress_stream -> zstd_decompress_buffer
      perf: zstd: factor out zstd_init_{c,d}stream()
      perf: zstd: add streaming decompression and format probe functions
      perf: support zstd-compressed kernel modules

 tools/perf/Makefile.config |   2 +-
 tools/perf/util/compress.h |  22 +++++-
 tools/perf/util/dso.c      |   5 +-
 tools/perf/util/tool.c     |   2 +-
 tools/perf/util/zstd.c     | 188 +++++++++++++++++++++++++++++++++++++--------
 5 files changed, 183 insertions(+), 36 deletions(-)
---
base-commit: 0fcb05b72344f40806cbe810de8872f1698bf053
change-id: 20261014-perf-zstd-279017105eb3

Best regards,
--  
Ivan Shapovalov <intelfx@intelfx.name>


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/4] perf: zstd: zstd_decompress_stream -> zstd_decompress_buffer
  2026-10-14 17:34 [PATCH 0/4] perf: support zstd-compressed kernel modules Ivan Shapovalov
@ 2026-10-14 17:34 ` Ivan Shapovalov
  2026-10-14 17:38   ` sashiko-bot
  2026-10-14 17:34 ` [PATCH 2/4] perf: zstd: factor out zstd_init_{c,d}stream() Ivan Shapovalov
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 9+ messages in thread
From: Ivan Shapovalov @ 2026-10-14 17:34 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, James Clark, Nick Terrell,
	David Sterba
  Cc: linux-perf-users, linux-kernel, Ivan Shapovalov

Existing zstd_decompress_stream() function is a misnomer. Rename that
to zstd_decompress_buffer() to free the name for a future _actual_
streaming decompression function.

Signed-off-by: Ivan Shapovalov <intelfx@intelfx.name>
---
 tools/perf/util/compress.h | 4 ++--
 tools/perf/util/tool.c     | 2 +-
 tools/perf/util/zstd.c     | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/compress.h b/tools/perf/util/compress.h
index ec6c38129e248..e7aa89d31fc6f 100644
--- a/tools/perf/util/compress.h
+++ b/tools/perf/util/compress.h
@@ -57,7 +57,7 @@ ssize_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_
 				       ssize_t process_header(void *record, size_t dst_size,
 							      size_t data_size));
 
-size_t zstd_decompress_stream(struct zstd_data *data, void *src, size_t src_size,
+size_t zstd_decompress_buffer(struct zstd_data *data, void *src, size_t src_size,
 			      void *dst, size_t dst_size);
 #else /* !HAVE_ZSTD_SUPPORT */
 
@@ -82,7 +82,7 @@ ssize_t zstd_compress_stream_to_records(struct zstd_data *data __maybe_unused,
 	return 0;
 }
 
-static inline size_t zstd_decompress_stream(struct zstd_data *data __maybe_unused, void *src __maybe_unused,
+static inline size_t zstd_decompress_buffer(struct zstd_data *data __maybe_unused, void *src __maybe_unused,
 					    size_t src_size __maybe_unused, void *dst __maybe_unused,
 					    size_t dst_size __maybe_unused)
 {
diff --git a/tools/perf/util/tool.c b/tools/perf/util/tool.c
index 25c9b378aa163..d7956cd75c26d 100644
--- a/tools/perf/util/tool.c
+++ b/tools/perf/util/tool.c
@@ -101,7 +101,7 @@ static int perf_session__process_compressed_event(const struct perf_tool *tool _
 		goto err_decomp;
 	}
 
-	decomp_size = zstd_decompress_stream(session->active_decomp->zstd_decomp, src, src_size,
+	decomp_size = zstd_decompress_buffer(session->active_decomp->zstd_decomp, src, src_size,
 				&(decomp->data[decomp_last_rem]), decomp_len - decomp_last_rem);
 	if (!decomp_size) {
 		munmap(decomp, mmap_len);
diff --git a/tools/perf/util/zstd.c b/tools/perf/util/zstd.c
index d98014902f012..af113660d1ce0 100644
--- a/tools/perf/util/zstd.c
+++ b/tools/perf/util/zstd.c
@@ -104,7 +104,7 @@ ssize_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_
 	return -1;
 }
 
-size_t zstd_decompress_stream(struct zstd_data *data, void *src, size_t src_size,
+size_t zstd_decompress_buffer(struct zstd_data *data, void *src, size_t src_size,
 			      void *dst, size_t dst_size)
 {
 	size_t ret;

-- 
2.55.0.8.g37e2a0019f


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/4] perf: zstd: factor out zstd_init_{c,d}stream()
  2026-10-14 17:34 [PATCH 0/4] perf: support zstd-compressed kernel modules Ivan Shapovalov
  2026-10-14 17:34 ` [PATCH 1/4] perf: zstd: zstd_decompress_stream -> zstd_decompress_buffer Ivan Shapovalov
@ 2026-10-14 17:34 ` Ivan Shapovalov
  2026-10-14 17:43   ` sashiko-bot
  2026-10-14 17:34 ` [PATCH 3/4] perf: zstd: add streaming decompression and format probe functions Ivan Shapovalov
  2026-10-14 17:34 ` [PATCH 4/4] perf: support zstd-compressed kernel modules Ivan Shapovalov
  3 siblings, 1 reply; 9+ messages in thread
From: Ivan Shapovalov @ 2026-10-14 17:34 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, James Clark, Nick Terrell,
	David Sterba
  Cc: linux-perf-users, linux-kernel, Ivan Shapovalov

Factor out functions to manage CStream/DStream in `struct zstd_data`
for reuse across multiple zstd (de)compression entry points.

Signed-off-by: Ivan Shapovalov <intelfx@intelfx.name>
---
 tools/perf/util/zstd.c | 82 ++++++++++++++++++++++++++++++++------------------
 1 file changed, 52 insertions(+), 30 deletions(-)

diff --git a/tools/perf/util/zstd.c b/tools/perf/util/zstd.c
index af113660d1ce0..3af8910bb87cf 100644
--- a/tools/perf/util/zstd.c
+++ b/tools/perf/util/zstd.c
@@ -14,6 +14,50 @@ int zstd_init(struct zstd_data *data, int level)
 	return 0;
 }
 
+static int zstd_init_cstream(struct zstd_data *data)
+{
+	size_t ret;
+
+	if (!data->cstream) {
+		data->cstream = ZSTD_createCStream();
+		if (data->cstream == NULL) {
+			pr_err("zstd: failed to create compression stream\n");
+			return -1;
+		}
+
+		ret = ZSTD_initCStream(data->cstream, data->comp_level);
+		if (ZSTD_isError(ret)) {
+			pr_err("zstd: failed to initialize compression stream: %s\n",
+				ZSTD_getErrorName(ret));
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+static int zstd_init_dstream(struct zstd_data *data)
+{
+	size_t ret;
+
+	if (!data->dstream) {
+		data->dstream = ZSTD_createDStream();
+		if (data->dstream == NULL) {
+			pr_err("zstd: failed to create decompression stream\n");
+			return -1;
+		}
+
+		ret = ZSTD_initDStream(data->dstream);
+		if (ZSTD_isError(ret)) {
+			pr_err("zstd: failed to initialize decompression stream: %s\n",
+				ZSTD_getErrorName(ret));
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
 int zstd_fini(struct zstd_data *data)
 {
 	if (data->dstream) {
@@ -34,26 +78,14 @@ ssize_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_
 				       ssize_t process_header(void *record, size_t dst_size,
 							      size_t data_size))
 {
-	size_t ret, compressed = 0;
-	ssize_t size;
+	ssize_t ret, size, compressed = 0;
 	ZSTD_inBuffer input = { src, src_size, 0 };
 	ZSTD_outBuffer output;
 	void *record;
 
-	if (!data->cstream) {
-		data->cstream = ZSTD_createCStream();
-		if (data->cstream == NULL) {
-			pr_err("Couldn't create compression stream.\n");
-			return -1;
-		}
-
-		ret = ZSTD_initCStream(data->cstream, data->comp_level);
-		if (ZSTD_isError(ret)) {
-			pr_err("Failed to initialize compression stream: %s\n",
-				ZSTD_getErrorName(ret));
-			return -1;
-		}
-	}
+	ret = zstd_init_cstream(data);
+	if (ret < 0)
+		return ret;
 
 	while (input.pos < input.size) {
 		record = dst;
@@ -107,24 +139,14 @@ ssize_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_
 size_t zstd_decompress_buffer(struct zstd_data *data, void *src, size_t src_size,
 			      void *dst, size_t dst_size)
 {
-	size_t ret;
+	ssize_t ret;
 	ZSTD_inBuffer input = { src, src_size, 0 };
 	ZSTD_outBuffer output = { dst, dst_size, 0 };
 
-	if (!data->dstream) {
-		data->dstream = ZSTD_createDStream();
-		if (data->dstream == NULL) {
-			pr_err("Couldn't create decompression stream.\n");
-			return 0;
-		}
+	ret = zstd_init_dstream(data);
+	if (ret < 0)
+		return ret;
 
-		ret = ZSTD_initDStream(data->dstream);
-		if (ZSTD_isError(ret)) {
-			pr_err("Failed to initialize decompression stream: %s\n",
-				ZSTD_getErrorName(ret));
-			return 0;
-		}
-	}
 	while (input.pos < input.size) {
 		size_t prev_in = input.pos;
 		size_t prev_out = output.pos;

-- 
2.55.0.8.g37e2a0019f


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/4] perf: zstd: add streaming decompression and format probe functions
  2026-10-14 17:34 [PATCH 0/4] perf: support zstd-compressed kernel modules Ivan Shapovalov
  2026-10-14 17:34 ` [PATCH 1/4] perf: zstd: zstd_decompress_stream -> zstd_decompress_buffer Ivan Shapovalov
  2026-10-14 17:34 ` [PATCH 2/4] perf: zstd: factor out zstd_init_{c,d}stream() Ivan Shapovalov
@ 2026-10-14 17:34 ` Ivan Shapovalov
  2026-10-14 17:51   ` sashiko-bot
  2026-10-14 17:34 ` [PATCH 4/4] perf: support zstd-compressed kernel modules Ivan Shapovalov
  3 siblings, 1 reply; 9+ messages in thread
From: Ivan Shapovalov @ 2026-10-14 17:34 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, James Clark, Nick Terrell,
	David Sterba
  Cc: linux-perf-users, linux-kernel, Ivan Shapovalov

Add an actual streaming zstd decompression (fd->fd) entry point,
plus a file->fd wrapper and a helper to detect zstd magic on a file
for compressions[] in dso.c.

Signed-off-by: Ivan Shapovalov <intelfx@intelfx.name>
---
 tools/perf/util/compress.h |  18 ++++++++
 tools/perf/util/zstd.c     | 104 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 122 insertions(+)

diff --git a/tools/perf/util/compress.h b/tools/perf/util/compress.h
index e7aa89d31fc6f..fd6b541358bb6 100644
--- a/tools/perf/util/compress.h
+++ b/tools/perf/util/compress.h
@@ -59,6 +59,9 @@ ssize_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_
 
 size_t zstd_decompress_buffer(struct zstd_data *data, void *src, size_t src_size,
 			      void *dst, size_t dst_size);
+int zstd_decompress_stream(struct zstd_data *data, int input_fd, int output_fd);
+int zstd_decompress_to_fd(const char *input, int output_fd);
+bool zstd_is_compressed(const char *input);
 #else /* !HAVE_ZSTD_SUPPORT */
 
 static inline int zstd_init(struct zstd_data *data __maybe_unused, int level __maybe_unused)
@@ -88,6 +91,21 @@ static inline size_t zstd_decompress_buffer(struct zstd_data *data __maybe_unuse
 {
 	return 0;
 }
+
+static inline int zstd_decompress_stream(struct zstd_data *data, int input_fd, int output_fd)
+{
+	return -1;
+}
+
+static inline int zstd_decompress_to_fd(const char *input, int output_fd)
+{
+	return -1;
+}
+
+static inline bool zstd_is_compressed(const char *input)
+{
+	return false;
+}
 #endif
 
 #endif /* PERF_COMPRESS_H */
diff --git a/tools/perf/util/zstd.c b/tools/perf/util/zstd.c
index 3af8910bb87cf..982655a1f1a51 100644
--- a/tools/perf/util/zstd.c
+++ b/tools/perf/util/zstd.c
@@ -1,7 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0
 
+#include <errno.h>
+#include <fcntl.h>
 #include <string.h>
+#include <unistd.h>
 #include <linux/perf_event.h>
+#include <internal/lib.h>
 
 #include "util/compress.h"
 #include "util/debug.h"
@@ -172,3 +176,103 @@ size_t zstd_decompress_buffer(struct zstd_data *data, void *src, size_t src_size
 
 	return output.pos;
 }
+
+int zstd_decompress_stream(struct zstd_data *data, int input_fd, int output_fd)
+{
+	ssize_t ret;
+	bool unflushed = false;
+	char buf_in[ZSTD_DStreamInSize()];
+	char buf_out[ZSTD_DStreamOutSize()];
+	ZSTD_inBuffer in = {};
+	ZSTD_outBuffer out = {};
+
+	ret = zstd_init_dstream(data);
+	if (ret < 0)
+		return ret;
+
+	for (;;) {
+		if (in.pos == in.size) {
+			/* out of input, read more */
+			ret = read(input_fd, buf_in, sizeof(buf_in));
+			if (ret < 0) {
+				pr_err("zstd: failed to read() %zu bytes: %s\n",
+				       sizeof(buf_in), strerror(errno));
+				return ret;
+			}
+			in = (ZSTD_inBuffer) {
+				.src = &buf_in,
+				.pos = 0,
+				.size = ret,
+			};
+		}
+
+		if (in.pos == in.size && !unflushed) {
+			/* out of input, out of file, and nothing to flush, exit */
+			break;
+		}
+
+		out = (ZSTD_outBuffer) {
+			.dst = &buf_out,
+			.pos = 0,
+			.size = sizeof(buf_out),
+		};
+		ret = ZSTD_decompressStream(data->dstream, &out, &in);
+		if (ZSTD_isError(ret)) {
+			pr_err("zstd: failed to decompress %zu bytes into buffer of %zu bytes (wrote %zu): %s\n",
+				in.size, out.size, out.pos, ZSTD_getErrorName(ret));
+			return -1;
+		}
+		unflushed = ret > 0;
+
+		ret = writen(output_fd, out.dst, out.pos);
+		if (ret < 0) {
+			pr_err("zstd: failed to write() %zu bytes: %s\n",
+			       out.pos, strerror(errno));
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+int zstd_decompress_to_fd(const char *input, int output_fd)
+{
+	int input_fd = -1;
+	int ret;
+	struct zstd_data data;
+
+	input_fd = open(input, O_RDONLY);
+	if (input_fd < 0) {
+		pr_err("zstd: failed to open(%s): %s\n", input, strerror(errno));
+		return -1;
+	}
+
+	ret = zstd_init(&data, ZSTD_CLEVEL_DEFAULT);
+	if (ret < 0)
+		goto err;
+
+	ret = zstd_decompress_stream(&data, input_fd, output_fd);
+
+err:
+	zstd_fini(&data);
+	close(input_fd);
+	return ret;
+}
+
+bool zstd_is_compressed(const char *file)
+{
+	int fd = open(file, O_RDONLY);
+	const uint32_t magic_le = htole32(ZSTD_MAGICNUMBER);
+	char buf[4];
+	ssize_t rc;
+
+	if (fd < 0) {
+		pr_err("zstd: failed to open(%s): %s\n", file, strerror(errno));
+		return -1;
+	}
+
+	rc = read(fd, buf, sizeof(buf));
+	close(fd);
+	return rc == sizeof(buf) ?
+	       memcmp(buf, (const char *) &magic_le, sizeof(buf)) == 0 : false;
+}

-- 
2.55.0.8.g37e2a0019f


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/4] perf: support zstd-compressed kernel modules
  2026-10-14 17:34 [PATCH 0/4] perf: support zstd-compressed kernel modules Ivan Shapovalov
                   ` (2 preceding siblings ...)
  2026-10-14 17:34 ` [PATCH 3/4] perf: zstd: add streaming decompression and format probe functions Ivan Shapovalov
@ 2026-10-14 17:34 ` Ivan Shapovalov
  2026-10-14 17:58   ` sashiko-bot
  3 siblings, 1 reply; 9+ messages in thread
From: Ivan Shapovalov @ 2026-10-14 17:34 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, James Clark, Nick Terrell,
	David Sterba
  Cc: linux-perf-users, linux-kernel, Ivan Shapovalov

Support handling loading zstd-compressed DSOs in perf (in addition to
existing support for gzip/xz formats). This allows loading of e.g.
zstd-compressed kernel modules, as shipped by various distros
including Arch.

Signed-off-by: Ivan Shapovalov <intelfx@intelfx.name>
---
 tools/perf/Makefile.config | 2 +-
 tools/perf/util/dso.c      | 5 ++++-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 4d5993da9f945..dfdda22becc39 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -982,7 +982,7 @@ ifndef NO_LIBZSTD
     EXTLIBS += -lzstd
     $(call detected,CONFIG_ZSTD)
   else
-    $(warning No libzstd found, disables trace compression, please install libzstd-dev[el] and/or set LIBZSTD_DIR)
+    $(warning No libzstd found, disables zstd kernel module decompression and trace compression, please install libzstd-dev[el] and/or set LIBZSTD_DIR)
     NO_LIBZSTD := 1
   endif
 endif
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 42bfe30a3b518..0e8886172e239 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -277,6 +277,9 @@ static const struct {
 #endif
 #ifdef HAVE_LZMA_SUPPORT
 	{ "xz", lzma_decompress_to_file, lzma_is_compressed },
+#endif
+#ifdef HAVE_ZSTD_SUPPORT
+	{ "zst", zstd_decompress_to_fd, zstd_is_compressed },
 #endif
 	{ NULL, NULL, NULL },
 };
@@ -460,7 +463,7 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
 
 	m->comp = is_supported_compression(ext + 1);
 	if (m->comp > COMP_ID__NONE)
-		ext -= 3;
+		ext -= strlen(compressions[m->comp].fmt);
 
 	/* Check .ko extension only if there's enough name left. */
 	if (ext > name)

-- 
2.55.0.8.g37e2a0019f


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/4] perf: zstd: zstd_decompress_stream -> zstd_decompress_buffer
  2026-10-14 17:34 ` [PATCH 1/4] perf: zstd: zstd_decompress_stream -> zstd_decompress_buffer Ivan Shapovalov
@ 2026-10-14 17:38   ` sashiko-bot
  0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-10-14 17:38 UTC (permalink / raw)
  To: Ivan Shapovalov; +Cc: linux-perf-users

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] perf: stale function name in comment for zstd_decompress_buffer
--

commit a8489356f2f1a85e8397e7dba79a95d1bfde0cb1
Author: Ivan Shapovalov <intelfx@intelfx.name>

perf: zstd: zstd_decompress_stream -> zstd_decompress_buffer

This commit renames zstd_decompress_stream() to zstd_decompress_buffer() to
free up the old name for an actual streaming decompression function.

> diff --git a/tools/perf/util/tool.c b/tools/perf/util/tool.c
> index 25c9b378aa163..d7956cd75c26d 100644
> --- a/tools/perf/util/tool.c
> +++ b/tools/perf/util/tool.c
[ ... ]
> @@ -92,15 +92,15 @@ static int perf_session__process_compressed_event(const struct perf_tool *tool _
>  		src = (void *)event + sizeof(struct perf_record_compressed2);
>  		src_size = event->pack2.data_size;
>  		/*
>  		 * data_size is independent of header.size (which
>  		 * includes padding); verify it doesn't exceed the
>  		 * actual payload to prevent out-of-bounds reads in
>  		 * zstd_decompress_stream().
>  		 */

[Severity: Low]
Could this comment in perf_session__process_compressed_event() be updated to
reference the renamed zstd_decompress_buffer() function?

Since the commit message indicates the old name will be reused for a different
function, leaving this stale comment could be confusing when the new function
is introduced.

>  		if (src_size > event->header.size - sizeof(struct perf_record_compressed2))
>  			goto err_decomp;
>  	} else {
>  		goto err_decomp;
>  	}
>  
> -	decomp_size = zstd_decompress_stream(session->active_decomp->zstd_decomp, src, src_size,
> +	decomp_size = zstd_decompress_buffer(session->active_decomp->zstd_decomp, src, src_size,
>  				&(decomp->data[decomp_last_rem]), decomp_len - decomp_last_rem);

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261014-perf-zstd-v1-0-9652727886fa@intelfx.name?part=1

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/4] perf: zstd: factor out zstd_init_{c,d}stream()
  2026-10-14 17:34 ` [PATCH 2/4] perf: zstd: factor out zstd_init_{c,d}stream() Ivan Shapovalov
@ 2026-10-14 17:43   ` sashiko-bot
  0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-10-14 17:43 UTC (permalink / raw)
  To: Ivan Shapovalov; +Cc: linux-perf-users

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] perf: zstd_decompress_buffer() returns SIZE_MAX instead of 0 on error
--

commit 1d761c8689bb9c7209c96548d100b2308a92f2a5
Author: Ivan Shapovalov <intelfx@intelfx.name>

perf: zstd: factor out zstd_init_{c,d}stream()

Factor out functions to manage CStream/DStream in struct zstd_data
for reuse across multiple zstd (de)compression entry points.

> diff --git a/tools/perf/util/zstd.c b/tools/perf/util/zstd.c
> index af113660d1ce0..3af8910bb87cf 100644
> --- a/tools/perf/util/zstd.c
> +++ b/tools/perf/util/zstd.c
[ ... ]
> @@ -107,24 +139,14 @@ ssize_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_
>  size_t zstd_decompress_buffer(struct zstd_data *data, void *src, size_t src_size,
>  			      void *dst, size_t dst_size)
>  {
> -	size_t ret;
> +	ssize_t ret;
>  	ZSTD_inBuffer input = { src, src_size, 0 };
>  	ZSTD_outBuffer output = { dst, dst_size, 0 };
>  
> -	if (!data->dstream) {
> -		data->dstream = ZSTD_createDStream();
> -		if (data->dstream == NULL) {
> -			pr_err("Couldn't create decompression stream.\n");
> -			return 0;
> -		}
> +	ret = zstd_init_dstream(data);
> +	if (ret < 0)
> +		return ret;

[Severity: High]
Since zstd_decompress_buffer() returns a size_t, will returning a negative
error code here implicitly cast -1 to SIZE_MAX?

It looks like callers such as perf_session__process_compressed_event() check
for a 0 return to detect failure. If zstd_init_dstream() fails, wouldn't
returning SIZE_MAX cause the caller to treat it as a huge success,
potentially leading to massive out-of-bounds size increments?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261014-perf-zstd-v1-0-9652727886fa@intelfx.name?part=2

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/4] perf: zstd: add streaming decompression and format probe functions
  2026-10-14 17:34 ` [PATCH 3/4] perf: zstd: add streaming decompression and format probe functions Ivan Shapovalov
@ 2026-10-14 17:51   ` sashiko-bot
  0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-10-14 17:51 UTC (permalink / raw)
  To: Ivan Shapovalov; +Cc: linux-perf-users

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] perf tools: zstd_is_compressed() returns true on file open failure
- [Low] perf: missing explicit <stdint.h> and <endian.h> for musl compatibility
--

commit a4c94e50df0d36cb48138075042eb1c0c1527f18
Author: Ivan Shapovalov <intelfx@intelfx.name>

    perf: zstd: add streaming decompression and format probe functions
    
    Add an actual streaming zstd decompression (fd->fd) entry point,
    plus a file->fd wrapper and a helper to detect zstd magic on a file
    for compressions[] in dso.c.

> diff --git a/tools/perf/util/zstd.c b/tools/perf/util/zstd.c
> index 3af8910bb87cf..982655a1f1a51 100644
> --- a/tools/perf/util/zstd.c
> +++ b/tools/perf/util/zstd.c

[ ... ]

> @@ -172,3 +176,103 @@ size_t zstd_decompress_buffer(struct zstd_data *data, void *src, size_t src_size

[ ... ]

> +bool zstd_is_compressed(const char *file)
> +{
> +	int fd = open(file, O_RDONLY);
> +	const uint32_t magic_le = htole32(ZSTD_MAGICNUMBER);

[Severity: Low]
Does this code need explicit inclusions for <stdint.h> and <endian.h>?

It appears compiling perf tools with musl libc could result in a build failure
here, since musl enforces strict POSIX header namespace separation and does not
leak uint32_t and htole32 through other standard library headers.

> +	char buf[4];
> +	ssize_t rc;
> +
> +	if (fd < 0) {
> +		pr_err("zstd: failed to open(%s): %s\n", file, strerror(errno));
> +		return -1;

[Severity: Medium]
Since zstd_is_compressed() returns a bool, does returning -1 here implicitly
evaluate to true?

If open() fails, returning true could cause callers probing file formats to
erroneously identify missing or unreadable files as valid ZSTD-compressed
archives. This could break fallback logic and lead to downstream decompression
attempts on missing files.

> +	}
> +
> +	rc = read(fd, buf, sizeof(buf));
> +	close(fd);
> +	return rc == sizeof(buf) ?
> +	       memcmp(buf, (const char *) &magic_le, sizeof(buf)) == 0 : false;
> +}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261014-perf-zstd-v1-0-9652727886fa@intelfx.name?part=3

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 4/4] perf: support zstd-compressed kernel modules
  2026-10-14 17:34 ` [PATCH 4/4] perf: support zstd-compressed kernel modules Ivan Shapovalov
@ 2026-10-14 17:58   ` sashiko-bot
  0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-10-14 17:58 UTC (permalink / raw)
  To: Ivan Shapovalov; +Cc: linux-perf-users

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] perf: Incorrect pointer arithmetic breaks gzip/xz module detection
--

commit db2ed0262b65a0b2dfef65f9c73099d856ec9244
Author: Ivan Shapovalov <intelfx@intelfx.name>

perf: support zstd-compressed kernel modules

This commit adds support for handling zstd-compressed DSOs in perf. It allows
perf to load zstd-compressed kernel modules by identifying the .zst extension.

> diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
> index 42bfe30a3b518..0e8886172e239 100644
> --- a/tools/perf/util/dso.c
> +++ b/tools/perf/util/dso.c
[ ... ]
> @@ -460,7 +463,7 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
>  
>  	m->comp = is_supported_compression(ext + 1);
>  	if (m->comp > COMP_ID__NONE)
> -		ext -= 3;
> +		ext -= strlen(compressions[m->comp].fmt);
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

[Severity: High]
Does this pointer arithmetic break the detection of gzip and xz compressed
modules?

When parsing a compressed module path like foo.ko.gz, ext initially points
to the last dot (for example, the dot before gz).

To check for the .ko extension, the code must shift the pointer backward by
3 bytes to point to the dot in .ko. The original code subtracted 3 because
the string .ko is exactly 3 bytes long.

By subtracting the length of the compression format string instead, this
now subtracts 2 for gz and xz formats. This shifts the pointer to the
character o in .ko rather than the dot.

The subsequent check in __kmod_path__parse():

	if (ext > name)
		m->kmod = !strncmp(ext, ".ko", 3);

will then compare o.g or o.x to .ko, which fails. This causes perf to
silently ignore .ko.gz and .ko.xz files and incorrectly flag them as not
being kernel modules.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261014-perf-zstd-v1-0-9652727886fa@intelfx.name?part=4

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-10-14 17:58 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-14 17:34 [PATCH 0/4] perf: support zstd-compressed kernel modules Ivan Shapovalov
2026-10-14 17:34 ` [PATCH 1/4] perf: zstd: zstd_decompress_stream -> zstd_decompress_buffer Ivan Shapovalov
2026-10-14 17:38   ` sashiko-bot
2026-10-14 17:34 ` [PATCH 2/4] perf: zstd: factor out zstd_init_{c,d}stream() Ivan Shapovalov
2026-10-14 17:43   ` sashiko-bot
2026-10-14 17:34 ` [PATCH 3/4] perf: zstd: add streaming decompression and format probe functions Ivan Shapovalov
2026-10-14 17:51   ` sashiko-bot
2026-10-14 17:34 ` [PATCH 4/4] perf: support zstd-compressed kernel modules Ivan Shapovalov
2026-10-14 17:58   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox