Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

zram: add zlib compression backend support

Add s/w zlib (inflate/deflate) compression.

Link: https://lkml.kernel.org/r/20240902105656.1383858-11-senozhatsky@chromium.org
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Nick Terrell <terrelln@fb.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Sergey Senozhatsky and committed by
Andrew Morton
84112e31 dbf2763c

+158
+11
drivers/block/zram/Kconfig
··· 38 38 select ZSTD_COMPRESS 39 39 select ZSTD_DECOMPRESS 40 40 41 + config ZRAM_BACKEND_DEFLATE 42 + bool "deflate compression support" 43 + depends on ZRAM 44 + select ZLIB_DEFLATE 45 + select ZLIB_INFLATE 46 + 41 47 choice 42 48 prompt "Default zram compressor" 43 49 default ZRAM_DEF_COMP_LZORLE ··· 69 63 bool "zstd" 70 64 depends on ZRAM_BACKEND_ZSTD 71 65 66 + config ZRAM_DEF_COMP_DEFLATE 67 + bool "deflate" 68 + depends on ZRAM_BACKEND_DEFLATE 69 + 72 70 endchoice 73 71 74 72 config ZRAM_DEF_COMP ··· 82 72 default "lz4" if ZRAM_DEF_COMP_LZ4 83 73 default "lz4hc" if ZRAM_DEF_COMP_LZ4HC 84 74 default "zstd" if ZRAM_DEF_COMP_ZSTD 75 + default "deflate" if ZRAM_DEF_COMP_DEFLATE 85 76 default "unset-value" 86 77 87 78 config ZRAM_WRITEBACK
+1
drivers/block/zram/Makefile
··· 6 6 zram-$(CONFIG_ZRAM_BACKEND_LZ4) += backend_lz4.o 7 7 zram-$(CONFIG_ZRAM_BACKEND_LZ4HC) += backend_lz4hc.o 8 8 zram-$(CONFIG_ZRAM_BACKEND_ZSTD) += backend_zstd.o 9 + zram-$(CONFIG_ZRAM_BACKEND_DEFLATE) += backend_deflate.o 9 10 10 11 obj-$(CONFIG_ZRAM) += zram.o
+132
drivers/block/zram/backend_deflate.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + 3 + #include <linux/kernel.h> 4 + #include <linux/slab.h> 5 + #include <linux/vmalloc.h> 6 + #include <linux/zlib.h> 7 + 8 + #include "backend_deflate.h" 9 + 10 + /* Use the same value as crypto API */ 11 + #define DEFLATE_DEF_WINBITS 11 12 + #define DEFLATE_DEF_MEMLEVEL MAX_MEM_LEVEL 13 + 14 + struct deflate_ctx { 15 + struct z_stream_s cctx; 16 + struct z_stream_s dctx; 17 + s32 level; 18 + }; 19 + 20 + static void deflate_destroy(void *ctx) 21 + { 22 + struct deflate_ctx *zctx = ctx; 23 + 24 + if (zctx->cctx.workspace) { 25 + zlib_deflateEnd(&zctx->cctx); 26 + vfree(zctx->cctx.workspace); 27 + } 28 + if (zctx->dctx.workspace) { 29 + zlib_inflateEnd(&zctx->dctx); 30 + vfree(zctx->dctx.workspace); 31 + } 32 + kfree(zctx); 33 + } 34 + 35 + static void *deflate_create(void) 36 + { 37 + struct deflate_ctx *ctx; 38 + size_t sz; 39 + int ret; 40 + 41 + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 42 + if (!ctx) 43 + return NULL; 44 + 45 + /* @FIXME: using a hardcoded Z_DEFAULT_COMPRESSION for now */ 46 + ctx->level = Z_DEFAULT_COMPRESSION; 47 + sz = zlib_deflate_workspacesize(-DEFLATE_DEF_WINBITS, MAX_MEM_LEVEL); 48 + ctx->cctx.workspace = vzalloc(sz); 49 + if (!ctx->cctx.workspace) 50 + goto error; 51 + 52 + ret = zlib_deflateInit2(&ctx->cctx, ctx->level, Z_DEFLATED, 53 + -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL, 54 + Z_DEFAULT_STRATEGY); 55 + if (ret != Z_OK) 56 + goto error; 57 + 58 + sz = zlib_inflate_workspacesize(); 59 + ctx->dctx.workspace = vzalloc(sz); 60 + if (!ctx->dctx.workspace) 61 + goto error; 62 + 63 + ret = zlib_inflateInit2(&ctx->dctx, -DEFLATE_DEF_WINBITS); 64 + if (ret != Z_OK) 65 + goto error; 66 + 67 + return ctx; 68 + 69 + error: 70 + deflate_destroy(ctx); 71 + return NULL; 72 + } 73 + 74 + static int deflate_compress(void *ctx, const unsigned char *src, 75 + size_t src_len, unsigned char *dst, 76 + size_t *dst_len) 77 + { 78 + struct deflate_ctx *zctx = ctx; 79 + struct z_stream_s *deflate; 80 + int ret; 81 + 82 + deflate = &zctx->cctx; 83 + ret = zlib_deflateReset(deflate); 84 + if (ret != Z_OK) 85 + return -EINVAL; 86 + 87 + deflate->next_in = (u8 *)src; 88 + deflate->avail_in = src_len; 89 + deflate->next_out = (u8 *)dst; 90 + deflate->avail_out = *dst_len; 91 + 92 + ret = zlib_deflate(deflate, Z_FINISH); 93 + if (ret != Z_STREAM_END) 94 + return -EINVAL; 95 + 96 + *dst_len = deflate->total_out; 97 + return 0; 98 + } 99 + 100 + static int deflate_decompress(void *ctx, const unsigned char *src, 101 + size_t src_len, unsigned char *dst, 102 + size_t dst_len) 103 + { 104 + struct deflate_ctx *zctx = ctx; 105 + struct z_stream_s *inflate; 106 + int ret; 107 + 108 + inflate = &zctx->dctx; 109 + 110 + ret = zlib_inflateReset(inflate); 111 + if (ret != Z_OK) 112 + return -EINVAL; 113 + 114 + inflate->next_in = (u8 *)src; 115 + inflate->avail_in = src_len; 116 + inflate->next_out = (u8 *)dst; 117 + inflate->avail_out = dst_len; 118 + 119 + ret = zlib_inflate(inflate, Z_SYNC_FLUSH); 120 + if (ret != Z_STREAM_END) 121 + return -EINVAL; 122 + 123 + return 0; 124 + } 125 + 126 + const struct zcomp_ops backend_deflate = { 127 + .compress = deflate_compress, 128 + .decompress = deflate_decompress, 129 + .create_ctx = deflate_create, 130 + .destroy_ctx = deflate_destroy, 131 + .name = "deflate", 132 + };
+10
drivers/block/zram/backend_deflate.h
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + 3 + #ifndef __BACKEND_DEFLATE_H__ 4 + #define __BACKEND_DEFLATE_H__ 5 + 6 + #include "zcomp.h" 7 + 8 + extern const struct zcomp_ops backend_deflate; 9 + 10 + #endif /* __BACKEND_DEFLATE_H__ */
+4
drivers/block/zram/zcomp.c
··· 17 17 #include "backend_lz4.h" 18 18 #include "backend_lz4hc.h" 19 19 #include "backend_zstd.h" 20 + #include "backend_deflate.h" 20 21 21 22 static const struct zcomp_ops *backends[] = { 22 23 #if IS_ENABLED(CONFIG_ZRAM_BACKEND_LZO) ··· 32 31 #endif 33 32 #if IS_ENABLED(CONFIG_ZRAM_BACKEND_ZSTD) 34 33 &backend_zstd, 34 + #endif 35 + #if IS_ENABLED(CONFIG_ZRAM_BACKEND_DEFLATE) 36 + &backend_deflate, 35 37 #endif 36 38 NULL 37 39 };