2014-06-24 20:42:29 +02:00
|
|
|
/***
|
|
|
|
This file is part of systemd
|
|
|
|
|
|
|
|
Copyright 2014 Ronny Chevalier
|
|
|
|
|
|
|
|
systemd is free software; you can redistribute it and/or modify it
|
|
|
|
under the terms of the GNU Lesser General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2.1 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
systemd is distributed in the hope that it will be useful, but
|
|
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Lesser General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
|
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
***/
|
|
|
|
|
2017-10-03 10:41:51 +02:00
|
|
|
#if HAVE_LZ4
|
2015-12-13 20:24:55 +01:00
|
|
|
#include <lz4.h>
|
|
|
|
#endif
|
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
#include "alloc-util.h"
|
2014-06-24 20:42:29 +02:00
|
|
|
#include "compress.h"
|
2015-10-25 13:14:12 +01:00
|
|
|
#include "fd-util.h"
|
2015-10-26 18:05:03 +01:00
|
|
|
#include "fileio.h"
|
2014-06-24 20:42:29 +02:00
|
|
|
#include "macro.h"
|
2015-04-10 22:27:10 +02:00
|
|
|
#include "random-util.h"
|
2015-10-25 13:14:12 +01:00
|
|
|
#include "util.h"
|
2014-06-24 20:42:29 +02:00
|
|
|
|
2017-10-03 10:41:51 +02:00
|
|
|
#if HAVE_XZ
|
2014-07-04 04:42:22 +02:00
|
|
|
# define XZ_OK 0
|
|
|
|
#else
|
|
|
|
# define XZ_OK -EPROTONOSUPPORT
|
|
|
|
#endif
|
|
|
|
|
2017-10-03 10:41:51 +02:00
|
|
|
#if HAVE_LZ4
|
2014-07-04 04:42:22 +02:00
|
|
|
# define LZ4_OK 0
|
|
|
|
#else
|
|
|
|
# define LZ4_OK -EPROTONOSUPPORT
|
|
|
|
#endif
|
|
|
|
|
|
|
|
typedef int (compress_blob_t)(const void *src, uint64_t src_size,
|
2015-12-13 19:39:12 +01:00
|
|
|
void *dst, size_t dst_alloc_size, size_t *dst_size);
|
2014-07-04 04:42:22 +02:00
|
|
|
typedef int (decompress_blob_t)(const void *src, uint64_t src_size,
|
2014-08-04 04:50:00 +02:00
|
|
|
void **dst, size_t *dst_alloc_size,
|
|
|
|
size_t* dst_size, size_t dst_max);
|
2014-07-04 04:42:22 +02:00
|
|
|
typedef int (decompress_sw_t)(const void *src, uint64_t src_size,
|
2014-08-04 04:50:00 +02:00
|
|
|
void **buffer, size_t *buffer_size,
|
|
|
|
const void *prefix, size_t prefix_len,
|
2014-07-04 04:42:22 +02:00
|
|
|
uint8_t extra);
|
|
|
|
|
2015-09-10 18:16:18 +02:00
|
|
|
typedef int (compress_stream_t)(int fdf, int fdt, uint64_t max_bytes);
|
|
|
|
typedef int (decompress_stream_t)(int fdf, int fdt, uint64_t max_size);
|
2014-07-04 04:42:22 +02:00
|
|
|
|
2017-10-03 10:41:51 +02:00
|
|
|
#if HAVE_XZ || HAVE_LZ4
|
2014-07-04 04:42:22 +02:00
|
|
|
static void test_compress_decompress(int compression,
|
|
|
|
compress_blob_t compress,
|
2014-08-30 20:47:36 +02:00
|
|
|
decompress_blob_t decompress,
|
|
|
|
const char *data,
|
|
|
|
size_t data_len,
|
|
|
|
bool may_fail) {
|
2014-06-24 20:42:29 +02:00
|
|
|
char compressed[512];
|
2015-12-13 19:39:12 +01:00
|
|
|
size_t csize, usize = 0;
|
2014-07-04 04:42:22 +02:00
|
|
|
_cleanup_free_ char *decompressed = NULL;
|
|
|
|
int r;
|
|
|
|
|
2014-08-30 20:47:36 +02:00
|
|
|
log_info("/* testing %s %s blob compression/decompression */",
|
|
|
|
object_compressed_to_string(compression), data);
|
|
|
|
|
2015-12-13 19:39:12 +01:00
|
|
|
r = compress(data, data_len, compressed, sizeof(compressed), &csize);
|
2014-08-30 20:47:36 +02:00
|
|
|
if (r == -ENOBUFS) {
|
2014-11-28 13:19:16 +01:00
|
|
|
log_info_errno(r, "compression failed: %m");
|
2014-11-30 02:16:19 +01:00
|
|
|
assert_se(may_fail);
|
2014-08-30 20:47:36 +02:00
|
|
|
} else {
|
2014-11-30 02:16:19 +01:00
|
|
|
assert_se(r == 0);
|
2014-08-30 20:47:36 +02:00
|
|
|
r = decompress(compressed, csize,
|
|
|
|
(void **) &decompressed, &usize, &csize, 0);
|
2014-11-30 02:16:19 +01:00
|
|
|
assert_se(r == 0);
|
2014-08-30 20:47:36 +02:00
|
|
|
assert_se(decompressed);
|
|
|
|
assert_se(memcmp(decompressed, data, data_len) == 0);
|
|
|
|
}
|
2014-07-04 04:42:22 +02:00
|
|
|
|
|
|
|
r = decompress("garbage", 7,
|
|
|
|
(void **) &decompressed, &usize, &csize, 0);
|
2014-11-30 02:16:19 +01:00
|
|
|
assert_se(r < 0);
|
2014-07-04 04:42:22 +02:00
|
|
|
|
|
|
|
/* make sure to have the minimal lz4 compressed size */
|
|
|
|
r = decompress("00000000\1g", 9,
|
|
|
|
(void **) &decompressed, &usize, &csize, 0);
|
2014-11-30 02:16:19 +01:00
|
|
|
assert_se(r < 0);
|
2014-07-04 04:42:22 +02:00
|
|
|
|
|
|
|
r = decompress("\100000000g", 9,
|
|
|
|
(void **) &decompressed, &usize, &csize, 0);
|
2014-11-30 02:16:19 +01:00
|
|
|
assert_se(r < 0);
|
2014-07-04 04:42:22 +02:00
|
|
|
|
|
|
|
memzero(decompressed, usize);
|
2014-06-24 20:42:29 +02:00
|
|
|
}
|
|
|
|
|
2014-07-04 04:42:22 +02:00
|
|
|
static void test_decompress_startswith(int compression,
|
|
|
|
compress_blob_t compress,
|
2014-08-30 20:47:36 +02:00
|
|
|
decompress_sw_t decompress_sw,
|
|
|
|
const char *data,
|
|
|
|
size_t data_len,
|
|
|
|
bool may_fail) {
|
2014-07-04 04:42:22 +02:00
|
|
|
|
2015-12-13 20:33:17 +01:00
|
|
|
char *compressed;
|
|
|
|
_cleanup_free_ char *compressed1 = NULL, *compressed2 = NULL, *decompressed = NULL;
|
|
|
|
size_t csize, usize = 0, len;
|
2014-08-30 20:47:36 +02:00
|
|
|
int r;
|
2014-07-04 04:42:22 +02:00
|
|
|
|
2017-02-24 18:14:02 +01:00
|
|
|
log_info("/* testing decompress_startswith with %s on %.20s text */",
|
2014-08-30 20:47:36 +02:00
|
|
|
object_compressed_to_string(compression), data);
|
|
|
|
|
2015-12-13 20:33:17 +01:00
|
|
|
#define BUFSIZE_1 512
|
|
|
|
#define BUFSIZE_2 20000
|
|
|
|
|
|
|
|
compressed = compressed1 = malloc(BUFSIZE_1);
|
|
|
|
assert_se(compressed1);
|
|
|
|
r = compress(data, data_len, compressed, BUFSIZE_1, &csize);
|
2014-08-30 20:47:36 +02:00
|
|
|
if (r == -ENOBUFS) {
|
2014-11-28 13:19:16 +01:00
|
|
|
log_info_errno(r, "compression failed: %m");
|
2014-11-30 02:16:19 +01:00
|
|
|
assert_se(may_fail);
|
2015-12-13 20:33:17 +01:00
|
|
|
|
|
|
|
compressed = compressed2 = malloc(BUFSIZE_2);
|
|
|
|
assert_se(compressed2);
|
|
|
|
r = compress(data, data_len, compressed, BUFSIZE_2, &csize);
|
|
|
|
assert(r == 0);
|
2014-08-30 20:47:36 +02:00
|
|
|
}
|
2014-11-30 02:16:19 +01:00
|
|
|
assert_se(r == 0);
|
2014-07-04 04:42:22 +02:00
|
|
|
|
2015-12-13 20:33:17 +01:00
|
|
|
len = strlen(data);
|
|
|
|
|
|
|
|
r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, len, '\0');
|
|
|
|
assert_se(r > 0);
|
|
|
|
r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, len, 'w');
|
|
|
|
assert_se(r == 0);
|
|
|
|
r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, "barbarbar", 9, ' ');
|
|
|
|
assert_se(r == 0);
|
|
|
|
r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, len - 1, data[len-1]);
|
|
|
|
assert_se(r > 0);
|
|
|
|
r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, len - 1, 'w');
|
|
|
|
assert_se(r == 0);
|
|
|
|
r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, len, '\0');
|
|
|
|
assert_se(r > 0);
|
2014-06-24 20:42:29 +02:00
|
|
|
}
|
|
|
|
|
2014-07-04 04:42:22 +02:00
|
|
|
static void test_compress_stream(int compression,
|
|
|
|
const char* cat,
|
|
|
|
compress_stream_t compress,
|
|
|
|
decompress_stream_t decompress,
|
|
|
|
const char *srcfile) {
|
|
|
|
|
2014-06-25 03:24:46 +02:00
|
|
|
_cleanup_close_ int src = -1, dst = -1, dst2 = -1;
|
coredump: use lz4frame api to compress coredumps
This converts the stream compression to use the new lz4frame api,
compatible with lz4cat. Previous code used custom headers, so the
compressed file was not compatible with lz4 command line tools.
I considered this the last blocker to using lz4 by default.
Speed seems to be reasonable, although a bit (a few percent) slower
than the lz4 binary, even though compression is the same. I don't
consider this important. It could be caused by the overhead of library
calls, but is probably caused by slightly different buffer sizes or
such. The code in this patch uses mmap, since since this allows the
buffer to be reused while not making the code more complicated at all.
In my testing, this version is noticably faster (~20%) than a naive
single-buffered version. mmap can cause the program to be killed with
SIGBUS, if the underlying file is truncated or a disk error occurs. We
only use this from within coredump and coredumpctl, so I don't
consider this an issue.
Old decompression code is retained and is used if the new code fails
indicating a format error. There have been reports of various smaller
distributions using previous lz4 code, i.e. the old format, and it is
nice to provide backwards compatibility. We can remove the legacy code
in a few versions.
The way that blobs are compressed in the journal is not affected.
2014-12-07 03:33:27 +01:00
|
|
|
char pattern[] = "/tmp/systemd-test.compressed.XXXXXX",
|
|
|
|
pattern2[] = "/tmp/systemd-test.compressed.XXXXXX";
|
2014-06-25 03:24:46 +02:00
|
|
|
int r;
|
2014-07-04 04:42:22 +02:00
|
|
|
_cleanup_free_ char *cmd = NULL, *cmd2;
|
2014-06-25 03:24:46 +02:00
|
|
|
struct stat st = {};
|
|
|
|
|
2014-07-04 04:42:22 +02:00
|
|
|
log_debug("/* testing %s compression */",
|
|
|
|
object_compressed_to_string(compression));
|
|
|
|
|
2014-06-25 03:24:46 +02:00
|
|
|
log_debug("/* create source from %s */", srcfile);
|
|
|
|
|
|
|
|
assert_se((src = open(srcfile, O_RDONLY|O_CLOEXEC)) >= 0);
|
|
|
|
|
|
|
|
log_debug("/* test compression */");
|
|
|
|
|
2016-09-13 08:20:38 +02:00
|
|
|
assert_se((dst = mkostemp_safe(pattern)) >= 0);
|
2014-06-25 03:24:46 +02:00
|
|
|
|
2014-08-26 07:05:02 +02:00
|
|
|
assert_se(compress(src, dst, -1) == 0);
|
2014-06-25 03:24:46 +02:00
|
|
|
|
2014-07-04 04:42:22 +02:00
|
|
|
if (cat) {
|
|
|
|
assert_se(asprintf(&cmd, "%s %s | diff %s -", cat, pattern, srcfile) > 0);
|
2014-08-26 07:05:02 +02:00
|
|
|
assert_se(system(cmd) == 0);
|
2014-07-04 04:42:22 +02:00
|
|
|
}
|
2014-06-25 03:24:46 +02:00
|
|
|
|
|
|
|
log_debug("/* test decompression */");
|
|
|
|
|
2016-09-13 08:20:38 +02:00
|
|
|
assert_se((dst2 = mkostemp_safe(pattern2)) >= 0);
|
2014-06-25 03:24:46 +02:00
|
|
|
|
|
|
|
assert_se(stat(srcfile, &st) == 0);
|
|
|
|
|
|
|
|
assert_se(lseek(dst, 0, SEEK_SET) == 0);
|
2014-07-04 04:42:22 +02:00
|
|
|
r = decompress(dst, dst2, st.st_size);
|
2015-01-22 22:53:42 +01:00
|
|
|
assert_se(r == 0);
|
2014-06-25 03:24:46 +02:00
|
|
|
|
|
|
|
assert_se(asprintf(&cmd2, "diff %s %s", srcfile, pattern2) > 0);
|
|
|
|
assert_se(system(cmd2) == 0);
|
|
|
|
|
|
|
|
log_debug("/* test faulty decompression */");
|
|
|
|
|
|
|
|
assert_se(lseek(dst, 1, SEEK_SET) == 1);
|
2014-07-04 04:42:22 +02:00
|
|
|
r = decompress(dst, dst2, st.st_size);
|
coredump: use lz4frame api to compress coredumps
This converts the stream compression to use the new lz4frame api,
compatible with lz4cat. Previous code used custom headers, so the
compressed file was not compatible with lz4 command line tools.
I considered this the last blocker to using lz4 by default.
Speed seems to be reasonable, although a bit (a few percent) slower
than the lz4 binary, even though compression is the same. I don't
consider this important. It could be caused by the overhead of library
calls, but is probably caused by slightly different buffer sizes or
such. The code in this patch uses mmap, since since this allows the
buffer to be reused while not making the code more complicated at all.
In my testing, this version is noticably faster (~20%) than a naive
single-buffered version. mmap can cause the program to be killed with
SIGBUS, if the underlying file is truncated or a disk error occurs. We
only use this from within coredump and coredumpctl, so I don't
consider this an issue.
Old decompression code is retained and is used if the new code fails
indicating a format error. There have been reports of various smaller
distributions using previous lz4 code, i.e. the old format, and it is
nice to provide backwards compatibility. We can remove the legacy code
in a few versions.
The way that blobs are compressed in the journal is not affected.
2014-12-07 03:33:27 +01:00
|
|
|
assert_se(r == -EBADMSG || r == 0);
|
2014-06-25 03:24:46 +02:00
|
|
|
|
|
|
|
assert_se(lseek(dst, 0, SEEK_SET) == 0);
|
|
|
|
assert_se(lseek(dst2, 0, SEEK_SET) == 0);
|
2014-07-04 04:42:22 +02:00
|
|
|
r = decompress(dst, dst2, st.st_size - 1);
|
2015-01-22 22:53:42 +01:00
|
|
|
assert_se(r == -EFBIG);
|
2014-06-25 03:24:46 +02:00
|
|
|
|
|
|
|
assert_se(unlink(pattern) == 0);
|
|
|
|
assert_se(unlink(pattern2) == 0);
|
|
|
|
}
|
2017-04-07 15:28:50 +02:00
|
|
|
#endif
|
2014-06-25 03:24:46 +02:00
|
|
|
|
2017-10-03 10:41:51 +02:00
|
|
|
#if HAVE_LZ4
|
2015-12-13 20:24:55 +01:00
|
|
|
static void test_lz4_decompress_partial(void) {
|
|
|
|
char buf[20000];
|
|
|
|
size_t buf_size = sizeof(buf), compressed;
|
|
|
|
int r;
|
2015-12-13 20:33:17 +01:00
|
|
|
_cleanup_free_ char *huge = NULL;
|
2015-12-13 20:24:55 +01:00
|
|
|
|
2015-12-13 20:33:17 +01:00
|
|
|
#define HUGE_SIZE (4096*1024)
|
|
|
|
huge = malloc(HUGE_SIZE);
|
|
|
|
memset(huge, 'x', HUGE_SIZE);
|
2015-12-13 20:24:55 +01:00
|
|
|
memcpy(huge, "HUGE=", 5);
|
|
|
|
|
2016-12-18 00:27:01 +01:00
|
|
|
#if LZ4_VERSION_NUMBER >= 10700
|
|
|
|
r = LZ4_compress_default(huge, buf, HUGE_SIZE, buf_size);
|
|
|
|
#else
|
2015-12-13 20:33:17 +01:00
|
|
|
r = LZ4_compress_limitedOutput(huge, buf, HUGE_SIZE, buf_size);
|
2016-12-18 00:27:01 +01:00
|
|
|
#endif
|
2015-12-13 20:24:55 +01:00
|
|
|
assert_se(r >= 0);
|
|
|
|
compressed = r;
|
2015-12-13 20:33:17 +01:00
|
|
|
log_info("Compressed %i → %zu", HUGE_SIZE, compressed);
|
2015-12-13 20:24:55 +01:00
|
|
|
|
2015-12-13 20:33:17 +01:00
|
|
|
r = LZ4_decompress_safe(buf, huge, r, HUGE_SIZE);
|
2015-12-13 20:24:55 +01:00
|
|
|
assert_se(r >= 0);
|
|
|
|
log_info("Decompressed → %i", r);
|
|
|
|
|
|
|
|
r = LZ4_decompress_safe_partial(buf, huge,
|
|
|
|
compressed,
|
2015-12-13 20:33:17 +01:00
|
|
|
12, HUGE_SIZE);
|
2015-12-13 20:24:55 +01:00
|
|
|
assert_se(r >= 0);
|
2015-12-13 20:33:17 +01:00
|
|
|
log_info("Decompressed partial %i/%i → %i", 12, HUGE_SIZE, r);
|
2015-12-13 20:24:55 +01:00
|
|
|
|
|
|
|
/* We expect this to fail, because that's how current lz4 works. If this
|
|
|
|
* call succeeds, then lz4 has been fixed, and we need to change our code.
|
|
|
|
*/
|
|
|
|
r = LZ4_decompress_safe_partial(buf, huge,
|
|
|
|
compressed,
|
2015-12-13 20:33:17 +01:00
|
|
|
12, HUGE_SIZE-1);
|
2015-12-13 20:24:55 +01:00
|
|
|
assert_se(r < 0);
|
2015-12-13 20:33:17 +01:00
|
|
|
log_info("Decompressed partial %i/%i → %i", 12, HUGE_SIZE-1, r);
|
2015-12-13 20:24:55 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-06-24 20:42:29 +02:00
|
|
|
int main(int argc, char *argv[]) {
|
2017-10-03 10:41:51 +02:00
|
|
|
#if HAVE_XZ || HAVE_LZ4
|
2014-08-30 20:47:36 +02:00
|
|
|
const char text[] =
|
|
|
|
"text\0foofoofoofoo AAAA aaaaaaaaa ghost busters barbarbar FFF"
|
|
|
|
"foofoofoofoo AAAA aaaaaaaaa ghost busters barbarbar FFF";
|
|
|
|
|
2016-10-31 18:16:44 +01:00
|
|
|
/* The file to test compression on can be specified as the first argument */
|
|
|
|
const char *srcfile = argc > 1 ? argv[1] : argv[0];
|
|
|
|
|
2014-08-30 20:47:36 +02:00
|
|
|
char data[512] = "random\0";
|
2014-06-25 03:24:46 +02:00
|
|
|
|
2015-12-13 20:33:17 +01:00
|
|
|
char huge[4096*1024];
|
|
|
|
memset(huge, 'x', sizeof(huge));
|
|
|
|
memcpy(huge, "HUGE=", 5);
|
|
|
|
char_array_0(huge);
|
|
|
|
|
2014-06-25 03:24:46 +02:00
|
|
|
log_set_max_level(LOG_DEBUG);
|
|
|
|
|
2014-08-30 20:47:36 +02:00
|
|
|
random_bytes(data + 7, sizeof(data) - 7);
|
|
|
|
|
2017-10-03 10:41:51 +02:00
|
|
|
#if HAVE_XZ
|
2014-08-30 20:47:36 +02:00
|
|
|
test_compress_decompress(OBJECT_COMPRESSED_XZ, compress_blob_xz, decompress_blob_xz,
|
|
|
|
text, sizeof(text), false);
|
|
|
|
test_compress_decompress(OBJECT_COMPRESSED_XZ, compress_blob_xz, decompress_blob_xz,
|
|
|
|
data, sizeof(data), true);
|
2015-12-13 20:33:17 +01:00
|
|
|
|
2014-08-30 20:47:36 +02:00
|
|
|
test_decompress_startswith(OBJECT_COMPRESSED_XZ,
|
|
|
|
compress_blob_xz, decompress_startswith_xz,
|
|
|
|
text, sizeof(text), false);
|
|
|
|
test_decompress_startswith(OBJECT_COMPRESSED_XZ,
|
|
|
|
compress_blob_xz, decompress_startswith_xz,
|
|
|
|
data, sizeof(data), true);
|
2015-12-13 20:33:17 +01:00
|
|
|
test_decompress_startswith(OBJECT_COMPRESSED_XZ,
|
|
|
|
compress_blob_xz, decompress_startswith_xz,
|
|
|
|
huge, sizeof(huge), true);
|
|
|
|
|
2014-07-04 04:42:22 +02:00
|
|
|
test_compress_stream(OBJECT_COMPRESSED_XZ, "xzcat",
|
2016-10-31 18:16:44 +01:00
|
|
|
compress_stream_xz, decompress_stream_xz, srcfile);
|
2014-07-04 04:42:22 +02:00
|
|
|
#else
|
|
|
|
log_info("/* XZ test skipped */");
|
|
|
|
#endif
|
2014-08-30 20:47:36 +02:00
|
|
|
|
2017-10-03 10:41:51 +02:00
|
|
|
#if HAVE_LZ4
|
2014-08-30 20:47:36 +02:00
|
|
|
test_compress_decompress(OBJECT_COMPRESSED_LZ4, compress_blob_lz4, decompress_blob_lz4,
|
|
|
|
text, sizeof(text), false);
|
|
|
|
test_compress_decompress(OBJECT_COMPRESSED_LZ4, compress_blob_lz4, decompress_blob_lz4,
|
|
|
|
data, sizeof(data), true);
|
2015-12-13 20:33:17 +01:00
|
|
|
|
2014-08-30 20:47:36 +02:00
|
|
|
test_decompress_startswith(OBJECT_COMPRESSED_LZ4,
|
|
|
|
compress_blob_lz4, decompress_startswith_lz4,
|
|
|
|
text, sizeof(text), false);
|
|
|
|
test_decompress_startswith(OBJECT_COMPRESSED_LZ4,
|
|
|
|
compress_blob_lz4, decompress_startswith_lz4,
|
|
|
|
data, sizeof(data), true);
|
2015-12-13 20:33:17 +01:00
|
|
|
test_decompress_startswith(OBJECT_COMPRESSED_LZ4,
|
|
|
|
compress_blob_lz4, decompress_startswith_lz4,
|
|
|
|
huge, sizeof(huge), true);
|
2014-07-04 04:42:22 +02:00
|
|
|
|
coredump: use lz4frame api to compress coredumps
This converts the stream compression to use the new lz4frame api,
compatible with lz4cat. Previous code used custom headers, so the
compressed file was not compatible with lz4 command line tools.
I considered this the last blocker to using lz4 by default.
Speed seems to be reasonable, although a bit (a few percent) slower
than the lz4 binary, even though compression is the same. I don't
consider this important. It could be caused by the overhead of library
calls, but is probably caused by slightly different buffer sizes or
such. The code in this patch uses mmap, since since this allows the
buffer to be reused while not making the code more complicated at all.
In my testing, this version is noticably faster (~20%) than a naive
single-buffered version. mmap can cause the program to be killed with
SIGBUS, if the underlying file is truncated or a disk error occurs. We
only use this from within coredump and coredumpctl, so I don't
consider this an issue.
Old decompression code is retained and is used if the new code fails
indicating a format error. There have been reports of various smaller
distributions using previous lz4 code, i.e. the old format, and it is
nice to provide backwards compatibility. We can remove the legacy code
in a few versions.
The way that blobs are compressed in the journal is not affected.
2014-12-07 03:33:27 +01:00
|
|
|
test_compress_stream(OBJECT_COMPRESSED_LZ4, "lz4cat",
|
2016-10-31 18:16:44 +01:00
|
|
|
compress_stream_lz4, decompress_stream_lz4, srcfile);
|
2015-12-13 20:24:55 +01:00
|
|
|
|
|
|
|
test_lz4_decompress_partial();
|
2014-07-04 04:42:22 +02:00
|
|
|
#else
|
|
|
|
log_info("/* LZ4 test skipped */");
|
|
|
|
#endif
|
2014-06-24 20:42:29 +02:00
|
|
|
|
|
|
|
return 0;
|
2017-04-07 15:28:50 +02:00
|
|
|
#else
|
|
|
|
return EXIT_TEST_SKIP;
|
|
|
|
#endif
|
2014-06-24 20:42:29 +02:00
|
|
|
}
|