lib_log: fix logfile compression corner case

This commit is contained in:
Thomas Schoebel-Theuer 2021-03-10 15:43:26 +01:00 committed by Thomas Schoebel-Theuer
parent 84f44fa106
commit 193c650377
2 changed files with 44 additions and 20 deletions

View File

@ -148,19 +148,43 @@ err:
} }
static static
int log_compress(struct log_status *logst, int len, __u32 *result_flags) int log_compress(struct log_status *logst, int len,
int *padded_len,
__u32 *result_flags)
{ {
struct mref_object *mref = logst->log_mref; struct mref_object *mref = logst->log_mref;
void *inplace_buf;
void *compr_buf;
int compr_len;
int res; int res;
if (unlikely(!mref || !mref->ref_data || len <= 0)) if (unlikely(!mref || !mref->ref_data || len <= 0))
return 0; return 0;
res = mars_compress(mref->ref_data + logst->payload_offset, len, compr_len = len + compress_overhead;
NULL, 0, compr_buf = brick_mem_alloc(compr_len);
inplace_buf = mref->ref_data + logst->payload_offset;
res = mars_compress(inplace_buf, len,
compr_buf, compr_len,
enabled_log_compressions, enabled_log_compressions,
result_flags); result_flags);
used_log_compression = *result_flags;
/* pad the resulting length */
if (res > 0) {
int pad_len = ((res + (_LOG_PAD - 1)) / _LOG_PAD) * _LOG_PAD;
/* Did compression pay off? */
if (pad_len < len) {
*padded_len = pad_len;
used_log_compression = *result_flags;
memcpy(inplace_buf, compr_buf, res);
} else {
*padded_len = len;
res = 0;
}
}
brick_mem_free(compr_buf);
return res; return res;
} }
@ -411,13 +435,16 @@ bool log_finalize(struct log_status *logst, int len, void (*endio)(void *private
decompr_len = 0; decompr_len = 0;
padded_len = len; padded_len = len;
if (logst->do_compress) { if (logst->do_compress) {
int new_len = log_compress(logst, len, &check_flags); __u32 new_check_flags = check_flags;
int padded_new_len = ((new_len + (_LOG_PAD-1)) / _LOG_PAD) * _LOG_PAD; int new_len = log_compress(logst, len,
&padded_len,
&new_check_flags);
if (new_len > 0 && padded_new_len < len) { /* When compression did not pay off, treat as uncompressed */
if (new_len > 0) {
check_flags = new_check_flags;
/* exchange the lengths */ /* exchange the lengths */
decompr_len = len; decompr_len = len;
padded_len = padded_new_len;
len = new_len; len = new_len;
} }
} }

View File

@ -705,9 +705,7 @@ int mars_compress(void *src_data,
if (!dst_data) { if (!dst_data) {
tmp_buf = brick_mem_alloc(max_len); tmp_buf = brick_mem_alloc(max_len);
} else if (dst_len < max_len) { } else if (dst_len < max_len) {
MARS_ERR("LZO compression buffer too small: %d < %d\n", return -ENOSPC;
dst_len, max_len);
return 0;
} }
wrkmem = brick_mem_alloc(LZO1X_1_MEM_COMPRESS); wrkmem = brick_mem_alloc(LZO1X_1_MEM_COMPRESS);
@ -717,7 +715,7 @@ int mars_compress(void *src_data,
/* ensure that the result is really smaller */ /* ensure that the result is really smaller */
if (status == LZO_E_OK && if (status == LZO_E_OK &&
res_len > 0 && res_len > 0 &&
res_len < src_len) { res_len <= dst_len) {
used_compression = MREF_COMPRESS_LZO; used_compression = MREF_COMPRESS_LZO;
*result_flags |= MREF_COMPRESS_LZO; *result_flags |= MREF_COMPRESS_LZO;
res = res_len; res = res_len;
@ -746,9 +744,7 @@ int mars_compress(void *src_data,
if (!dst_data) { if (!dst_data) {
tmp_buf = brick_mem_alloc(max_len); tmp_buf = brick_mem_alloc(max_len);
} else if (dst_len < max_len) { } else if (dst_len < max_len) {
MARS_ERR("LZ4 compression buffer too small: %d < %lu\n", return -ENOSPC;
dst_len, max_len);
return 0;
} }
wrkmem = brick_block_alloc(0, LZ4_MEM_COMPRESS); wrkmem = brick_block_alloc(0, LZ4_MEM_COMPRESS);
@ -766,7 +762,9 @@ int mars_compress(void *src_data,
tmp_buf, &res_len, tmp_buf, &res_len,
wrkmem); wrkmem);
#endif #endif
if (likely(!status && res_len > 0 && res_len < src_len)) { if (likely(!status &&
res_len > 0 &&
res_len <= dst_len)) {
used_compression = MREF_COMPRESS_LZ4; used_compression = MREF_COMPRESS_LZ4;
*result_flags |= MREF_COMPRESS_LZ4; *result_flags |= MREF_COMPRESS_LZ4;
res = res_len; res = res_len;
@ -792,9 +790,7 @@ int mars_compress(void *src_data,
if (!dst_data) { if (!dst_data) {
tmp_buf = brick_mem_alloc(src_len); tmp_buf = brick_mem_alloc(src_len);
} else if (dst_len < src_len) { } else if (dst_len < src_len) {
MARS_ERR("ZLIB compression buffer too small: %d < %d\n", return -ENOSPC;
dst_len, src_len);
return 0;
} }
status = zlib_deflateInit(&stream, mars_zlib_compression_level); status = zlib_deflateInit(&stream, mars_zlib_compression_level);
@ -813,7 +809,8 @@ int mars_compress(void *src_data,
goto zlib_err; goto zlib_err;
status = zlib_deflateEnd(&stream); status = zlib_deflateEnd(&stream);
if (status == Z_OK && stream.total_out < src_len) { if (status == Z_OK &&
stream.total_out <= dst_len) {
used_compression = MREF_COMPRESS_ZLIB; used_compression = MREF_COMPRESS_ZLIB;
*result_flags |= MREF_COMPRESS_ZLIB; *result_flags |= MREF_COMPRESS_ZLIB;
res = stream.total_out; res = stream.total_out;