Skip to content

Commit

Permalink
perf tools: Add lzma decompression support for kernel module
Browse files Browse the repository at this point in the history
In short, Fedora compresses kernel modules now (since version 21) with
lzma compression.

Adding lzma decompress support into the dso.c:compressions array
introduced by Namhyung earlier.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-2glp65kdtbrk0gblmirsjsnt@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
  • Loading branch information
olsajiri authored and acmel committed Mar 21, 2015
1 parent 6c6f0f6 commit 80a32e5
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 0 deletions.
2 changes: 2 additions & 0 deletions tools/perf/Makefile.perf
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ include config/utilities.mak
#
# Define NO_LIBBABELTRACE if you do not want libbabeltrace support
# for CTF data format.
#
# Define NO_LZMA if you do not want to support compressed (xz) kernel modules

ifeq ($(srctree),)
srctree := $(patsubst %/,%,$(dir $(shell pwd)))
Expand Down
11 changes: 11 additions & 0 deletions tools/perf/config/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,17 @@ ifndef NO_ZLIB
endif
endif

ifndef NO_LZMA
ifeq ($(feature-lzma), 1)
CFLAGS += -DHAVE_LZMA_SUPPORT
EXTLIBS += -llzma
$(call detected,CONFIG_LZMA)
else
msg := $(warning No liblzma found, disables xz kernel module decompression, please install xz-devel/liblzma-dev);
NO_LZMA := 1
endif
endif

ifndef NO_BACKTRACE
ifeq ($(feature-backtrace), 1)
CFLAGS += -DHAVE_BACKTRACE_SUPPORT
Expand Down
1 change: 1 addition & 0 deletions tools/perf/util/Build
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ libperf-y += scripting-engines/

libperf-$(CONFIG_PERF_REGS) += perf_regs.o
libperf-$(CONFIG_ZLIB) += zlib.o
libperf-$(CONFIG_LZMA) += lzma.o

CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
CFLAGS_exec_cmd.o += -DPERF_EXEC_PATH="BUILD_STR($(perfexecdir_SQ))" -DPREFIX="BUILD_STR($(prefix_SQ))"
Expand Down
3 changes: 3 additions & 0 deletions tools/perf/util/dso.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ static const struct {
} compressions[] = {
#ifdef HAVE_ZLIB_SUPPORT
{ "gz", gzip_decompress_to_file },
#endif
#ifdef HAVE_LZMA_SUPPORT
{ "xz", lzma_decompress_to_file },
#endif
{ NULL, NULL },
};
Expand Down
95 changes: 95 additions & 0 deletions tools/perf/util/lzma.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#include <lzma.h>
#include <stdio.h>
#include <linux/compiler.h>
#include "util.h"
#include "debug.h"

#define BUFSIZE 8192

static const char *lzma_strerror(lzma_ret ret)
{
switch ((int) ret) {
case LZMA_MEM_ERROR:
return "Memory allocation failed";
case LZMA_OPTIONS_ERROR:
return "Unsupported decompressor flags";
case LZMA_FORMAT_ERROR:
return "The input is not in the .xz format";
case LZMA_DATA_ERROR:
return "Compressed file is corrupt";
case LZMA_BUF_ERROR:
return "Compressed file is truncated or otherwise corrupt";
default:
return "Unknown error, possibly a bug";
}
}

int lzma_decompress_to_file(const char *input, int output_fd)
{
lzma_action action = LZMA_RUN;
lzma_stream strm = LZMA_STREAM_INIT;
lzma_ret ret;

u8 buf_in[BUFSIZE];
u8 buf_out[BUFSIZE];
FILE *infile;

infile = fopen(input, "rb");
if (!infile) {
pr_err("lzma: fopen failed on %s: '%s'\n",
input, strerror(errno));
return -1;
}

ret = lzma_stream_decoder(&strm, UINT64_MAX, LZMA_CONCATENATED);
if (ret != LZMA_OK) {
pr_err("lzma: lzma_stream_decoder failed %s (%d)\n",
lzma_strerror(ret), ret);
return -1;
}

strm.next_in = NULL;
strm.avail_in = 0;
strm.next_out = buf_out;
strm.avail_out = sizeof(buf_out);

while (1) {
if (strm.avail_in == 0 && !feof(infile)) {
strm.next_in = buf_in;
strm.avail_in = fread(buf_in, 1, sizeof(buf_in), infile);

if (ferror(infile)) {
pr_err("lzma: read error: %s\n", strerror(errno));
return -1;
}

if (feof(infile))
action = LZMA_FINISH;
}

ret = lzma_code(&strm, action);

if (strm.avail_out == 0 || ret == LZMA_STREAM_END) {
ssize_t write_size = sizeof(buf_out) - strm.avail_out;

if (writen(output_fd, buf_out, write_size) != write_size) {
pr_err("lzma: write error: %s\n", strerror(errno));
return -1;
}

strm.next_out = buf_out;
strm.avail_out = sizeof(buf_out);
}

if (ret != LZMA_OK) {
if (ret == LZMA_STREAM_END)
return 0;

pr_err("lzma: failed %s\n", lzma_strerror(ret));
return -1;
}
}

fclose(infile);
return 0;
}
4 changes: 4 additions & 0 deletions tools/perf/util/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -329,4 +329,8 @@ bool find_process(const char *name);
int gzip_decompress_to_file(const char *input, int output_fd);
#endif

#ifdef HAVE_LZMA_SUPPORT
int lzma_decompress_to_file(const char *input, int output_fd);
#endif

#endif /* GIT_COMPAT_UTIL_H */

0 comments on commit 80a32e5

Please sign in to comment.