From 347272731e15d3c4a70fad7ccd7185e8e8059d01 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 25 Jun 2014 20:53:40 -0400 Subject: [PATCH] coredump: make compression configurable Add Compression={none,xz} and CompressionLevel=0-9 settings. Defaults are xz/6. Compression=filesystem may be added later. I picked "xz" for the compression "type", since we might want to add different compressors later on. XZ is fairly memory and CPU intensive, and embedded users will likely want to use LZO or some other lightweight compression mechanism. --- src/journal/compress.c | 4 +- src/journal/compress.h | 2 +- src/journal/coredump.c | 73 +++++++++++++++++++++++++++++-------- src/journal/test-compress.c | 2 +- 4 files changed, 62 insertions(+), 19 deletions(-) diff --git a/src/journal/compress.c b/src/journal/compress.c index f36c43080..1fc62ead2 100644 --- a/src/journal/compress.c +++ b/src/journal/compress.c @@ -203,7 +203,7 @@ fail: return b; } -int compress_stream(int fdf, int fdt, off_t max_bytes) { +int compress_stream(int fdf, int fdt, uint32_t preset, off_t max_bytes) { _cleanup_(lzma_end) lzma_stream s = LZMA_STREAM_INIT; lzma_ret ret; @@ -213,7 +213,7 @@ int compress_stream(int fdf, int fdt, off_t max_bytes) { assert(fdf >= 0); assert(fdt >= 0); - ret = lzma_easy_encoder(&s, LZMA_PRESET_DEFAULT, LZMA_CHECK_CRC64); + ret = lzma_easy_encoder(&s, preset, LZMA_CHECK_CRC64); if (ret != LZMA_OK) { log_error("Failed to initialize XZ encoder: code %d", ret); return -EINVAL; diff --git a/src/journal/compress.h b/src/journal/compress.h index f37a6b3d1..f25fe86ab 100644 --- a/src/journal/compress.h +++ b/src/journal/compress.h @@ -35,5 +35,5 @@ bool uncompress_startswith(const void *src, uint64_t src_size, const void *prefix, uint64_t prefix_len, uint8_t extra); -int compress_stream(int fdf, int fdt, off_t max_size); +int compress_stream(int fdf, int fdt, uint32_t preset, off_t max_size); int decompress_stream(int fdf, int fdt, off_t max_size); diff --git a/src/journal/coredump.c b/src/journal/coredump.c index 1c5c99c39..afd69cda5 100644 --- a/src/journal/coredump.c +++ b/src/journal/coredump.c @@ -44,8 +44,14 @@ #include "compress.h" #ifdef HAVE_ACL -#include -#include "acl-util.h" +# include +# include "acl-util.h" +#endif + +#ifdef HAVE_XZ +# include +#else +# define LZMA_PRESET_DEFAULT 0 #endif /* The maximum size up to which we process coredumps */ @@ -83,11 +89,6 @@ typedef enum CoredumpStorage { _COREDUMP_STORAGE_INVALID = -1 } CoredumpStorage; -static CoredumpStorage arg_storage = COREDUMP_STORAGE_EXTERNAL; -static off_t arg_process_size_max = PROCESS_SIZE_MAX; -static off_t arg_external_size_max = EXTERNAL_SIZE_MAX; -static size_t arg_journal_size_max = JOURNAL_SIZE_MAX; - static const char* const coredump_storage_table[_COREDUMP_STORAGE_MAX] = { [COREDUMP_STORAGE_NONE] = "none", [COREDUMP_STORAGE_EXTERNAL] = "external", @@ -96,15 +97,45 @@ static const char* const coredump_storage_table[_COREDUMP_STORAGE_MAX] = { }; DEFINE_PRIVATE_STRING_TABLE_LOOKUP(coredump_storage, CoredumpStorage); -static DEFINE_CONFIG_PARSE_ENUM(config_parse_coredump_storage, coredump_storage, CoredumpStorage, "Failed to parse storage setting"); +static DEFINE_CONFIG_PARSE_ENUM(config_parse_coredump_storage, coredump_storage, + CoredumpStorage, + "Failed to parse storage setting"); + +typedef enum CoredumpCompression { + COREDUMP_COMPRESSION_NONE, + COREDUMP_COMPRESSION_XZ, + _COREDUMP_COMPRESSION_MAX, + _COREDUMP_COMPRESSION_INVALID = -1 +} CoredumpCompression; + +static const char* const coredump_compression_table[_COREDUMP_COMPRESSION_MAX] = { + [COREDUMP_COMPRESSION_NONE] = "none", + [COREDUMP_COMPRESSION_XZ] = "xz", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP(coredump_compression, CoredumpCompression); +static DEFINE_CONFIG_PARSE_ENUM(config_parse_coredump_compression, coredump_compression, + CoredumpCompression, + "Failed to parse compression setting"); + +static CoredumpStorage arg_storage = COREDUMP_STORAGE_EXTERNAL; +static CoredumpCompression arg_compression = COREDUMP_COMPRESSION_XZ; +static unsigned arg_compression_level = LZMA_PRESET_DEFAULT; + +static off_t arg_process_size_max = PROCESS_SIZE_MAX; +static off_t arg_external_size_max = EXTERNAL_SIZE_MAX; +static size_t arg_journal_size_max = JOURNAL_SIZE_MAX; static int parse_config(void) { static const ConfigTableItem items[] = { - { "Coredump", "ProcessSizeMax", config_parse_iec_off, 0, &arg_process_size_max }, - { "Coredump", "ExternalSizeMax", config_parse_iec_off, 0, &arg_external_size_max }, - { "Coredump", "JournalSizeMax", config_parse_iec_size, 0, &arg_journal_size_max }, - { "Coredump", "Storage", config_parse_coredump_storage, 0, &arg_storage }, + { "Coredump", "Storage", config_parse_coredump_storage, 0, &arg_storage }, + { "Coredump", "Compression", config_parse_coredump_compression, 0, &arg_compression }, + { "Coredump", "CompressionLevel", config_parse_unsigned, 0, &arg_compression_level }, + + { "Coredump", "ProcessSizeMax", config_parse_iec_off, 0, &arg_process_size_max }, + { "Coredump", "ExternalSizeMax", config_parse_iec_off, 0, &arg_external_size_max }, + { "Coredump", "JournalSizeMax", config_parse_iec_size, 0, &arg_journal_size_max }, {} }; @@ -118,6 +149,13 @@ static int parse_config(void) { false, false, NULL); + +#ifdef HAVE_XZ + if (arg_compression_level > 9) { + log_warning("Invalid CompressionLevel %u, ignoring.", arg_compression_level); + arg_compression_level = LZMA_PRESET_DEFAULT; + } +#endif } static int fix_acl(int fd, uid_t uid) { @@ -319,7 +357,8 @@ static int save_external_coredump(const char *info[_INFO_LEN], #ifdef HAVE_XZ /* If we will remove the coredump anyway, do not compress. */ - if (maybe_remove_external_coredump(NULL, st.st_size) == 0) { + if (maybe_remove_external_coredump(NULL, st.st_size) == 0 + && arg_compression == COREDUMP_COMPRESSION_XZ) { _cleanup_free_ char *fn2 = NULL; char *tmp2; @@ -332,7 +371,7 @@ static int save_external_coredump(const char *info[_INFO_LEN], goto uncompressed; } - r = compress_stream(fd, fd2, -1); + r = compress_stream(fd, fd2, arg_compression_level, -1); if (r < 0) { log_error("Failed to compress %s: %s", tmp2, strerror(-r)); unlink_noerrno(tmp2); @@ -458,7 +497,11 @@ int main(int argc, char* argv[]) { /* Ignore all parse errors */ parse_config(); - log_debug("Selected storage '%s'.", coredump_storage_to_string(arg_storage)); + log_debug("Selected storage '%s'.", + coredump_storage_to_string(arg_storage)); + log_debug("Selected compression %s:%u.", + coredump_compression_to_string(arg_storage), + arg_compression_level); r = parse_uid(argv[INFO_UID + 1], &uid); if (r < 0) { diff --git a/src/journal/test-compress.c b/src/journal/test-compress.c index b098ef93a..0806145d4 100644 --- a/src/journal/test-compress.c +++ b/src/journal/test-compress.c @@ -84,7 +84,7 @@ static void test_compress_stream(const char *srcfile) { assert_se((dst = mkostemp_safe(pattern, O_RDWR|O_CLOEXEC)) >= 0); - r = compress_stream(src, dst, -1); + r = compress_stream(src, dst, 1, -1); assert(r == 0); assert_se(asprintf(&cmd, "xzcat %s | diff %s -", pattern, srcfile) > 0); -- 2.30.2