Skip to content

Commit

Permalink
staging: Add Snappy compression support to zram
Browse files Browse the repository at this point in the history
Zram currently uses LZO compression. With Snappy, it uses less CPU time and is
thus more useful. The sacrifice in compression ratio is small.
Zram's LZO and Snappy support can be independently enabled at compile time and
each zram device can switch between compression methods when unused.
When only a single compression method was enabled at compile time, no idirection
penalty is incurred.

Signed-off-by: Zeev Tarantov <zeev.tarantov at gmail.com>
Signed-off-by: CTCaer <ctcaer@gmail.com>
Signed-off-by: garwedgess <garethwilliams21@gmail.com>
  • Loading branch information
CTCaer authored and garwedgess committed Jun 11, 2013
1 parent 41d9650 commit c2fccfe
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 15 deletions.
22 changes: 20 additions & 2 deletions drivers/staging/zram/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ config ZRAM
tristate "Compressed RAM block device support"
depends on BLOCK && SYSFS
select XVMALLOC
select LZO_COMPRESS
select LZO_DECOMPRESS
default n
help
Creates virtual block devices called /dev/zramX (X = 0, 1, ...).
Expand All @@ -28,3 +26,23 @@ config ZRAM_DEBUG
help
This option adds additional debugging code to the compressed
RAM block device driver.

choice ZRAM_COMPRESS
prompt "compression method"
depends on ZRAM
default ZRAM_LZO
help
Select the compression method used by zram.
LZO is the default. Snappy compresses a bit worse (around ~2%) but
much (~2x) faster, at least on x86-64.

config ZRAM_LZO
bool "LZO compression"
select LZO_COMPRESS
select LZO_DECOMPRESS

config ZRAM_SNAPPY
bool "Snappy compression"
depends on SNAPPY_COMPRESS
depends on SNAPPY_DECOMPRESS
endchoice
62 changes: 49 additions & 13 deletions drivers/staging/zram/zram_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,56 @@
#include <linux/genhd.h>
#include <linux/highmem.h>
#include <linux/slab.h>
#include <linux/lzo.h>
#include <linux/string.h>
#include <linux/vmalloc.h>

#include "zram_drv.h"

#if defined(CONFIG_ZRAM_LZO)
#include <linux/lzo.h>
#define WMSIZE LZO1X_MEM_COMPRESS
#define COMPRESS(s, sl, d, dl, wm) \
lzo1x_1_compress(s, sl, d, dl, wm)
#define DECOMPRESS(s, sl, d, dl) \
lzo1x_decompress_safe(s, sl, d, dl)
#elif defined(CONFIG_ZRAM_SNAPPY)
#include "../snappy/csnappy.h" /* if built in drivers/staging */
#define WMSIZE_ORDER ((PAGE_SHIFT > 14) ? (15) : (PAGE_SHIFT+1))
#define WMSIZE (1 << WMSIZE_ORDER)
static int
snappy_compress_(
const unsigned char *src,
size_t src_len,
unsigned char *dst,
size_t *dst_len,
void *workmem)
{
const unsigned char *end = csnappy_compress_fragment(
src, (uint32_t)src_len, dst, workmem, WMSIZE_ORDER);
*dst_len = end - dst;
return 0;
}
static int
snappy_decompress_(
const unsigned char *src,
size_t src_len,
unsigned char *dst,
size_t *dst_len)
{
uint32_t dst_len_ = (uint32_t)*dst_len;
int ret = csnappy_decompress_noheader(src, src_len, dst, &dst_len_);
*dst_len = (size_t)dst_len_;
return ret;
}
#define COMPRESS(s, sl, d, dl, wm) \
snappy_compress_(s, sl, d, dl, wm)
#define DECOMPRESS(s, sl, d, dl) \
snappy_decompress_(s, sl, d, dl)
#else
#error either CONFIG_ZRAM_LZO or CONFIG_ZRAM_SNAPPY must be defined
#endif


/* Globals */
static int zram_major;
struct zram *devices;
Expand Down Expand Up @@ -251,16 +295,15 @@ static void zram_read(struct zram *zram, struct bio *bio)
cmem = kmap_atomic(zram->table[index].page, KM_USER1) +
zram->table[index].offset;

ret = lzo1x_decompress_safe(
cmem + sizeof(*zheader),
ret = DECOMPRESS(cmem + sizeof(*zheader),
xv_get_object_size(cmem) - sizeof(*zheader),
user_mem, &clen);

kunmap_atomic(user_mem, KM_USER0);
kunmap_atomic(cmem, KM_USER1);

/* Should NEVER happen. Return bio error if it does. */
if (unlikely(ret != LZO_E_OK)) {
if (unlikely(ret)) {
pr_err("Decompression failed! err=%d, page=%u\n",
ret, index);
zram_stat64_inc(zram, &zram->stats.failed_reads);
Expand Down Expand Up @@ -319,18 +362,11 @@ static void zram_write(struct zram *zram, struct bio *bio)
continue;
}

ret = lzo1x_1_compress(user_mem, PAGE_SIZE, src, &clen,
ret = COMPRESS(user_mem, PAGE_SIZE, src, &clen,
zram->compress_workmem);

kunmap_atomic(user_mem, KM_USER0);

if (unlikely(ret != LZO_E_OK)) {
mutex_unlock(&zram->lock);
pr_err("Compression failed! err=%d\n", ret);
zram_stat64_inc(zram, &zram->stats.failed_writes);
goto out;
}

/*
* Page is incompressible. Store it as-is (uncompressed)
* since we do not want to return too many disk write
Expand Down Expand Up @@ -511,7 +547,7 @@ int zram_init_device(struct zram *zram)

zram_set_disksize(zram, totalram_pages << PAGE_SHIFT);

zram->compress_workmem = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
zram->compress_workmem = kzalloc(WMSIZE, GFP_KERNEL);
if (!zram->compress_workmem) {
pr_err("Error allocating compressor working memory!\n");
ret = -ENOMEM;
Expand Down

0 comments on commit c2fccfe

Please sign in to comment.