summaryrefslogtreecommitdiff
path: root/fs/btrfs
diff options
context:
space:
mode:
authorMarek BehĂșn <marek.behun@nic.cz>2019-04-29 22:40:45 +0200
committerTom Rini <trini@konsulko.com>2019-05-05 08:48:50 -0400
commit53290e6efdc10b5a40955fa4c5b0960651180bf2 (patch)
tree4d45ae2ac1842f95bfb8ae6d33bd3c56e9da0c9c /fs/btrfs
parent8509f22aacf04ae892e28c2df3a79c1d72c39c25 (diff)
fs: btrfs: add zstd decompression support
This adds decompression support for Zstandard, which has been included in Linux btrfs driver for some time. Signed-off-by: Marek BehĂșn <marek.behun@nic.cz>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/Kconfig1
-rw-r--r--fs/btrfs/btrfs_tree.h5
-rw-r--r--fs/btrfs/compression.c59
3 files changed, 63 insertions, 2 deletions
diff --git a/fs/btrfs/Kconfig b/fs/btrfs/Kconfig
index 22909d9fcc..f302b1fbef 100644
--- a/fs/btrfs/Kconfig
+++ b/fs/btrfs/Kconfig
@@ -2,6 +2,7 @@ config FS_BTRFS
bool "Enable BTRFS filesystem support"
select CRC32C
select LZO
+ select ZSTD
select RBTREE
help
This provides a single-device read-only BTRFS support. BTRFS is a
diff --git a/fs/btrfs/btrfs_tree.h b/fs/btrfs/btrfs_tree.h
index f90fbb2951..aa0f3d6c86 100644
--- a/fs/btrfs/btrfs_tree.h
+++ b/fs/btrfs/btrfs_tree.h
@@ -647,8 +647,9 @@ enum btrfs_compression_type {
BTRFS_COMPRESS_NONE = 0,
BTRFS_COMPRESS_ZLIB = 1,
BTRFS_COMPRESS_LZO = 2,
- BTRFS_COMPRESS_TYPES = 2,
- BTRFS_COMPRESS_LAST = 3,
+ BTRFS_COMPRESS_ZSTD = 3,
+ BTRFS_COMPRESS_TYPES = 3,
+ BTRFS_COMPRESS_LAST = 4,
};
struct btrfs_file_extent_item {
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index e5601b8f2b..346875d45a 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -6,7 +6,9 @@
*/
#include "btrfs.h"
+#include <malloc.h>
#include <linux/lzo.h>
+#include <linux/zstd.h>
#include <u-boot/zlib.h>
#include <asm/unaligned.h>
@@ -108,6 +110,61 @@ static u32 decompress_zlib(const u8 *_cbuf, u32 clen, u8 *dbuf, u32 dlen)
return res;
}
+#define ZSTD_BTRFS_MAX_WINDOWLOG 17
+#define ZSTD_BTRFS_MAX_INPUT (1 << ZSTD_BTRFS_MAX_WINDOWLOG)
+
+static u32 decompress_zstd(const u8 *cbuf, u32 clen, u8 *dbuf, u32 dlen)
+{
+ ZSTD_DStream *dstream;
+ ZSTD_inBuffer in_buf;
+ ZSTD_outBuffer out_buf;
+ void *workspace;
+ size_t wsize;
+ u32 res = -1;
+
+ wsize = ZSTD_DStreamWorkspaceBound(ZSTD_BTRFS_MAX_INPUT);
+ workspace = malloc(wsize);
+ if (!workspace) {
+ debug("%s: cannot allocate workspace of size %zu\n", __func__,
+ wsize);
+ return -1;
+ }
+
+ dstream = ZSTD_initDStream(ZSTD_BTRFS_MAX_INPUT, workspace, wsize);
+ if (!dstream) {
+ printf("%s: ZSTD_initDStream failed\n", __func__);
+ goto err_free;
+ }
+
+ in_buf.src = cbuf;
+ in_buf.pos = 0;
+ in_buf.size = clen;
+
+ out_buf.dst = dbuf;
+ out_buf.pos = 0;
+ out_buf.size = dlen;
+
+ while (1) {
+ size_t ret;
+
+ ret = ZSTD_decompressStream(dstream, &out_buf, &in_buf);
+ if (ZSTD_isError(ret)) {
+ printf("%s: ZSTD_decompressStream error %d\n", __func__,
+ ZSTD_getErrorCode(ret));
+ goto err_free;
+ }
+
+ if (in_buf.pos >= clen || !ret)
+ break;
+ }
+
+ res = out_buf.pos;
+
+err_free:
+ free(workspace);
+ return res;
+}
+
u32 btrfs_decompress(u8 type, const char *c, u32 clen, char *d, u32 dlen)
{
u32 res;
@@ -126,6 +183,8 @@ u32 btrfs_decompress(u8 type, const char *c, u32 clen, char *d, u32 dlen)
return decompress_zlib(cbuf, clen, dbuf, dlen);
case BTRFS_COMPRESS_LZO:
return decompress_lzo(cbuf, clen, dbuf, dlen);
+ case BTRFS_COMPRESS_ZSTD:
+ return decompress_zstd(cbuf, clen, dbuf, dlen);
default:
printf("%s: Unsupported compression in extent: %i\n", __func__,
type);