1 // SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0
2 /*
3 * Copyright (C) 2023, Alibaba Cloud
4 * Copyright (C) 2023, Gao Xiang <[email protected]>
5 */
6 #include "erofs/internal.h"
7 #include "erofs/print.h"
8 #include "erofs/config.h"
9 #include "compressor.h"
10 #include "erofs/atomic.h"
11
12 void *kite_deflate_init(int level, unsigned int dict_size);
13 void kite_deflate_end(void *s);
14 int kite_deflate_destsize(void *s, const u8 *in, u8 *out,
15 unsigned int *srcsize, unsigned int target_dstsize);
16
deflate_compress_destsize(const struct erofs_compress * c,const void * src,unsigned int * srcsize,void * dst,unsigned int dstsize)17 static int deflate_compress_destsize(const struct erofs_compress *c,
18 const void *src, unsigned int *srcsize,
19 void *dst, unsigned int dstsize)
20 {
21 int rc = kite_deflate_destsize(c->private_data, src, dst,
22 srcsize, dstsize);
23
24 if (rc <= 0)
25 return -EFAULT;
26 return rc;
27 }
28
compressor_deflate_exit(struct erofs_compress * c)29 static int compressor_deflate_exit(struct erofs_compress *c)
30 {
31 if (!c->private_data)
32 return -EINVAL;
33
34 kite_deflate_end(c->private_data);
35 return 0;
36 }
37
compressor_deflate_init(struct erofs_compress * c)38 static int compressor_deflate_init(struct erofs_compress *c)
39 {
40 static erofs_atomic_bool_t __warnonce;
41
42 if (c->private_data) {
43 kite_deflate_end(c->private_data);
44 c->private_data = NULL;
45 }
46 c->private_data = kite_deflate_init(c->compression_level, c->dict_size);
47 if (IS_ERR_VALUE(c->private_data))
48 return PTR_ERR(c->private_data);
49
50 if (!erofs_atomic_test_and_set(&__warnonce)) {
51 erofs_warn("EXPERIMENTAL DEFLATE algorithm in use. Use at your own risk!");
52 erofs_warn("*Carefully* check filesystem data correctness to avoid corruption!");
53 erofs_warn("Please send a report to <[email protected]> if something is wrong.");
54 }
55 return 0;
56 }
57
erofs_compressor_deflate_setlevel(struct erofs_compress * c,int compression_level)58 static int erofs_compressor_deflate_setlevel(struct erofs_compress *c,
59 int compression_level)
60 {
61 if (compression_level < 0)
62 compression_level = erofs_compressor_deflate.default_level;
63
64 if (compression_level > erofs_compressor_deflate.best_level) {
65 erofs_err("invalid compression level %d", compression_level);
66 return -EINVAL;
67 }
68 c->compression_level = compression_level;
69 return 0;
70 }
71
erofs_compressor_deflate_setdictsize(struct erofs_compress * c,u32 dict_size)72 static int erofs_compressor_deflate_setdictsize(struct erofs_compress *c,
73 u32 dict_size)
74 {
75 if (!dict_size)
76 dict_size = erofs_compressor_deflate.default_dictsize;
77
78 if (dict_size > erofs_compressor_deflate.max_dictsize) {
79 erofs_err("dictionary size %u is too large", dict_size);
80 return -EINVAL;
81 }
82 c->dict_size = dict_size;
83 return 0;
84 }
85
86 const struct erofs_compressor erofs_compressor_deflate = {
87 .default_level = 1,
88 .best_level = 9,
89 .default_dictsize = 1 << 15,
90 .max_dictsize = 1 << 15,
91 .init = compressor_deflate_init,
92 .exit = compressor_deflate_exit,
93 .setlevel = erofs_compressor_deflate_setlevel,
94 .setdictsize = erofs_compressor_deflate_setdictsize,
95 .compress_destsize = deflate_compress_destsize,
96 };
97