* [PATCHv5 01/23] lib: zstd: export API needed for dictionary support
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 8:20 ` [PATCH v5 " Markus Elfring
2024-07-06 4:56 ` [PATCHv5 02/23] lib: lz4hc: export LZ4_resetStreamHC symbol Sergey Senozhatsky
` (23 subsequent siblings)
24 siblings, 1 reply; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky, Nick Terrell
We need to export a number of API functions that enable
advanced zstd usage - C/D dictionaries, dictionaries
sharing between contexts, etc.
Cc: Nick Terrell <terrelln@fb.com>
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
include/linux/zstd.h | 167 ++++++++++++++++++++++++++++++
lib/zstd/zstd_compress_module.c | 49 +++++++++
lib/zstd/zstd_decompress_module.c | 36 +++++++
3 files changed, 252 insertions(+)
diff --git a/include/linux/zstd.h b/include/linux/zstd.h
index f109d49f43f8..ac59ae9a18d7 100644
--- a/include/linux/zstd.h
+++ b/include/linux/zstd.h
@@ -77,6 +77,30 @@ int zstd_min_clevel(void);
*/
int zstd_max_clevel(void);
+/**
+ * zstd_default_clevel() - default compression level
+ *
+ * Return: Default compression level.
+ */
+int zstd_default_clevel(void);
+
+/**
+ * struct zstd_custom_mem - custom memory allocation
+ */
+typedef ZSTD_customMem zstd_custom_mem;
+
+/**
+ * struct zstd_dict_load_method - Dictionary load method.
+ * See zstd_lib.h.
+ */
+typedef ZSTD_dictLoadMethod_e zstd_dict_load_method;
+
+/**
+ * struct zstd_dict_content_type - Dictionary context type.
+ * See zstd_lib.h.
+ */
+typedef ZSTD_dictContentType_e zstd_dict_content_type;
+
/* ====== Parameter Selection ====== */
/**
@@ -136,6 +160,19 @@ typedef ZSTD_parameters zstd_parameters;
zstd_parameters zstd_get_params(int level,
unsigned long long estimated_src_size);
+
+/**
+ * zstd_get_cparams() - returns zstd_compression_parameters for selected level
+ * @level: The compression level
+ * @estimated_src_size: The estimated source size to compress or 0
+ * if unknown.
+ * @dict_size: Dictionary size.
+ *
+ * Return: The selected zstd_compression_parameters.
+ */
+zstd_compression_parameters zstd_get_cparams(int level,
+ unsigned long long estimated_src_size, size_t dict_size);
+
/* ====== Single-pass Compression ====== */
typedef ZSTD_CCtx zstd_cctx;
@@ -180,6 +217,71 @@ zstd_cctx *zstd_init_cctx(void *workspace, size_t workspace_size);
size_t zstd_compress_cctx(zstd_cctx *cctx, void *dst, size_t dst_capacity,
const void *src, size_t src_size, const zstd_parameters *parameters);
+/**
+ * zstd_create_cctx_advanced() - Create compression context
+ * @custom_mem: Custom allocator.
+ *
+ * Return: NULL on error, pointer to compression context otherwise.
+ */
+zstd_cctx *zstd_create_cctx_advanced(zstd_custom_mem custom_mem);
+
+/**
+ * zstd_free_cctx() - Free compression context
+ * @cdict: Pointer to compression context.
+ *
+ * Return: Always 0.
+ */
+size_t zstd_free_cctx(zstd_cctx* cctx);
+
+/**
+ * struct zstd_cdict - Compression dictionary.
+ * See zstd_lib.h.
+ */
+typedef ZSTD_CDict zstd_cdict;
+
+/**
+ * zstd_create_cdict_byreference() - Create compression dictionary
+ * @dict: Pointer to dictionary buffer.
+ * @dict_size: Size of the dictionary buffer.
+ * @dict_load_method: Dictionary load method.
+ * @dict_content_type: Dictionary content type.
+ * @custom_mem: Memory allocator.
+ *
+ * Note, this uses @dict by reference (ZSTD_dlm_byRef), so it should be
+ * free before zstd_cdict is destroyed.
+ *
+ * Return: NULL on error, pointer to compression dictionary
+ * otherwise.
+ */
+zstd_cdict *zstd_create_cdict_byreference(const void *dict, size_t dict_size,
+ zstd_compression_parameters cparams,
+ zstd_custom_mem custom_mem);
+
+/**
+ * zstd_free_cdict() - Free compression dictionary
+ * @cdict: Pointer to compression dictionary.
+ *
+ * Return: Always 0.
+ */
+size_t zstd_free_cdict(zstd_cdict* cdict);
+
+/**
+ * zstd_compress_using_cdict() - compress src into dst using a dictionary
+ * @cctx: The context. Must have been initialized with zstd_init_cctx().
+ * @dst: The buffer to compress src into.
+ * @dst_capacity: The size of the destination buffer. May be any size, but
+ * ZSTD_compressBound(srcSize) is guaranteed to be large enough.
+ * @src: The data to compress.
+ * @src_size: The size of the data to compress.
+ * @cdict: The dictionary to be used.
+ *
+ * Return: The compressed size or an error, which can be checked using
+ * zstd_is_error().
+ */
+size_t zstd_compress_using_cdict(zstd_cctx *cctx, void *dst,
+ size_t dst_capacity, const void *src, size_t src_size,
+ const zstd_cdict *cdict);
+
/* ====== Single-pass Decompression ====== */
typedef ZSTD_DCtx zstd_dctx;
@@ -220,6 +322,71 @@ zstd_dctx *zstd_init_dctx(void *workspace, size_t workspace_size);
size_t zstd_decompress_dctx(zstd_dctx *dctx, void *dst, size_t dst_capacity,
const void *src, size_t src_size);
+/**
+ * struct zstd_ddict - Decompression dictionary.
+ * See zstd_lib.h.
+ */
+typedef ZSTD_DDict zstd_ddict;
+
+/**
+ * zstd_create_ddict_byreference() - Create decompression dictionary
+ * @dict: Pointer to dictionary buffer.
+ * @dict_size: Size of the dictionary buffer.
+ * @dict_load_method: Dictionary load method.
+ * @dict_content_type: Dictionary content type.
+ * @custom_mem: Memory allocator.
+ *
+ * Note, this uses @dict by reference (ZSTD_dlm_byRef), so it should be
+ * free before zstd_ddict is destroyed.
+ *
+ * Return: NULL on error, pointer to decompression dictionary
+ * otherwise.
+ */
+zstd_ddict *zstd_create_ddict_byreference(const void *dict, size_t dict_size,
+ zstd_custom_mem custom_mem);
+/**
+ * zstd_free_ddict() - Free decompression dictionary
+ * @dict: Pointer to the dictionary.
+ *
+ * Return: Always 0.
+ */
+size_t zstd_free_ddict(zstd_ddict *ddict);
+
+/**
+ * zstd_create_dctx_advanced() - Create decompression context
+ * @custom_mem: Custom allocator.
+ *
+ * Return: NULL on error, pointer to decompression context otherwise.
+ */
+zstd_dctx *zstd_create_dctx_advanced(zstd_custom_mem custom_mem);
+
+/**
+ * zstd_free_dctx() -- Free decompression context
+ * @dctx: Pointer to decompression context.
+ * Return: Always 0.
+ */
+size_t zstd_free_dctx(zstd_dctx *dctx);
+
+/**
+ * zstd_decompress_using_ddict() - decompress src into dst using a dictionary
+ * @dctx: The decompression context.
+ * @dst: The buffer to decompress src into.
+ * @dst_capacity: The size of the destination buffer. Must be at least as large
+ * as the decompressed size. If the caller cannot upper bound the
+ * decompressed size, then it's better to use the streaming API.
+ * @src: The zstd compressed data to decompress. Multiple concatenated
+ * frames and skippable frames are allowed.
+ * @src_size: The exact size of the data to decompress.
+ * @ddict: The dictionary to be used.
+ *
+ * Return: The decompressed size or an error, which can be checked using
+ * zstd_is_error().
+ */
+size_t zstd_decompress_using_ddict(zstd_dctx *dctx,
+ void *dst, size_t dst_capacity, const void *src, size_t src_size,
+ const zstd_ddict *ddict);
+
+
/* ====== Streaming Buffers ====== */
/**
diff --git a/lib/zstd/zstd_compress_module.c b/lib/zstd/zstd_compress_module.c
index 8ecf43226af2..ceaf352d03e2 100644
--- a/lib/zstd/zstd_compress_module.c
+++ b/lib/zstd/zstd_compress_module.c
@@ -66,6 +66,12 @@ int zstd_max_clevel(void)
}
EXPORT_SYMBOL(zstd_max_clevel);
+int zstd_default_clevel(void)
+{
+ return ZSTD_defaultCLevel();
+}
+EXPORT_SYMBOL(zstd_default_clevel);
+
size_t zstd_compress_bound(size_t src_size)
{
return ZSTD_compressBound(src_size);
@@ -79,6 +85,13 @@ zstd_parameters zstd_get_params(int level,
}
EXPORT_SYMBOL(zstd_get_params);
+zstd_compression_parameters zstd_get_cparams(int level,
+ unsigned long long estimated_src_size, size_t dict_size)
+{
+ return ZSTD_getCParams(level, estimated_src_size, dict_size);
+}
+EXPORT_SYMBOL(zstd_get_cparams);
+
size_t zstd_cctx_workspace_bound(const zstd_compression_parameters *cparams)
{
return ZSTD_estimateCCtxSize_usingCParams(*cparams);
@@ -93,6 +106,33 @@ zstd_cctx *zstd_init_cctx(void *workspace, size_t workspace_size)
}
EXPORT_SYMBOL(zstd_init_cctx);
+zstd_cctx *zstd_create_cctx_advanced(zstd_custom_mem custom_mem)
+{
+ return ZSTD_createCCtx_advanced(custom_mem);
+}
+EXPORT_SYMBOL(zstd_create_cctx_advanced);
+
+size_t zstd_free_cctx(zstd_cctx *cctx)
+{
+ return ZSTD_freeCCtx(cctx);
+}
+EXPORT_SYMBOL(zstd_free_cctx);
+
+zstd_cdict *zstd_create_cdict_byreference(const void *dict, size_t dict_size,
+ zstd_compression_parameters cparams,
+ zstd_custom_mem custom_mem)
+{
+ return ZSTD_createCDict_advanced(dict, dict_size, ZSTD_dlm_byRef,
+ ZSTD_dct_auto, cparams, custom_mem);
+}
+EXPORT_SYMBOL(zstd_create_cdict_byreference);
+
+size_t zstd_free_cdict(zstd_cdict *cdict)
+{
+ return ZSTD_freeCDict(cdict);
+}
+EXPORT_SYMBOL(zstd_free_cdict);
+
size_t zstd_compress_cctx(zstd_cctx *cctx, void *dst, size_t dst_capacity,
const void *src, size_t src_size, const zstd_parameters *parameters)
{
@@ -101,6 +141,15 @@ size_t zstd_compress_cctx(zstd_cctx *cctx, void *dst, size_t dst_capacity,
}
EXPORT_SYMBOL(zstd_compress_cctx);
+size_t zstd_compress_using_cdict(zstd_cctx *cctx, void *dst,
+ size_t dst_capacity, const void *src, size_t src_size,
+ const ZSTD_CDict *cdict)
+{
+ return ZSTD_compress_usingCDict(cctx, dst, dst_capacity,
+ src, src_size, cdict);
+}
+EXPORT_SYMBOL(zstd_compress_using_cdict);
+
size_t zstd_cstream_workspace_bound(const zstd_compression_parameters *cparams)
{
return ZSTD_estimateCStreamSize_usingCParams(*cparams);
diff --git a/lib/zstd/zstd_decompress_module.c b/lib/zstd/zstd_decompress_module.c
index 7d31518e9d5a..0ae819f0c927 100644
--- a/lib/zstd/zstd_decompress_module.c
+++ b/lib/zstd/zstd_decompress_module.c
@@ -44,6 +44,33 @@ size_t zstd_dctx_workspace_bound(void)
}
EXPORT_SYMBOL(zstd_dctx_workspace_bound);
+zstd_dctx *zstd_create_dctx_advanced(zstd_custom_mem custom_mem)
+{
+ return ZSTD_createDCtx_advanced(custom_mem);
+}
+EXPORT_SYMBOL(zstd_create_dctx_advanced);
+
+size_t zstd_free_dctx(zstd_dctx *dctx)
+{
+ return ZSTD_freeDCtx(dctx);
+}
+EXPORT_SYMBOL(zstd_free_dctx);
+
+zstd_ddict *zstd_create_ddict_byreference(const void *dict, size_t dict_size,
+ zstd_custom_mem custom_mem)
+{
+ return ZSTD_createDDict_advanced(dict, dict_size, ZSTD_dlm_byRef,
+ ZSTD_dct_auto, custom_mem);
+
+}
+EXPORT_SYMBOL(zstd_create_ddict_byreference);
+
+size_t zstd_free_ddict(zstd_ddict *ddict)
+{
+ return ZSTD_freeDDict(ddict);
+}
+EXPORT_SYMBOL(zstd_free_ddict);
+
zstd_dctx *zstd_init_dctx(void *workspace, size_t workspace_size)
{
if (workspace == NULL)
@@ -59,6 +86,15 @@ size_t zstd_decompress_dctx(zstd_dctx *dctx, void *dst, size_t dst_capacity,
}
EXPORT_SYMBOL(zstd_decompress_dctx);
+size_t zstd_decompress_using_ddict(zstd_dctx *dctx,
+ void *dst, size_t dst_capacity, const void* src, size_t src_size,
+ const zstd_ddict* ddict)
+{
+ return ZSTD_decompress_usingDDict(dctx, dst, dst_capacity, src,
+ src_size, ddict);
+}
+EXPORT_SYMBOL(zstd_decompress_using_ddict);
+
size_t zstd_dstream_workspace_bound(size_t max_window_size)
{
return ZSTD_estimateDStreamSize(max_window_size);
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCHv5 02/23] lib: lz4hc: export LZ4_resetStreamHC symbol
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 01/23] lib: zstd: export API needed for dictionary support Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 03/23] lib: zstd: fix null-deref in ZSTD_createCDict_advanced2() Sergey Senozhatsky
` (22 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky, Nick Terrell
This symbol is needed to enable lz4hc dictionary support.
Cc: Nick Terrell <terrelln@fb.com>
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
lib/lz4/lz4hc_compress.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/lz4/lz4hc_compress.c b/lib/lz4/lz4hc_compress.c
index e7ac8694b797..bc45594ad2a8 100644
--- a/lib/lz4/lz4hc_compress.c
+++ b/lib/lz4/lz4hc_compress.c
@@ -621,6 +621,7 @@ void LZ4_resetStreamHC(LZ4_streamHC_t *LZ4_streamHCPtr, int compressionLevel)
LZ4_streamHCPtr->internal_donotuse.base = NULL;
LZ4_streamHCPtr->internal_donotuse.compressionLevel = (unsigned int)compressionLevel;
}
+EXPORT_SYMBOL(LZ4_resetStreamHC);
int LZ4_loadDictHC(LZ4_streamHC_t *LZ4_streamHCPtr,
const char *dictionary,
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCHv5 03/23] lib: zstd: fix null-deref in ZSTD_createCDict_advanced2()
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 01/23] lib: zstd: export API needed for dictionary support Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 02/23] lib: lz4hc: export LZ4_resetStreamHC symbol Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 7:20 ` [PATCH v5 " Markus Elfring
2024-07-06 4:56 ` [PATCHv5 04/23] zram: introduce custom comp backends API Sergey Senozhatsky
` (21 subsequent siblings)
24 siblings, 1 reply; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky, Nick Terrell
ZSTD_createCDict_advanced2() must ensure that
ZSTD_createCDict_advanced_internal() has successfully
allocated cdict. customMalloc() may be called under
low memory condition and may be unable to allocate
workspace for cdict.
Cc: Nick Terrell <terrelln@fb.com>
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
lib/zstd/compress/zstd_compress.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lib/zstd/compress/zstd_compress.c b/lib/zstd/compress/zstd_compress.c
index c1c316e9e289..e48c73880477 100644
--- a/lib/zstd/compress/zstd_compress.c
+++ b/lib/zstd/compress/zstd_compress.c
@@ -5336,6 +5336,8 @@ ZSTD_CDict* ZSTD_createCDict_advanced2(
dictLoadMethod, cctxParams.cParams,
cctxParams.useRowMatchFinder, cctxParams.enableDedicatedDictSearch,
customMem);
+ if (!cdict)
+ return NULL;
if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
dict, dictSize,
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCHv5 04/23] zram: introduce custom comp backends API
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (2 preceding siblings ...)
2024-07-06 4:56 ` [PATCHv5 03/23] lib: zstd: fix null-deref in ZSTD_createCDict_advanced2() Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 7:50 ` Thomas Weißschuh
2024-07-06 4:56 ` [PATCHv5 05/23] zram: add lzo and lzorle compression backends support Sergey Senozhatsky
` (20 subsequent siblings)
24 siblings, 1 reply; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky
Moving to custom backends implementation gives us ability to
have our own minimalistic and extendable API, and algorithms
tunings becomes possible.
The list of compression backends is empty at this point,
we will add backends in the followup patches.
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
drivers/block/zram/Kconfig | 39 +--------
drivers/block/zram/zcomp.c | 151 +++++++++++-----------------------
drivers/block/zram/zcomp.h | 29 ++++---
drivers/block/zram/zram_drv.c | 9 +-
4 files changed, 76 insertions(+), 152 deletions(-)
diff --git a/drivers/block/zram/Kconfig b/drivers/block/zram/Kconfig
index eacf1cba7bf4..ace5698db5f6 100644
--- a/drivers/block/zram/Kconfig
+++ b/drivers/block/zram/Kconfig
@@ -3,7 +3,6 @@ config ZRAM
tristate "Compressed RAM block device support"
depends on BLOCK && SYSFS && MMU
depends on HAVE_ZSMALLOC
- depends on CRYPTO_LZO || CRYPTO_ZSTD || CRYPTO_LZ4 || CRYPTO_LZ4HC || CRYPTO_842
select ZSMALLOC
help
Creates virtual block devices called /dev/zramX (X = 0, 1, ...).
@@ -16,45 +15,9 @@ config ZRAM
See Documentation/admin-guide/blockdev/zram.rst for more information.
-choice
- prompt "Default zram compressor"
- default ZRAM_DEF_COMP_LZORLE
- depends on ZRAM
-
-config ZRAM_DEF_COMP_LZORLE
- bool "lzo-rle"
- depends on CRYPTO_LZO
-
-config ZRAM_DEF_COMP_ZSTD
- bool "zstd"
- depends on CRYPTO_ZSTD
-
-config ZRAM_DEF_COMP_LZ4
- bool "lz4"
- depends on CRYPTO_LZ4
-
-config ZRAM_DEF_COMP_LZO
- bool "lzo"
- depends on CRYPTO_LZO
-
-config ZRAM_DEF_COMP_LZ4HC
- bool "lz4hc"
- depends on CRYPTO_LZ4HC
-
-config ZRAM_DEF_COMP_842
- bool "842"
- depends on CRYPTO_842
-
-endchoice
-
config ZRAM_DEF_COMP
string
- default "lzo-rle" if ZRAM_DEF_COMP_LZORLE
- default "zstd" if ZRAM_DEF_COMP_ZSTD
- default "lz4" if ZRAM_DEF_COMP_LZ4
- default "lzo" if ZRAM_DEF_COMP_LZO
- default "lz4hc" if ZRAM_DEF_COMP_LZ4HC
- default "842" if ZRAM_DEF_COMP_842
+ default "unset-value"
config ZRAM_WRITEBACK
bool "Write back incompressible or idle page to backing device"
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
index 8237b08c49d8..5075934ce388 100644
--- a/drivers/block/zram/zcomp.c
+++ b/drivers/block/zram/zcomp.c
@@ -1,7 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2014 Sergey Senozhatsky.
- */
#include <linux/kernel.h>
#include <linux/string.h>
@@ -15,92 +12,68 @@
#include "zcomp.h"
-static const char * const backends[] = {
-#if IS_ENABLED(CONFIG_CRYPTO_LZO)
- "lzo",
- "lzo-rle",
-#endif
-#if IS_ENABLED(CONFIG_CRYPTO_LZ4)
- "lz4",
-#endif
-#if IS_ENABLED(CONFIG_CRYPTO_LZ4HC)
- "lz4hc",
-#endif
-#if IS_ENABLED(CONFIG_CRYPTO_842)
- "842",
-#endif
-#if IS_ENABLED(CONFIG_CRYPTO_ZSTD)
- "zstd",
-#endif
+static struct zcomp_ops *backends[] = {
+ NULL
};
-static void zcomp_strm_free(struct zcomp_strm *zstrm)
+static void zcomp_strm_free(struct zcomp *comp, struct zcomp_strm *zstrm)
{
- if (!IS_ERR_OR_NULL(zstrm->tfm))
- crypto_free_comp(zstrm->tfm);
+ if (zstrm->ctx)
+ comp->ops->destroy_ctx(zstrm->ctx);
vfree(zstrm->buffer);
- zstrm->tfm = NULL;
+ zstrm->ctx = NULL;
zstrm->buffer = NULL;
}
-/*
- * Initialize zcomp_strm structure with ->tfm initialized by backend, and
- * ->buffer. Return a negative value on error.
- */
-static int zcomp_strm_init(struct zcomp_strm *zstrm, struct zcomp *comp)
+static int zcomp_strm_init(struct zcomp *comp, struct zcomp_strm *zstrm)
{
- zstrm->tfm = crypto_alloc_comp(comp->name, 0, 0);
+ zstrm->ctx = comp->ops->create_ctx();
+
/*
* allocate 2 pages. 1 for compressed data, plus 1 extra for the
* case when compressed size is larger than the original one
*/
zstrm->buffer = vzalloc(2 * PAGE_SIZE);
- if (IS_ERR_OR_NULL(zstrm->tfm) || !zstrm->buffer) {
- zcomp_strm_free(zstrm);
+ if (!zstrm->ctx || !zstrm->buffer) {
+ zcomp_strm_free(comp, zstrm);
return -ENOMEM;
}
return 0;
}
+static struct zcomp_ops *lookup_backend_ops(const char *comp)
+{
+ int i = 0;
+
+ while (backends[i]) {
+ if (sysfs_streq(comp, backends[i]->name))
+ break;
+ i++;
+ }
+ return backends[i];
+}
+
bool zcomp_available_algorithm(const char *comp)
{
- /*
- * Crypto does not ignore a trailing new line symbol,
- * so make sure you don't supply a string containing
- * one.
- * This also means that we permit zcomp initialisation
- * with any compressing algorithm known to crypto api.
- */
- return crypto_has_comp(comp, 0, 0) == 1;
+ return lookup_backend_ops(comp) != NULL;
}
/* show available compressors */
ssize_t zcomp_available_show(const char *comp, char *buf)
{
- bool known_algorithm = false;
ssize_t sz = 0;
int i;
- for (i = 0; i < ARRAY_SIZE(backends); i++) {
- if (!strcmp(comp, backends[i])) {
- known_algorithm = true;
+ for (i = 0; i < ARRAY_SIZE(backends) - 1; i++) {
+ if (!strcmp(comp, backends[i]->name)) {
sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2,
- "[%s] ", backends[i]);
+ "[%s] ", backends[i]->name);
} else {
sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2,
- "%s ", backends[i]);
+ "%s ", backends[i]->name);
}
}
- /*
- * Out-of-tree module known to crypto api or a missing
- * entry in `backends'.
- */
- if (!known_algorithm && crypto_has_comp(comp, 0, 0) == 1)
- sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2,
- "[%s] ", comp);
-
- sz += scnprintf(buf + sz, PAGE_SIZE - sz, "\n");
return sz;
}
@@ -115,38 +88,25 @@ void zcomp_stream_put(struct zcomp *comp)
local_unlock(&comp->stream->lock);
}
-int zcomp_compress(struct zcomp_strm *zstrm,
- const void *src, unsigned int *dst_len)
+int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm,
+ const void *src, unsigned int *dst_len)
{
- /*
- * Our dst memory (zstrm->buffer) is always `2 * PAGE_SIZE' sized
- * because sometimes we can endup having a bigger compressed data
- * due to various reasons: for example compression algorithms tend
- * to add some padding to the compressed buffer. Speaking of padding,
- * comp algorithm `842' pads the compressed length to multiple of 8
- * and returns -ENOSP when the dst memory is not big enough, which
- * is not something that ZRAM wants to see. We can handle the
- * `compressed_size > PAGE_SIZE' case easily in ZRAM, but when we
- * receive -ERRNO from the compressing backend we can't help it
- * anymore. To make `842' happy we need to tell the exact size of
- * the dst buffer, zram_drv will take care of the fact that
- * compressed buffer is too big.
- */
- *dst_len = PAGE_SIZE * 2;
+ /* The dst buffer should always be 2 * PAGE_SIZE */
+ size_t dlen = 2 * PAGE_SIZE;
+ int ret;
- return crypto_comp_compress(zstrm->tfm,
- src, PAGE_SIZE,
- zstrm->buffer, dst_len);
+ ret = comp->ops->compress(zstrm->ctx, src, PAGE_SIZE,
+ zstrm->buffer, &dlen);
+ if (!ret)
+ *dst_len = dlen;
+ return ret;
}
-int zcomp_decompress(struct zcomp_strm *zstrm,
- const void *src, unsigned int src_len, void *dst)
+int zcomp_decompress(struct zcomp *comp, struct zcomp_strm *zstrm,
+ const void *src, unsigned int src_len, void *dst)
{
- unsigned int dst_len = PAGE_SIZE;
-
- return crypto_comp_decompress(zstrm->tfm,
- src, src_len,
- dst, &dst_len);
+ return comp->ops->decompress(zstrm->ctx, src, src_len,
+ dst, PAGE_SIZE);
}
int zcomp_cpu_up_prepare(unsigned int cpu, struct hlist_node *node)
@@ -158,7 +118,7 @@ int zcomp_cpu_up_prepare(unsigned int cpu, struct hlist_node *node)
zstrm = per_cpu_ptr(comp->stream, cpu);
local_lock_init(&zstrm->lock);
- ret = zcomp_strm_init(zstrm, comp);
+ ret = zcomp_strm_init(comp, zstrm);
if (ret)
pr_err("Can't allocate a compression stream\n");
return ret;
@@ -170,7 +130,7 @@ int zcomp_cpu_dead(unsigned int cpu, struct hlist_node *node)
struct zcomp_strm *zstrm;
zstrm = per_cpu_ptr(comp->stream, cpu);
- zcomp_strm_free(zstrm);
+ zcomp_strm_free(comp, zstrm);
return 0;
}
@@ -199,32 +159,21 @@ void zcomp_destroy(struct zcomp *comp)
kfree(comp);
}
-/*
- * search available compressors for requested algorithm.
- * allocate new zcomp and initialize it. return compressing
- * backend pointer or ERR_PTR if things went bad. ERR_PTR(-EINVAL)
- * if requested algorithm is not supported, ERR_PTR(-ENOMEM) in
- * case of allocation error, or any other error potentially
- * returned by zcomp_init().
- */
struct zcomp *zcomp_create(const char *alg)
{
struct zcomp *comp;
int error;
- /*
- * Crypto API will execute /sbin/modprobe if the compression module
- * is not loaded yet. We must do it here, otherwise we are about to
- * call /sbin/modprobe under CPU hot-plug lock.
- */
- if (!zcomp_available_algorithm(alg))
- return ERR_PTR(-EINVAL);
-
comp = kzalloc(sizeof(struct zcomp), GFP_KERNEL);
if (!comp)
return ERR_PTR(-ENOMEM);
- comp->name = alg;
+ comp->ops = lookup_backend_ops(alg);
+ if (!comp->ops) {
+ kfree(comp);
+ return ERR_PTR(-EINVAL);
+ }
+
error = zcomp_init(comp);
if (error) {
kfree(comp);
diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h
index e9fe63da0e9b..dde28a8d32d4 100644
--- a/drivers/block/zram/zcomp.h
+++ b/drivers/block/zram/zcomp.h
@@ -1,7 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2014 Sergey Senozhatsky.
- */
#ifndef _ZCOMP_H_
#define _ZCOMP_H_
@@ -12,13 +9,26 @@ struct zcomp_strm {
local_lock_t lock;
/* compression/decompression buffer */
void *buffer;
- struct crypto_comp *tfm;
+ void *ctx;
+};
+
+struct zcomp_ops {
+ int (*compress)(void *ctx, const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t *dst_len);
+
+ int (*decompress)(void *ctx, const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t dst_len);
+
+ void *(*create_ctx)(void);
+ void (*destroy_ctx)(void *ctx);
+
+ const char *name;
};
/* dynamic per-device compression frontend */
struct zcomp {
struct zcomp_strm __percpu *stream;
- const char *name;
+ struct zcomp_ops *ops;
struct hlist_node node;
};
@@ -33,10 +43,9 @@ void zcomp_destroy(struct zcomp *comp);
struct zcomp_strm *zcomp_stream_get(struct zcomp *comp);
void zcomp_stream_put(struct zcomp *comp);
-int zcomp_compress(struct zcomp_strm *zstrm,
- const void *src, unsigned int *dst_len);
-
-int zcomp_decompress(struct zcomp_strm *zstrm,
- const void *src, unsigned int src_len, void *dst);
+int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm,
+ const void *src, unsigned int *dst_len);
+int zcomp_decompress(struct zcomp *comp, struct zcomp_strm *zstrm,
+ const void *src, unsigned int src_len, void *dst);
#endif /* _ZCOMP_H_ */
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index efcb8d9d274c..93042da8ccdf 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -1327,7 +1327,8 @@ static int zram_read_from_zspool(struct zram *zram, struct page *page,
ret = 0;
} else {
dst = kmap_local_page(page);
- ret = zcomp_decompress(zstrm, src, size, dst);
+ ret = zcomp_decompress(zram->comps[prio], zstrm,
+ src, size, dst);
kunmap_local(dst);
zcomp_stream_put(zram->comps[prio]);
}
@@ -1414,7 +1415,8 @@ static int zram_write_page(struct zram *zram, struct page *page, u32 index)
compress_again:
zstrm = zcomp_stream_get(zram->comps[ZRAM_PRIMARY_COMP]);
src = kmap_local_page(page);
- ret = zcomp_compress(zstrm, src, &comp_len);
+ ret = zcomp_compress(zram->comps[ZRAM_PRIMARY_COMP], zstrm,
+ src, &comp_len);
kunmap_local(src);
if (unlikely(ret)) {
@@ -1601,7 +1603,8 @@ static int zram_recompress(struct zram *zram, u32 index, struct page *page,
num_recomps++;
zstrm = zcomp_stream_get(zram->comps[prio]);
src = kmap_local_page(page);
- ret = zcomp_compress(zstrm, src, &comp_len_new);
+ ret = zcomp_compress(zram->comps[prio], zstrm,
+ src, &comp_len_new);
kunmap_local(src);
if (ret) {
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [PATCHv5 04/23] zram: introduce custom comp backends API
2024-07-06 4:56 ` [PATCHv5 04/23] zram: introduce custom comp backends API Sergey Senozhatsky
@ 2024-07-06 7:50 ` Thomas Weißschuh
2024-07-07 1:31 ` Sergey Senozhatsky
0 siblings, 1 reply; 30+ messages in thread
From: Thomas Weißschuh @ 2024-07-06 7:50 UTC (permalink / raw)
To: Sergey Senozhatsky; +Cc: Andrew Morton, Minchan Kim, linux-kernel
On 2024-07-06 13:56:06+0000, Sergey Senozhatsky wrote:
> Moving to custom backends implementation gives us ability to
> have our own minimalistic and extendable API, and algorithms
> tunings becomes possible.
>
> The list of compression backends is empty at this point,
> we will add backends in the followup patches.
>
> Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
> ---
> drivers/block/zram/Kconfig | 39 +--------
> drivers/block/zram/zcomp.c | 151 +++++++++++-----------------------
> drivers/block/zram/zcomp.h | 29 ++++---
> drivers/block/zram/zram_drv.c | 9 +-
> 4 files changed, 76 insertions(+), 152 deletions(-)
<snip>
> --- a/drivers/block/zram/zcomp.h
> +++ b/drivers/block/zram/zcomp.h
> @@ -1,7 +1,4 @@
> /* SPDX-License-Identifier: GPL-2.0-or-later */
> -/*
> - * Copyright (C) 2014 Sergey Senozhatsky.
> - */
>
> #ifndef _ZCOMP_H_
> #define _ZCOMP_H_
> @@ -12,13 +9,26 @@ struct zcomp_strm {
> local_lock_t lock;
> /* compression/decompression buffer */
> void *buffer;
> - struct crypto_comp *tfm;
> + void *ctx;
> +};
> +
> +struct zcomp_ops {
> + int (*compress)(void *ctx, const unsigned char *src, size_t src_len,
> + unsigned char *dst, size_t *dst_len);
> +
> + int (*decompress)(void *ctx, const unsigned char *src, size_t src_len,
> + unsigned char *dst, size_t dst_len);
> +
> + void *(*create_ctx)(void);
> + void (*destroy_ctx)(void *ctx);
> +
> + const char *name;
> };
>
> /* dynamic per-device compression frontend */
> struct zcomp {
> struct zcomp_strm __percpu *stream;
> - const char *name;
> + struct zcomp_ops *ops;
If this is "const struct zcomp_ops *ops" then all the backend struct
zcomp_ops definitions could be constified, improving security.
"zcomp_ops" could also be added to scripts/const_structs.checkpatch,
but there probably won't be many of them anyways.
> struct hlist_node node;
> };
<snip>
^ permalink raw reply [flat|nested] 30+ messages in thread* Re: [PATCHv5 04/23] zram: introduce custom comp backends API
2024-07-06 7:50 ` Thomas Weißschuh
@ 2024-07-07 1:31 ` Sergey Senozhatsky
0 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-07 1:31 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Sergey Senozhatsky, Andrew Morton, Minchan Kim, linux-kernel
On (24/07/06 09:50), Thomas Weißschuh wrote:
> > /* dynamic per-device compression frontend */
> > struct zcomp {
> > struct zcomp_strm __percpu *stream;
> > - const char *name;
> > + struct zcomp_ops *ops;
>
> If this is "const struct zcomp_ops *ops" then all the backend struct
> zcomp_ops definitions could be constified, improving security.
I guess I can do that.
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCHv5 05/23] zram: add lzo and lzorle compression backends support
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (3 preceding siblings ...)
2024-07-06 4:56 ` [PATCHv5 04/23] zram: introduce custom comp backends API Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 06/23] zram: add lz4 compression backend support Sergey Senozhatsky
` (19 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky
Add s/w lzo/lzorle compression support.
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
drivers/block/zram/Kconfig | 23 +++++++++++++++
drivers/block/zram/Makefile | 3 ++
drivers/block/zram/backend_lzo.c | 43 ++++++++++++++++++++++++++++
drivers/block/zram/backend_lzo.h | 10 +++++++
drivers/block/zram/backend_lzorle.c | 44 +++++++++++++++++++++++++++++
drivers/block/zram/backend_lzorle.h | 10 +++++++
drivers/block/zram/zcomp.c | 7 +++++
7 files changed, 140 insertions(+)
create mode 100644 drivers/block/zram/backend_lzo.c
create mode 100644 drivers/block/zram/backend_lzo.h
create mode 100644 drivers/block/zram/backend_lzorle.c
create mode 100644 drivers/block/zram/backend_lzorle.h
diff --git a/drivers/block/zram/Kconfig b/drivers/block/zram/Kconfig
index ace5698db5f6..ce70b8ef3405 100644
--- a/drivers/block/zram/Kconfig
+++ b/drivers/block/zram/Kconfig
@@ -15,8 +15,31 @@ config ZRAM
See Documentation/admin-guide/blockdev/zram.rst for more information.
+config ZRAM_BACKEND_LZO
+ bool "lzo and lzo-rle compression support"
+ depends on ZRAM
+ select LZO_COMPRESS
+ select LZO_DECOMPRESS
+
+choice
+ prompt "Default zram compressor"
+ default ZRAM_DEF_COMP_LZORLE
+ depends on ZRAM
+
+config ZRAM_DEF_COMP_LZORLE
+ bool "lzo-rle"
+ depends on ZRAM_BACKEND_LZO
+
+config ZRAM_DEF_COMP_LZO
+ bool "lzo"
+ depends on ZRAM_BACKEND_LZO
+
+endchoice
+
config ZRAM_DEF_COMP
string
+ default "lzo-rle" if ZRAM_DEF_COMP_LZORLE
+ default "lzo" if ZRAM_DEF_COMP_LZO
default "unset-value"
config ZRAM_WRITEBACK
diff --git a/drivers/block/zram/Makefile b/drivers/block/zram/Makefile
index de9e457907b1..2a3db3368af9 100644
--- a/drivers/block/zram/Makefile
+++ b/drivers/block/zram/Makefile
@@ -1,4 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
+
zram-y := zcomp.o zram_drv.o
+zram-$(CONFIG_ZRAM_BACKEND_LZO) += backend_lzorle.o backend_lzo.o
+
obj-$(CONFIG_ZRAM) += zram.o
diff --git a/drivers/block/zram/backend_lzo.c b/drivers/block/zram/backend_lzo.c
new file mode 100644
index 000000000000..7eb0d2709a73
--- /dev/null
+++ b/drivers/block/zram/backend_lzo.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/lzo.h>
+
+#include "backend_lzo.h"
+
+static void *lzo_create(void)
+{
+ return kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
+}
+
+static void lzo_destroy(void *ctx)
+{
+ kfree(ctx);
+}
+
+static int lzo_compress(void *ctx, const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t *dst_len)
+{
+ int ret;
+
+ ret = lzo1x_1_compress(src, src_len, dst, dst_len, ctx);
+ return ret == LZO_E_OK ? 0 : ret;
+}
+
+static int lzo_decompress(void *ctx, const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t dst_len)
+{
+ int ret;
+
+ ret = lzo1x_decompress_safe(src, src_len, dst, &dst_len);
+ return ret == LZO_E_OK ? 0 : ret;
+}
+
+struct zcomp_ops backend_lzo = {
+ .compress = lzo_compress,
+ .decompress = lzo_decompress,
+ .create_ctx = lzo_create,
+ .destroy_ctx = lzo_destroy,
+ .name = "lzo",
+};
diff --git a/drivers/block/zram/backend_lzo.h b/drivers/block/zram/backend_lzo.h
new file mode 100644
index 000000000000..dad334013539
--- /dev/null
+++ b/drivers/block/zram/backend_lzo.h
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#ifndef __BACKEND_LZO_H__
+#define __BACKEND_LZO_H__
+
+#include "zcomp.h"
+
+extern struct zcomp_ops backend_lzo;
+
+#endif /* __BACKEND_LZO_H__ */
diff --git a/drivers/block/zram/backend_lzorle.c b/drivers/block/zram/backend_lzorle.c
new file mode 100644
index 000000000000..68fcdccb2f53
--- /dev/null
+++ b/drivers/block/zram/backend_lzorle.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/lzo.h>
+
+#include "backend_lzorle.h"
+
+static void *lzorle_create(void)
+{
+ return kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
+}
+
+static void lzorle_destroy(void *ctx)
+{
+ kfree(ctx);
+}
+
+static int lzorle_compress(void *ctx, const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t *dst_len)
+{
+ int ret;
+
+ ret = lzorle1x_1_compress(src, src_len, dst, dst_len, ctx);
+ return ret == LZO_E_OK ? 0 : ret;
+}
+
+static int lzorle_decompress(void *ctx, const unsigned char *src,
+ size_t src_len, unsigned char *dst,
+ size_t dst_len)
+{
+ int ret;
+
+ ret = lzo1x_decompress_safe(src, src_len, dst, &dst_len);
+ return ret == LZO_E_OK ? 0 : ret;
+}
+
+struct zcomp_ops backend_lzorle = {
+ .compress = lzorle_compress,
+ .decompress = lzorle_decompress,
+ .create_ctx = lzorle_create,
+ .destroy_ctx = lzorle_destroy,
+ .name = "lzo-rle",
+};
diff --git a/drivers/block/zram/backend_lzorle.h b/drivers/block/zram/backend_lzorle.h
new file mode 100644
index 000000000000..b96ccb82ac48
--- /dev/null
+++ b/drivers/block/zram/backend_lzorle.h
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#ifndef __BACKEND_LZORLE_H__
+#define __BACKEND_LZORLE_H__
+
+#include "zcomp.h"
+
+extern struct zcomp_ops backend_lzorle;
+
+#endif /* __BACKEND_LZORLE_H__ */
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
index 5075934ce388..fa074b8d167e 100644
--- a/drivers/block/zram/zcomp.c
+++ b/drivers/block/zram/zcomp.c
@@ -12,7 +12,14 @@
#include "zcomp.h"
+#include "backend_lzo.h"
+#include "backend_lzorle.h"
+
static struct zcomp_ops *backends[] = {
+#if IS_ENABLED(CONFIG_ZRAM_BACKEND_LZO)
+ &backend_lzorle,
+ &backend_lzo,
+#endif
NULL
};
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCHv5 06/23] zram: add lz4 compression backend support
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (4 preceding siblings ...)
2024-07-06 4:56 ` [PATCHv5 05/23] zram: add lzo and lzorle compression backends support Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 07/23] zram: add lz4hc " Sergey Senozhatsky
` (18 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky
Add s/w lz4 compression support.
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
drivers/block/zram/Kconfig | 11 +++++
drivers/block/zram/Makefile | 1 +
drivers/block/zram/backend_lz4.c | 72 ++++++++++++++++++++++++++++++++
drivers/block/zram/backend_lz4.h | 10 +++++
drivers/block/zram/zcomp.c | 4 ++
5 files changed, 98 insertions(+)
create mode 100644 drivers/block/zram/backend_lz4.c
create mode 100644 drivers/block/zram/backend_lz4.h
diff --git a/drivers/block/zram/Kconfig b/drivers/block/zram/Kconfig
index ce70b8ef3405..28288e9432d4 100644
--- a/drivers/block/zram/Kconfig
+++ b/drivers/block/zram/Kconfig
@@ -21,6 +21,12 @@ config ZRAM_BACKEND_LZO
select LZO_COMPRESS
select LZO_DECOMPRESS
+config ZRAM_BACKEND_LZ4
+ bool "lz4 compression support"
+ depends on ZRAM
+ select LZ4_COMPRESS
+ select LZ4_DECOMPRESS
+
choice
prompt "Default zram compressor"
default ZRAM_DEF_COMP_LZORLE
@@ -34,12 +40,17 @@ config ZRAM_DEF_COMP_LZO
bool "lzo"
depends on ZRAM_BACKEND_LZO
+config ZRAM_DEF_COMP_LZ4
+ bool "lz4"
+ depends on ZRAM_BACKEND_LZ4
+
endchoice
config ZRAM_DEF_COMP
string
default "lzo-rle" if ZRAM_DEF_COMP_LZORLE
default "lzo" if ZRAM_DEF_COMP_LZO
+ default "lz4" if ZRAM_DEF_COMP_LZ4
default "unset-value"
config ZRAM_WRITEBACK
diff --git a/drivers/block/zram/Makefile b/drivers/block/zram/Makefile
index 2a3db3368af9..567f4434aee8 100644
--- a/drivers/block/zram/Makefile
+++ b/drivers/block/zram/Makefile
@@ -3,5 +3,6 @@
zram-y := zcomp.o zram_drv.o
zram-$(CONFIG_ZRAM_BACKEND_LZO) += backend_lzorle.o backend_lzo.o
+zram-$(CONFIG_ZRAM_BACKEND_LZ4) += backend_lz4.o
obj-$(CONFIG_ZRAM) += zram.o
diff --git a/drivers/block/zram/backend_lz4.c b/drivers/block/zram/backend_lz4.c
new file mode 100644
index 000000000000..4de389fb3463
--- /dev/null
+++ b/drivers/block/zram/backend_lz4.c
@@ -0,0 +1,72 @@
+#include <linux/kernel.h>
+#include <linux/lz4.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#include "backend_lz4.h"
+
+struct lz4_ctx {
+ void *mem;
+ s32 level;
+};
+
+static void lz4_destroy(void *ctx)
+{
+ struct lz4_ctx *zctx = ctx;
+
+ vfree(zctx->mem);
+ kfree(zctx);
+}
+
+static void *lz4_create(void)
+{
+ struct lz4_ctx *ctx;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return NULL;
+
+ /* @FIXME: using a hardcoded LZ4_ACCELERATION_DEFAULT for now */
+ ctx->level = LZ4_ACCELERATION_DEFAULT;
+ ctx->mem = vmalloc(LZ4_MEM_COMPRESS);
+ if (!ctx->mem)
+ goto error;
+
+ return ctx;
+error:
+ lz4_destroy(ctx);
+ return NULL;
+}
+
+static int lz4_compress(void *ctx, const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t *dst_len)
+{
+ struct lz4_ctx *zctx = ctx;
+ int ret;
+
+ ret = LZ4_compress_fast(src, dst, src_len, *dst_len,
+ zctx->level, zctx->mem);
+ if (!ret)
+ return -EINVAL;
+ *dst_len = ret;
+ return 0;
+}
+
+static int lz4_decompress(void *ctx, const unsigned char *src,
+ size_t src_len, unsigned char *dst, size_t dst_len)
+{
+ int ret;
+
+ ret = LZ4_decompress_safe(src, dst, src_len, dst_len);
+ if (ret < 0)
+ return -EINVAL;
+ return 0;
+}
+
+struct zcomp_ops backend_lz4 = {
+ .compress = lz4_compress,
+ .decompress = lz4_decompress,
+ .create_ctx = lz4_create,
+ .destroy_ctx = lz4_destroy,
+ .name = "lz4",
+};
diff --git a/drivers/block/zram/backend_lz4.h b/drivers/block/zram/backend_lz4.h
new file mode 100644
index 000000000000..2e1df0a80887
--- /dev/null
+++ b/drivers/block/zram/backend_lz4.h
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#ifndef __BACKEND_LZ4_H__
+#define __BACKEND_LZ4_H__
+
+#include "zcomp.h"
+
+extern struct zcomp_ops backend_lz4;
+
+#endif /* __BACKEND_LZ4_H__ */
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
index fa074b8d167e..8c1a904e95b6 100644
--- a/drivers/block/zram/zcomp.c
+++ b/drivers/block/zram/zcomp.c
@@ -14,11 +14,15 @@
#include "backend_lzo.h"
#include "backend_lzorle.h"
+#include "backend_lz4.h"
static struct zcomp_ops *backends[] = {
#if IS_ENABLED(CONFIG_ZRAM_BACKEND_LZO)
&backend_lzorle,
&backend_lzo,
+#endif
+#if IS_ENABLED(CONFIG_ZRAM_BACKEND_LZ4)
+ &backend_lz4,
#endif
NULL
};
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCHv5 07/23] zram: add lz4hc compression backend support
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (5 preceding siblings ...)
2024-07-06 4:56 ` [PATCHv5 06/23] zram: add lz4 compression backend support Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 08/23] zram: add zstd " Sergey Senozhatsky
` (17 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky
Add s/w lz4hc compression support.
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
drivers/block/zram/Kconfig | 11 +++++
drivers/block/zram/Makefile | 5 ++-
drivers/block/zram/backend_lz4hc.c | 72 ++++++++++++++++++++++++++++++
drivers/block/zram/backend_lz4hc.h | 10 +++++
drivers/block/zram/zcomp.c | 4 ++
5 files changed, 100 insertions(+), 2 deletions(-)
create mode 100644 drivers/block/zram/backend_lz4hc.c
create mode 100644 drivers/block/zram/backend_lz4hc.h
diff --git a/drivers/block/zram/Kconfig b/drivers/block/zram/Kconfig
index 28288e9432d4..72751cb2b532 100644
--- a/drivers/block/zram/Kconfig
+++ b/drivers/block/zram/Kconfig
@@ -27,6 +27,12 @@ config ZRAM_BACKEND_LZ4
select LZ4_COMPRESS
select LZ4_DECOMPRESS
+config ZRAM_BACKEND_LZ4HC
+ bool "lz4hc compression support"
+ depends on ZRAM
+ select LZ4HC_COMPRESS
+ select LZ4_DECOMPRESS
+
choice
prompt "Default zram compressor"
default ZRAM_DEF_COMP_LZORLE
@@ -44,6 +50,10 @@ config ZRAM_DEF_COMP_LZ4
bool "lz4"
depends on ZRAM_BACKEND_LZ4
+config ZRAM_DEF_COMP_LZ4HC
+ bool "lz4hc"
+ depends on ZRAM_BACKEND_LZ4HC
+
endchoice
config ZRAM_DEF_COMP
@@ -51,6 +61,7 @@ config ZRAM_DEF_COMP
default "lzo-rle" if ZRAM_DEF_COMP_LZORLE
default "lzo" if ZRAM_DEF_COMP_LZO
default "lz4" if ZRAM_DEF_COMP_LZ4
+ default "lz4hc" if ZRAM_DEF_COMP_LZ4HC
default "unset-value"
config ZRAM_WRITEBACK
diff --git a/drivers/block/zram/Makefile b/drivers/block/zram/Makefile
index 567f4434aee8..727c9d68e3e3 100644
--- a/drivers/block/zram/Makefile
+++ b/drivers/block/zram/Makefile
@@ -2,7 +2,8 @@
zram-y := zcomp.o zram_drv.o
-zram-$(CONFIG_ZRAM_BACKEND_LZO) += backend_lzorle.o backend_lzo.o
-zram-$(CONFIG_ZRAM_BACKEND_LZ4) += backend_lz4.o
+zram-$(CONFIG_ZRAM_BACKEND_LZO) += backend_lzorle.o backend_lzo.o
+zram-$(CONFIG_ZRAM_BACKEND_LZ4) += backend_lz4.o
+zram-$(CONFIG_ZRAM_BACKEND_LZ4HC) += backend_lz4hc.o
obj-$(CONFIG_ZRAM) += zram.o
diff --git a/drivers/block/zram/backend_lz4hc.c b/drivers/block/zram/backend_lz4hc.c
new file mode 100644
index 000000000000..50e998c1e321
--- /dev/null
+++ b/drivers/block/zram/backend_lz4hc.c
@@ -0,0 +1,72 @@
+#include <linux/kernel.h>
+#include <linux/lz4.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#include "backend_lz4hc.h"
+
+struct lz4hc_ctx {
+ void *mem;
+ s32 level;
+};
+
+static void lz4hc_destroy(void *ctx)
+{
+ struct lz4hc_ctx *zctx = ctx;
+
+ vfree(zctx->mem);
+ kfree(zctx);
+}
+
+static void *lz4hc_create(void)
+{
+ struct lz4hc_ctx *ctx;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return NULL;
+
+ /* @FIXME: using a hardcoded LZ4HC_DEFAULT_CLEVEL for now */
+ ctx->level = LZ4HC_DEFAULT_CLEVEL;
+ ctx->mem = vmalloc(LZ4HC_MEM_COMPRESS);
+ if (!ctx->mem)
+ goto error;
+
+ return ctx;
+error:
+ lz4hc_destroy(ctx);
+ return NULL;
+}
+
+static int lz4hc_compress(void *ctx, const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t *dst_len)
+{
+ struct lz4hc_ctx *zctx = ctx;
+ int ret;
+
+ ret = LZ4_compress_HC(src, dst, src_len, *dst_len,
+ zctx->level, zctx->mem);
+ if (!ret)
+ return -EINVAL;
+ *dst_len = ret;
+ return 0;
+}
+
+static int lz4hc_decompress(void *ctx, const unsigned char *src,
+ size_t src_len, unsigned char *dst, size_t dst_len)
+{
+ int ret;
+
+ ret = LZ4_decompress_safe(src, dst, src_len, dst_len);
+ if (ret < 0)
+ return -EINVAL;
+ return 0;
+}
+
+struct zcomp_ops backend_lz4hc = {
+ .compress = lz4hc_compress,
+ .decompress = lz4hc_decompress,
+ .create_ctx = lz4hc_create,
+ .destroy_ctx = lz4hc_destroy,
+ .name = "lz4hc",
+};
diff --git a/drivers/block/zram/backend_lz4hc.h b/drivers/block/zram/backend_lz4hc.h
new file mode 100644
index 000000000000..93a11c3acf28
--- /dev/null
+++ b/drivers/block/zram/backend_lz4hc.h
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#ifndef __BACKEND_LZ4HC_H__
+#define __BACKEND_LZ4HC_H__
+
+#include "zcomp.h"
+
+extern struct zcomp_ops backend_lz4hc;
+
+#endif /* __BACKEND_LZ4HC_H__ */
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
index 8c1a904e95b6..1423b177dc30 100644
--- a/drivers/block/zram/zcomp.c
+++ b/drivers/block/zram/zcomp.c
@@ -15,6 +15,7 @@
#include "backend_lzo.h"
#include "backend_lzorle.h"
#include "backend_lz4.h"
+#include "backend_lz4hc.h"
static struct zcomp_ops *backends[] = {
#if IS_ENABLED(CONFIG_ZRAM_BACKEND_LZO)
@@ -23,6 +24,9 @@ static struct zcomp_ops *backends[] = {
#endif
#if IS_ENABLED(CONFIG_ZRAM_BACKEND_LZ4)
&backend_lz4,
+#endif
+#if IS_ENABLED(CONFIG_ZRAM_BACKEND_LZ4HC)
+ &backend_lz4hc,
#endif
NULL
};
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCHv5 08/23] zram: add zstd compression backend support
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (6 preceding siblings ...)
2024-07-06 4:56 ` [PATCHv5 07/23] zram: add lz4hc " Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 09/23] zram: pass estimated src size hint to zstd Sergey Senozhatsky
` (16 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky
Add s/w zstd compression.
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
drivers/block/zram/Kconfig | 11 ++++
drivers/block/zram/Makefile | 1 +
drivers/block/zram/backend_zstd.c | 97 +++++++++++++++++++++++++++++++
drivers/block/zram/backend_zstd.h | 10 ++++
drivers/block/zram/zcomp.c | 4 ++
5 files changed, 123 insertions(+)
create mode 100644 drivers/block/zram/backend_zstd.c
create mode 100644 drivers/block/zram/backend_zstd.h
diff --git a/drivers/block/zram/Kconfig b/drivers/block/zram/Kconfig
index 72751cb2b532..ee4fe2ee3413 100644
--- a/drivers/block/zram/Kconfig
+++ b/drivers/block/zram/Kconfig
@@ -33,6 +33,12 @@ config ZRAM_BACKEND_LZ4HC
select LZ4HC_COMPRESS
select LZ4_DECOMPRESS
+config ZRAM_BACKEND_ZSTD
+ bool "zstd compression support"
+ depends on ZRAM
+ select ZSTD_COMPRESS
+ select ZSTD_DECOMPRESS
+
choice
prompt "Default zram compressor"
default ZRAM_DEF_COMP_LZORLE
@@ -54,6 +60,10 @@ config ZRAM_DEF_COMP_LZ4HC
bool "lz4hc"
depends on ZRAM_BACKEND_LZ4HC
+config ZRAM_DEF_COMP_ZSTD
+ bool "zstd"
+ depends on ZRAM_BACKEND_ZSTD
+
endchoice
config ZRAM_DEF_COMP
@@ -62,6 +72,7 @@ config ZRAM_DEF_COMP
default "lzo" if ZRAM_DEF_COMP_LZO
default "lz4" if ZRAM_DEF_COMP_LZ4
default "lz4hc" if ZRAM_DEF_COMP_LZ4HC
+ default "zstd" if ZRAM_DEF_COMP_ZSTD
default "unset-value"
config ZRAM_WRITEBACK
diff --git a/drivers/block/zram/Makefile b/drivers/block/zram/Makefile
index 727c9d68e3e3..a2ca227e199c 100644
--- a/drivers/block/zram/Makefile
+++ b/drivers/block/zram/Makefile
@@ -5,5 +5,6 @@ zram-y := zcomp.o zram_drv.o
zram-$(CONFIG_ZRAM_BACKEND_LZO) += backend_lzorle.o backend_lzo.o
zram-$(CONFIG_ZRAM_BACKEND_LZ4) += backend_lz4.o
zram-$(CONFIG_ZRAM_BACKEND_LZ4HC) += backend_lz4hc.o
+zram-$(CONFIG_ZRAM_BACKEND_ZSTD) += backend_zstd.o
obj-$(CONFIG_ZRAM) += zram.o
diff --git a/drivers/block/zram/backend_zstd.c b/drivers/block/zram/backend_zstd.c
new file mode 100644
index 000000000000..d0d01df2261f
--- /dev/null
+++ b/drivers/block/zram/backend_zstd.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/zstd.h>
+
+#include "backend_zstd.h"
+
+struct zstd_ctx {
+ zstd_cctx *cctx;
+ zstd_dctx *dctx;
+ void *cctx_mem;
+ void *dctx_mem;
+ s32 level;
+};
+
+static void zstd_destroy(void *ctx)
+{
+ struct zstd_ctx *zctx = ctx;
+
+ vfree(zctx->cctx_mem);
+ vfree(zctx->dctx_mem);
+ kfree(zctx);
+}
+
+static void *zstd_create(void)
+{
+ zstd_parameters params;
+ struct zstd_ctx *ctx;
+ size_t sz;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return NULL;
+
+ ctx->level = zstd_default_clevel();
+ params = zstd_get_params(ctx->level, 0);
+ sz = zstd_cctx_workspace_bound(¶ms.cParams);
+ ctx->cctx_mem = vzalloc(sz);
+ if (!ctx->cctx_mem)
+ goto error;
+
+ ctx->cctx = zstd_init_cctx(ctx->cctx_mem, sz);
+ if (!ctx->cctx)
+ goto error;
+
+ sz = zstd_dctx_workspace_bound();
+ ctx->dctx_mem = vzalloc(sz);
+ if (!ctx->dctx_mem)
+ goto error;
+
+ ctx->dctx = zstd_init_dctx(ctx->dctx_mem, sz);
+ if (!ctx->dctx)
+ goto error;
+
+ return ctx;
+
+error:
+ zstd_destroy(ctx);
+ return NULL;
+}
+
+static int zstd_compress(void *ctx, const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t *dst_len)
+{
+ struct zstd_ctx *zctx = ctx;
+ const zstd_parameters params = zstd_get_params(zctx->level, 0);
+ size_t ret;
+
+ ret = zstd_compress_cctx(zctx->cctx, dst, *dst_len,
+ src, src_len, ¶ms);
+ if (zstd_is_error(ret))
+ return -EINVAL;
+ *dst_len = ret;
+ return 0;
+}
+
+static int zstd_decompress(void *ctx, const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t dst_len)
+{
+ struct zstd_ctx *zctx = ctx;
+ size_t ret;
+
+ ret = zstd_decompress_dctx(zctx->dctx, dst, dst_len, src, src_len);
+ if (zstd_is_error(ret))
+ return -EINVAL;
+ return 0;
+}
+
+struct zcomp_ops backend_zstd = {
+ .compress = zstd_compress,
+ .decompress = zstd_decompress,
+ .create_ctx = zstd_create,
+ .destroy_ctx = zstd_destroy,
+ .name = "zstd",
+};
diff --git a/drivers/block/zram/backend_zstd.h b/drivers/block/zram/backend_zstd.h
new file mode 100644
index 000000000000..300b9fe635a1
--- /dev/null
+++ b/drivers/block/zram/backend_zstd.h
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#ifndef __BACKEND_ZSTD_H__
+#define __BACKEND_ZSTD_H__
+
+#include "zcomp.h"
+
+extern struct zcomp_ops backend_zstd;
+
+#endif /* __BACKEND_ZSTD_H__ */
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
index 1423b177dc30..c2441023356f 100644
--- a/drivers/block/zram/zcomp.c
+++ b/drivers/block/zram/zcomp.c
@@ -16,6 +16,7 @@
#include "backend_lzorle.h"
#include "backend_lz4.h"
#include "backend_lz4hc.h"
+#include "backend_zstd.h"
static struct zcomp_ops *backends[] = {
#if IS_ENABLED(CONFIG_ZRAM_BACKEND_LZO)
@@ -27,6 +28,9 @@ static struct zcomp_ops *backends[] = {
#endif
#if IS_ENABLED(CONFIG_ZRAM_BACKEND_LZ4HC)
&backend_lz4hc,
+#endif
+#if IS_ENABLED(CONFIG_ZRAM_BACKEND_ZSTD)
+ &backend_zstd,
#endif
NULL
};
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCHv5 09/23] zram: pass estimated src size hint to zstd
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (7 preceding siblings ...)
2024-07-06 4:56 ` [PATCHv5 08/23] zram: add zstd " Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 10/23] zram: add zlib compression backend support Sergey Senozhatsky
` (15 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky
zram works with PAGE_SIZE buffers, so we always know exact
size of the source buffer and hence can pass estimated_src_size
to zstd_get_params().
This hint on x86_64, for example, reduces the size of the work
memory buffer from 1303520 bytes down to 90080 bytes. Given that
compression streams are per-CPU that's quite some memory saving.
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
drivers/block/zram/backend_zstd.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/block/zram/backend_zstd.c b/drivers/block/zram/backend_zstd.c
index d0d01df2261f..e70e6dd2b4d6 100644
--- a/drivers/block/zram/backend_zstd.c
+++ b/drivers/block/zram/backend_zstd.c
@@ -35,7 +35,7 @@ static void *zstd_create(void)
return NULL;
ctx->level = zstd_default_clevel();
- params = zstd_get_params(ctx->level, 0);
+ params = zstd_get_params(ctx->level, PAGE_SIZE);
sz = zstd_cctx_workspace_bound(¶ms.cParams);
ctx->cctx_mem = vzalloc(sz);
if (!ctx->cctx_mem)
@@ -65,7 +65,7 @@ static int zstd_compress(void *ctx, const unsigned char *src, size_t src_len,
unsigned char *dst, size_t *dst_len)
{
struct zstd_ctx *zctx = ctx;
- const zstd_parameters params = zstd_get_params(zctx->level, 0);
+ const zstd_parameters params = zstd_get_params(zctx->level, PAGE_SIZE);
size_t ret;
ret = zstd_compress_cctx(zctx->cctx, dst, *dst_len,
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCHv5 10/23] zram: add zlib compression backend support
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (8 preceding siblings ...)
2024-07-06 4:56 ` [PATCHv5 09/23] zram: pass estimated src size hint to zstd Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 11/23] zram: add 842 " Sergey Senozhatsky
` (14 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky
Add s/w zlib (inflate/deflate) compression.
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
drivers/block/zram/Kconfig | 11 +++
drivers/block/zram/Makefile | 1 +
drivers/block/zram/backend_deflate.c | 132 +++++++++++++++++++++++++++
drivers/block/zram/backend_deflate.h | 10 ++
drivers/block/zram/zcomp.c | 4 +
5 files changed, 158 insertions(+)
create mode 100644 drivers/block/zram/backend_deflate.c
create mode 100644 drivers/block/zram/backend_deflate.h
diff --git a/drivers/block/zram/Kconfig b/drivers/block/zram/Kconfig
index ee4fe2ee3413..bc3a1d0455b1 100644
--- a/drivers/block/zram/Kconfig
+++ b/drivers/block/zram/Kconfig
@@ -39,6 +39,12 @@ config ZRAM_BACKEND_ZSTD
select ZSTD_COMPRESS
select ZSTD_DECOMPRESS
+config ZRAM_BACKEND_DEFLATE
+ bool "deflate compression support"
+ depends on ZRAM
+ select ZLIB_DEFLATE
+ select ZLIB_INFLATE
+
choice
prompt "Default zram compressor"
default ZRAM_DEF_COMP_LZORLE
@@ -64,6 +70,10 @@ config ZRAM_DEF_COMP_ZSTD
bool "zstd"
depends on ZRAM_BACKEND_ZSTD
+config ZRAM_DEF_COMP_DEFLATE
+ bool "deflate"
+ depends on ZRAM_BACKEND_DEFLATE
+
endchoice
config ZRAM_DEF_COMP
@@ -73,6 +83,7 @@ config ZRAM_DEF_COMP
default "lz4" if ZRAM_DEF_COMP_LZ4
default "lz4hc" if ZRAM_DEF_COMP_LZ4HC
default "zstd" if ZRAM_DEF_COMP_ZSTD
+ default "deflate" if ZRAM_DEF_COMP_DEFLATE
default "unset-value"
config ZRAM_WRITEBACK
diff --git a/drivers/block/zram/Makefile b/drivers/block/zram/Makefile
index a2ca227e199c..266430548437 100644
--- a/drivers/block/zram/Makefile
+++ b/drivers/block/zram/Makefile
@@ -6,5 +6,6 @@ zram-$(CONFIG_ZRAM_BACKEND_LZO) += backend_lzorle.o backend_lzo.o
zram-$(CONFIG_ZRAM_BACKEND_LZ4) += backend_lz4.o
zram-$(CONFIG_ZRAM_BACKEND_LZ4HC) += backend_lz4hc.o
zram-$(CONFIG_ZRAM_BACKEND_ZSTD) += backend_zstd.o
+zram-$(CONFIG_ZRAM_BACKEND_DEFLATE) += backend_deflate.o
obj-$(CONFIG_ZRAM) += zram.o
diff --git a/drivers/block/zram/backend_deflate.c b/drivers/block/zram/backend_deflate.c
new file mode 100644
index 000000000000..489694b0d5d9
--- /dev/null
+++ b/drivers/block/zram/backend_deflate.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/zlib.h>
+
+#include "backend_deflate.h"
+
+/* Use the same value as crypto API */
+#define DEFLATE_DEF_WINBITS 11
+#define DEFLATE_DEF_MEMLEVEL MAX_MEM_LEVEL
+
+struct deflate_ctx {
+ struct z_stream_s cctx;
+ struct z_stream_s dctx;
+ s32 level;
+};
+
+static void deflate_destroy(void *ctx)
+{
+ struct deflate_ctx *zctx = ctx;
+
+ if (zctx->cctx.workspace) {
+ zlib_deflateEnd(&zctx->cctx);
+ vfree(zctx->cctx.workspace);
+ }
+ if (zctx->dctx.workspace) {
+ zlib_inflateEnd(&zctx->dctx);
+ vfree(zctx->dctx.workspace);
+ }
+ kfree(zctx);
+}
+
+static void *deflate_create(void)
+{
+ struct deflate_ctx *ctx;
+ size_t sz;
+ int ret;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return NULL;
+
+ /* @FIXME: using a hardcoded Z_DEFAULT_COMPRESSION for now */
+ ctx->level = Z_DEFAULT_COMPRESSION;
+ sz = zlib_deflate_workspacesize(-DEFLATE_DEF_WINBITS, MAX_MEM_LEVEL);
+ ctx->cctx.workspace = vzalloc(sz);
+ if (!ctx->cctx.workspace)
+ goto error;
+
+ ret = zlib_deflateInit2(&ctx->cctx, ctx->level, Z_DEFLATED,
+ -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
+ Z_DEFAULT_STRATEGY);
+ if (ret != Z_OK)
+ goto error;
+
+ sz = zlib_inflate_workspacesize();
+ ctx->dctx.workspace = vzalloc(sz);
+ if (!ctx->dctx.workspace)
+ goto error;
+
+ ret = zlib_inflateInit2(&ctx->dctx, -DEFLATE_DEF_WINBITS);
+ if (ret != Z_OK)
+ goto error;
+
+ return ctx;
+
+error:
+ deflate_destroy(ctx);
+ return NULL;
+}
+
+static int deflate_compress(void *ctx, const unsigned char *src,
+ size_t src_len, unsigned char *dst,
+ size_t *dst_len)
+{
+ struct deflate_ctx *zctx = ctx;
+ struct z_stream_s *deflate;
+ int ret;
+
+ deflate = &zctx->cctx;
+ ret = zlib_deflateReset(deflate);
+ if (ret != Z_OK)
+ return -EINVAL;
+
+ deflate->next_in = (u8 *)src;
+ deflate->avail_in = src_len;
+ deflate->next_out = (u8 *)dst;
+ deflate->avail_out = *dst_len;
+
+ ret = zlib_deflate(deflate, Z_FINISH);
+ if (ret != Z_STREAM_END)
+ return -EINVAL;
+
+ *dst_len = deflate->total_out;
+ return 0;
+}
+
+static int deflate_decompress(void *ctx, const unsigned char *src,
+ size_t src_len, unsigned char *dst,
+ size_t dst_len)
+{
+ struct deflate_ctx *zctx = ctx;
+ struct z_stream_s *inflate;
+ int ret;
+
+ inflate = &zctx->dctx;
+
+ ret = zlib_inflateReset(inflate);
+ if (ret != Z_OK)
+ return -EINVAL;
+
+ inflate->next_in = (u8 *)src;
+ inflate->avail_in = src_len;
+ inflate->next_out = (u8 *)dst;
+ inflate->avail_out = dst_len;
+
+ ret = zlib_inflate(inflate, Z_SYNC_FLUSH);
+ if (ret != Z_STREAM_END)
+ return -EINVAL;
+
+ return 0;
+}
+
+struct zcomp_ops backend_deflate = {
+ .compress = deflate_compress,
+ .decompress = deflate_decompress,
+ .create_ctx = deflate_create,
+ .destroy_ctx = deflate_destroy,
+ .name = "deflate",
+};
diff --git a/drivers/block/zram/backend_deflate.h b/drivers/block/zram/backend_deflate.h
new file mode 100644
index 000000000000..d0a9b35c289f
--- /dev/null
+++ b/drivers/block/zram/backend_deflate.h
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#ifndef __BACKEND_DEFLATE_H__
+#define __BACKEND_DEFLATE_H__
+
+#include "zcomp.h"
+
+extern struct zcomp_ops backend_deflate;
+
+#endif /* __BACKEND_DEFLATE_H__ */
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
index c2441023356f..13c58e197d60 100644
--- a/drivers/block/zram/zcomp.c
+++ b/drivers/block/zram/zcomp.c
@@ -17,6 +17,7 @@
#include "backend_lz4.h"
#include "backend_lz4hc.h"
#include "backend_zstd.h"
+#include "backend_deflate.h"
static struct zcomp_ops *backends[] = {
#if IS_ENABLED(CONFIG_ZRAM_BACKEND_LZO)
@@ -31,6 +32,9 @@ static struct zcomp_ops *backends[] = {
#endif
#if IS_ENABLED(CONFIG_ZRAM_BACKEND_ZSTD)
&backend_zstd,
+#endif
+#if IS_ENABLED(CONFIG_ZRAM_BACKEND_DEFLATE)
+ &backend_deflate,
#endif
NULL
};
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCHv5 11/23] zram: add 842 compression backend support
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (9 preceding siblings ...)
2024-07-06 4:56 ` [PATCHv5 10/23] zram: add zlib compression backend support Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 12/23] zram: check that backends array has at least one backend Sergey Senozhatsky
` (13 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky
Add s/w 842 compression support.
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
drivers/block/zram/Kconfig | 11 ++++++
drivers/block/zram/Makefile | 1 +
drivers/block/zram/backend_842.c | 68 ++++++++++++++++++++++++++++++++
drivers/block/zram/backend_842.h | 10 +++++
drivers/block/zram/zcomp.c | 4 ++
5 files changed, 94 insertions(+)
create mode 100644 drivers/block/zram/backend_842.c
create mode 100644 drivers/block/zram/backend_842.h
diff --git a/drivers/block/zram/Kconfig b/drivers/block/zram/Kconfig
index bc3a1d0455b1..ddc19853ea96 100644
--- a/drivers/block/zram/Kconfig
+++ b/drivers/block/zram/Kconfig
@@ -45,6 +45,12 @@ config ZRAM_BACKEND_DEFLATE
select ZLIB_DEFLATE
select ZLIB_INFLATE
+config ZRAM_BACKEND_842
+ bool "842 compression support"
+ depends on ZRAM
+ select 842_COMPRESS
+ select 842_DECOMPRESS
+
choice
prompt "Default zram compressor"
default ZRAM_DEF_COMP_LZORLE
@@ -74,6 +80,10 @@ config ZRAM_DEF_COMP_DEFLATE
bool "deflate"
depends on ZRAM_BACKEND_DEFLATE
+config ZRAM_DEF_COMP_842
+ bool "842"
+ depends on ZRAM_BACKEND_842
+
endchoice
config ZRAM_DEF_COMP
@@ -84,6 +94,7 @@ config ZRAM_DEF_COMP
default "lz4hc" if ZRAM_DEF_COMP_LZ4HC
default "zstd" if ZRAM_DEF_COMP_ZSTD
default "deflate" if ZRAM_DEF_COMP_DEFLATE
+ default "842" if ZRAM_DEF_COMP_842
default "unset-value"
config ZRAM_WRITEBACK
diff --git a/drivers/block/zram/Makefile b/drivers/block/zram/Makefile
index 266430548437..0fdefd576691 100644
--- a/drivers/block/zram/Makefile
+++ b/drivers/block/zram/Makefile
@@ -7,5 +7,6 @@ zram-$(CONFIG_ZRAM_BACKEND_LZ4) += backend_lz4.o
zram-$(CONFIG_ZRAM_BACKEND_LZ4HC) += backend_lz4hc.o
zram-$(CONFIG_ZRAM_BACKEND_ZSTD) += backend_zstd.o
zram-$(CONFIG_ZRAM_BACKEND_DEFLATE) += backend_deflate.o
+zram-$(CONFIG_ZRAM_BACKEND_842) += backend_842.o
obj-$(CONFIG_ZRAM) += zram.o
diff --git a/drivers/block/zram/backend_842.c b/drivers/block/zram/backend_842.c
new file mode 100644
index 000000000000..83802d6c0e7d
--- /dev/null
+++ b/drivers/block/zram/backend_842.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sw842.h>
+#include <linux/vmalloc.h>
+
+#include "backend_842.h"
+
+struct sw842_ctx {
+ void *mem;
+};
+
+static void destroy_842(void *ctx)
+{
+ struct sw842_ctx *zctx = ctx;
+
+ kfree(zctx->mem);
+ kfree(zctx);
+}
+
+static void *create_842(void)
+{
+ struct sw842_ctx *ctx;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return NULL;
+
+ ctx->mem = kmalloc(SW842_MEM_COMPRESS, GFP_KERNEL);
+ if (!ctx->mem)
+ goto error;
+
+ return ctx;
+
+error:
+ destroy_842(ctx);
+ return NULL;
+}
+
+static int compress_842(void *ctx, const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t *dst_len)
+{
+ struct sw842_ctx *zctx = ctx;
+ unsigned int dlen = *dst_len;
+ int ret;
+
+ ret = sw842_compress(src, src_len, dst, &dlen, zctx->mem);
+ if (ret == 0)
+ *dst_len = dlen;
+ return ret;
+}
+
+static int decompress_842(void *ctx, const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t dst_len)
+{
+ unsigned int dlen = dst_len;
+
+ return sw842_decompress(src, src_len, dst, &dlen);
+}
+
+struct zcomp_ops backend_842 = {
+ .compress = compress_842,
+ .decompress = decompress_842,
+ .create_ctx = create_842,
+ .destroy_ctx = destroy_842,
+ .name = "842",
+};
diff --git a/drivers/block/zram/backend_842.h b/drivers/block/zram/backend_842.h
new file mode 100644
index 000000000000..898ac1410329
--- /dev/null
+++ b/drivers/block/zram/backend_842.h
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#ifndef __BACKEND_842_H__
+#define __BACKEND_842_H__
+
+#include "zcomp.h"
+
+extern struct zcomp_ops backend_842;
+
+#endif /* __BACKEND_842_H__ */
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
index 13c58e197d60..280dcc48fb5e 100644
--- a/drivers/block/zram/zcomp.c
+++ b/drivers/block/zram/zcomp.c
@@ -18,6 +18,7 @@
#include "backend_lz4hc.h"
#include "backend_zstd.h"
#include "backend_deflate.h"
+#include "backend_842.h"
static struct zcomp_ops *backends[] = {
#if IS_ENABLED(CONFIG_ZRAM_BACKEND_LZO)
@@ -35,6 +36,9 @@ static struct zcomp_ops *backends[] = {
#endif
#if IS_ENABLED(CONFIG_ZRAM_BACKEND_DEFLATE)
&backend_deflate,
+#endif
+#if IS_ENABLED(CONFIG_ZRAM_BACKEND_842)
+ &backend_842,
#endif
NULL
};
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCHv5 12/23] zram: check that backends array has at least one backend
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (10 preceding siblings ...)
2024-07-06 4:56 ` [PATCHv5 11/23] zram: add 842 " Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 13/23] zram: introduce zcomp_params structure Sergey Senozhatsky
` (12 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky
Make sure that backends array has anything apart from the
sentinel NULL value.
We also select LZO_BACKEND if none backends were selected.
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
drivers/block/zram/Kconfig | 19 +++++++++++++------
drivers/block/zram/zcomp.c | 8 ++++++++
2 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/drivers/block/zram/Kconfig b/drivers/block/zram/Kconfig
index ddc19853ea96..40e035468de2 100644
--- a/drivers/block/zram/Kconfig
+++ b/drivers/block/zram/Kconfig
@@ -15,12 +15,6 @@ config ZRAM
See Documentation/admin-guide/blockdev/zram.rst for more information.
-config ZRAM_BACKEND_LZO
- bool "lzo and lzo-rle compression support"
- depends on ZRAM
- select LZO_COMPRESS
- select LZO_DECOMPRESS
-
config ZRAM_BACKEND_LZ4
bool "lz4 compression support"
depends on ZRAM
@@ -51,6 +45,19 @@ config ZRAM_BACKEND_842
select 842_COMPRESS
select 842_DECOMPRESS
+config ZRAM_BACKEND_FORCE_LZO
+ depends on ZRAM
+ def_bool !ZRAM_BACKEND_LZ4 && !ZRAM_BACKEND_LZ4HC && \
+ !ZRAM_BACKEND_ZSTD && !ZRAM_BACKEND_DEFLATE && \
+ !ZRAM_BACKEND_842
+
+config ZRAM_BACKEND_LZO
+ bool "lzo and lzo-rle compression support" if !ZRAM_BACKEND_FORCE_LZO
+ depends on ZRAM
+ default ZRAM_BACKEND_FORCE_LZO
+ select LZO_COMPRESS
+ select LZO_DECOMPRESS
+
choice
prompt "Default zram compressor"
default ZRAM_DEF_COMP_LZORLE
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
index 280dcc48fb5e..1888d4dd9245 100644
--- a/drivers/block/zram/zcomp.c
+++ b/drivers/block/zram/zcomp.c
@@ -191,6 +191,14 @@ struct zcomp *zcomp_create(const char *alg)
struct zcomp *comp;
int error;
+ /*
+ * The backends array has a sentinel NULL value, so the minimum
+ * size is 1. In order to be valid the array, apart from the
+ * sentinel NULL element, should have at least one compression
+ * backend selected.
+ */
+ BUILD_BUG_ON(ARRAY_SIZE(backends) <= 1);
+
comp = kzalloc(sizeof(struct zcomp), GFP_KERNEL);
if (!comp)
return ERR_PTR(-ENOMEM);
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCHv5 13/23] zram: introduce zcomp_params structure
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (11 preceding siblings ...)
2024-07-06 4:56 ` [PATCHv5 12/23] zram: check that backends array has at least one backend Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 14/23] zram: recalculate zstd compression params once Sergey Senozhatsky
` (11 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky
We will store a per-algorithm parameters there (compression level,
dictionary, dictionary size, etc.).
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
drivers/block/zram/backend_842.c | 2 +-
drivers/block/zram/backend_deflate.c | 9 ++++++---
drivers/block/zram/backend_lz4.c | 9 ++++++---
drivers/block/zram/backend_lz4hc.c | 9 ++++++---
drivers/block/zram/backend_lzo.c | 2 +-
drivers/block/zram/backend_lzorle.c | 2 +-
drivers/block/zram/backend_zstd.c | 18 +++++++++++-------
drivers/block/zram/zcomp.c | 5 +++--
drivers/block/zram/zcomp.h | 14 ++++++++++++--
drivers/block/zram/zram_drv.c | 20 +++++++++++++++++++-
drivers/block/zram/zram_drv.h | 1 +
11 files changed, 67 insertions(+), 24 deletions(-)
diff --git a/drivers/block/zram/backend_842.c b/drivers/block/zram/backend_842.c
index 83802d6c0e7d..9193391626a9 100644
--- a/drivers/block/zram/backend_842.c
+++ b/drivers/block/zram/backend_842.c
@@ -19,7 +19,7 @@ static void destroy_842(void *ctx)
kfree(zctx);
}
-static void *create_842(void)
+static void *create_842(struct zcomp_params *params)
{
struct sw842_ctx *ctx;
diff --git a/drivers/block/zram/backend_deflate.c b/drivers/block/zram/backend_deflate.c
index 489694b0d5d9..415ab55f8aeb 100644
--- a/drivers/block/zram/backend_deflate.c
+++ b/drivers/block/zram/backend_deflate.c
@@ -32,7 +32,7 @@ static void deflate_destroy(void *ctx)
kfree(zctx);
}
-static void *deflate_create(void)
+static void *deflate_create(struct zcomp_params *params)
{
struct deflate_ctx *ctx;
size_t sz;
@@ -42,8 +42,11 @@ static void *deflate_create(void)
if (!ctx)
return NULL;
- /* @FIXME: using a hardcoded Z_DEFAULT_COMPRESSION for now */
- ctx->level = Z_DEFAULT_COMPRESSION;
+ if (params->level != ZCOMP_PARAM_NO_LEVEL)
+ ctx->level = params->level;
+ else
+ ctx->level = Z_DEFAULT_COMPRESSION;
+
sz = zlib_deflate_workspacesize(-DEFLATE_DEF_WINBITS, MAX_MEM_LEVEL);
ctx->cctx.workspace = vzalloc(sz);
if (!ctx->cctx.workspace)
diff --git a/drivers/block/zram/backend_lz4.c b/drivers/block/zram/backend_lz4.c
index 4de389fb3463..90801a7a8f75 100644
--- a/drivers/block/zram/backend_lz4.c
+++ b/drivers/block/zram/backend_lz4.c
@@ -18,7 +18,7 @@ static void lz4_destroy(void *ctx)
kfree(zctx);
}
-static void *lz4_create(void)
+static void *lz4_create(struct zcomp_params *params)
{
struct lz4_ctx *ctx;
@@ -26,8 +26,11 @@ static void *lz4_create(void)
if (!ctx)
return NULL;
- /* @FIXME: using a hardcoded LZ4_ACCELERATION_DEFAULT for now */
- ctx->level = LZ4_ACCELERATION_DEFAULT;
+ if (params->level != ZCOMP_PARAM_NO_LEVEL)
+ ctx->level = params->level;
+ else
+ ctx->level = LZ4_ACCELERATION_DEFAULT;
+
ctx->mem = vmalloc(LZ4_MEM_COMPRESS);
if (!ctx->mem)
goto error;
diff --git a/drivers/block/zram/backend_lz4hc.c b/drivers/block/zram/backend_lz4hc.c
index 50e998c1e321..30de6ec511a5 100644
--- a/drivers/block/zram/backend_lz4hc.c
+++ b/drivers/block/zram/backend_lz4hc.c
@@ -18,7 +18,7 @@ static void lz4hc_destroy(void *ctx)
kfree(zctx);
}
-static void *lz4hc_create(void)
+static void *lz4hc_create(struct zcomp_params *params)
{
struct lz4hc_ctx *ctx;
@@ -26,8 +26,11 @@ static void *lz4hc_create(void)
if (!ctx)
return NULL;
- /* @FIXME: using a hardcoded LZ4HC_DEFAULT_CLEVEL for now */
- ctx->level = LZ4HC_DEFAULT_CLEVEL;
+ if (params->level != ZCOMP_PARAM_NO_LEVEL)
+ ctx->level = params->level;
+ else
+ ctx->level = LZ4HC_DEFAULT_CLEVEL;
+
ctx->mem = vmalloc(LZ4HC_MEM_COMPRESS);
if (!ctx->mem)
goto error;
diff --git a/drivers/block/zram/backend_lzo.c b/drivers/block/zram/backend_lzo.c
index 7eb0d2709a73..c903c15610f8 100644
--- a/drivers/block/zram/backend_lzo.c
+++ b/drivers/block/zram/backend_lzo.c
@@ -6,7 +6,7 @@
#include "backend_lzo.h"
-static void *lzo_create(void)
+static void *lzo_create(struct zcomp_params *params)
{
return kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
}
diff --git a/drivers/block/zram/backend_lzorle.c b/drivers/block/zram/backend_lzorle.c
index 68fcdccb2f53..3622625abfd9 100644
--- a/drivers/block/zram/backend_lzorle.c
+++ b/drivers/block/zram/backend_lzorle.c
@@ -6,7 +6,7 @@
#include "backend_lzorle.h"
-static void *lzorle_create(void)
+static void *lzorle_create(struct zcomp_params *params)
{
return kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
}
diff --git a/drivers/block/zram/backend_zstd.c b/drivers/block/zram/backend_zstd.c
index e70e6dd2b4d6..2328a462b82c 100644
--- a/drivers/block/zram/backend_zstd.c
+++ b/drivers/block/zram/backend_zstd.c
@@ -24,9 +24,9 @@ static void zstd_destroy(void *ctx)
kfree(zctx);
}
-static void *zstd_create(void)
+static void *zstd_create(struct zcomp_params *params)
{
- zstd_parameters params;
+ zstd_parameters prm;
struct zstd_ctx *ctx;
size_t sz;
@@ -34,9 +34,13 @@ static void *zstd_create(void)
if (!ctx)
return NULL;
- ctx->level = zstd_default_clevel();
- params = zstd_get_params(ctx->level, PAGE_SIZE);
- sz = zstd_cctx_workspace_bound(¶ms.cParams);
+ if (params->level != ZCOMP_PARAM_NO_LEVEL)
+ ctx->level = params->level;
+ else
+ ctx->level = zstd_default_clevel();
+
+ prm = zstd_get_params(ctx->level, PAGE_SIZE);
+ sz = zstd_cctx_workspace_bound(&prm.cParams);
ctx->cctx_mem = vzalloc(sz);
if (!ctx->cctx_mem)
goto error;
@@ -65,11 +69,11 @@ static int zstd_compress(void *ctx, const unsigned char *src, size_t src_len,
unsigned char *dst, size_t *dst_len)
{
struct zstd_ctx *zctx = ctx;
- const zstd_parameters params = zstd_get_params(zctx->level, PAGE_SIZE);
+ const zstd_parameters prm = zstd_get_params(zctx->level, PAGE_SIZE);
size_t ret;
ret = zstd_compress_cctx(zctx->cctx, dst, *dst_len,
- src, src_len, ¶ms);
+ src, src_len, &prm);
if (zstd_is_error(ret))
return -EINVAL;
*dst_len = ret;
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
index 1888d4dd9245..eacead28cc2b 100644
--- a/drivers/block/zram/zcomp.c
+++ b/drivers/block/zram/zcomp.c
@@ -54,7 +54,7 @@ static void zcomp_strm_free(struct zcomp *comp, struct zcomp_strm *zstrm)
static int zcomp_strm_init(struct zcomp *comp, struct zcomp_strm *zstrm)
{
- zstrm->ctx = comp->ops->create_ctx();
+ zstrm->ctx = comp->ops->create_ctx(comp->params);
/*
* allocate 2 pages. 1 for compressed data, plus 1 extra for the
@@ -186,7 +186,7 @@ void zcomp_destroy(struct zcomp *comp)
kfree(comp);
}
-struct zcomp *zcomp_create(const char *alg)
+struct zcomp *zcomp_create(const char *alg, struct zcomp_params *params)
{
struct zcomp *comp;
int error;
@@ -203,6 +203,7 @@ struct zcomp *zcomp_create(const char *alg)
if (!comp)
return ERR_PTR(-ENOMEM);
+ comp->params = params;
comp->ops = lookup_backend_ops(alg);
if (!comp->ops) {
kfree(comp);
diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h
index dde28a8d32d4..3639c36fb9a9 100644
--- a/drivers/block/zram/zcomp.h
+++ b/drivers/block/zram/zcomp.h
@@ -2,8 +2,17 @@
#ifndef _ZCOMP_H_
#define _ZCOMP_H_
+
#include <linux/local_lock.h>
+#define ZCOMP_PARAM_NO_LEVEL INT_MIN
+
+struct zcomp_params {
+ void *dict;
+ size_t dict_sz;
+ s32 level;
+};
+
struct zcomp_strm {
/* The members ->buffer and ->tfm are protected by ->lock. */
local_lock_t lock;
@@ -19,7 +28,7 @@ struct zcomp_ops {
int (*decompress)(void *ctx, const unsigned char *src, size_t src_len,
unsigned char *dst, size_t dst_len);
- void *(*create_ctx)(void);
+ void *(*create_ctx)(struct zcomp_params *params);
void (*destroy_ctx)(void *ctx);
const char *name;
@@ -29,6 +38,7 @@ struct zcomp_ops {
struct zcomp {
struct zcomp_strm __percpu *stream;
struct zcomp_ops *ops;
+ struct zcomp_params *params;
struct hlist_node node;
};
@@ -37,7 +47,7 @@ int zcomp_cpu_dead(unsigned int cpu, struct hlist_node *node);
ssize_t zcomp_available_show(const char *comp, char *buf);
bool zcomp_available_algorithm(const char *comp);
-struct zcomp *zcomp_create(const char *alg);
+struct zcomp *zcomp_create(const char *alg, struct zcomp_params *params);
void zcomp_destroy(struct zcomp *comp);
struct zcomp_strm *zcomp_stream_get(struct zcomp *comp);
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 93042da8ccdf..84757f0c8166 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -1979,6 +1979,20 @@ static void zram_slot_free_notify(struct block_device *bdev,
zram_slot_unlock(zram, index);
}
+static void zram_reset_comp_params(struct zram *zram)
+{
+ u32 prio;
+
+ for (prio = 0; prio < ZRAM_MAX_COMPS; prio++) {
+ struct zcomp_params *params = &zram->params[prio];
+
+ vfree(params->dict);
+ params->level = ZCOMP_PARAM_NO_LEVEL;
+ params->dict_sz = 0;
+ params->dict = NULL;
+ }
+}
+
static void zram_destroy_comps(struct zram *zram)
{
u32 prio;
@@ -1992,6 +2006,8 @@ static void zram_destroy_comps(struct zram *zram)
zcomp_destroy(comp);
zram->num_active_comps--;
}
+
+ zram_reset_comp_params(zram);
}
static void zram_reset_device(struct zram *zram)
@@ -2049,7 +2065,8 @@ static ssize_t disksize_store(struct device *dev,
if (!zram->comp_algs[prio])
continue;
- comp = zcomp_create(zram->comp_algs[prio]);
+ comp = zcomp_create(zram->comp_algs[prio],
+ &zram->params[prio]);
if (IS_ERR(comp)) {
pr_err("Cannot initialise %s compressing backend\n",
zram->comp_algs[prio]);
@@ -2254,6 +2271,7 @@ static int zram_add(void)
if (ret)
goto out_cleanup_disk;
+ zram_reset_comp_params(zram);
comp_algorithm_set(zram, ZRAM_PRIMARY_COMP, default_compressor);
zram_debugfs_register(zram);
diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
index 35e322144629..b976824ead67 100644
--- a/drivers/block/zram/zram_drv.h
+++ b/drivers/block/zram/zram_drv.h
@@ -107,6 +107,7 @@ struct zram {
struct zram_table_entry *table;
struct zs_pool *mem_pool;
struct zcomp *comps[ZRAM_MAX_COMPS];
+ struct zcomp_params params[ZRAM_MAX_COMPS];
struct gendisk *disk;
/* Prevent concurrent execution of device init */
struct rw_semaphore init_lock;
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCHv5 14/23] zram: recalculate zstd compression params once
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (12 preceding siblings ...)
2024-07-06 4:56 ` [PATCHv5 13/23] zram: introduce zcomp_params structure Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 15/23] zram: extend comp_algorithm attr write handling Sergey Senozhatsky
` (10 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky
zstd compression params depends on level, but are constant
for a given instance of zstd compression backend. Calculate
once (during ctx creation).
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
drivers/block/zram/backend_zstd.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/block/zram/backend_zstd.c b/drivers/block/zram/backend_zstd.c
index 2328a462b82c..a9808abcf5f2 100644
--- a/drivers/block/zram/backend_zstd.c
+++ b/drivers/block/zram/backend_zstd.c
@@ -10,6 +10,7 @@
struct zstd_ctx {
zstd_cctx *cctx;
zstd_dctx *dctx;
+ zstd_parameters cprm;
void *cctx_mem;
void *dctx_mem;
s32 level;
@@ -40,6 +41,7 @@ static void *zstd_create(struct zcomp_params *params)
ctx->level = zstd_default_clevel();
prm = zstd_get_params(ctx->level, PAGE_SIZE);
+ ctx->cprm = zstd_get_params(ctx->level, PAGE_SIZE);
sz = zstd_cctx_workspace_bound(&prm.cParams);
ctx->cctx_mem = vzalloc(sz);
if (!ctx->cctx_mem)
@@ -69,11 +71,10 @@ static int zstd_compress(void *ctx, const unsigned char *src, size_t src_len,
unsigned char *dst, size_t *dst_len)
{
struct zstd_ctx *zctx = ctx;
- const zstd_parameters prm = zstd_get_params(zctx->level, PAGE_SIZE);
size_t ret;
ret = zstd_compress_cctx(zctx->cctx, dst, *dst_len,
- src, src_len, &prm);
+ src, src_len, &zctx->cprm);
if (zstd_is_error(ret))
return -EINVAL;
*dst_len = ret;
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCHv5 15/23] zram: extend comp_algorithm attr write handling
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (13 preceding siblings ...)
2024-07-06 4:56 ` [PATCHv5 14/23] zram: recalculate zstd compression params once Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 16/23] zram: add support for dict comp config Sergey Senozhatsky
` (9 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky
Previously comp_algorithm device attr would accept only
algorithm name param, however in order to enabled comp
configuration we need to extend comp_algorithm_store()
with param=value support.
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
drivers/block/zram/zram_drv.c | 54 +++++++++++++++++++++++++++++++++--
1 file changed, 52 insertions(+), 2 deletions(-)
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 84757f0c8166..a2c23ca033b5 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -998,6 +998,12 @@ static int __comp_algorithm_store(struct zram *zram, u32 prio, const char *buf)
return 0;
}
+static int comp_params_store(struct zram *zram, u32 prio, s32 level)
+{
+ zram->params[prio].level = level;
+ return 0;
+}
+
static ssize_t comp_algorithm_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -1013,9 +1019,43 @@ static ssize_t comp_algorithm_store(struct device *dev,
size_t len)
{
struct zram *zram = dev_to_zram(dev);
+ char *args, *param, *val;
+ char *alg = NULL;
+ s32 level = ZCOMP_PARAM_NO_LEVEL;
int ret;
- ret = __comp_algorithm_store(zram, ZRAM_PRIMARY_COMP, buf);
+ args = skip_spaces(buf);
+ while (*args) {
+ args = next_arg(args, ¶m, &val);
+
+ /*
+ * We need to support 'param' without value, which is an
+ * old format for this attr (algorithm name only).
+ */
+ if (!val || !*val) {
+ alg = param;
+ continue;
+ }
+
+ if (!strcmp(param, "algo")) {
+ alg = val;
+ continue;
+ }
+
+ if (!strcmp(param, "level")) {
+ ret = kstrtoint(val, 10, &level);
+ if (ret)
+ return ret;
+ continue;
+ }
+ }
+
+ if (!alg)
+ return -EINVAL;
+
+ ret = comp_params_store(zram, ZRAM_PRIMARY_COMP, level);
+ if (!ret)
+ ret = __comp_algorithm_store(zram, ZRAM_PRIMARY_COMP, alg);
return ret ? ret : len;
}
@@ -1048,6 +1088,7 @@ static ssize_t recomp_algorithm_store(struct device *dev,
int prio = ZRAM_SECONDARY_COMP;
char *args, *param, *val;
char *alg = NULL;
+ s32 level = ZCOMP_PARAM_NO_LEVEL;
int ret;
args = skip_spaces(buf);
@@ -1068,6 +1109,13 @@ static ssize_t recomp_algorithm_store(struct device *dev,
return ret;
continue;
}
+
+ if (!strcmp(param, "level")) {
+ ret = kstrtoint(val, 10, &level);
+ if (ret)
+ return ret;
+ continue;
+ }
}
if (!alg)
@@ -1076,7 +1124,9 @@ static ssize_t recomp_algorithm_store(struct device *dev,
if (prio < ZRAM_SECONDARY_COMP || prio >= ZRAM_MAX_COMPS)
return -EINVAL;
- ret = __comp_algorithm_store(zram, prio, alg);
+ ret = comp_params_store(zram, prio, level);
+ if (!ret)
+ ret = __comp_algorithm_store(zram, prio, alg);
return ret ? ret : len;
}
#endif
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCHv5 16/23] zram: add support for dict comp config
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (14 preceding siblings ...)
2024-07-06 4:56 ` [PATCHv5 15/23] zram: extend comp_algorithm attr write handling Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 17/23] zram: introduce zcomp_req structure Sergey Senozhatsky
` (8 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky
Handle dict=path param so that we can read a pre-trained
compression algorithm dictionary which we then pass to the
backend configuration.
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
drivers/block/zram/zram_drv.c | 60 +++++++++++++++++++++++++++--------
1 file changed, 46 insertions(+), 14 deletions(-)
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index a2c23ca033b5..d471ec14c76a 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -33,6 +33,7 @@
#include <linux/debugfs.h>
#include <linux/cpuhotplug.h>
#include <linux/part_stat.h>
+#include <linux/kernel_read_file.h>
#include "zram_drv.h"
@@ -998,8 +999,34 @@ static int __comp_algorithm_store(struct zram *zram, u32 prio, const char *buf)
return 0;
}
-static int comp_params_store(struct zram *zram, u32 prio, s32 level)
+static void comp_params_reset(struct zram *zram, u32 prio)
{
+ struct zcomp_params *params = &zram->params[prio];
+
+ vfree(params->dict);
+ params->level = ZCOMP_PARAM_NO_LEVEL;
+ params->dict_sz = 0;
+ params->dict = NULL;
+}
+
+static int comp_params_store(struct zram *zram, u32 prio, s32 level,
+ const char *dict_path)
+{
+ ssize_t sz = 0;
+
+ comp_params_reset(zram, prio);
+
+ if (dict_path) {
+ sz = kernel_read_file_from_path(dict_path, 0,
+ &zram->params[prio].dict,
+ INT_MAX,
+ NULL,
+ READING_POLICY);
+ if (sz < 0)
+ return -EINVAL;
+ }
+
+ zram->params[prio].dict_sz = sz;
zram->params[prio].level = level;
return 0;
}
@@ -1020,7 +1047,7 @@ static ssize_t comp_algorithm_store(struct device *dev,
{
struct zram *zram = dev_to_zram(dev);
char *args, *param, *val;
- char *alg = NULL;
+ char *alg = NULL, *dict_path = NULL;
s32 level = ZCOMP_PARAM_NO_LEVEL;
int ret;
@@ -1048,12 +1075,17 @@ static ssize_t comp_algorithm_store(struct device *dev,
return ret;
continue;
}
+
+ if (!strcmp(param, "dict")) {
+ dict_path = val;
+ continue;
+ }
}
if (!alg)
return -EINVAL;
- ret = comp_params_store(zram, ZRAM_PRIMARY_COMP, level);
+ ret = comp_params_store(zram, ZRAM_PRIMARY_COMP, level, dict_path);
if (!ret)
ret = __comp_algorithm_store(zram, ZRAM_PRIMARY_COMP, alg);
return ret ? ret : len;
@@ -1087,7 +1119,7 @@ static ssize_t recomp_algorithm_store(struct device *dev,
struct zram *zram = dev_to_zram(dev);
int prio = ZRAM_SECONDARY_COMP;
char *args, *param, *val;
- char *alg = NULL;
+ char *alg = NULL, *dict_path = NULL;
s32 level = ZCOMP_PARAM_NO_LEVEL;
int ret;
@@ -1116,6 +1148,11 @@ static ssize_t recomp_algorithm_store(struct device *dev,
return ret;
continue;
}
+
+ if (!strcmp(param, "dict")) {
+ dict_path = val;
+ continue;
+ }
}
if (!alg)
@@ -1124,7 +1161,7 @@ static ssize_t recomp_algorithm_store(struct device *dev,
if (prio < ZRAM_SECONDARY_COMP || prio >= ZRAM_MAX_COMPS)
return -EINVAL;
- ret = comp_params_store(zram, prio, level);
+ ret = comp_params_store(zram, prio, level, dict_path);
if (!ret)
ret = __comp_algorithm_store(zram, prio, alg);
return ret ? ret : len;
@@ -2029,17 +2066,12 @@ static void zram_slot_free_notify(struct block_device *bdev,
zram_slot_unlock(zram, index);
}
-static void zram_reset_comp_params(struct zram *zram)
+static void zram_comp_params_reset(struct zram *zram)
{
u32 prio;
for (prio = 0; prio < ZRAM_MAX_COMPS; prio++) {
- struct zcomp_params *params = &zram->params[prio];
-
- vfree(params->dict);
- params->level = ZCOMP_PARAM_NO_LEVEL;
- params->dict_sz = 0;
- params->dict = NULL;
+ comp_params_reset(zram, prio);
}
}
@@ -2057,7 +2089,7 @@ static void zram_destroy_comps(struct zram *zram)
zram->num_active_comps--;
}
- zram_reset_comp_params(zram);
+ zram_comp_params_reset(zram);
}
static void zram_reset_device(struct zram *zram)
@@ -2321,7 +2353,7 @@ static int zram_add(void)
if (ret)
goto out_cleanup_disk;
- zram_reset_comp_params(zram);
+ zram_comp_params_reset(zram);
comp_algorithm_set(zram, ZRAM_PRIMARY_COMP, default_compressor);
zram_debugfs_register(zram);
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCHv5 17/23] zram: introduce zcomp_req structure
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (15 preceding siblings ...)
2024-07-06 4:56 ` [PATCHv5 16/23] zram: add support for dict comp config Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 18/23] zram: introduce zcomp_ctx structure Sergey Senozhatsky
` (7 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky
Encapsulate compression/decompression data in zcomp_req
structure.
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
drivers/block/zram/backend_842.c | 17 ++++++++---------
drivers/block/zram/backend_deflate.c | 26 +++++++++++---------------
drivers/block/zram/backend_lz4.c | 15 +++++++--------
drivers/block/zram/backend_lz4hc.c | 13 ++++++-------
drivers/block/zram/backend_lzo.c | 12 ++++++------
drivers/block/zram/backend_lzorle.c | 13 ++++++-------
drivers/block/zram/backend_zstd.c | 15 +++++++--------
drivers/block/zram/zcomp.c | 23 ++++++++++++++++-------
drivers/block/zram/zcomp.h | 15 ++++++++++-----
9 files changed, 77 insertions(+), 72 deletions(-)
diff --git a/drivers/block/zram/backend_842.c b/drivers/block/zram/backend_842.c
index 9193391626a9..1df0de5a9863 100644
--- a/drivers/block/zram/backend_842.c
+++ b/drivers/block/zram/backend_842.c
@@ -38,25 +38,24 @@ static void *create_842(struct zcomp_params *params)
return NULL;
}
-static int compress_842(void *ctx, const unsigned char *src, size_t src_len,
- unsigned char *dst, size_t *dst_len)
+static int compress_842(void *ctx, struct zcomp_req *req)
{
struct sw842_ctx *zctx = ctx;
- unsigned int dlen = *dst_len;
+ unsigned int dlen = req->dst_len;
int ret;
- ret = sw842_compress(src, src_len, dst, &dlen, zctx->mem);
+ ret = sw842_compress(req->src, req->src_len, req->dst, &dlen,
+ zctx->mem);
if (ret == 0)
- *dst_len = dlen;
+ req->dst_len = dlen;
return ret;
}
-static int decompress_842(void *ctx, const unsigned char *src, size_t src_len,
- unsigned char *dst, size_t dst_len)
+static int decompress_842(void *ctx, struct zcomp_req *req)
{
- unsigned int dlen = dst_len;
+ unsigned int dlen = req->dst_len;
- return sw842_decompress(src, src_len, dst, &dlen);
+ return sw842_decompress(req->src, req->src_len, req->dst, &dlen);
}
struct zcomp_ops backend_842 = {
diff --git a/drivers/block/zram/backend_deflate.c b/drivers/block/zram/backend_deflate.c
index 415ab55f8aeb..19bb61369eb0 100644
--- a/drivers/block/zram/backend_deflate.c
+++ b/drivers/block/zram/backend_deflate.c
@@ -74,9 +74,7 @@ static void *deflate_create(struct zcomp_params *params)
return NULL;
}
-static int deflate_compress(void *ctx, const unsigned char *src,
- size_t src_len, unsigned char *dst,
- size_t *dst_len)
+static int deflate_compress(void *ctx, struct zcomp_req *req)
{
struct deflate_ctx *zctx = ctx;
struct z_stream_s *deflate;
@@ -87,22 +85,20 @@ static int deflate_compress(void *ctx, const unsigned char *src,
if (ret != Z_OK)
return -EINVAL;
- deflate->next_in = (u8 *)src;
- deflate->avail_in = src_len;
- deflate->next_out = (u8 *)dst;
- deflate->avail_out = *dst_len;
+ deflate->next_in = (u8 *)req->src;
+ deflate->avail_in = req->src_len;
+ deflate->next_out = (u8 *)req->dst;
+ deflate->avail_out = req->dst_len;
ret = zlib_deflate(deflate, Z_FINISH);
if (ret != Z_STREAM_END)
return -EINVAL;
- *dst_len = deflate->total_out;
+ req->dst_len = deflate->total_out;
return 0;
}
-static int deflate_decompress(void *ctx, const unsigned char *src,
- size_t src_len, unsigned char *dst,
- size_t dst_len)
+static int deflate_decompress(void *ctx, struct zcomp_req *req)
{
struct deflate_ctx *zctx = ctx;
struct z_stream_s *inflate;
@@ -114,10 +110,10 @@ static int deflate_decompress(void *ctx, const unsigned char *src,
if (ret != Z_OK)
return -EINVAL;
- inflate->next_in = (u8 *)src;
- inflate->avail_in = src_len;
- inflate->next_out = (u8 *)dst;
- inflate->avail_out = dst_len;
+ inflate->next_in = (u8 *)req->src;
+ inflate->avail_in = req->src_len;
+ inflate->next_out = (u8 *)req->dst;
+ inflate->avail_out = req->dst_len;
ret = zlib_inflate(inflate, Z_SYNC_FLUSH);
if (ret != Z_STREAM_END)
diff --git a/drivers/block/zram/backend_lz4.c b/drivers/block/zram/backend_lz4.c
index 90801a7a8f75..cb623f16604e 100644
--- a/drivers/block/zram/backend_lz4.c
+++ b/drivers/block/zram/backend_lz4.c
@@ -41,26 +41,25 @@ static void *lz4_create(struct zcomp_params *params)
return NULL;
}
-static int lz4_compress(void *ctx, const unsigned char *src, size_t src_len,
- unsigned char *dst, size_t *dst_len)
+static int lz4_compress(void *ctx, struct zcomp_req *req)
{
struct lz4_ctx *zctx = ctx;
int ret;
- ret = LZ4_compress_fast(src, dst, src_len, *dst_len,
- zctx->level, zctx->mem);
+ ret = LZ4_compress_fast(req->src, req->dst, req->src_len,
+ req->dst_len, zctx->level, zctx->mem);
if (!ret)
return -EINVAL;
- *dst_len = ret;
+ req->dst_len = ret;
return 0;
}
-static int lz4_decompress(void *ctx, const unsigned char *src,
- size_t src_len, unsigned char *dst, size_t dst_len)
+static int lz4_decompress(void *ctx, struct zcomp_req *req)
{
int ret;
- ret = LZ4_decompress_safe(src, dst, src_len, dst_len);
+ ret = LZ4_decompress_safe(req->src, req->dst, req->src_len,
+ req->dst_len);
if (ret < 0)
return -EINVAL;
return 0;
diff --git a/drivers/block/zram/backend_lz4hc.c b/drivers/block/zram/backend_lz4hc.c
index 30de6ec511a5..a2314e4c7e9a 100644
--- a/drivers/block/zram/backend_lz4hc.c
+++ b/drivers/block/zram/backend_lz4hc.c
@@ -41,26 +41,25 @@ static void *lz4hc_create(struct zcomp_params *params)
return NULL;
}
-static int lz4hc_compress(void *ctx, const unsigned char *src, size_t src_len,
- unsigned char *dst, size_t *dst_len)
+static int lz4hc_compress(void *ctx, struct zcomp_req *req)
{
struct lz4hc_ctx *zctx = ctx;
int ret;
- ret = LZ4_compress_HC(src, dst, src_len, *dst_len,
+ ret = LZ4_compress_HC(req->src, req->dst, req->src_len, req->dst_len,
zctx->level, zctx->mem);
if (!ret)
return -EINVAL;
- *dst_len = ret;
+ req->dst_len = ret;
return 0;
}
-static int lz4hc_decompress(void *ctx, const unsigned char *src,
- size_t src_len, unsigned char *dst, size_t dst_len)
+static int lz4hc_decompress(void *ctx, struct zcomp_req *req)
{
int ret;
- ret = LZ4_decompress_safe(src, dst, src_len, dst_len);
+ ret = LZ4_decompress_safe(req->src, req->dst, req->src_len,
+ req->dst_len);
if (ret < 0)
return -EINVAL;
return 0;
diff --git a/drivers/block/zram/backend_lzo.c b/drivers/block/zram/backend_lzo.c
index c903c15610f8..48d3f051c258 100644
--- a/drivers/block/zram/backend_lzo.c
+++ b/drivers/block/zram/backend_lzo.c
@@ -16,21 +16,21 @@ static void lzo_destroy(void *ctx)
kfree(ctx);
}
-static int lzo_compress(void *ctx, const unsigned char *src, size_t src_len,
- unsigned char *dst, size_t *dst_len)
+static int lzo_compress(void *ctx, struct zcomp_req *req)
{
int ret;
- ret = lzo1x_1_compress(src, src_len, dst, dst_len, ctx);
+ ret = lzo1x_1_compress(req->src, req->src_len, req->dst,
+ &req->dst_len, ctx);
return ret == LZO_E_OK ? 0 : ret;
}
-static int lzo_decompress(void *ctx, const unsigned char *src, size_t src_len,
- unsigned char *dst, size_t dst_len)
+static int lzo_decompress(void *ctx, struct zcomp_req *req)
{
int ret;
- ret = lzo1x_decompress_safe(src, src_len, dst, &dst_len);
+ ret = lzo1x_decompress_safe(req->src, req->src_len,
+ req->dst, &req->dst_len);
return ret == LZO_E_OK ? 0 : ret;
}
diff --git a/drivers/block/zram/backend_lzorle.c b/drivers/block/zram/backend_lzorle.c
index 3622625abfd9..4638431326c2 100644
--- a/drivers/block/zram/backend_lzorle.c
+++ b/drivers/block/zram/backend_lzorle.c
@@ -16,22 +16,21 @@ static void lzorle_destroy(void *ctx)
kfree(ctx);
}
-static int lzorle_compress(void *ctx, const unsigned char *src, size_t src_len,
- unsigned char *dst, size_t *dst_len)
+static int lzorle_compress(void *ctx, struct zcomp_req *req)
{
int ret;
- ret = lzorle1x_1_compress(src, src_len, dst, dst_len, ctx);
+ ret = lzorle1x_1_compress(req->src, req->src_len, req->dst,
+ &req->dst_len, ctx);
return ret == LZO_E_OK ? 0 : ret;
}
-static int lzorle_decompress(void *ctx, const unsigned char *src,
- size_t src_len, unsigned char *dst,
- size_t dst_len)
+static int lzorle_decompress(void *ctx, struct zcomp_req *req)
{
int ret;
- ret = lzo1x_decompress_safe(src, src_len, dst, &dst_len);
+ ret = lzo1x_decompress_safe(req->src, req->src_len,
+ req->dst, &req->dst_len);
return ret == LZO_E_OK ? 0 : ret;
}
diff --git a/drivers/block/zram/backend_zstd.c b/drivers/block/zram/backend_zstd.c
index a9808abcf5f2..7e7e4af620fc 100644
--- a/drivers/block/zram/backend_zstd.c
+++ b/drivers/block/zram/backend_zstd.c
@@ -67,27 +67,26 @@ static void *zstd_create(struct zcomp_params *params)
return NULL;
}
-static int zstd_compress(void *ctx, const unsigned char *src, size_t src_len,
- unsigned char *dst, size_t *dst_len)
+static int zstd_compress(void *ctx, struct zcomp_req *req)
{
struct zstd_ctx *zctx = ctx;
size_t ret;
- ret = zstd_compress_cctx(zctx->cctx, dst, *dst_len,
- src, src_len, &zctx->cprm);
+ ret = zstd_compress_cctx(zctx->cctx, req->dst, req->dst_len,
+ req->src, req->src_len, &zctx->cprm);
if (zstd_is_error(ret))
return -EINVAL;
- *dst_len = ret;
+ req->dst_len = ret;
return 0;
}
-static int zstd_decompress(void *ctx, const unsigned char *src, size_t src_len,
- unsigned char *dst, size_t dst_len)
+static int zstd_decompress(void *ctx, struct zcomp_req *req)
{
struct zstd_ctx *zctx = ctx;
size_t ret;
- ret = zstd_decompress_dctx(zctx->dctx, dst, dst_len, src, src_len);
+ ret = zstd_decompress_dctx(zctx->dctx, req->dst, req->dst_len,
+ req->src, req->src_len);
if (zstd_is_error(ret))
return -EINVAL;
return 0;
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
index eacead28cc2b..defb04a25d52 100644
--- a/drivers/block/zram/zcomp.c
+++ b/drivers/block/zram/zcomp.c
@@ -118,22 +118,31 @@ void zcomp_stream_put(struct zcomp *comp)
int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm,
const void *src, unsigned int *dst_len)
{
- /* The dst buffer should always be 2 * PAGE_SIZE */
- size_t dlen = 2 * PAGE_SIZE;
+ struct zcomp_req req = {
+ .src = src,
+ .dst = zstrm->buffer,
+ .src_len = PAGE_SIZE,
+ .dst_len = 2 * PAGE_SIZE,
+ };
int ret;
- ret = comp->ops->compress(zstrm->ctx, src, PAGE_SIZE,
- zstrm->buffer, &dlen);
+ ret = comp->ops->compress(zstrm->ctx, &req);
if (!ret)
- *dst_len = dlen;
+ *dst_len = req.dst_len;
return ret;
}
int zcomp_decompress(struct zcomp *comp, struct zcomp_strm *zstrm,
const void *src, unsigned int src_len, void *dst)
{
- return comp->ops->decompress(zstrm->ctx, src, src_len,
- dst, PAGE_SIZE);
+ struct zcomp_req req = {
+ .src = src,
+ .dst = dst,
+ .src_len = src_len,
+ .dst_len = PAGE_SIZE,
+ };
+
+ return comp->ops->decompress(zstrm->ctx, &req);
}
int zcomp_cpu_up_prepare(unsigned int cpu, struct hlist_node *node)
diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h
index 3639c36fb9a9..963c1e80830c 100644
--- a/drivers/block/zram/zcomp.h
+++ b/drivers/block/zram/zcomp.h
@@ -21,12 +21,17 @@ struct zcomp_strm {
void *ctx;
};
-struct zcomp_ops {
- int (*compress)(void *ctx, const unsigned char *src, size_t src_len,
- unsigned char *dst, size_t *dst_len);
+struct zcomp_req {
+ const unsigned char *src;
+ const size_t src_len;
+
+ unsigned char *dst;
+ size_t dst_len;
+};
- int (*decompress)(void *ctx, const unsigned char *src, size_t src_len,
- unsigned char *dst, size_t dst_len);
+struct zcomp_ops {
+ int (*compress)(void *ctx, struct zcomp_req *req);
+ int (*decompress)(void *ctx, struct zcomp_req *req);
void *(*create_ctx)(struct zcomp_params *params);
void (*destroy_ctx)(void *ctx);
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCHv5 18/23] zram: introduce zcomp_ctx structure
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (16 preceding siblings ...)
2024-07-06 4:56 ` [PATCHv5 17/23] zram: introduce zcomp_req structure Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 19/23] zram: move immutable comp params away from per-CPU context Sergey Senozhatsky
` (6 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky
Keep run-time driver data (scratch buffers, etc.) in
zcomp_ctx structure. This structure is allocated per-CPU
because drivers (backends) need to modify its content
during requests execution.
We will split mutable and immutable driver data, this is
a preparation path.
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
drivers/block/zram/backend_842.c | 39 ++++++--------------
drivers/block/zram/backend_deflate.c | 46 +++++++++++++-----------
drivers/block/zram/backend_lz4.c | 36 ++++++++++---------
drivers/block/zram/backend_lz4hc.c | 36 ++++++++++---------
drivers/block/zram/backend_lzo.c | 17 +++++----
drivers/block/zram/backend_lzorle.c | 17 +++++----
drivers/block/zram/backend_zstd.c | 54 +++++++++++++++-------------
drivers/block/zram/zcomp.c | 16 +++++----
drivers/block/zram/zcomp.h | 23 ++++++++----
9 files changed, 149 insertions(+), 135 deletions(-)
diff --git a/drivers/block/zram/backend_842.c b/drivers/block/zram/backend_842.c
index 1df0de5a9863..8364837d300d 100644
--- a/drivers/block/zram/backend_842.c
+++ b/drivers/block/zram/backend_842.c
@@ -7,51 +7,32 @@
#include "backend_842.h"
-struct sw842_ctx {
- void *mem;
-};
-
-static void destroy_842(void *ctx)
+static void destroy_842(struct zcomp_ctx *ctx)
{
- struct sw842_ctx *zctx = ctx;
-
- kfree(zctx->mem);
- kfree(zctx);
+ kfree(ctx->context);
}
-static void *create_842(struct zcomp_params *params)
+static int create_842(struct zcomp_params *params, struct zcomp_ctx *ctx)
{
- struct sw842_ctx *ctx;
-
- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
- if (!ctx)
- return NULL;
-
- ctx->mem = kmalloc(SW842_MEM_COMPRESS, GFP_KERNEL);
- if (!ctx->mem)
- goto error;
-
- return ctx;
-
-error:
- destroy_842(ctx);
- return NULL;
+ ctx->context = kmalloc(SW842_MEM_COMPRESS, GFP_KERNEL);
+ if (!ctx->context)
+ return -ENOMEM;
+ return 0;
}
-static int compress_842(void *ctx, struct zcomp_req *req)
+static int compress_842(struct zcomp_ctx *ctx, struct zcomp_req *req)
{
- struct sw842_ctx *zctx = ctx;
unsigned int dlen = req->dst_len;
int ret;
ret = sw842_compress(req->src, req->src_len, req->dst, &dlen,
- zctx->mem);
+ ctx->context);
if (ret == 0)
req->dst_len = dlen;
return ret;
}
-static int decompress_842(void *ctx, struct zcomp_req *req)
+static int decompress_842(struct zcomp_ctx *ctx, struct zcomp_req *req)
{
unsigned int dlen = req->dst_len;
diff --git a/drivers/block/zram/backend_deflate.c b/drivers/block/zram/backend_deflate.c
index 19bb61369eb0..63a29c26d64c 100644
--- a/drivers/block/zram/backend_deflate.c
+++ b/drivers/block/zram/backend_deflate.c
@@ -17,9 +17,12 @@ struct deflate_ctx {
s32 level;
};
-static void deflate_destroy(void *ctx)
+static void deflate_destroy(struct zcomp_ctx *ctx)
{
- struct deflate_ctx *zctx = ctx;
+ struct deflate_ctx *zctx = ctx->context;
+
+ if (!zctx)
+ return;
if (zctx->cctx.workspace) {
zlib_deflateEnd(&zctx->cctx);
@@ -32,51 +35,52 @@ static void deflate_destroy(void *ctx)
kfree(zctx);
}
-static void *deflate_create(struct zcomp_params *params)
+static int deflate_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
{
- struct deflate_ctx *ctx;
+ struct deflate_ctx *zctx;
size_t sz;
int ret;
- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
- if (!ctx)
- return NULL;
+ zctx = kzalloc(sizeof(*zctx), GFP_KERNEL);
+ if (!zctx)
+ return -ENOMEM;
+ ctx->context = zctx;
if (params->level != ZCOMP_PARAM_NO_LEVEL)
- ctx->level = params->level;
+ zctx->level = params->level;
else
- ctx->level = Z_DEFAULT_COMPRESSION;
+ zctx->level = Z_DEFAULT_COMPRESSION;
sz = zlib_deflate_workspacesize(-DEFLATE_DEF_WINBITS, MAX_MEM_LEVEL);
- ctx->cctx.workspace = vzalloc(sz);
- if (!ctx->cctx.workspace)
+ zctx->cctx.workspace = vzalloc(sz);
+ if (!zctx->cctx.workspace)
goto error;
- ret = zlib_deflateInit2(&ctx->cctx, ctx->level, Z_DEFLATED,
+ ret = zlib_deflateInit2(&zctx->cctx, zctx->level, Z_DEFLATED,
-DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
Z_DEFAULT_STRATEGY);
if (ret != Z_OK)
goto error;
sz = zlib_inflate_workspacesize();
- ctx->dctx.workspace = vzalloc(sz);
- if (!ctx->dctx.workspace)
+ zctx->dctx.workspace = vzalloc(sz);
+ if (!zctx->dctx.workspace)
goto error;
- ret = zlib_inflateInit2(&ctx->dctx, -DEFLATE_DEF_WINBITS);
+ ret = zlib_inflateInit2(&zctx->dctx, -DEFLATE_DEF_WINBITS);
if (ret != Z_OK)
goto error;
- return ctx;
+ return 0;
error:
deflate_destroy(ctx);
- return NULL;
+ return -EINVAL;
}
-static int deflate_compress(void *ctx, struct zcomp_req *req)
+static int deflate_compress(struct zcomp_ctx *ctx, struct zcomp_req *req)
{
- struct deflate_ctx *zctx = ctx;
+ struct deflate_ctx *zctx = ctx->context;
struct z_stream_s *deflate;
int ret;
@@ -98,9 +102,9 @@ static int deflate_compress(void *ctx, struct zcomp_req *req)
return 0;
}
-static int deflate_decompress(void *ctx, struct zcomp_req *req)
+static int deflate_decompress(struct zcomp_ctx *ctx, struct zcomp_req *req)
{
- struct deflate_ctx *zctx = ctx;
+ struct deflate_ctx *zctx = ctx->context;
struct z_stream_s *inflate;
int ret;
diff --git a/drivers/block/zram/backend_lz4.c b/drivers/block/zram/backend_lz4.c
index cb623f16604e..1ff6b1a6b5ae 100644
--- a/drivers/block/zram/backend_lz4.c
+++ b/drivers/block/zram/backend_lz4.c
@@ -10,40 +10,44 @@ struct lz4_ctx {
s32 level;
};
-static void lz4_destroy(void *ctx)
+static void lz4_destroy(struct zcomp_ctx *ctx)
{
- struct lz4_ctx *zctx = ctx;
+ struct lz4_ctx *zctx = ctx->context;
+
+ if (!zctx)
+ return;
vfree(zctx->mem);
kfree(zctx);
}
-static void *lz4_create(struct zcomp_params *params)
+static int lz4_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
{
- struct lz4_ctx *ctx;
+ struct lz4_ctx *zctx;
- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
- if (!ctx)
- return NULL;
+ zctx = kzalloc(sizeof(*zctx), GFP_KERNEL);
+ if (!zctx)
+ return -ENOMEM;
+ ctx->context = zctx;
if (params->level != ZCOMP_PARAM_NO_LEVEL)
- ctx->level = params->level;
+ zctx->level = params->level;
else
- ctx->level = LZ4_ACCELERATION_DEFAULT;
+ zctx->level = LZ4_ACCELERATION_DEFAULT;
- ctx->mem = vmalloc(LZ4_MEM_COMPRESS);
- if (!ctx->mem)
+ zctx->mem = vmalloc(LZ4_MEM_COMPRESS);
+ if (!zctx->mem)
goto error;
- return ctx;
+ return 0;
error:
lz4_destroy(ctx);
- return NULL;
+ return -EINVAL;
}
-static int lz4_compress(void *ctx, struct zcomp_req *req)
+static int lz4_compress(struct zcomp_ctx *ctx, struct zcomp_req *req)
{
- struct lz4_ctx *zctx = ctx;
+ struct lz4_ctx *zctx = ctx->context;
int ret;
ret = LZ4_compress_fast(req->src, req->dst, req->src_len,
@@ -54,7 +58,7 @@ static int lz4_compress(void *ctx, struct zcomp_req *req)
return 0;
}
-static int lz4_decompress(void *ctx, struct zcomp_req *req)
+static int lz4_decompress(struct zcomp_ctx *ctx, struct zcomp_req *req)
{
int ret;
diff --git a/drivers/block/zram/backend_lz4hc.c b/drivers/block/zram/backend_lz4hc.c
index a2314e4c7e9a..0daab12836de 100644
--- a/drivers/block/zram/backend_lz4hc.c
+++ b/drivers/block/zram/backend_lz4hc.c
@@ -10,40 +10,44 @@ struct lz4hc_ctx {
s32 level;
};
-static void lz4hc_destroy(void *ctx)
+static void lz4hc_destroy(struct zcomp_ctx *ctx)
{
- struct lz4hc_ctx *zctx = ctx;
+ struct lz4hc_ctx *zctx = ctx->context;
+
+ if (!zctx)
+ return;
vfree(zctx->mem);
kfree(zctx);
}
-static void *lz4hc_create(struct zcomp_params *params)
+static int lz4hc_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
{
- struct lz4hc_ctx *ctx;
+ struct lz4hc_ctx *zctx;
- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
- if (!ctx)
- return NULL;
+ zctx = kzalloc(sizeof(*zctx), GFP_KERNEL);
+ if (!zctx)
+ return -ENOMEM;
+ ctx->context = zctx;
if (params->level != ZCOMP_PARAM_NO_LEVEL)
- ctx->level = params->level;
+ zctx->level = params->level;
else
- ctx->level = LZ4HC_DEFAULT_CLEVEL;
+ zctx->level = LZ4HC_DEFAULT_CLEVEL;
- ctx->mem = vmalloc(LZ4HC_MEM_COMPRESS);
- if (!ctx->mem)
+ zctx->mem = vmalloc(LZ4HC_MEM_COMPRESS);
+ if (!zctx->mem)
goto error;
- return ctx;
+ return 0;
error:
lz4hc_destroy(ctx);
- return NULL;
+ return -EINVAL;
}
-static int lz4hc_compress(void *ctx, struct zcomp_req *req)
+static int lz4hc_compress(struct zcomp_ctx *ctx, struct zcomp_req *req)
{
- struct lz4hc_ctx *zctx = ctx;
+ struct lz4hc_ctx *zctx = ctx->context;
int ret;
ret = LZ4_compress_HC(req->src, req->dst, req->src_len, req->dst_len,
@@ -54,7 +58,7 @@ static int lz4hc_compress(void *ctx, struct zcomp_req *req)
return 0;
}
-static int lz4hc_decompress(void *ctx, struct zcomp_req *req)
+static int lz4hc_decompress(struct zcomp_ctx *ctx, struct zcomp_req *req)
{
int ret;
diff --git a/drivers/block/zram/backend_lzo.c b/drivers/block/zram/backend_lzo.c
index 48d3f051c258..699e8ef147a8 100644
--- a/drivers/block/zram/backend_lzo.c
+++ b/drivers/block/zram/backend_lzo.c
@@ -6,26 +6,29 @@
#include "backend_lzo.h"
-static void *lzo_create(struct zcomp_params *params)
+static int lzo_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
{
- return kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
+ ctx->context = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
+ if (!ctx->context)
+ return -ENOMEM;
+ return 0;
}
-static void lzo_destroy(void *ctx)
+static void lzo_destroy(struct zcomp_ctx *ctx)
{
- kfree(ctx);
+ kfree(ctx->context);
}
-static int lzo_compress(void *ctx, struct zcomp_req *req)
+static int lzo_compress(struct zcomp_ctx *ctx, struct zcomp_req *req)
{
int ret;
ret = lzo1x_1_compress(req->src, req->src_len, req->dst,
- &req->dst_len, ctx);
+ &req->dst_len, ctx->context);
return ret == LZO_E_OK ? 0 : ret;
}
-static int lzo_decompress(void *ctx, struct zcomp_req *req)
+static int lzo_decompress(struct zcomp_ctx *ctx, struct zcomp_req *req)
{
int ret;
diff --git a/drivers/block/zram/backend_lzorle.c b/drivers/block/zram/backend_lzorle.c
index 4638431326c2..48e4d4dc8437 100644
--- a/drivers/block/zram/backend_lzorle.c
+++ b/drivers/block/zram/backend_lzorle.c
@@ -6,26 +6,29 @@
#include "backend_lzorle.h"
-static void *lzorle_create(struct zcomp_params *params)
+static int lzorle_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
{
- return kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
+ ctx->context = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
+ if (!ctx->context)
+ return -ENOMEM;
+ return 0;
}
-static void lzorle_destroy(void *ctx)
+static void lzorle_destroy(struct zcomp_ctx *ctx)
{
- kfree(ctx);
+ kfree(ctx->context);
}
-static int lzorle_compress(void *ctx, struct zcomp_req *req)
+static int lzorle_compress(struct zcomp_ctx *ctx, struct zcomp_req *req)
{
int ret;
ret = lzorle1x_1_compress(req->src, req->src_len, req->dst,
- &req->dst_len, ctx);
+ &req->dst_len, ctx->context);
return ret == LZO_E_OK ? 0 : ret;
}
-static int lzorle_decompress(void *ctx, struct zcomp_req *req)
+static int lzorle_decompress(struct zcomp_ctx *ctx, struct zcomp_req *req)
{
int ret;
diff --git a/drivers/block/zram/backend_zstd.c b/drivers/block/zram/backend_zstd.c
index 7e7e4af620fc..1cc3a4a1f265 100644
--- a/drivers/block/zram/backend_zstd.c
+++ b/drivers/block/zram/backend_zstd.c
@@ -16,60 +16,64 @@ struct zstd_ctx {
s32 level;
};
-static void zstd_destroy(void *ctx)
+static void zstd_destroy(struct zcomp_ctx *ctx)
{
- struct zstd_ctx *zctx = ctx;
+ struct zstd_ctx *zctx = ctx->context;
+
+ if (!zctx)
+ return;
vfree(zctx->cctx_mem);
vfree(zctx->dctx_mem);
kfree(zctx);
}
-static void *zstd_create(struct zcomp_params *params)
+static int zstd_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
{
+ struct zstd_ctx *zctx;
zstd_parameters prm;
- struct zstd_ctx *ctx;
size_t sz;
- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
- if (!ctx)
- return NULL;
+ zctx = kzalloc(sizeof(*zctx), GFP_KERNEL);
+ if (!zctx)
+ return -ENOMEM;
+ ctx->context = zctx;
if (params->level != ZCOMP_PARAM_NO_LEVEL)
- ctx->level = params->level;
+ zctx->level = params->level;
else
- ctx->level = zstd_default_clevel();
+ zctx->level = zstd_default_clevel();
- prm = zstd_get_params(ctx->level, PAGE_SIZE);
- ctx->cprm = zstd_get_params(ctx->level, PAGE_SIZE);
+ prm = zstd_get_params(zctx->level, PAGE_SIZE);
+ zctx->cprm = zstd_get_params(zctx->level, PAGE_SIZE);
sz = zstd_cctx_workspace_bound(&prm.cParams);
- ctx->cctx_mem = vzalloc(sz);
- if (!ctx->cctx_mem)
+ zctx->cctx_mem = vzalloc(sz);
+ if (!zctx->cctx_mem)
goto error;
- ctx->cctx = zstd_init_cctx(ctx->cctx_mem, sz);
- if (!ctx->cctx)
+ zctx->cctx = zstd_init_cctx(zctx->cctx_mem, sz);
+ if (!zctx->cctx)
goto error;
sz = zstd_dctx_workspace_bound();
- ctx->dctx_mem = vzalloc(sz);
- if (!ctx->dctx_mem)
+ zctx->dctx_mem = vzalloc(sz);
+ if (!zctx->dctx_mem)
goto error;
- ctx->dctx = zstd_init_dctx(ctx->dctx_mem, sz);
- if (!ctx->dctx)
+ zctx->dctx = zstd_init_dctx(zctx->dctx_mem, sz);
+ if (!zctx->dctx)
goto error;
- return ctx;
+ return 0;
error:
zstd_destroy(ctx);
- return NULL;
+ return -EINVAL;
}
-static int zstd_compress(void *ctx, struct zcomp_req *req)
+static int zstd_compress(struct zcomp_ctx *ctx, struct zcomp_req *req)
{
- struct zstd_ctx *zctx = ctx;
+ struct zstd_ctx *zctx = ctx->context;
size_t ret;
ret = zstd_compress_cctx(zctx->cctx, req->dst, req->dst_len,
@@ -80,9 +84,9 @@ static int zstd_compress(void *ctx, struct zcomp_req *req)
return 0;
}
-static int zstd_decompress(void *ctx, struct zcomp_req *req)
+static int zstd_decompress(struct zcomp_ctx *ctx, struct zcomp_req *req)
{
- struct zstd_ctx *zctx = ctx;
+ struct zstd_ctx *zctx = ctx->context;
size_t ret;
ret = zstd_decompress_dctx(zctx->dctx, req->dst, req->dst_len,
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
index defb04a25d52..1964e6195b4b 100644
--- a/drivers/block/zram/zcomp.c
+++ b/drivers/block/zram/zcomp.c
@@ -45,23 +45,25 @@ static struct zcomp_ops *backends[] = {
static void zcomp_strm_free(struct zcomp *comp, struct zcomp_strm *zstrm)
{
- if (zstrm->ctx)
- comp->ops->destroy_ctx(zstrm->ctx);
+ comp->ops->destroy_ctx(&zstrm->ctx);
vfree(zstrm->buffer);
- zstrm->ctx = NULL;
zstrm->buffer = NULL;
}
static int zcomp_strm_init(struct zcomp *comp, struct zcomp_strm *zstrm)
{
- zstrm->ctx = comp->ops->create_ctx(comp->params);
+ int ret;
+
+ ret = comp->ops->create_ctx(comp->params, &zstrm->ctx);
+ if (ret)
+ return ret;
/*
* allocate 2 pages. 1 for compressed data, plus 1 extra for the
* case when compressed size is larger than the original one
*/
zstrm->buffer = vzalloc(2 * PAGE_SIZE);
- if (!zstrm->ctx || !zstrm->buffer) {
+ if (!zstrm->buffer) {
zcomp_strm_free(comp, zstrm);
return -ENOMEM;
}
@@ -126,7 +128,7 @@ int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm,
};
int ret;
- ret = comp->ops->compress(zstrm->ctx, &req);
+ ret = comp->ops->compress(&zstrm->ctx, &req);
if (!ret)
*dst_len = req.dst_len;
return ret;
@@ -142,7 +144,7 @@ int zcomp_decompress(struct zcomp *comp, struct zcomp_strm *zstrm,
.dst_len = PAGE_SIZE,
};
- return comp->ops->decompress(zstrm->ctx, &req);
+ return comp->ops->decompress(&zstrm->ctx, &req);
}
int zcomp_cpu_up_prepare(unsigned int cpu, struct hlist_node *node)
diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h
index 963c1e80830c..ebab7dbca68d 100644
--- a/drivers/block/zram/zcomp.h
+++ b/drivers/block/zram/zcomp.h
@@ -13,12 +13,20 @@ struct zcomp_params {
s32 level;
};
+/*
+ * Run-time driver context - scratch buffers, etc. It is modified during
+ * request execution (compression/decompression), cannot be shared, so
+ * it's in per-CPU area.
+ */
+struct zcomp_ctx {
+ void *context;
+};
+
struct zcomp_strm {
- /* The members ->buffer and ->tfm are protected by ->lock. */
local_lock_t lock;
- /* compression/decompression buffer */
+ /* compression buffer */
void *buffer;
- void *ctx;
+ struct zcomp_ctx ctx;
};
struct zcomp_req {
@@ -30,11 +38,12 @@ struct zcomp_req {
};
struct zcomp_ops {
- int (*compress)(void *ctx, struct zcomp_req *req);
- int (*decompress)(void *ctx, struct zcomp_req *req);
+ int (*compress)(struct zcomp_ctx *ctx, struct zcomp_req *req);
+ int (*decompress)(struct zcomp_ctx *ctx, struct zcomp_req *req);
- void *(*create_ctx)(struct zcomp_params *params);
- void (*destroy_ctx)(void *ctx);
+ int (*create_ctx)(struct zcomp_params *params,
+ struct zcomp_ctx *ctx);
+ void (*destroy_ctx)(struct zcomp_ctx *ctx);
const char *name;
};
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCHv5 19/23] zram: move immutable comp params away from per-CPU context
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (17 preceding siblings ...)
2024-07-06 4:56 ` [PATCHv5 18/23] zram: introduce zcomp_ctx structure Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 20/23] zram: add dictionary support to lz4 Sergey Senozhatsky
` (5 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky
Immutable params never change once comp has been allocated
and setup, so we don't need to store multiple copies of
them in each per-CPU backend context. Move those to
per-comp zcomp_params and pass it to backends callbacks
for requests execution. Basically, this means parameters
sharing between different contexts.
Also introduce two new backends callbacks: setup_params()
and release_params(). First, we need to validate params
in a driver-specific way; second, driver may want to
allocate its specific representation of the params which
is needed to execute requests.
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
drivers/block/zram/backend_842.c | 17 ++++++++--
drivers/block/zram/backend_deflate.c | 29 +++++++++++-----
drivers/block/zram/backend_lz4.c | 51 +++++++++++-----------------
drivers/block/zram/backend_lz4hc.c | 51 +++++++++++-----------------
drivers/block/zram/backend_lzo.c | 17 ++++++++--
drivers/block/zram/backend_lzorle.c | 17 ++++++++--
drivers/block/zram/backend_zstd.c | 47 ++++++++++++++++++-------
drivers/block/zram/zcomp.c | 17 +++++++---
drivers/block/zram/zcomp.h | 20 ++++++++---
9 files changed, 168 insertions(+), 98 deletions(-)
diff --git a/drivers/block/zram/backend_842.c b/drivers/block/zram/backend_842.c
index 8364837d300d..8722cdfff411 100644
--- a/drivers/block/zram/backend_842.c
+++ b/drivers/block/zram/backend_842.c
@@ -7,6 +7,15 @@
#include "backend_842.h"
+static void release_params_842(struct zcomp_params *params)
+{
+}
+
+static int setup_params_842(struct zcomp_params *params)
+{
+ return 0;
+}
+
static void destroy_842(struct zcomp_ctx *ctx)
{
kfree(ctx->context);
@@ -20,7 +29,8 @@ static int create_842(struct zcomp_params *params, struct zcomp_ctx *ctx)
return 0;
}
-static int compress_842(struct zcomp_ctx *ctx, struct zcomp_req *req)
+static int compress_842(struct zcomp_params *params, struct zcomp_ctx *ctx,
+ struct zcomp_req *req)
{
unsigned int dlen = req->dst_len;
int ret;
@@ -32,7 +42,8 @@ static int compress_842(struct zcomp_ctx *ctx, struct zcomp_req *req)
return ret;
}
-static int decompress_842(struct zcomp_ctx *ctx, struct zcomp_req *req)
+static int decompress_842(struct zcomp_params *params, struct zcomp_ctx *ctx,
+ struct zcomp_req *req)
{
unsigned int dlen = req->dst_len;
@@ -44,5 +55,7 @@ struct zcomp_ops backend_842 = {
.decompress = decompress_842,
.create_ctx = create_842,
.destroy_ctx = destroy_842,
+ .setup_params = setup_params_842,
+ .release_params = release_params_842,
.name = "842",
};
diff --git a/drivers/block/zram/backend_deflate.c b/drivers/block/zram/backend_deflate.c
index 63a29c26d64c..7882b6fe0d7c 100644
--- a/drivers/block/zram/backend_deflate.c
+++ b/drivers/block/zram/backend_deflate.c
@@ -14,9 +14,20 @@
struct deflate_ctx {
struct z_stream_s cctx;
struct z_stream_s dctx;
- s32 level;
};
+static void deflate_release_params(struct zcomp_params *params)
+{
+}
+
+static int deflate_setup_params(struct zcomp_params *params)
+{
+ if (params->level == ZCOMP_PARAM_NO_LEVEL)
+ params->level = Z_DEFAULT_COMPRESSION;
+
+ return 0;
+}
+
static void deflate_destroy(struct zcomp_ctx *ctx)
{
struct deflate_ctx *zctx = ctx->context;
@@ -46,17 +57,12 @@ static int deflate_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
return -ENOMEM;
ctx->context = zctx;
- if (params->level != ZCOMP_PARAM_NO_LEVEL)
- zctx->level = params->level;
- else
- zctx->level = Z_DEFAULT_COMPRESSION;
-
sz = zlib_deflate_workspacesize(-DEFLATE_DEF_WINBITS, MAX_MEM_LEVEL);
zctx->cctx.workspace = vzalloc(sz);
if (!zctx->cctx.workspace)
goto error;
- ret = zlib_deflateInit2(&zctx->cctx, zctx->level, Z_DEFLATED,
+ ret = zlib_deflateInit2(&zctx->cctx, params->level, Z_DEFLATED,
-DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
Z_DEFAULT_STRATEGY);
if (ret != Z_OK)
@@ -78,7 +84,8 @@ static int deflate_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
return -EINVAL;
}
-static int deflate_compress(struct zcomp_ctx *ctx, struct zcomp_req *req)
+static int deflate_compress(struct zcomp_params *params, struct zcomp_ctx *ctx,
+ struct zcomp_req *req)
{
struct deflate_ctx *zctx = ctx->context;
struct z_stream_s *deflate;
@@ -102,7 +109,9 @@ static int deflate_compress(struct zcomp_ctx *ctx, struct zcomp_req *req)
return 0;
}
-static int deflate_decompress(struct zcomp_ctx *ctx, struct zcomp_req *req)
+static int deflate_decompress(struct zcomp_params *params,
+ struct zcomp_ctx *ctx,
+ struct zcomp_req *req)
{
struct deflate_ctx *zctx = ctx->context;
struct z_stream_s *inflate;
@@ -131,5 +140,7 @@ struct zcomp_ops backend_deflate = {
.decompress = deflate_decompress,
.create_ctx = deflate_create,
.destroy_ctx = deflate_destroy,
+ .setup_params = deflate_setup_params,
+ .release_params = deflate_release_params,
.name = "deflate",
};
diff --git a/drivers/block/zram/backend_lz4.c b/drivers/block/zram/backend_lz4.c
index 1ff6b1a6b5ae..cdcf6e3c1826 100644
--- a/drivers/block/zram/backend_lz4.c
+++ b/drivers/block/zram/backend_lz4.c
@@ -5,60 +5,47 @@
#include "backend_lz4.h"
-struct lz4_ctx {
- void *mem;
- s32 level;
-};
+static void lz4_release_params(struct zcomp_params *params)
+{
+}
-static void lz4_destroy(struct zcomp_ctx *ctx)
+static int lz4_setup_params(struct zcomp_params *params)
{
- struct lz4_ctx *zctx = ctx->context;
+ if (params->level == ZCOMP_PARAM_NO_LEVEL)
+ params->level = LZ4_ACCELERATION_DEFAULT;
- if (!zctx)
- return;
+ return 0;
+}
- vfree(zctx->mem);
- kfree(zctx);
+static void lz4_destroy(struct zcomp_ctx *ctx)
+{
+ vfree(ctx->context);
}
static int lz4_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
{
- struct lz4_ctx *zctx;
-
- zctx = kzalloc(sizeof(*zctx), GFP_KERNEL);
- if (!zctx)
+ ctx->context = vmalloc(LZ4_MEM_COMPRESS);
+ if (!ctx->context)
return -ENOMEM;
- ctx->context = zctx;
- if (params->level != ZCOMP_PARAM_NO_LEVEL)
- zctx->level = params->level;
- else
- zctx->level = LZ4_ACCELERATION_DEFAULT;
-
- zctx->mem = vmalloc(LZ4_MEM_COMPRESS);
- if (!zctx->mem)
- goto error;
-
return 0;
-error:
- lz4_destroy(ctx);
- return -EINVAL;
}
-static int lz4_compress(struct zcomp_ctx *ctx, struct zcomp_req *req)
+static int lz4_compress(struct zcomp_params *params, struct zcomp_ctx *ctx,
+ struct zcomp_req *req)
{
- struct lz4_ctx *zctx = ctx->context;
int ret;
ret = LZ4_compress_fast(req->src, req->dst, req->src_len,
- req->dst_len, zctx->level, zctx->mem);
+ req->dst_len, params->level, ctx->context);
if (!ret)
return -EINVAL;
req->dst_len = ret;
return 0;
}
-static int lz4_decompress(struct zcomp_ctx *ctx, struct zcomp_req *req)
+static int lz4_decompress(struct zcomp_params *params, struct zcomp_ctx *ctx,
+ struct zcomp_req *req)
{
int ret;
@@ -74,5 +61,7 @@ struct zcomp_ops backend_lz4 = {
.decompress = lz4_decompress,
.create_ctx = lz4_create,
.destroy_ctx = lz4_destroy,
+ .setup_params = lz4_setup_params,
+ .release_params = lz4_release_params,
.name = "lz4",
};
diff --git a/drivers/block/zram/backend_lz4hc.c b/drivers/block/zram/backend_lz4hc.c
index 0daab12836de..e7dc0e03f13c 100644
--- a/drivers/block/zram/backend_lz4hc.c
+++ b/drivers/block/zram/backend_lz4hc.c
@@ -5,60 +5,47 @@
#include "backend_lz4hc.h"
-struct lz4hc_ctx {
- void *mem;
- s32 level;
-};
+static void lz4hc_release_params(struct zcomp_params *params)
+{
+}
-static void lz4hc_destroy(struct zcomp_ctx *ctx)
+static int lz4hc_setup_params(struct zcomp_params *params)
{
- struct lz4hc_ctx *zctx = ctx->context;
+ if (params->level == ZCOMP_PARAM_NO_LEVEL)
+ params->level = LZ4HC_DEFAULT_CLEVEL;
- if (!zctx)
- return;
+ return 0;
+}
- vfree(zctx->mem);
- kfree(zctx);
+static void lz4hc_destroy(struct zcomp_ctx *ctx)
+{
+ vfree(ctx->context);
}
static int lz4hc_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
{
- struct lz4hc_ctx *zctx;
-
- zctx = kzalloc(sizeof(*zctx), GFP_KERNEL);
- if (!zctx)
+ ctx->context = vmalloc(LZ4HC_MEM_COMPRESS);
+ if (!ctx->context)
return -ENOMEM;
- ctx->context = zctx;
- if (params->level != ZCOMP_PARAM_NO_LEVEL)
- zctx->level = params->level;
- else
- zctx->level = LZ4HC_DEFAULT_CLEVEL;
-
- zctx->mem = vmalloc(LZ4HC_MEM_COMPRESS);
- if (!zctx->mem)
- goto error;
-
return 0;
-error:
- lz4hc_destroy(ctx);
- return -EINVAL;
}
-static int lz4hc_compress(struct zcomp_ctx *ctx, struct zcomp_req *req)
+static int lz4hc_compress(struct zcomp_params *params, struct zcomp_ctx *ctx,
+ struct zcomp_req *req)
{
- struct lz4hc_ctx *zctx = ctx->context;
int ret;
ret = LZ4_compress_HC(req->src, req->dst, req->src_len, req->dst_len,
- zctx->level, zctx->mem);
+ params->level, ctx->context);
if (!ret)
return -EINVAL;
req->dst_len = ret;
return 0;
}
-static int lz4hc_decompress(struct zcomp_ctx *ctx, struct zcomp_req *req)
+static int lz4hc_decompress(struct zcomp_params *params, struct zcomp_ctx *ctx,
+ struct zcomp_req *req)
{
int ret;
@@ -74,5 +61,7 @@ struct zcomp_ops backend_lz4hc = {
.decompress = lz4hc_decompress,
.create_ctx = lz4hc_create,
.destroy_ctx = lz4hc_destroy,
+ .setup_params = lz4hc_setup_params,
+ .release_params = lz4hc_release_params,
.name = "lz4hc",
};
diff --git a/drivers/block/zram/backend_lzo.c b/drivers/block/zram/backend_lzo.c
index 699e8ef147a8..76a2e47c4665 100644
--- a/drivers/block/zram/backend_lzo.c
+++ b/drivers/block/zram/backend_lzo.c
@@ -6,6 +6,15 @@
#include "backend_lzo.h"
+static void lzo_release_params(struct zcomp_params *params)
+{
+}
+
+static int lzo_setup_params(struct zcomp_params *params)
+{
+ return 0;
+}
+
static int lzo_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
{
ctx->context = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
@@ -19,7 +28,8 @@ static void lzo_destroy(struct zcomp_ctx *ctx)
kfree(ctx->context);
}
-static int lzo_compress(struct zcomp_ctx *ctx, struct zcomp_req *req)
+static int lzo_compress(struct zcomp_params *params, struct zcomp_ctx *ctx,
+ struct zcomp_req *req)
{
int ret;
@@ -28,7 +38,8 @@ static int lzo_compress(struct zcomp_ctx *ctx, struct zcomp_req *req)
return ret == LZO_E_OK ? 0 : ret;
}
-static int lzo_decompress(struct zcomp_ctx *ctx, struct zcomp_req *req)
+static int lzo_decompress(struct zcomp_params *params, struct zcomp_ctx *ctx,
+ struct zcomp_req *req)
{
int ret;
@@ -42,5 +53,7 @@ struct zcomp_ops backend_lzo = {
.decompress = lzo_decompress,
.create_ctx = lzo_create,
.destroy_ctx = lzo_destroy,
+ .setup_params = lzo_setup_params,
+ .release_params = lzo_release_params,
.name = "lzo",
};
diff --git a/drivers/block/zram/backend_lzorle.c b/drivers/block/zram/backend_lzorle.c
index 48e4d4dc8437..b1cfab65cb8e 100644
--- a/drivers/block/zram/backend_lzorle.c
+++ b/drivers/block/zram/backend_lzorle.c
@@ -6,6 +6,15 @@
#include "backend_lzorle.h"
+static void lzorle_release_params(struct zcomp_params *params)
+{
+}
+
+static int lzorle_setup_params(struct zcomp_params *params)
+{
+ return 0;
+}
+
static int lzorle_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
{
ctx->context = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
@@ -19,7 +28,8 @@ static void lzorle_destroy(struct zcomp_ctx *ctx)
kfree(ctx->context);
}
-static int lzorle_compress(struct zcomp_ctx *ctx, struct zcomp_req *req)
+static int lzorle_compress(struct zcomp_params *params, struct zcomp_ctx *ctx,
+ struct zcomp_req *req)
{
int ret;
@@ -28,7 +38,8 @@ static int lzorle_compress(struct zcomp_ctx *ctx, struct zcomp_req *req)
return ret == LZO_E_OK ? 0 : ret;
}
-static int lzorle_decompress(struct zcomp_ctx *ctx, struct zcomp_req *req)
+static int lzorle_decompress(struct zcomp_params *params, struct zcomp_ctx *ctx,
+ struct zcomp_req *req)
{
int ret;
@@ -42,5 +53,7 @@ struct zcomp_ops backend_lzorle = {
.decompress = lzorle_decompress,
.create_ctx = lzorle_create,
.destroy_ctx = lzorle_destroy,
+ .setup_params = lzorle_setup_params,
+ .release_params = lzorle_release_params,
.name = "lzo-rle",
};
diff --git a/drivers/block/zram/backend_zstd.c b/drivers/block/zram/backend_zstd.c
index 1cc3a4a1f265..3c8ba3232881 100644
--- a/drivers/block/zram/backend_zstd.c
+++ b/drivers/block/zram/backend_zstd.c
@@ -10,12 +10,36 @@
struct zstd_ctx {
zstd_cctx *cctx;
zstd_dctx *dctx;
- zstd_parameters cprm;
void *cctx_mem;
void *dctx_mem;
- s32 level;
};
+struct zstd_params {
+ zstd_parameters cprm;
+};
+
+static void zstd_release_params(struct zcomp_params *params)
+{
+ kfree(params->drv_data);
+}
+
+static int zstd_setup_params(struct zcomp_params *params)
+{
+ struct zstd_params *zp;
+
+ zp = kzalloc(sizeof(*zp), GFP_KERNEL);
+ if (!zp)
+ return -ENOMEM;
+
+ if (params->level == ZCOMP_PARAM_NO_LEVEL)
+ params->level = zstd_default_clevel();
+
+ zp->cprm = zstd_get_params(params->level, PAGE_SIZE);
+ params->drv_data = zp;
+
+ return 0;
+}
+
static void zstd_destroy(struct zcomp_ctx *ctx)
{
struct zstd_ctx *zctx = ctx->context;
@@ -39,13 +63,7 @@ static int zstd_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
return -ENOMEM;
ctx->context = zctx;
- if (params->level != ZCOMP_PARAM_NO_LEVEL)
- zctx->level = params->level;
- else
- zctx->level = zstd_default_clevel();
-
- prm = zstd_get_params(zctx->level, PAGE_SIZE);
- zctx->cprm = zstd_get_params(zctx->level, PAGE_SIZE);
+ prm = zstd_get_params(params->level, PAGE_SIZE);
sz = zstd_cctx_workspace_bound(&prm.cParams);
zctx->cctx_mem = vzalloc(sz);
if (!zctx->cctx_mem)
@@ -71,20 +89,23 @@ static int zstd_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
return -EINVAL;
}
-static int zstd_compress(struct zcomp_ctx *ctx, struct zcomp_req *req)
+static int zstd_compress(struct zcomp_params *params, struct zcomp_ctx *ctx,
+ struct zcomp_req *req)
{
+ struct zstd_params *zp = params->drv_data;
struct zstd_ctx *zctx = ctx->context;
size_t ret;
ret = zstd_compress_cctx(zctx->cctx, req->dst, req->dst_len,
- req->src, req->src_len, &zctx->cprm);
+ req->src, req->src_len, &zp->cprm);
if (zstd_is_error(ret))
return -EINVAL;
req->dst_len = ret;
return 0;
}
-static int zstd_decompress(struct zcomp_ctx *ctx, struct zcomp_req *req)
+static int zstd_decompress(struct zcomp_params *params, struct zcomp_ctx *ctx,
+ struct zcomp_req *req)
{
struct zstd_ctx *zctx = ctx->context;
size_t ret;
@@ -101,5 +122,7 @@ struct zcomp_ops backend_zstd = {
.decompress = zstd_decompress,
.create_ctx = zstd_create,
.destroy_ctx = zstd_destroy,
+ .setup_params = zstd_setup_params,
+ .release_params = zstd_release_params,
.name = "zstd",
};
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
index 1964e6195b4b..a508e692999f 100644
--- a/drivers/block/zram/zcomp.c
+++ b/drivers/block/zram/zcomp.c
@@ -128,7 +128,7 @@ int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm,
};
int ret;
- ret = comp->ops->compress(&zstrm->ctx, &req);
+ ret = comp->ops->compress(comp->params, &zstrm->ctx, &req);
if (!ret)
*dst_len = req.dst_len;
return ret;
@@ -144,7 +144,7 @@ int zcomp_decompress(struct zcomp *comp, struct zcomp_strm *zstrm,
.dst_len = PAGE_SIZE,
};
- return comp->ops->decompress(&zstrm->ctx, &req);
+ return comp->ops->decompress(comp->params, &zstrm->ctx, &req);
}
int zcomp_cpu_up_prepare(unsigned int cpu, struct hlist_node *node)
@@ -172,7 +172,7 @@ int zcomp_cpu_dead(unsigned int cpu, struct hlist_node *node)
return 0;
}
-static int zcomp_init(struct zcomp *comp)
+static int zcomp_init(struct zcomp *comp, struct zcomp_params *params)
{
int ret;
@@ -180,12 +180,19 @@ static int zcomp_init(struct zcomp *comp)
if (!comp->stream)
return -ENOMEM;
+ comp->params = params;
+ ret = comp->ops->setup_params(comp->params);
+ if (ret)
+ goto cleanup;
+
ret = cpuhp_state_add_instance(CPUHP_ZCOMP_PREPARE, &comp->node);
if (ret < 0)
goto cleanup;
+
return 0;
cleanup:
+ comp->ops->release_params(comp->params);
free_percpu(comp->stream);
return ret;
}
@@ -193,6 +200,7 @@ static int zcomp_init(struct zcomp *comp)
void zcomp_destroy(struct zcomp *comp)
{
cpuhp_state_remove_instance(CPUHP_ZCOMP_PREPARE, &comp->node);
+ comp->ops->release_params(comp->params);
free_percpu(comp->stream);
kfree(comp);
}
@@ -214,14 +222,13 @@ struct zcomp *zcomp_create(const char *alg, struct zcomp_params *params)
if (!comp)
return ERR_PTR(-ENOMEM);
- comp->params = params;
comp->ops = lookup_backend_ops(alg);
if (!comp->ops) {
kfree(comp);
return ERR_PTR(-EINVAL);
}
- error = zcomp_init(comp);
+ error = zcomp_init(comp, params);
if (error) {
kfree(comp);
return ERR_PTR(error);
diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h
index ebab7dbca68d..6cb081e5b23e 100644
--- a/drivers/block/zram/zcomp.h
+++ b/drivers/block/zram/zcomp.h
@@ -7,10 +7,18 @@
#define ZCOMP_PARAM_NO_LEVEL INT_MIN
+/*
+ * Immutable driver (backend) parameters. The driver may attach private
+ * data to it (e.g. driver representation of the dictionary, etc.).
+ *
+ * This data is kept per-comp and is shared among execution contexts.
+ */
struct zcomp_params {
void *dict;
size_t dict_sz;
s32 level;
+
+ void *drv_data;
};
/*
@@ -38,13 +46,17 @@ struct zcomp_req {
};
struct zcomp_ops {
- int (*compress)(struct zcomp_ctx *ctx, struct zcomp_req *req);
- int (*decompress)(struct zcomp_ctx *ctx, struct zcomp_req *req);
+ int (*compress)(struct zcomp_params *params, struct zcomp_ctx *ctx,
+ struct zcomp_req *req);
+ int (*decompress)(struct zcomp_params *params, struct zcomp_ctx *ctx,
+ struct zcomp_req *req);
- int (*create_ctx)(struct zcomp_params *params,
- struct zcomp_ctx *ctx);
+ int (*create_ctx)(struct zcomp_params *params, struct zcomp_ctx *ctx);
void (*destroy_ctx)(struct zcomp_ctx *ctx);
+ int (*setup_params)(struct zcomp_params *params);
+ void (*release_params)(struct zcomp_params *params);
+
const char *name;
};
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCHv5 20/23] zram: add dictionary support to lz4
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (18 preceding siblings ...)
2024-07-06 4:56 ` [PATCHv5 19/23] zram: move immutable comp params away from per-CPU context Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 21/23] zram: add dictionary support to lz4hc Sergey Senozhatsky
` (4 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky
Support pre-trained dictionary param. lz4 doesn't
mandate specific format of the dictionary and even
zstd --train can be used to train a dictionary for
lz4, according to [1].
TEST
====
*** lz4
/sys/block/zram0/mm_stat
1750654976 664188565 676864000 0 676864000 1 0 34288 34288
*** lz4 dict=/home/ss/lz4-dict-amd64
/sys/block/zram0/mm_stat
1750638592 619891141 632053760 0 632053760 1 0 34278 34278
*** lz4 level=5 dict=/home/ss/lz4-dict-amd64
/sys/block/zram0/mm_stat
1750638592 727174243 740810752 0 740810752 1 0 34437 34437
[1] https://github.com/lz4/lz4/issues/557
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
drivers/block/zram/backend_lz4.c | 74 +++++++++++++++++++++++++++++---
1 file changed, 67 insertions(+), 7 deletions(-)
diff --git a/drivers/block/zram/backend_lz4.c b/drivers/block/zram/backend_lz4.c
index cdcf6e3c1826..f686157fb401 100644
--- a/drivers/block/zram/backend_lz4.c
+++ b/drivers/block/zram/backend_lz4.c
@@ -5,6 +5,13 @@
#include "backend_lz4.h"
+struct lz4_ctx {
+ void *mem;
+
+ LZ4_streamDecode_t *dstrm;
+ LZ4_stream_t *cstrm;
+};
+
static void lz4_release_params(struct zcomp_params *params)
{
}
@@ -19,25 +26,66 @@ static int lz4_setup_params(struct zcomp_params *params)
static void lz4_destroy(struct zcomp_ctx *ctx)
{
- vfree(ctx->context);
+ struct lz4_ctx *zctx = ctx->context;
+
+ if (!zctx)
+ return;
+
+ vfree(zctx->mem);
+ kfree(zctx->dstrm);
+ kfree(zctx->cstrm);
+ kfree(zctx);
}
static int lz4_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
{
- ctx->context = vmalloc(LZ4_MEM_COMPRESS);
- if (!ctx->context)
+ struct lz4_ctx *zctx;
+
+ zctx = kzalloc(sizeof(*zctx), GFP_KERNEL);
+ if (!zctx)
return -ENOMEM;
+ ctx->context = zctx;
+ if (params->dict_sz == 0) {
+ zctx->mem = vmalloc(LZ4_MEM_COMPRESS);
+ if (!zctx->mem)
+ goto error;
+ } else {
+ zctx->dstrm = kzalloc(sizeof(*zctx->dstrm), GFP_KERNEL);
+ if (!zctx->dstrm)
+ goto error;
+
+ zctx->cstrm = kzalloc(sizeof(*zctx->cstrm), GFP_KERNEL);
+ if (!zctx->cstrm)
+ goto error;
+ }
+
return 0;
+
+error:
+ lz4_destroy(ctx);
+ return -ENOMEM;
}
static int lz4_compress(struct zcomp_params *params, struct zcomp_ctx *ctx,
struct zcomp_req *req)
{
+ struct lz4_ctx *zctx = ctx->context;
int ret;
- ret = LZ4_compress_fast(req->src, req->dst, req->src_len,
- req->dst_len, params->level, ctx->context);
+ if (!zctx->cstrm) {
+ ret = LZ4_compress_fast(req->src, req->dst, req->src_len,
+ req->dst_len, params->level,
+ zctx->mem);
+ } else {
+ /* Cstrm needs to be reset */
+ ret = LZ4_loadDict(zctx->cstrm, params->dict, params->dict_sz);
+ if (ret != params->dict_sz)
+ return -EINVAL;
+ ret = LZ4_compress_fast_continue(zctx->cstrm, req->src,
+ req->dst, req->src_len,
+ req->dst_len, params->level);
+ }
if (!ret)
return -EINVAL;
req->dst_len = ret;
@@ -47,10 +95,22 @@ static int lz4_compress(struct zcomp_params *params, struct zcomp_ctx *ctx,
static int lz4_decompress(struct zcomp_params *params, struct zcomp_ctx *ctx,
struct zcomp_req *req)
{
+ struct lz4_ctx *zctx = ctx->context;
int ret;
- ret = LZ4_decompress_safe(req->src, req->dst, req->src_len,
- req->dst_len);
+ if (!zctx->dstrm) {
+ ret = LZ4_decompress_safe(req->src, req->dst, req->src_len,
+ req->dst_len);
+ } else {
+ /* Dstrm needs to be reset */
+ ret = LZ4_setStreamDecode(zctx->dstrm, params->dict,
+ params->dict_sz);
+ if (!ret)
+ return -EINVAL;
+ ret = LZ4_decompress_safe_continue(zctx->dstrm, req->src,
+ req->dst, req->src_len,
+ req->dst_len);
+ }
if (ret < 0)
return -EINVAL;
return 0;
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCHv5 21/23] zram: add dictionary support to lz4hc
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (19 preceding siblings ...)
2024-07-06 4:56 ` [PATCHv5 20/23] zram: add dictionary support to lz4 Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 22/23] zram: add dictionary support to zstd backend Sergey Senozhatsky
` (3 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky
Support pre-trained dictionary param. Just like lz4,
lz4hc doesn't mandate specific format of the dictionary
and zstd --train can be used to train a dictionary for
lz4, according to [1].
TEST
====
*** lz4hc
/sys/block/zram0/mm_stat
1750638592 608954620 621031424 0 621031424 1 0 34288 34288
*** lz4hc dict=/home/ss/lz4-dict-amd64
/sys/block/zram0/mm_stat
1750671360 505068582 514994176 0 514994176 1 0 34278 34278
[1] https://github.com/lz4/lz4/issues/557
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
drivers/block/zram/backend_lz4hc.c | 75 +++++++++++++++++++++++++++---
1 file changed, 68 insertions(+), 7 deletions(-)
diff --git a/drivers/block/zram/backend_lz4hc.c b/drivers/block/zram/backend_lz4hc.c
index e7dc0e03f13c..79ff2c968f6b 100644
--- a/drivers/block/zram/backend_lz4hc.c
+++ b/drivers/block/zram/backend_lz4hc.c
@@ -5,6 +5,13 @@
#include "backend_lz4hc.h"
+struct lz4hc_ctx {
+ void *mem;
+
+ LZ4_streamDecode_t *dstrm;
+ LZ4_streamHC_t *cstrm;
+};
+
static void lz4hc_release_params(struct zcomp_params *params)
{
}
@@ -19,25 +26,67 @@ static int lz4hc_setup_params(struct zcomp_params *params)
static void lz4hc_destroy(struct zcomp_ctx *ctx)
{
- vfree(ctx->context);
+ struct lz4hc_ctx *zctx = ctx->context;
+
+ if (!zctx)
+ return;
+
+ kfree(zctx->dstrm);
+ kfree(zctx->cstrm);
+ vfree(zctx->mem);
+ kfree(zctx);
}
static int lz4hc_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
{
- ctx->context = vmalloc(LZ4HC_MEM_COMPRESS);
- if (!ctx->context)
+ struct lz4hc_ctx *zctx;
+
+ zctx = kzalloc(sizeof(*zctx), GFP_KERNEL);
+ if (!zctx)
return -ENOMEM;
+ ctx->context = zctx;
+ if (params->dict_sz == 0) {
+ zctx->mem = vmalloc(LZ4HC_MEM_COMPRESS);
+ if (!zctx->mem)
+ goto error;
+ } else {
+ zctx->dstrm = kzalloc(sizeof(*zctx->dstrm), GFP_KERNEL);
+ if (!zctx->dstrm)
+ goto error;
+
+ zctx->cstrm = kzalloc(sizeof(*zctx->cstrm), GFP_KERNEL);
+ if (!zctx->cstrm)
+ goto error;
+ }
+
return 0;
+
+error:
+ lz4hc_destroy(ctx);
+ return -EINVAL;
}
static int lz4hc_compress(struct zcomp_params *params, struct zcomp_ctx *ctx,
struct zcomp_req *req)
{
+ struct lz4hc_ctx *zctx = ctx->context;
int ret;
- ret = LZ4_compress_HC(req->src, req->dst, req->src_len, req->dst_len,
- params->level, ctx->context);
+ if (!zctx->cstrm) {
+ ret = LZ4_compress_HC(req->src, req->dst, req->src_len,
+ req->dst_len, params->level,
+ zctx->mem);
+ } else {
+ /* Cstrm needs to be reset */
+ LZ4_resetStreamHC(zctx->cstrm, params->level);
+ ret = LZ4_loadDictHC(zctx->cstrm, params->dict,
+ params->dict_sz);
+ if (ret != params->dict_sz)
+ return -EINVAL;
+ ret = LZ4_compress_HC_continue(zctx->cstrm, req->src, req->dst,
+ req->src_len, req->dst_len);
+ }
if (!ret)
return -EINVAL;
req->dst_len = ret;
@@ -47,10 +96,22 @@ static int lz4hc_compress(struct zcomp_params *params, struct zcomp_ctx *ctx,
static int lz4hc_decompress(struct zcomp_params *params, struct zcomp_ctx *ctx,
struct zcomp_req *req)
{
+ struct lz4hc_ctx *zctx = ctx->context;
int ret;
- ret = LZ4_decompress_safe(req->src, req->dst, req->src_len,
- req->dst_len);
+ if (!zctx->dstrm) {
+ ret = LZ4_decompress_safe(req->src, req->dst, req->src_len,
+ req->dst_len);
+ } else {
+ /* Dstrm needs to be reset */
+ ret = LZ4_setStreamDecode(zctx->dstrm, params->dict,
+ params->dict_sz);
+ if (!ret)
+ return -EINVAL;
+ ret = LZ4_decompress_safe_continue(zctx->dstrm, req->src,
+ req->dst, req->src_len,
+ req->dst_len);
+ }
if (ret < 0)
return -EINVAL;
return 0;
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCHv5 22/23] zram: add dictionary support to zstd backend
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (20 preceding siblings ...)
2024-07-06 4:56 ` [PATCHv5 21/23] zram: add dictionary support to lz4hc Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 4:56 ` [PATCHv5 23/23] Documentation/zram: add documentation for algorithm parameters Sergey Senozhatsky
` (2 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky
This adds support for pre-trained zstd dictionaries [1]
Dictionary is setup in params once (per-comp) and loaded
to Cctx and Dctx by reference, so we don't allocate extra
memory.
TEST
====
*** zstd
/sys/block/zram0/mm_stat
1750654976 504565092 514203648 0 514203648 1 0 34204 34204
*** zstd dict=/home/ss/zstd-dict-amd64
/sys/block/zram0/mm_stat
1750638592 465851259 475373568 0 475373568 1 0 34185 34185
*** zstd level=8 dict=/home/ss/zstd-dict-amd64
/sys/block/zram0/mm_stat
1750642688 430765171 439955456 0 439955456 1 0 34185 34185
[1] https://github.com/facebook/zstd/blob/dev/programs/zstd.1.md#dictionary-builder
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
drivers/block/zram/backend_zstd.c | 150 ++++++++++++++++++++++++------
1 file changed, 124 insertions(+), 26 deletions(-)
diff --git a/drivers/block/zram/backend_zstd.c b/drivers/block/zram/backend_zstd.c
index 3c8ba3232881..5a6940136cef 100644
--- a/drivers/block/zram/backend_zstd.c
+++ b/drivers/block/zram/backend_zstd.c
@@ -15,29 +15,87 @@ struct zstd_ctx {
};
struct zstd_params {
+ zstd_custom_mem custom_mem;
+ zstd_cdict *cdict;
+ zstd_ddict *ddict;
zstd_parameters cprm;
};
+/*
+ * For C/D dictionaries we need to provide zstd with zstd_custom_mem,
+ * which zstd uses internally to allocate/free memory when needed.
+ *
+ * This means that allocator.customAlloc() can be called from zcomp_compress()
+ * under local-lock (per-CPU compression stream), in which case we must use
+ * GFP_ATOMIC.
+ *
+ * Another complication here is that we can be configured as a swap device.
+ */
+static void *zstd_custom_alloc(void *opaque, size_t size)
+{
+ if (!preemptible())
+ return kvzalloc(size, GFP_ATOMIC);
+
+ return kvzalloc(size, __GFP_KSWAPD_RECLAIM | __GFP_NOWARN);
+}
+
+static void zstd_custom_free(void *opaque, void *address)
+{
+ kvfree(address);
+}
+
static void zstd_release_params(struct zcomp_params *params)
{
- kfree(params->drv_data);
+ struct zstd_params *zp = params->drv_data;
+
+ params->drv_data = NULL;
+ if (!zp)
+ return;
+
+ zstd_free_cdict(zp->cdict);
+ zstd_free_ddict(zp->ddict);
+ kfree(zp);
}
static int zstd_setup_params(struct zcomp_params *params)
{
+ zstd_compression_parameters prm;
struct zstd_params *zp;
zp = kzalloc(sizeof(*zp), GFP_KERNEL);
if (!zp)
return -ENOMEM;
+ params->drv_data = zp;
if (params->level == ZCOMP_PARAM_NO_LEVEL)
params->level = zstd_default_clevel();
zp->cprm = zstd_get_params(params->level, PAGE_SIZE);
- params->drv_data = zp;
+
+ zp->custom_mem.customAlloc = zstd_custom_alloc;
+ zp->custom_mem.customFree = zstd_custom_free;
+
+ prm = zstd_get_cparams(params->level, PAGE_SIZE,
+ params->dict_sz);
+
+ zp->cdict = zstd_create_cdict_byreference(params->dict,
+ params->dict_sz,
+ prm,
+ zp->custom_mem);
+ if (!zp->cdict)
+ goto error;
+
+ zp->ddict = zstd_create_ddict_byreference(params->dict,
+ params->dict_sz,
+ zp->custom_mem);
+ if (!zp->ddict)
+ goto error;
return 0;
+
+error:
+ zstd_release_params(params);
+ return -EINVAL;
}
static void zstd_destroy(struct zcomp_ctx *ctx)
@@ -47,8 +105,23 @@ static void zstd_destroy(struct zcomp_ctx *ctx)
if (!zctx)
return;
- vfree(zctx->cctx_mem);
- vfree(zctx->dctx_mem);
+ /*
+ * If ->cctx_mem and ->dctx_mem were allocated then we didn't use
+ * C/D dictionary and ->cctx / ->dctx were "embedded" into these
+ * buffers.
+ *
+ * If otherwise then we need to explicitly release ->cctx / ->dctx.
+ */
+ if (zctx->cctx_mem)
+ vfree(zctx->cctx_mem);
+ else
+ zstd_free_cctx(zctx->cctx);
+
+ if (zctx->dctx_mem)
+ vfree(zctx->dctx_mem);
+ else
+ zstd_free_dctx(zctx->dctx);
+
kfree(zctx);
}
@@ -63,28 +136,41 @@ static int zstd_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
return -ENOMEM;
ctx->context = zctx;
- prm = zstd_get_params(params->level, PAGE_SIZE);
- sz = zstd_cctx_workspace_bound(&prm.cParams);
- zctx->cctx_mem = vzalloc(sz);
- if (!zctx->cctx_mem)
- goto error;
-
- zctx->cctx = zstd_init_cctx(zctx->cctx_mem, sz);
- if (!zctx->cctx)
- goto error;
-
- sz = zstd_dctx_workspace_bound();
- zctx->dctx_mem = vzalloc(sz);
- if (!zctx->dctx_mem)
- goto error;
-
- zctx->dctx = zstd_init_dctx(zctx->dctx_mem, sz);
- if (!zctx->dctx)
- goto error;
+ if (params->dict_sz == 0) {
+ prm = zstd_get_params(params->level, PAGE_SIZE);
+ sz = zstd_cctx_workspace_bound(&prm.cParams);
+ zctx->cctx_mem = vzalloc(sz);
+ if (!zctx->cctx_mem)
+ goto error;
+
+ zctx->cctx = zstd_init_cctx(zctx->cctx_mem, sz);
+ if (!zctx->cctx)
+ goto error;
+
+ sz = zstd_dctx_workspace_bound();
+ zctx->dctx_mem = vzalloc(sz);
+ if (!zctx->dctx_mem)
+ goto error;
+
+ zctx->dctx = zstd_init_dctx(zctx->dctx_mem, sz);
+ if (!zctx->dctx)
+ goto error;
+ } else {
+ struct zstd_params *zp = params->drv_data;
+
+ zctx->cctx = zstd_create_cctx_advanced(zp->custom_mem);
+ if (!zctx->cctx)
+ goto error;
+
+ zctx->dctx = zstd_create_dctx_advanced(zp->custom_mem);
+ if (!zctx->dctx)
+ goto error;
+ }
return 0;
error:
+ zstd_release_params(params);
zstd_destroy(ctx);
return -EINVAL;
}
@@ -96,8 +182,14 @@ static int zstd_compress(struct zcomp_params *params, struct zcomp_ctx *ctx,
struct zstd_ctx *zctx = ctx->context;
size_t ret;
- ret = zstd_compress_cctx(zctx->cctx, req->dst, req->dst_len,
- req->src, req->src_len, &zp->cprm);
+ if (params->dict_sz == 0)
+ ret = zstd_compress_cctx(zctx->cctx, req->dst, req->dst_len,
+ req->src, req->src_len, &zp->cprm);
+ else
+ ret = zstd_compress_using_cdict(zctx->cctx, req->dst,
+ req->dst_len, req->src,
+ req->src_len,
+ zp->cdict);
if (zstd_is_error(ret))
return -EINVAL;
req->dst_len = ret;
@@ -107,11 +199,17 @@ static int zstd_compress(struct zcomp_params *params, struct zcomp_ctx *ctx,
static int zstd_decompress(struct zcomp_params *params, struct zcomp_ctx *ctx,
struct zcomp_req *req)
{
+ struct zstd_params *zp = params->drv_data;
struct zstd_ctx *zctx = ctx->context;
size_t ret;
- ret = zstd_decompress_dctx(zctx->dctx, req->dst, req->dst_len,
- req->src, req->src_len);
+ if (params->dict_sz == 0)
+ ret = zstd_decompress_dctx(zctx->dctx, req->dst, req->dst_len,
+ req->src, req->src_len);
+ else
+ ret = zstd_decompress_using_ddict(zctx->dctx, req->dst,
+ req->dst_len, req->src,
+ req->src_len, zp->ddict);
if (zstd_is_error(ret))
return -EINVAL;
return 0;
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCHv5 23/23] Documentation/zram: add documentation for algorithm parameters
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (21 preceding siblings ...)
2024-07-06 4:56 ` [PATCHv5 22/23] zram: add dictionary support to zstd backend Sergey Senozhatsky
@ 2024-07-06 4:56 ` Sergey Senozhatsky
2024-07-06 5:01 ` [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
2024-07-06 7:03 ` Markus Elfring
24 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 4:56 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky
Document brief description of compression algorithms' parameters:
compression level and pre-trained dictionary.
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
Documentation/admin-guide/blockdev/zram.rst | 45 ++++++++++++++++-----
1 file changed, 36 insertions(+), 9 deletions(-)
diff --git a/Documentation/admin-guide/blockdev/zram.rst b/Documentation/admin-guide/blockdev/zram.rst
index 091e8bb38887..e3cdbf4ba61f 100644
--- a/Documentation/admin-guide/blockdev/zram.rst
+++ b/Documentation/admin-guide/blockdev/zram.rst
@@ -102,15 +102,33 @@ Examples::
#select lzo compression algorithm
echo lzo > /sys/block/zram0/comp_algorithm
-For the time being, the `comp_algorithm` content does not necessarily
-show every compression algorithm supported by the kernel. We keep this
-list primarily to simplify device configuration and one can configure
-a new device with a compression algorithm that is not listed in
-`comp_algorithm`. The thing is that, internally, ZRAM uses Crypto API
-and, if some of the algorithms were built as modules, it's impossible
-to list all of them using, for instance, /proc/crypto or any other
-method. This, however, has an advantage of permitting the usage of
-custom crypto compression modules (implementing S/W or H/W compression).
+For the time being, the `comp_algorithm` content shows only compression
+algorithms that are supported by zram.
+
+It is also possible to pass algorithm specific configuration parameters::
+
+ #set compression level to 8
+ echo "zstd level=8" > /sys/block/zram0/comp_algorithm
+
+Note that `comp_algorithm` also supports `algo=name` format::
+
+ #set compression level to 8
+ echo "algo=zstd level=8" > /sys/block/zram0/comp_algorithm
+
+Certain compression algorithms support pre-trained dictionaries, which
+significantly change algorithms' characteristics. In order to configure
+compression algorithm to use external pre-trained dictionary, pass full
+path to the dictionary along with other parameters::
+
+ #pass path to pre-trained dictionary
+ echo "algo=zstd dict=/etc/dictioary" > /sys/block/zram0/comp_algorithm
+
+Parameters are algorithm specific: not all algorithms support pre-trained
+dictionaries, not all algorithms support 'level'. Furthermore, for certain
+algorithms 'level' controls the compression level (the higher the value the
+better the compression ratio, it even can take negatives values for some
+algorithms), for other algorithms 'level' is acceleration level (the higher
+the value the lower the compression ratio).
4) Set Disksize
===============
@@ -442,6 +460,15 @@ configuration:::
#select deflate recompression algorithm, priority 2
echo "algo=deflate priority=2" > /sys/block/zramX/recomp_algorithm
+The `recomp_algorithm` also supports algorithm configuration parameters, e.g.
+compression level and pre-trained dircionary::
+
+ #pass compression level
+ echo "algo=zstd level=8" > /sys/block/zramX/recomp_algorithm
+
+ #pass path to pre-trained dictionary
+ echo "algo=zstd dict=/etc/dictioary" > /sys/block/zramX/recomp_algorithm
+
Another device attribute that CONFIG_ZRAM_MULTI_COMP enables is recompress,
which controls recompression.
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [PATCHv5 00/23] zram: compression algorithms tunables
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (22 preceding siblings ...)
2024-07-06 4:56 ` [PATCHv5 23/23] Documentation/zram: add documentation for algorithm parameters Sergey Senozhatsky
@ 2024-07-06 5:01 ` Sergey Senozhatsky
2024-07-06 7:03 ` Markus Elfring
24 siblings, 0 replies; 30+ messages in thread
From: Sergey Senozhatsky @ 2024-07-06 5:01 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim; +Cc: linux-kernel, Sergey Senozhatsky
On (24/07/06 13:56), Sergey Senozhatsky wrote:
> This series introduces support for run-time compression algorithms
> tuning, so users, for instance, can adjust compression/acceleration
> levels and provide pre-trained compression/decompression dictionaries
> which certain algorithms support.
>
> At this point we stop supporting (old/deprecated) comp API. We may
> add new acomp API support in the future, but before that zram needs
> to undergo some major rework (we are not ready for async compression).
This is, mostly, what we previously had in mm-unstable for several weeks,
however, given that there were some major changes in the series, I'd
label it as 6.11 material.
^ permalink raw reply [flat|nested] 30+ messages in thread* Re: [PATCHv5 00/23] zram: compression algorithms tunables
2024-07-06 4:56 [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
` (23 preceding siblings ...)
2024-07-06 5:01 ` [PATCHv5 00/23] zram: compression algorithms tunables Sergey Senozhatsky
@ 2024-07-06 7:03 ` Markus Elfring
24 siblings, 0 replies; 30+ messages in thread
From: Markus Elfring @ 2024-07-06 7:03 UTC (permalink / raw)
To: Sergey Senozhatsky, kernel-janitors, Andrew Morton, Minchan Kim; +Cc: LKML
> This series introduces support for run-time compression algorithms
…
I find it helpful to separate the version identifier from the previous key word
in message subjects.
Regards,
Markus
^ permalink raw reply [flat|nested] 30+ messages in thread