diff --git a/kernel/Kconfig b/kernel/Kconfig index b679c62c..c4986719 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -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 diff --git a/kernel/compat.h b/kernel/compat.h index c0ed17aa..a9717a20 100644 --- a/kernel/compat.h +++ b/kernel/compat.h @@ -229,4 +229,7 @@ extern int _compat_unlink( #define HAS_SHA1 #endif +/* compression stuff */ +#include + #endif /* _MARS_COMPAT */ diff --git a/kernel/mars.h b/kernel/mars.h index 21fa9042..1be0007e 100644 --- a/kernel/mars.h +++ b/kernel/mars.h @@ -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. diff --git a/kernel/mars_generic.c b/kernel/mars_generic.c index 75906b07..32bc9ba8 100644 --- a/kernel/mars_generic.c +++ b/kernel/mars_generic.c @@ -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 */ diff --git a/kernel/sy_old/mars_main.c b/kernel/sy_old/mars_main.c index 9d8aeb75..70a02ab9 100644 --- a/kernel/sy_old/mars_main.c +++ b/kernel/sy_old/mars_main.c @@ -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 @@ -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) {