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.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2014-06-25 20:53:40 -04:00
parent cfd652ed61
commit 347272731e
4 changed files with 62 additions and 19 deletions

View file

@ -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;

View file

@ -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);

View file

@ -44,8 +44,14 @@
#include "compress.h"
#ifdef HAVE_ACL
#include <sys/acl.h>
#include "acl-util.h"
# include <sys/acl.h>
# include "acl-util.h"
#endif
#ifdef HAVE_XZ
# include <lzma.h>
#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) {

View file

@ -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);