Skip to content

Instantly share code, notes, and snippets.

@tuxoko
Created April 17, 2014 10:51
Show Gist options
  • Save tuxoko/10973465 to your computer and use it in GitHub Desktop.
Save tuxoko/10973465 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#define FIELD_SIZE (1024*1024)
#define GUARD_SIZE (8192)
#define FIELD_AVAIL (FIELD_SIZE-2*GUARD_SIZE)
#define POISON (0x5a)
int lz4_decompress_zfs(void *s_start, void *d_start, size_t s_len, size_t d_len, int n);
size_t lz4_compress_zfs(void *s_start, void *d_start, size_t s_len, size_t d_len, int n);
int lzjb_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n);
size_t lzjb_compress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n);
void die(int err)
{
fprintf(stderr, "err=%d\n", err);
exit(err);
}
void set_guard(void *addr, size_t gsize, size_t bsize)
{
if (gsize * 2 >= bsize)
die(3);
if (mprotect(addr, gsize, PROT_NONE))
die(4);
if (mprotect(addr+(bsize-gsize), gsize, PROT_NONE))
die(5);
}
void unset_guard(void *addr, size_t bsize)
{
if (mprotect(addr, bsize, PROT_READ|PROT_WRITE))
die(12);
}
void *alloc_from_field(void *field, size_t len)
{
size_t off;
memset(field+GUARD_SIZE, POISON, FIELD_AVAIL);
off = rand() % (FIELD_AVAIL - len);
return field + GUARD_SIZE + off;
}
void *free_to_field(void *field, void *buf, size_t len)
{
void *p = field+GUARD_SIZE;
for (; p != buf; p++)
if (*(unsigned char *)p != POISON)
die(6);
for (p = buf+len; p != field+(FIELD_SIZE-GUARD_SIZE); p++)
if (*(unsigned char *)p != POISON)
die(7);
}
#define SYMS 12
void init_buf(void *buf, size_t len)
{
unsigned char sym[SYMS];
int i;
for (i = 0; i < SYMS; i++)
sym[i] = rand();
for (i = 0; i < len; i++)
((unsigned char *)buf)[i] = sym[rand()%SYMS];
}
void test(void *s, void *d, const char *algo, int run)
{
void *src, *dst, *tmp;
size_t slen, dlen, r;
int ret;
slen = dlen = (rand() % 130561) + 512;
src = alloc_from_field(s, slen);
dst = alloc_from_field(d, dlen);
init_buf(src, slen);
tmp = malloc(slen);
memcpy(tmp, src, slen);
if (strcmp(algo, "lz4") == 0)
r = lz4_compress_zfs(src, dst, slen, dlen, 0);
else if (strcmp(algo, "lzjb") == 0)
r = lzjb_compress(src, dst, slen, dlen, 0);
else
die(10);
if (r >= slen) {
free_to_field(s, src, slen);
free_to_field(d, dst, dlen);
free(tmp);
fprintf(stderr, "compression failed: %s\n", algo);
return;
}
if (strcmp(algo, "lz4") == 0)
ret = lz4_decompress_zfs(dst, src, r, slen, 0);
else if (strcmp(algo, "lzjb") == 0)
ret = lzjb_decompress(dst, src, r, slen, 0);
else
die(11);
if (ret)
die(8);
if (memcmp(src, tmp, slen)) {
char fn[256];
int ofd, nfd;
sprintf(fn, "orig.%s.%d", algo, run);
ofd = open(fn, O_WRONLY|O_CREAT|O_TRUNC, 0644);
sprintf(fn, "new.%s.%d", algo, run);
nfd = open(fn, O_WRONLY|O_CREAT|O_TRUNC, 0644);
write(ofd, tmp, slen);
write(nfd, src, slen);
close(ofd);
close(nfd);
fprintf(stderr, "memcmp failed: %s\n", algo);
} else
printf("memcmp success: %s\n", algo);
free_to_field(s, src, slen);
free_to_field(d, dst, dlen);
free(tmp);
}
int main(int argc, char *argv[])
{
void *s, *d;
time_t seed = time(NULL);
srand(seed);
printf("Random seed=%lu\n", seed);
lz4_init();
if (posix_memalign(&s, 4096, FIELD_SIZE))
die(1);
if (posix_memalign(&d, 4096, FIELD_SIZE))
die(2);
set_guard(s, GUARD_SIZE, FIELD_SIZE);
set_guard(d, GUARD_SIZE, FIELD_SIZE);
test(s, d, "lz4", 0);
test(s, d, "lzjb", 0);
test(s, d, "lz4", 1);
test(s, d, "lzjb", 1);
test(s, d, "lz4", 2);
test(s, d, "lzjb", 2);
unset_guard(s, FIELD_SIZE);
unset_guard(d, FIELD_SIZE);
free(s);
free(d);
lz4_fini();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment