Add zlib support
* New args to cbd format. * HAVE_* -> COMPRESS_HAVE_*. * Verify header params algorithm and compression. * Move percpu alloc to lbdcache. * Alloc percpu data in lbdcache_ctr, free in lbdcache_dtr.
This commit is contained in:
parent
eeafc209a5
commit
164a09b9aa
18
TODO
18
TODO
|
@ -1,22 +1,6 @@
|
|||
In lbd, atomic writes will require a pblk array in the lbd object. Not sure
|
||||
how to roll back partial allocations yet but it should be doable.
|
||||
|
||||
For async reads:
|
||||
- lbd_read() is called by compress_read() and compress_write().
|
||||
lbd may have multiple simultaneous callers.
|
||||
lbd calls lbatview_read() and reads its own data.
|
||||
- lbatview_read() is called by lbd.
|
||||
lbatview may have multiple simultaneous callers.
|
||||
lbatview calls pbat_read() and reads its own data.
|
||||
- pbat_read() is called by lbatview_alloc_pblk() and lbatview_free_pblk().
|
||||
pbat may have multiple simultaneous callers.
|
||||
pbat calls pbat_read().
|
||||
|
||||
Rework cache ownership:
|
||||
- compress_open() should alloc only lbdcache.
|
||||
- lbdcache should alloc only lbatviewcache.
|
||||
- lbatviewcache should alloc lbatpagecache and pbatcache.
|
||||
|
||||
Cache object sizing:
|
||||
- lbdcache size: multiple of num_online_cpus().
|
||||
- lbatviewcache:
|
||||
|
@ -37,8 +21,6 @@ Cache object sizing:
|
|||
1/2 lbatviewcache size is way too large.
|
||||
Ratio of lbatview to pbat is 1:lbat_per_pbat.
|
||||
|
||||
Cache objects should dynamically expand.
|
||||
|
||||
|
||||
TODO:
|
||||
- Move back to module based build system.
|
||||
|
|
43
cbd/cbd.c
43
cbd/cbd.c
|
@ -23,7 +23,7 @@
|
|||
* If no suffix is given, bytes are assumed.
|
||||
*/
|
||||
static bool
|
||||
parse_arg(const char* arg, uint64_t* val)
|
||||
parse_numeric_arg(const char* arg, uint64_t* val)
|
||||
{
|
||||
unsigned long ulval;
|
||||
const char* end;
|
||||
|
@ -88,6 +88,8 @@ usage(void)
|
|||
" -c --compress-factor Compression factor [2.0]\n"
|
||||
" -l --logical-shift Logical block shift [4]\n"
|
||||
" -s --size Logical size\n"
|
||||
" -z --compress-alg Compression algorithm [lz4]\n"
|
||||
" -Z --compress-level Compression level [?]\n"
|
||||
" Note:\n"
|
||||
" -c and -s are different ways of specifying the compressed device size.\n"
|
||||
" Only one may be used, not both.\n"
|
||||
|
@ -110,13 +112,15 @@ usage(void)
|
|||
static int
|
||||
do_format(int argc, char** argv)
|
||||
{
|
||||
static const char short_opts[] = "S:L:c:l:s:";
|
||||
static const char short_opts[] = "S:L:c:l:s:z:Z:";
|
||||
static const struct option long_opts[] = {
|
||||
{ "physical-size", required_argument, NULL, 'S' },
|
||||
{ "logical-blksize", required_argument, NULL, 'L' },
|
||||
{ "compress-factor", required_argument, NULL, 'c' },
|
||||
{ "logical-shift", required_argument, NULL, 'l' },
|
||||
{ "size", required_argument, NULL, 's' },
|
||||
{ "compress-alg", required_argument, NULL, 'z' },
|
||||
{ "compress-level", required_argument, NULL, 'Z' },
|
||||
{ NULL, no_argument, NULL, 0 }
|
||||
};
|
||||
char opt;
|
||||
|
@ -124,19 +128,21 @@ do_format(int argc, char** argv)
|
|||
uint64_t psize = 0;
|
||||
uint16_t lshift = 0;
|
||||
uint64_t lsize = 0;
|
||||
enum cbd_alg alg = CBD_ALG_LZ4;
|
||||
uint level = 1;
|
||||
|
||||
const char* dev;
|
||||
|
||||
while ((opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 'S':
|
||||
if (!parse_arg(optarg, &optval)) {
|
||||
if (!parse_numeric_arg(optarg, &optval)) {
|
||||
error("Failed to parse \"%s\"\n", optarg);
|
||||
}
|
||||
psize = optval;
|
||||
break;
|
||||
case 'L':
|
||||
if (!parse_arg(optarg, &optval)) {
|
||||
if (!parse_numeric_arg(optarg, &optval)) {
|
||||
error("Failed to parse \"%s\"\n", optarg);
|
||||
}
|
||||
if ((optval & (optval-1)) || optval < PBLK_SIZE) {
|
||||
|
@ -148,17 +154,38 @@ do_format(int argc, char** argv)
|
|||
error("Implement me!\n");
|
||||
break;
|
||||
case 'l':
|
||||
if (!parse_arg(optarg, &optval)) {
|
||||
if (!parse_numeric_arg(optarg, &optval)) {
|
||||
error("Failed to parse \"%s\"\n", optarg);
|
||||
}
|
||||
lshift = optval;
|
||||
break;
|
||||
case 's':
|
||||
if (!parse_arg(optarg, &optval)) {
|
||||
if (!parse_numeric_arg(optarg, &optval)) {
|
||||
error("Failed to parse \"%s\"\n", optarg);
|
||||
}
|
||||
lsize = optval;
|
||||
break;
|
||||
case 'z':
|
||||
alg = CBD_ALG_NONE;
|
||||
if (!strcmp(optarg, "lz4")) {
|
||||
alg = CBD_ALG_LZ4;
|
||||
}
|
||||
if (!strcmp(optarg, "zlib")) {
|
||||
alg = CBD_ALG_ZLIB;
|
||||
}
|
||||
if (alg == CBD_ALG_NONE) {
|
||||
error("Invalid compression algorithm \"%s\"\n", optarg);
|
||||
}
|
||||
break;
|
||||
case 'Z':
|
||||
if (!parse_numeric_arg(optarg, &optval)) {
|
||||
error("Failed to parse \"%s\"\n", optarg);
|
||||
}
|
||||
if (optval < 1 || optval > 9) {
|
||||
error("Compression level \"%s\" out of bounds\n", optarg);
|
||||
}
|
||||
level = optval;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
@ -168,7 +195,7 @@ do_format(int argc, char** argv)
|
|||
}
|
||||
dev = argv[optind++];
|
||||
|
||||
cbd_format(dev, psize, lshift, lsize);
|
||||
cbd_format(dev, psize, lshift, lsize, alg, level);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -284,7 +311,7 @@ do_resize(int argc, char** argv)
|
|||
while ((opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 's':
|
||||
if (!parse_arg(optarg, &optval)) {
|
||||
if (!parse_numeric_arg(optarg, &optval)) {
|
||||
fprintf(stderr, "Failed to parse \"%s\"\n", optarg);
|
||||
usage();
|
||||
}
|
||||
|
|
|
@ -53,7 +53,6 @@ struct compress
|
|||
struct dm_dev* dev;
|
||||
|
||||
struct cbd_params params;
|
||||
void* percpu;
|
||||
struct lbdcache* lc;
|
||||
|
||||
struct workqueue_struct* io_workq;
|
||||
|
@ -119,7 +118,31 @@ compress_open(struct compress* c, u64 dev_nr_pblks)
|
|||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (header.params.algorithm == CBD_ALG_NONE ||
|
||||
header.params.algorithm >= CBD_ALG_MAX) {
|
||||
printk(KERN_ERR "%s: bad algorithm\n", __func__);
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
#ifndef COMPRESS_HAVE_LZ4
|
||||
if (header.params.algorithm == CBD_ALG_LZ4) {
|
||||
printk(KERN_ERR "%s: algorithm lz4 is not built into kernel\n", __func__);
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
#ifndef COMPRESS_HAVE_ZLIB
|
||||
if (header.params.algorithm == CBD_ALG_ZLIB) {
|
||||
printk(KERN_ERR "%s: algorithm zlib is not built into kernel\n", __func__);
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
if (header.params.compression < 1 || header.params.compression > 9) {
|
||||
printk(KERN_ERR "%s: bad compression\n", __func__);
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (header.params.lblk_shift < LBLK_SHIFT_MIN ||
|
||||
header.params.lblk_shift > LBLK_SHIFT_MAX) {
|
||||
printk(KERN_ERR "%s: bad lblk_shift\n", __func__);
|
||||
|
@ -151,7 +174,6 @@ compress_open(struct compress* c, u64 dev_nr_pblks)
|
|||
printk(KERN_INFO " lblk_per_zone=%u\n", (unsigned int)header.params.lblk_per_zone);
|
||||
|
||||
memcpy(&c->params, &header.params, sizeof(header.params));
|
||||
c->percpu = alloc_percpu(void*);
|
||||
|
||||
c->lc = kmalloc(lbdcache_size(), GFP_KERNEL);
|
||||
if (!c->lc) {
|
||||
|
@ -159,7 +181,7 @@ compress_open(struct compress* c, u64 dev_nr_pblks)
|
|||
printk(KERN_ERR "Failed to alloc lbdcache\n");
|
||||
goto out;
|
||||
}
|
||||
if (!lbdcache_ctr(c->lc, &c->params, c->percpu)) {
|
||||
if (!lbdcache_ctr(c->lc, &c->params)) {
|
||||
err = -ENOMEM;
|
||||
printk(KERN_ERR "Failed to init logical block cache\n");
|
||||
goto out;
|
||||
|
@ -406,7 +428,6 @@ compress_dtr(struct dm_target *ti)
|
|||
c = ti->private;
|
||||
lbdcache_dtr(c->lc);
|
||||
kfree(c->lc);
|
||||
free_percpu(c->percpu);
|
||||
if (c->io_workq) {
|
||||
destroy_workqueue(c->io_workq);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/mutex.h>
|
||||
|
||||
#include <linux/lz4.h>
|
||||
#include <linux/zlib.h>
|
||||
|
||||
#include <linux/dm-compress.h>
|
||||
|
||||
|
@ -91,65 +92,45 @@ lblk_is_zeros(struct cbd_params* params, struct lbd* lbd)
|
|||
#endif
|
||||
}
|
||||
|
||||
struct lz4_state {
|
||||
u8* wrkmem;
|
||||
struct lblk_compress_state {
|
||||
struct page* pages;
|
||||
u8* buf;
|
||||
#ifdef COMPRESS_HAVE_LZ4
|
||||
u8* lz4_workmem;
|
||||
#endif
|
||||
#ifdef COMPRESS_HAVE_ZLIB
|
||||
z_stream zlib_cstream;
|
||||
z_stream zlib_dstream;
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct lz4_state*
|
||||
lblk_get_lz4_state(struct lbd* lbd, int cpu)
|
||||
static struct lblk_compress_state*
|
||||
lblk_get_compress_state(void* percpu, const struct cbd_params* params, int cpu)
|
||||
{
|
||||
struct lz4_state** statep;
|
||||
struct lz4_state* state;
|
||||
struct lblk_compress_state** statep;
|
||||
|
||||
statep = per_cpu_ptr(lbd->percpu, cpu);
|
||||
if (*statep) {
|
||||
return *statep;
|
||||
}
|
||||
state = kmalloc(sizeof(struct lz4_state), GFP_NOWAIT);
|
||||
if (!state) {
|
||||
printk(KERN_ERR "%s: failed to alloc state\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
state->wrkmem = kmalloc(LZ4_compressBound(PBLK_SIZE * lblk_per_pblk(lbd->params)), GFP_NOWAIT);
|
||||
state->pages = cbd_alloc_pages_nowait(lblk_per_pblk(lbd->params));
|
||||
if (!state->wrkmem || !state->pages) {
|
||||
kfree(state->wrkmem);
|
||||
cbd_free_pages(state->pages, lblk_per_pblk(lbd->params));
|
||||
kfree(state);
|
||||
printk(KERN_ERR "%s: failed to alloc buffers\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
state->buf = page_address(state->pages);
|
||||
*statep = state;
|
||||
|
||||
return state;
|
||||
statep = per_cpu_ptr(percpu, cpu);
|
||||
return *statep;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compress dc->lblk into dc->lz4_cbuf
|
||||
*
|
||||
* Returns number of bytes in cbuf or 0 for failure.
|
||||
*/
|
||||
#ifdef COMPRESS_HAVE_LZ4
|
||||
static size_t
|
||||
lblk_compress(struct lbd* lbd)
|
||||
lblk_compress_lz4(struct lbd* lbd)
|
||||
{
|
||||
int clen;
|
||||
int cpu;
|
||||
struct lz4_state* state;
|
||||
struct lblk_compress_state* state;
|
||||
|
||||
cpu = get_cpu();
|
||||
state = lblk_get_lz4_state(lbd, cpu);
|
||||
state = lblk_get_compress_state(lbd->percpu, lbd->params, cpu);
|
||||
if (!state) {
|
||||
put_cpu();
|
||||
return 0;
|
||||
}
|
||||
clen = LZ4_compress_default(lbd->buf,
|
||||
state->buf,
|
||||
clen = LZ4_compress_fast(lbd->buf, state->buf,
|
||||
PBLK_SIZE * lblk_per_pblk(lbd->params),
|
||||
PBLK_SIZE * (lblk_per_pblk(lbd->params) - 1),
|
||||
state->wrkmem);
|
||||
lbd->params->compression, state->lz4_workmem);
|
||||
if (clen <= 0) {
|
||||
put_cpu();
|
||||
return 0;
|
||||
|
@ -160,6 +141,130 @@ lblk_compress(struct lbd* lbd)
|
|||
return (size_t)clen;
|
||||
}
|
||||
|
||||
static bool
|
||||
lblk_decompress_lz4(struct lbd* lbd, u32 clen)
|
||||
{
|
||||
int ret;
|
||||
int cpu;
|
||||
struct lblk_compress_state* state;
|
||||
u32 dlen = PBLK_SIZE * lblk_per_pblk(lbd->params);
|
||||
|
||||
cpu = get_cpu();
|
||||
state = lblk_get_compress_state(lbd->percpu, lbd->params, cpu);
|
||||
if (!state) {
|
||||
put_cpu();
|
||||
return false;
|
||||
}
|
||||
ret = LZ4_decompress_safe(lbd->buf,
|
||||
state->buf,
|
||||
clen,
|
||||
dlen);
|
||||
if (ret != dlen) {
|
||||
put_cpu();
|
||||
return false;
|
||||
}
|
||||
memcpy(lbd->buf, state->buf, dlen);
|
||||
put_cpu();
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef COMPRESS_HAVE_ZLIB
|
||||
static size_t
|
||||
lblk_compress_zlib(struct lbd* lbd)
|
||||
{
|
||||
int ret;
|
||||
int cpu;
|
||||
struct lblk_compress_state* state;
|
||||
z_stream* stream;
|
||||
|
||||
cpu = get_cpu();
|
||||
state = lblk_get_compress_state(lbd->percpu, lbd->params, cpu);
|
||||
if (!state) {
|
||||
put_cpu();
|
||||
return 0;
|
||||
}
|
||||
stream = &state->zlib_cstream;
|
||||
ret = zlib_deflateReset(stream);
|
||||
BUG_ON(ret != Z_OK);
|
||||
stream->next_in = lbd->buf;
|
||||
stream->avail_in = PBLK_SIZE * lblk_per_pblk(lbd->params);
|
||||
stream->next_out = state->buf;
|
||||
stream->avail_out = PBLK_SIZE * (lblk_per_pblk(lbd->params) - 1);
|
||||
ret = zlib_deflate(stream, Z_FINISH);
|
||||
if (ret != Z_STREAM_END) {
|
||||
put_cpu();
|
||||
return 0;
|
||||
}
|
||||
memcpy(lbd->buf, state->buf, stream->total_out);
|
||||
put_cpu();
|
||||
|
||||
return stream->total_out;
|
||||
}
|
||||
|
||||
static bool
|
||||
lblk_decompress_zlib(struct lbd* lbd, u32 clen)
|
||||
{
|
||||
int ret;
|
||||
int cpu;
|
||||
struct lblk_compress_state* state;
|
||||
z_stream* stream;
|
||||
u32 dlen = PBLK_SIZE * lblk_per_pblk(lbd->params);
|
||||
|
||||
cpu = get_cpu();
|
||||
state = lblk_get_compress_state(lbd->percpu, lbd->params, cpu);
|
||||
if (!state) {
|
||||
put_cpu();
|
||||
return false;
|
||||
}
|
||||
stream = &state->zlib_dstream;
|
||||
ret = zlib_inflateReset(stream);
|
||||
BUG_ON(ret != Z_OK);
|
||||
stream->next_in = lbd->buf;
|
||||
stream->avail_in = clen;
|
||||
stream->next_out = state->buf;
|
||||
stream->avail_out = dlen;
|
||||
ret = zlib_inflate(stream, Z_SYNC_FLUSH);
|
||||
/* See xxx */
|
||||
if (ret == Z_OK && !stream->avail_in && stream->avail_out) {
|
||||
u8 zerostuff = 0;
|
||||
stream->next_in = &zerostuff;
|
||||
stream->avail_in = 1;
|
||||
ret = zlib_inflate(stream, Z_FINISH);
|
||||
}
|
||||
if (ret != Z_STREAM_END || stream->total_out != dlen) {
|
||||
put_cpu();
|
||||
return false;
|
||||
}
|
||||
memcpy(lbd->buf, state->buf, dlen);
|
||||
put_cpu();
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Compress dc->lblk into dc->lz4_cbuf
|
||||
*
|
||||
* Returns number of bytes in cbuf or 0 for failure.
|
||||
*/
|
||||
static size_t
|
||||
lblk_compress(struct lbd* lbd)
|
||||
{
|
||||
#ifdef COMPRESS_HAVE_LZ4
|
||||
if (lbd->params->algorithm == CBD_ALG_LZ4) {
|
||||
return lblk_compress_lz4(lbd);
|
||||
}
|
||||
#endif
|
||||
#ifdef COMPRESS_HAVE_ZLIB
|
||||
if (lbd->params->algorithm == CBD_ALG_ZLIB) {
|
||||
return lblk_compress_zlib(lbd);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decompress dc->lz4_cbuf of size clen into dc->lblk
|
||||
*
|
||||
|
@ -168,29 +273,17 @@ lblk_compress(struct lbd* lbd)
|
|||
static int
|
||||
lblk_decompress(struct lbd* lbd, u32 clen)
|
||||
{
|
||||
int ret;
|
||||
int cpu;
|
||||
struct lz4_state* state;
|
||||
u32 dlen = PBLK_SIZE * lblk_per_pblk(lbd->params);
|
||||
|
||||
cpu = get_cpu();
|
||||
state = lblk_get_lz4_state(lbd, cpu);
|
||||
if (!state) {
|
||||
put_cpu();
|
||||
return -1;
|
||||
#ifdef COMPRESS_HAVE_LZ4
|
||||
if (lbd->params->algorithm == CBD_ALG_LZ4) {
|
||||
return lblk_decompress_lz4(lbd, clen);
|
||||
}
|
||||
ret = LZ4_decompress_safe(lbd->buf,
|
||||
state->buf,
|
||||
clen,
|
||||
dlen);
|
||||
if (ret != dlen) {
|
||||
put_cpu();
|
||||
return -1;
|
||||
#endif
|
||||
#ifdef COMPRESS_HAVE_ZLIB
|
||||
if (lbd->params->algorithm == CBD_ALG_ZLIB) {
|
||||
return lblk_decompress_zlib(lbd, clen);
|
||||
}
|
||||
memcpy(lbd->buf, state->buf, dlen);
|
||||
put_cpu();
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -381,7 +474,7 @@ lbd_read(struct lbd* lbd)
|
|||
}
|
||||
}
|
||||
if (is_compressed) {
|
||||
if (lblk_decompress(lbd, c_len) != 0) {
|
||||
if (!lblk_decompress(lbd, c_len)) {
|
||||
printk(KERN_ERR " decompress failed\n");
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
|
@ -473,15 +566,94 @@ lbdcache_realloc(struct lbdcache* lc, unsigned int len)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
lbdcache_alloc_compress_state(void* percpu, const struct cbd_params* params, int cpu)
|
||||
{
|
||||
struct lblk_compress_state* state;
|
||||
struct lblk_compress_state** statep;
|
||||
size_t workmem_len;
|
||||
#ifdef COMPRESS_HAVE_ZLIB
|
||||
int ret;
|
||||
#endif
|
||||
|
||||
state = kzalloc(sizeof(struct lblk_compress_state), GFP_NOWAIT);
|
||||
if (!state) {
|
||||
printk(KERN_ERR "%s: failed to alloc state\n", __func__);
|
||||
return false;
|
||||
}
|
||||
statep = per_cpu_ptr(percpu, cpu);
|
||||
*statep = state;
|
||||
state->pages = cbd_alloc_pages_nowait(lblk_per_pblk(params));
|
||||
if (!state->pages) {
|
||||
return false;
|
||||
}
|
||||
state->buf = page_address(state->pages);
|
||||
#ifdef COMPRESS_HAVE_LZ4
|
||||
workmem_len = LZ4_compressBound(PBLK_SIZE * lblk_per_pblk(params));
|
||||
state->lz4_workmem = kzalloc(workmem_len, GFP_NOWAIT);
|
||||
if (!state->lz4_workmem) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#ifdef COMPRESS_HAVE_ZLIB
|
||||
workmem_len = zlib_deflate_workspacesize(MAX_WBITS, DEF_MEM_LEVEL);
|
||||
state->zlib_cstream.workspace = kzalloc(workmem_len, GFP_NOWAIT);
|
||||
if (!state->zlib_cstream.workspace) {
|
||||
return false;
|
||||
}
|
||||
ret = zlib_deflateInit2(&state->zlib_cstream, params->compression,
|
||||
Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
|
||||
Z_DEFAULT_STRATEGY);
|
||||
BUG_ON(ret != Z_OK);
|
||||
workmem_len = zlib_inflate_workspacesize();
|
||||
state->zlib_dstream.workspace = kzalloc(workmem_len, GFP_NOWAIT);
|
||||
if (!state->zlib_dstream.workspace) {
|
||||
return false;
|
||||
}
|
||||
ret = zlib_inflateInit2(&state->zlib_dstream, DEF_WBITS);
|
||||
BUG_ON(ret != Z_OK);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
lbdcache_free_compress_state(void* percpu, const struct cbd_params* params, int cpu)
|
||||
{
|
||||
struct lblk_compress_state** statep;
|
||||
struct lblk_compress_state* state;
|
||||
|
||||
statep = per_cpu_ptr(percpu, cpu);
|
||||
state = *statep;
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
#ifdef COMPRESS_HAVE_ZLIB
|
||||
kfree(state->zlib_dstream.workspace);
|
||||
kfree(state->zlib_cstream.workspace);
|
||||
#endif
|
||||
#ifdef COMPRESS_HAVE_LZ4
|
||||
kfree(state->lz4_workmem);
|
||||
#endif
|
||||
cbd_free_pages(state->pages, lblk_per_pblk(params));
|
||||
kfree(state);
|
||||
}
|
||||
|
||||
bool
|
||||
lbdcache_ctr(struct lbdcache* lc,
|
||||
struct cbd_params* params,
|
||||
void* percpu)
|
||||
struct cbd_params* params)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
memset(lc, 0, sizeof(struct lbdcache));
|
||||
mutex_init(&lc->lock);
|
||||
lc->params = params;
|
||||
lc->percpu = percpu;
|
||||
lc->percpu = alloc_percpu(void*);
|
||||
for (cpu = 0; cpu < num_online_cpus(); ++cpu) {
|
||||
if (!lbdcache_alloc_compress_state(lc->percpu, params, cpu)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
lc->lvc = kzalloc(lbatviewcache_size(), GFP_KERNEL);
|
||||
if (!lc->lvc) {
|
||||
return false;
|
||||
|
@ -498,6 +670,7 @@ lbdcache_dtr(struct lbdcache* lc)
|
|||
{
|
||||
unsigned int n;
|
||||
struct lbd* lbd;
|
||||
int cpu;
|
||||
|
||||
for (n = 0; n < lc->len; ++n) {
|
||||
lbd = lc->cache[n];
|
||||
|
@ -516,6 +689,11 @@ lbdcache_dtr(struct lbdcache* lc)
|
|||
lbatviewcache_dtr(lc->lvc);
|
||||
kfree(lc->lvc);
|
||||
lc->lvc = NULL;
|
||||
for (cpu = 0; cpu < num_online_cpus(); ++cpu) {
|
||||
lbdcache_free_compress_state(lc->percpu, lc->params, cpu);
|
||||
}
|
||||
free_percpu(lc->percpu);
|
||||
lc->percpu = NULL;
|
||||
lc->params = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,8 @@ typedef enum {
|
|||
} tristate_t;
|
||||
|
||||
int cbd_format(const char* dev,
|
||||
uint64_t psize, uint16_t lshift, uint64_t lsize);
|
||||
uint64_t psize, uint16_t lshift, uint64_t lsize,
|
||||
enum cbd_alg alg, uint level);
|
||||
int cbd_open(const char* dev,
|
||||
const char* name);
|
||||
int cbd_close(const char* name);
|
||||
|
|
|
@ -444,6 +444,13 @@ lba_put(const struct cbd_params* params,
|
|||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#if defined(CONFIG_LZ4_COMPRESS) || defined(CONFIG_LZ4_COMPRESS_MODULE)
|
||||
#define COMPRESS_HAVE_LZ4 1
|
||||
#endif
|
||||
#if defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)
|
||||
#define COMPRESS_HAVE_ZLIB 1
|
||||
#endif
|
||||
|
||||
enum cache_state {
|
||||
CACHE_STATE_UNCACHED,
|
||||
CACHE_STATE_CLEAN,
|
||||
|
@ -548,8 +555,7 @@ void lbd_data_write(struct lbd* lbd, u32 off, u32 len, const u8* buf);
|
|||
struct lbdcache;
|
||||
size_t lbdcache_size(void);
|
||||
bool lbdcache_ctr(struct lbdcache* lc,
|
||||
struct cbd_params* params,
|
||||
void* percpu);
|
||||
struct cbd_params* params);
|
||||
void lbdcache_dtr(struct lbdcache* lc);
|
||||
struct lbd*
|
||||
lbdcache_get(struct lbdcache* lc, u64 lblk);
|
||||
|
|
|
@ -27,7 +27,8 @@ pblk_write(int fd, u64 pblk, u32 count, const u8* data)
|
|||
|
||||
int
|
||||
cbd_format(const char* dev,
|
||||
uint64_t psize, uint16_t lshift, uint64_t lsize)
|
||||
uint64_t psize, uint16_t lshift, uint64_t lsize,
|
||||
enum cbd_alg alg, uint level)
|
||||
{
|
||||
int devfd;
|
||||
uint32_t lblk_size;
|
||||
|
@ -67,6 +68,12 @@ cbd_format(const char* dev,
|
|||
if (lsize % (1 << (lshift + PBLK_SHIFT))) {
|
||||
error("Logical size %lu is not a multiple of %u bytes\n", (ulong)psize, (uint)lblk_size);
|
||||
}
|
||||
if (alg <= CBD_ALG_NONE || alg >= CBD_ALG_MAX) {
|
||||
error("Compression algorithm %d unknown\n", (int)alg);
|
||||
}
|
||||
if (level < 1 || level > 9) {
|
||||
error("Compression level %u out of bounds\n", level);
|
||||
}
|
||||
|
||||
printf("%s: paramaters...\n", __func__);
|
||||
printf(" psize=%lu\n", (unsigned long)psize);
|
||||
|
@ -76,8 +83,8 @@ cbd_format(const char* dev,
|
|||
memcpy(header.magic, CBD_MAGIC, sizeof(header.magic));
|
||||
header.version_major = CBD_VERSION_MAJOR;
|
||||
header.version_minor = CBD_VERSION_MINOR;
|
||||
header.params.algorithm = CBD_ALG_LZ4;
|
||||
header.params.compression = 1;
|
||||
header.params.algorithm = alg;
|
||||
header.params.compression = level;
|
||||
header.params.lblk_shift = lshift;
|
||||
header.params.nr_pblk = psize / PBLK_SIZE;
|
||||
/* XXX: Initial estimate */
|
||||
|
@ -86,6 +93,8 @@ cbd_format(const char* dev,
|
|||
header.params.nr_zones = ((psize >> PBLK_SHIFT) - CBD_HEADER_BLOCKS) / zone_len(&header.params);
|
||||
header.params.lblk_per_zone = DIV_ROUND_UP(lsize / lblk_size, header.params.nr_zones);
|
||||
printf("%s: parameters...\n", __func__);
|
||||
printf(" algorithm=%d\n", (int)header.params.algorithm);
|
||||
printf(" compression=%u\n", (unsigned int)header.params.compression);
|
||||
printf(" lblk_shift=%hu\n", (unsigned short)header.params.lblk_shift);
|
||||
printf(" nr_pblk=%lu\n", (unsigned long)header.params.nr_pblk);
|
||||
printf(" nr_zones=%lu\n", (unsigned long)header.params.nr_zones);
|
||||
|
|
Loading…
Reference in New Issue