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