summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2017-03-09 08:41:05 -0900
committerKent Overstreet <kent.overstreet@gmail.com>2017-04-02 22:25:42 -0800
commit3d8f1a9b4c8c6544b24410523fd4ece6d35fcb34 (patch)
tree01a09a1535f425b6663db9a70646566da966ff1a
parentdcabfc55070c8e89d66d83da857be86333327442 (diff)
bcache: zstd compression supportbcachefs-zstd
-rw-r--r--fs/bcachefs/Kconfig1
-rw-r--r--fs/bcachefs/bcachefs_format.h3
-rw-r--r--fs/bcachefs/compress.c55
3 files changed, 58 insertions, 1 deletions
diff --git a/fs/bcachefs/Kconfig b/fs/bcachefs/Kconfig
index cdd848f1e4a6..bad70a54fdbd 100644
--- a/fs/bcachefs/Kconfig
+++ b/fs/bcachefs/Kconfig
@@ -9,6 +9,7 @@ config BCACHE_FS
select FS_POSIX_ACL
select LZ4_COMPRESS
select LZ4_DECOMPRESS
+ select ZSTD
select ZLIB_DEFLATE
select ZLIB_INFLATE
select CRYPTO_SHA256
diff --git a/fs/bcachefs/bcachefs_format.h b/fs/bcachefs/bcachefs_format.h
index 0a0dc8708b94..e964a0831ecd 100644
--- a/fs/bcachefs/bcachefs_format.h
+++ b/fs/bcachefs/bcachefs_format.h
@@ -1025,7 +1025,8 @@ enum bch_compression_opts {
BCH_COMPRESSION_NONE = 0,
BCH_COMPRESSION_LZ4 = 1,
BCH_COMPRESSION_GZIP = 2,
- BCH_COMPRESSION_NR = 3,
+ BCH_COMPRESSION_ZSTD = 3,
+ BCH_COMPRESSION_NR = 4,
};
/* backing device specific stuff: */
diff --git a/fs/bcachefs/compress.c b/fs/bcachefs/compress.c
index 547ea73213e2..45da21cb8681 100644
--- a/fs/bcachefs/compress.c
+++ b/fs/bcachefs/compress.c
@@ -6,6 +6,7 @@
#include <linux/lz4.h>
#include <linux/zlib.h>
+#include <linux/zstd.h>
enum bounced {
BOUNCED_CONTIG,
@@ -186,6 +187,22 @@ static int __bio_uncompress(struct bch_fs *c, struct bio *src,
}
break;
}
+ case BCH_COMPRESSION_ZSTD: {
+ ZSTD_DCtx *dctx = ZSTD_createDCtx();
+
+ src_len = le32_to_cpup(src_data);
+
+ ret = ZSTD_decompressDCtx(dctx,
+ dst_data, dst_len,
+ src_data + 4, src_len);
+ ZSTD_freeDCtx(dctx);
+
+ if (ret != dst_len) {
+ pr_info("ret %i", ret);
+ ret = -EIO;
+ }
+ break;
+ }
default:
BUG();
}
@@ -362,6 +379,41 @@ zlib_err:
*src_len = strm.total_in;
break;
}
+ case BCH_COMPRESSION_ZSTD: {
+ ZSTD_CCtx *workspace = ZSTD_createCCtx();
+
+ *dst_len = dst->bi_iter.bi_size;
+ *src_len = src->bi_iter.bi_size;
+
+ while (*src_len > block_bytes(c) &&
+ (ret = ZSTD_compressCCtx(workspace,
+ dst_data + 4, *dst_len - 4,
+ src_data, *src_len,
+ 10)) <= 0) {
+ /*
+ * On error, the compressed data was bigger than
+ * dst_len, and -ret is the amount of data we were able
+ * to compress - round down to nearest block and try
+ * again:
+ */
+ BUG_ON(ret > 0);
+ BUG_ON(-ret >= *src_len);
+
+ *src_len = round_down(-ret, block_bytes(c));
+ }
+
+ if (ret > 0) {
+ *((__le32 *) dst_data) = cpu_to_le32(ret);
+ *dst_len = ret + 4;
+ ret = 0;
+ }
+
+ ZSTD_freeCCtx(workspace);
+
+ if (ret)
+ goto err;
+ break;
+ }
default:
BUG();
}
@@ -399,6 +451,9 @@ void bch2_bio_compress(struct bch_fs *c,
unsigned orig_dst = dst->bi_iter.bi_size;
unsigned orig_src = src->bi_iter.bi_size;
+ if (*compression_type == BCH_COMPRESSION_LZ4)
+ *compression_type = BCH_COMPRESSION_ZSTD;
+
/* Don't consume more than BCH_ENCODED_EXTENT_MAX from @src: */
src->bi_iter.bi_size =
min(src->bi_iter.bi_size, BCH_ENCODED_EXTENT_MAX << 9);