fs: ubifs: Add support for ZSTD decompression
ZSTD can be a better tradeoff between NAND IO operations and decompression
speed giving a better boot time.
Signed-off-by: Piotr Wojtaszczyk <piotr.wojtaszczyk@timesys.com>
Reviewed-by: Heiko Schocher <hs@denx.de>
diff --git a/fs/ubifs/ubifs-media.h b/fs/ubifs/ubifs-media.h
index 2b5b26a..299d80f 100644
--- a/fs/ubifs/ubifs-media.h
+++ b/fs/ubifs/ubifs-media.h
@@ -320,12 +320,14 @@
* UBIFS_COMPR_NONE: no compression
* UBIFS_COMPR_LZO: LZO compression
* UBIFS_COMPR_ZLIB: ZLIB compression
+ * UBIFS_COMPR_ZSTD: ZSTD compression
* UBIFS_COMPR_TYPES_CNT: count of supported compression types
*/
enum {
UBIFS_COMPR_NONE,
UBIFS_COMPR_LZO,
UBIFS_COMPR_ZLIB,
+ UBIFS_COMPR_ZSTD,
UBIFS_COMPR_TYPES_CNT,
};
diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c
index 75de01e..f0ea7e5 100644
--- a/fs/ubifs/ubifs.c
+++ b/fs/ubifs/ubifs.c
@@ -26,6 +26,11 @@
#include <linux/err.h>
#include <linux/lzo.h>
+#if IS_ENABLED(CONFIG_ZSTD)
+#include <linux/zstd.h>
+#include <abuf.h>
+#endif
+
DECLARE_GLOBAL_DATA_PTR;
/* compress.c */
@@ -41,6 +46,25 @@
(unsigned long *)out_len, 0, 0);
}
+#if IS_ENABLED(CONFIG_ZSTD)
+static int zstd_decompress_wrapper(const unsigned char *in, size_t in_len,
+ unsigned char *out, size_t *out_len)
+{
+ struct abuf abuf_in, abuf_out;
+ int ret;
+
+ abuf_init_set(&abuf_in, (void *)in, in_len);
+ abuf_init_set(&abuf_out, (void *)out, *out_len);
+
+ ret = zstd_decompress(&abuf_in, &abuf_out);
+ if (ret < 0)
+ return ret;
+
+ *out_len = ret;
+ return 0;
+}
+#endif
+
/* Fake description object for the "none" compressor */
static struct ubifs_compressor none_compr = {
.compr_type = UBIFS_COMPR_NONE,
@@ -69,9 +93,22 @@
.capi_name = "deflate",
.decompress = gzip_decompress,
};
+
+#if IS_ENABLED(CONFIG_ZSTD)
+static struct ubifs_compressor zstd_compr = {
+ .compr_type = UBIFS_COMPR_ZSTD,
+#ifndef __UBOOT__
+ .comp_mutex = &zstd_enc_mutex,
+ .decomp_mutex = &zstd_dec_mutex,
+#endif
+ .name = "zstd",
+ .capi_name = "zstd",
+ .decompress = zstd_decompress_wrapper,
+};
+#endif
/* All UBIFS compressors */
-struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
+struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT] = {NULL};
#ifdef __UBOOT__
@@ -165,8 +202,14 @@
compr = ubifs_compressors[compr_type];
+ if (unlikely(!compr)) {
+ ubifs_err(c, "compression type %d is not compiled in", compr_type);
+ return -EINVAL;
+ }
+
if (unlikely(!compr->capi_name)) {
- ubifs_err(c, "%s compression is not compiled in", compr->name);
+ ubifs_err(c, "%s compression is not compiled in",
+ compr->name ? compr->name : "unknown");
return -EINVAL;
}
@@ -231,6 +274,12 @@
if (err)
return err;
+#if IS_ENABLED(CONFIG_ZSTD)
+ err = compr_init(&zstd_compr);
+ if (err)
+ return err;
+#endif
+
err = compr_init(&none_compr);
if (err)
return err;