infra: add compression infrastructure

This commit is contained in:
Thomas Schoebel-Theuer 2019-07-25 08:55:17 +02:00 committed by Thomas Schoebel-Theuer
parent 2d35812d50
commit 375ae7c84b
5 changed files with 172 additions and 2 deletions

View File

@ -7,6 +7,8 @@ config MARS
depends on m
depends on BLOCK && PROC_SYSCTL && HIGH_RES_TIMERS
default n
select LZO_COMPRESS
select LZO_DECOMPRESS
select CRYPTO_MD5
select CRYPTO_CRC32
select CRYPTO_CRC32C

View File

@ -229,4 +229,7 @@ extern int _compat_unlink(
#define HAS_SHA1
#endif
/* compression stuff */
#include <linux/lzo.h>
#endif /* _MARS_COMPAT */

View File

@ -179,6 +179,8 @@ enum _MREF_FLAGS {
_MREF_CHKSUM_CRC32,
_MREF_CHKSUM_SHA1,
_MREF_CHKSUM_LAST,
_MREF_COMPRESS_LZO = 24,
_MREF_COMPRESS_LAST,
};
#define MREF_UPTODATE (1UL << _MREF_UPTODATE)
@ -194,12 +196,14 @@ enum _MREF_FLAGS {
#define MREF_CHKSUM_CRC32 (1UL << _MREF_CHKSUM_CRC32)
#define MREF_CHKSUM_SHA1 (1UL << _MREF_CHKSUM_SHA1)
#define MREF_CHKSUM_LAST (1UL << _MREF_CHKSUM_LAST)
#define MREF_COMPRESS_LZO (1UL << _MREF_COMPRESS_LZO)
#define MREF_CHKSUM_ANY (MREF_CHKSUM_MD5_OLD | \
MREF_CHKSUM_MD5 | \
MREF_CHKSUM_CRC32C | \
MREF_CHKSUM_CRC32 | \
MREF_CHKSUM_SHA1 | \
MREF_CHKSUM_LAST)
#define MREF_COMPRESS_ANY (MREF_COMPRESS_LZO)
#define MREF_OBJECT(OBJTYPE) \
CALLBACK_OBJECT(OBJTYPE); \
@ -529,6 +533,30 @@ extern __u32 mars_digest(__u32 digest_flags,
extern void mref_checksum(struct mref_object *mref);
/*******************************************************************/
/* compression stuff */
#define MARS_MAX_COMPR_SIZE (PAGE_SIZE * 8)
extern int compress_overhead;
extern __u32 available_compression_mask;
extern __u32 usable_compression_mask;
extern int mars_compress(void *src_data,
int src_len,
void *dst_data,
int dst_len,
__u32 check_flags,
__u32 *result_flags);
void *mars_decompress(void *src_data,
int src_len,
void *dst_data,
int dst_len,
__u32 check_flags);
/////////////////////////////////////////////////////////////////////////
/* Crash-testing instrumentation.

View File

@ -632,6 +632,134 @@ void mref_checksum(struct mref_object *mref)
memcpy(&mref->ref_checksum, checksum, len);
}
/*******************************************************************/
/* compression */
int compress_overhead = 0;
__u32 available_compression_mask =
0;
__u32 usable_compression_mask = 0;
__u32 used_compression = 0;
int mars_compress(void *src_data,
int src_len,
void *dst_data,
int dst_len,
__u32 check_flags,
__u32 *result_flags)
{
void *tmp_buf = dst_data;
int res = 0;
check_flags &= usable_compression_mask;
if (!(check_flags & MREF_COMPRESS_ANY)) {
used_compression = 0;
return 0;
}
if (unlikely(src_len > MARS_MAX_COMPR_SIZE)) {
MARS_ERR("tryping to compress %d, more than %ld bytes\n",
src_len, MARS_MAX_COMPR_SIZE);
goto done;
}
done:
if (!dst_data)
brick_mem_free(tmp_buf);
return res;
}
void *mars_decompress(void *src_data,
int src_len,
void *dst_data,
int dst_len,
__u32 check_flags)
{
void *res_buf = dst_data;
if (!res_buf)
res_buf = brick_mem_alloc(dst_len);
MARS_ERR("decompression not compiled into kernel module\n");
err:
if (!dst_data)
brick_mem_free(res_buf);
res_buf = NULL;
done:
return res_buf;
}
#ifdef CONFIG_MARS_BENCHMARK
#define MARS_CLEAN_SIZE 256
static
void make_fake_page(__u32 *testpage)
{
int i;
/* some fake compression data */
for (i = 0; i < PAGE_SIZE / sizeof(__u32); i++)
testpage[i] = (__u32)i;
}
static
void benchmark_compress(char *name, __u32 flags)
{
void *testpage = kmalloc(PAGE_SIZE, GFP_KERNEL);
__u32 result_flags;
long long delta;
int status;
int i;
usable_compression_mask = MREF_COMPRESS_ANY;
make_fake_page(testpage);
delta = TIME_THIS(
for (i = 0; i < 10000; i++) {
memset(testpage, 0, MARS_CLEAN_SIZE);
result_flags = 0;
status =
mars_compress(testpage, PAGE_SIZE,
NULL, PAGE_SIZE + compress_overhead,
flags, &result_flags);
if (unlikely(status <= 0) || !(flags & result_flags)) {
MARS_ERR("%s compress failure, status=%d, flags=%x\n",
name, status, result_flags);
goto err;
}
}
);
printk("%-8s compress duration = %12lld ns\n", name, delta);
err:
kfree(testpage);
usable_compression_mask = 0;
}
#endif
static
int init_mars_compress(void)
{
int max_len = 0;
#ifdef CONFIG_MARS_BENCHMARK
(void)benchmark_compress;
#endif
return 0;
}
static
void exit_mars_compress(void)
{
}
/////////////////////////////////////////////////////////////////////
// tracing
@ -843,6 +971,8 @@ int __init init_mars(void)
}
#endif /* MARS_HAS_NEW_CRYPTO */
init_mars_compress();
return 0;
}
@ -852,6 +982,8 @@ void exit_mars(void)
put_fake();
exit_mars_compress();
#ifdef MARS_HAS_NEW_CRYPTO
exit_mars_digest();
#else /* MARS_HAS_NEW_CRYPTO */

View File

@ -88,6 +88,7 @@ static int _tmp_features_version = OPTIONAL_FEATURES_VERSION;
static int _tmp_strategy_version = OPTIONAL_STRATEGY_VERSION;
static __u32 _tmp_digest_mask = MREF_CHKSUM_MD5_OLD;
static __u32 _tmp_compression_mask = MREF_COMPRESS_ANY;
/* Portability: can we use get_random_int() in a module? */
#include <linux/string_helpers.h>
@ -2683,13 +2684,14 @@ void _make_alive(void)
features = path_make(stringify(OPTIONAL_FEATURES_VERSION)
","
stringify(OPTIONAL_STRATEGY_VERSION)
",0x%08x", available_digest_mask);
",0x%08x",
available_digest_mask | available_compression_mask);
__make_alivelink_str("features", features, true);
brick_string_free(features);
features = path_make("%d,%d,0x%08x",
usable_features_version,
usable_strategy_version,
usable_digest_mask);
usable_digest_mask | usable_compression_mask);
__make_alivelink_str("usable", features, true);
brick_string_free(features);
__make_alivelink_str("buildtag", BUILDTAG "(" BUILDDATE ")", true);
@ -2936,6 +2938,7 @@ int _make_peer(struct mars_global *global, struct mars_dent *dent)
/* at least one digest must remain usable */
peer->available_mask |= MREF_CHKSUM_MD5_OLD;
_tmp_digest_mask &= peer->available_mask;
_tmp_compression_mask &= peer->available_mask;
if (peer->features_version < _tmp_features_version)
_tmp_features_version = peer->features_version;
if (peer->strategy_version < _tmp_strategy_version)
@ -6436,9 +6439,11 @@ static int _main_thread(void *data)
usable_features_version = _tmp_features_version;
usable_strategy_version = _tmp_strategy_version;
usable_digest_mask = _tmp_digest_mask;
usable_compression_mask = (_tmp_compression_mask & available_compression_mask);
_tmp_features_version = OPTIONAL_FEATURES_VERSION;
_tmp_strategy_version = OPTIONAL_STRATEGY_VERSION;
_tmp_digest_mask = available_digest_mask;
_tmp_compression_mask = available_compression_mask;
down_read(&rot_sem);
for (tmp = rot_anchor.next; tmp != &rot_anchor; tmp = tmp->next) {