From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752816AbbHMN4t (ORCPT ); Thu, 13 Aug 2015 09:56:49 -0400 Received: from mail-pa0-f53.google.com ([209.85.220.53]:35781 "EHLO mail-pa0-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752506AbbHMN4p (ORCPT ); Thu, 13 Aug 2015 09:56:45 -0400 From: Sergey Senozhatsky To: Minchan Kim , Joonsoo Kim Cc: Andrew Morton , linux-kernel@vger.kernel.org, Sergey Senozhatsky , Sergey Senozhatsky Subject: [RFC][PATCH 3/4] zram: add zlib backend Date: Thu, 13 Aug 2015 22:55:22 +0900 Message-Id: <1439474123-11279-4-git-send-email-sergey.senozhatsky@gmail.com> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1439474123-11279-1-git-send-email-sergey.senozhatsky@gmail.com> References: <1439474123-11279-1-git-send-email-sergey.senozhatsky@gmail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add ZLIB backend (disabled yet, will be enalbed in later patch). ====================================================================== TEST Copy dir with the linux kernel to a zram device (du -sh 2.3G) and check memory usage stats. mm_stat fields: orig_data_size compr_data_size mem_used_total mem_limit mem_used_max zero_pages num_migrated zlib cat /sys/block/zram0/mm_stat 2522685440 1210486447 1230729216 0 1230729216 5461 0 lzo cat /sys/block/zram0/mm_stat 2525872128 1713351248 1738387456 0 1738387456 4682 0 ZLIB uses 484+MiB less memory in the test. Signed-off-by: Sergey Senozhatsky --- drivers/block/zram/Makefile | 1 + drivers/block/zram/zcomp.c | 11 ++++ drivers/block/zram/zcomp.h | 2 + drivers/block/zram/zcomp_zlib.c | 120 ++++++++++++++++++++++++++++++++++++++++ drivers/block/zram/zcomp_zlib.h | 17 ++++++ 5 files changed, 151 insertions(+) create mode 100644 drivers/block/zram/zcomp_zlib.c create mode 100644 drivers/block/zram/zcomp_zlib.h diff --git a/drivers/block/zram/Makefile b/drivers/block/zram/Makefile index be0763f..0922f54 100644 --- a/drivers/block/zram/Makefile +++ b/drivers/block/zram/Makefile @@ -1,5 +1,6 @@ zram-y := zcomp_lzo.o zcomp.o zram_drv.o zram-$(CONFIG_ZRAM_LZ4_COMPRESS) += zcomp_lz4.o +zram-$(CONFIG_ZRAM_ZLIB_COMPRESS) += zcomp_zlib.o obj-$(CONFIG_ZRAM) += zram.o diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c index a1c67be..a0cef0b 100644 --- a/drivers/block/zram/zcomp.c +++ b/drivers/block/zram/zcomp.c @@ -19,6 +19,9 @@ #ifdef CONFIG_ZRAM_LZ4_COMPRESS #include "zcomp_lz4.h" #endif +#ifdef CONFIG_ZRAM_ZLIB_COMPRESS +#include "zcomp_zlib.h" +#endif /* * single zcomp_strm backend @@ -48,6 +51,9 @@ static struct zcomp_backend *backends[] = { #ifdef CONFIG_ZRAM_LZ4_COMPRESS &zcomp_lz4, #endif +#ifdef CONFIG_ZRAM_ZLIB_COMPRESS + &zcomp_zlib, +#endif NULL }; @@ -328,11 +334,16 @@ void zcomp_destroy(struct zcomp *comp) void *zcomp_decompress_begin(struct zcomp *comp) { + if (unlikely(comp->backend->flags() & ZCOMP_NEED_READ_ZSTRM)) + return zcomp_strm_find(comp); + return NULL; } void zcomp_decompress_end(struct zcomp *comp, void *private) { + if (unlikely(private)) + zcomp_strm_release(comp, private); } /* diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h index 5cb9a0b..dbb7f1f 100644 --- a/drivers/block/zram/zcomp.h +++ b/drivers/block/zram/zcomp.h @@ -12,6 +12,8 @@ #include +#define ZCOMP_NEED_READ_ZSTRM (1 << 0) + struct zcomp_strm { /* compression/decompression buffer */ void *buffer; diff --git a/drivers/block/zram/zcomp_zlib.c b/drivers/block/zram/zcomp_zlib.c new file mode 100644 index 0000000..711eddd --- /dev/null +++ b/drivers/block/zram/zcomp_zlib.c @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2015 Sergey Senozhatsky. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include + +#include "zcomp_zlib.h" + +#define ZLIB_COMPRESSION_LEVEL 3 + +static void *zlib_create(void) +{ + z_stream *stream; + size_t size; + + stream = kzalloc(sizeof(*stream), GFP_KERNEL); + if (!stream) + return NULL; + + size = max(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL), + zlib_inflate_workspacesize()); + stream->workspace = vmalloc(size); + if (!stream->workspace) { + kfree(stream); + stream = NULL; + } + + return stream; +} + +static void zlib_destroy(void *private) +{ + z_stream *stream = private; + + vfree(stream->workspace); + kfree(stream); +} + +static int zlib_flags(void) +{ + return ZCOMP_NEED_READ_ZSTRM; +} + +static int zlib_compress(const unsigned char *src, unsigned char *dst, + size_t *dst_len, void *private) +{ + z_stream *stream = private; + int err; + + err = zlib_deflateInit(stream, ZLIB_COMPRESSION_LEVEL); + if (err != Z_OK) + goto out; + + stream->next_in = src; + stream->avail_in = PAGE_SIZE; + stream->total_in = 0; + stream->next_out = dst; + stream->avail_out = PAGE_SIZE; + stream->total_out = 0; + + err = zlib_deflate(stream, Z_FINISH); + if (err != Z_STREAM_END) + goto out; + + err = zlib_deflateEnd(stream); + if (err != Z_OK) + goto out; + + if (stream->total_out >= stream->total_in) + goto out; + + *dst_len = stream->total_out; +out: + return err == Z_OK ? 0 : err; +} + +static int zlib_decompress(const unsigned char *src, size_t src_len, + unsigned char *dst, void *private) +{ + z_stream *stream = private; + int err; + + err = zlib_inflateInit(stream); + if (err != Z_OK) + goto out; + + stream->next_in = src; + stream->avail_in = src_len; + stream->total_in = 0; + stream->next_out = dst; + stream->avail_out = PAGE_SIZE; + stream->total_out = 0; + + err = zlib_inflate(stream, Z_FINISH); + if (err != Z_STREAM_END) + goto out; + + err = zlib_inflateEnd(stream); + if (err != Z_OK) + goto out; +out: + return err == Z_OK ? 0 : err; +} + +struct zcomp_backend zcomp_zlib = { + .compress = zlib_compress, + .decompress = zlib_decompress, + .create = zlib_create, + .destroy = zlib_destroy, + .flags = zlib_flags, + .name = "zlib", +}; diff --git a/drivers/block/zram/zcomp_zlib.h b/drivers/block/zram/zcomp_zlib.h new file mode 100644 index 0000000..d0e4fa0 --- /dev/null +++ b/drivers/block/zram/zcomp_zlib.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2015 Sergey Senozhatsky. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ZCOMP_ZLIB_H_ +#define _ZCOMP_ZLIB_H_ + +#include "zcomp.h" + +extern struct zcomp_backend zcomp_zlib; + +#endif /* _ZCOMP_ZLIB_H_ */ -- 2.5.0