xref: /aosp_15_r20/external/erofs-utils/lib/compressor.c (revision 33b1fccf6a0fada2c2875d400ed01119b7676ee5)
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) 2018-2019 HUAWEI, Inc.
4*33b1fccfSAndroid Build Coastguard Worker  *             http://www.huawei.com/
5*33b1fccfSAndroid Build Coastguard Worker  * Created by Gao Xiang <[email protected]>
6*33b1fccfSAndroid Build Coastguard Worker  */
7*33b1fccfSAndroid Build Coastguard Worker #include "erofs/internal.h"
8*33b1fccfSAndroid Build Coastguard Worker #include "compressor.h"
9*33b1fccfSAndroid Build Coastguard Worker #include "erofs/print.h"
10*33b1fccfSAndroid Build Coastguard Worker 
11*33b1fccfSAndroid Build Coastguard Worker static const struct erofs_algorithm erofs_algs[] = {
12*33b1fccfSAndroid Build Coastguard Worker 	{ "lz4",
13*33b1fccfSAndroid Build Coastguard Worker #if LZ4_ENABLED
14*33b1fccfSAndroid Build Coastguard Worker 		&erofs_compressor_lz4,
15*33b1fccfSAndroid Build Coastguard Worker #else
16*33b1fccfSAndroid Build Coastguard Worker 		NULL,
17*33b1fccfSAndroid Build Coastguard Worker #endif
18*33b1fccfSAndroid Build Coastguard Worker 	  Z_EROFS_COMPRESSION_LZ4, false },
19*33b1fccfSAndroid Build Coastguard Worker 
20*33b1fccfSAndroid Build Coastguard Worker #if LZ4HC_ENABLED
21*33b1fccfSAndroid Build Coastguard Worker 	{ "lz4hc", &erofs_compressor_lz4hc,
22*33b1fccfSAndroid Build Coastguard Worker 	  Z_EROFS_COMPRESSION_LZ4, true },
23*33b1fccfSAndroid Build Coastguard Worker #endif
24*33b1fccfSAndroid Build Coastguard Worker 
25*33b1fccfSAndroid Build Coastguard Worker 	{ "lzma",
26*33b1fccfSAndroid Build Coastguard Worker #if HAVE_LIBLZMA
27*33b1fccfSAndroid Build Coastguard Worker 		&erofs_compressor_lzma,
28*33b1fccfSAndroid Build Coastguard Worker #else
29*33b1fccfSAndroid Build Coastguard Worker 		NULL,
30*33b1fccfSAndroid Build Coastguard Worker #endif
31*33b1fccfSAndroid Build Coastguard Worker 	  Z_EROFS_COMPRESSION_LZMA, false },
32*33b1fccfSAndroid Build Coastguard Worker 
33*33b1fccfSAndroid Build Coastguard Worker 	{ "deflate", &erofs_compressor_deflate,
34*33b1fccfSAndroid Build Coastguard Worker 	  Z_EROFS_COMPRESSION_DEFLATE, false },
35*33b1fccfSAndroid Build Coastguard Worker 
36*33b1fccfSAndroid Build Coastguard Worker #if HAVE_LIBDEFLATE
37*33b1fccfSAndroid Build Coastguard Worker 	{ "libdeflate", &erofs_compressor_libdeflate,
38*33b1fccfSAndroid Build Coastguard Worker 	  Z_EROFS_COMPRESSION_DEFLATE, true },
39*33b1fccfSAndroid Build Coastguard Worker #endif
40*33b1fccfSAndroid Build Coastguard Worker 
41*33b1fccfSAndroid Build Coastguard Worker 	{ "zstd",
42*33b1fccfSAndroid Build Coastguard Worker #ifdef HAVE_LIBZSTD
43*33b1fccfSAndroid Build Coastguard Worker 		&erofs_compressor_libzstd,
44*33b1fccfSAndroid Build Coastguard Worker #else
45*33b1fccfSAndroid Build Coastguard Worker 		NULL,
46*33b1fccfSAndroid Build Coastguard Worker #endif
47*33b1fccfSAndroid Build Coastguard Worker 	  Z_EROFS_COMPRESSION_ZSTD, false },
48*33b1fccfSAndroid Build Coastguard Worker };
49*33b1fccfSAndroid Build Coastguard Worker 
z_erofs_get_compress_algorithm_id(const struct erofs_compress * c)50*33b1fccfSAndroid Build Coastguard Worker int z_erofs_get_compress_algorithm_id(const struct erofs_compress *c)
51*33b1fccfSAndroid Build Coastguard Worker {
52*33b1fccfSAndroid Build Coastguard Worker 	DBG_BUGON(!c->alg);
53*33b1fccfSAndroid Build Coastguard Worker 	return c->alg->id;
54*33b1fccfSAndroid Build Coastguard Worker }
55*33b1fccfSAndroid Build Coastguard Worker 
z_erofs_list_supported_algorithms(int i,unsigned int * mask)56*33b1fccfSAndroid Build Coastguard Worker const char *z_erofs_list_supported_algorithms(int i, unsigned int *mask)
57*33b1fccfSAndroid Build Coastguard Worker {
58*33b1fccfSAndroid Build Coastguard Worker 	if (i >= ARRAY_SIZE(erofs_algs))
59*33b1fccfSAndroid Build Coastguard Worker 		return NULL;
60*33b1fccfSAndroid Build Coastguard Worker 	if (!erofs_algs[i].optimisor && (*mask & (1 << erofs_algs[i].id))) {
61*33b1fccfSAndroid Build Coastguard Worker 		*mask ^= 1 << erofs_algs[i].id;
62*33b1fccfSAndroid Build Coastguard Worker 		return erofs_algs[i].name;
63*33b1fccfSAndroid Build Coastguard Worker 	}
64*33b1fccfSAndroid Build Coastguard Worker 	return "";
65*33b1fccfSAndroid Build Coastguard Worker }
66*33b1fccfSAndroid Build Coastguard Worker 
z_erofs_list_available_compressors(int * i)67*33b1fccfSAndroid Build Coastguard Worker const struct erofs_algorithm *z_erofs_list_available_compressors(int *i)
68*33b1fccfSAndroid Build Coastguard Worker {
69*33b1fccfSAndroid Build Coastguard Worker 	for (;*i < ARRAY_SIZE(erofs_algs); ++*i) {
70*33b1fccfSAndroid Build Coastguard Worker 		if (!erofs_algs[*i].c)
71*33b1fccfSAndroid Build Coastguard Worker 			continue;
72*33b1fccfSAndroid Build Coastguard Worker 		return &erofs_algs[(*i)++];
73*33b1fccfSAndroid Build Coastguard Worker 	}
74*33b1fccfSAndroid Build Coastguard Worker 	return NULL;
75*33b1fccfSAndroid Build Coastguard Worker }
76*33b1fccfSAndroid Build Coastguard Worker 
erofs_compress_destsize(const struct erofs_compress * c,const void * src,unsigned int * srcsize,void * dst,unsigned int dstsize)77*33b1fccfSAndroid Build Coastguard Worker int erofs_compress_destsize(const struct erofs_compress *c,
78*33b1fccfSAndroid Build Coastguard Worker 			    const void *src, unsigned int *srcsize,
79*33b1fccfSAndroid Build Coastguard Worker 			    void *dst, unsigned int dstsize)
80*33b1fccfSAndroid Build Coastguard Worker {
81*33b1fccfSAndroid Build Coastguard Worker 	DBG_BUGON(!c->alg);
82*33b1fccfSAndroid Build Coastguard Worker 	if (!c->alg->c->compress_destsize)
83*33b1fccfSAndroid Build Coastguard Worker 		return -EOPNOTSUPP;
84*33b1fccfSAndroid Build Coastguard Worker 
85*33b1fccfSAndroid Build Coastguard Worker 	return c->alg->c->compress_destsize(c, src, srcsize, dst, dstsize);
86*33b1fccfSAndroid Build Coastguard Worker }
87*33b1fccfSAndroid Build Coastguard Worker 
erofs_compressor_init(struct erofs_sb_info * sbi,struct erofs_compress * c,char * alg_name,int compression_level,u32 dict_size)88*33b1fccfSAndroid Build Coastguard Worker int erofs_compressor_init(struct erofs_sb_info *sbi, struct erofs_compress *c,
89*33b1fccfSAndroid Build Coastguard Worker 			  char *alg_name, int compression_level, u32 dict_size)
90*33b1fccfSAndroid Build Coastguard Worker {
91*33b1fccfSAndroid Build Coastguard Worker 	int ret, i;
92*33b1fccfSAndroid Build Coastguard Worker 
93*33b1fccfSAndroid Build Coastguard Worker 	c->sbi = sbi;
94*33b1fccfSAndroid Build Coastguard Worker 
95*33b1fccfSAndroid Build Coastguard Worker 	/* should be written in "minimum compression ratio * 100" */
96*33b1fccfSAndroid Build Coastguard Worker 	c->compress_threshold = 100;
97*33b1fccfSAndroid Build Coastguard Worker 	c->compression_level = -1;
98*33b1fccfSAndroid Build Coastguard Worker 	c->dict_size = 0;
99*33b1fccfSAndroid Build Coastguard Worker 
100*33b1fccfSAndroid Build Coastguard Worker 	if (!alg_name) {
101*33b1fccfSAndroid Build Coastguard Worker 		c->alg = NULL;
102*33b1fccfSAndroid Build Coastguard Worker 		return 0;
103*33b1fccfSAndroid Build Coastguard Worker 	}
104*33b1fccfSAndroid Build Coastguard Worker 
105*33b1fccfSAndroid Build Coastguard Worker 	ret = -EINVAL;
106*33b1fccfSAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(erofs_algs); ++i) {
107*33b1fccfSAndroid Build Coastguard Worker 		if (alg_name && strcmp(alg_name, erofs_algs[i].name))
108*33b1fccfSAndroid Build Coastguard Worker 			continue;
109*33b1fccfSAndroid Build Coastguard Worker 
110*33b1fccfSAndroid Build Coastguard Worker 		if (!erofs_algs[i].c)
111*33b1fccfSAndroid Build Coastguard Worker 			continue;
112*33b1fccfSAndroid Build Coastguard Worker 
113*33b1fccfSAndroid Build Coastguard Worker 		if (erofs_algs[i].c->setlevel) {
114*33b1fccfSAndroid Build Coastguard Worker 			ret = erofs_algs[i].c->setlevel(c, compression_level);
115*33b1fccfSAndroid Build Coastguard Worker 			if (ret) {
116*33b1fccfSAndroid Build Coastguard Worker 				erofs_err("failed to set compression level %d for %s",
117*33b1fccfSAndroid Build Coastguard Worker 					  compression_level, alg_name);
118*33b1fccfSAndroid Build Coastguard Worker 				return ret;
119*33b1fccfSAndroid Build Coastguard Worker 			}
120*33b1fccfSAndroid Build Coastguard Worker 		} else if (compression_level >= 0) {
121*33b1fccfSAndroid Build Coastguard Worker 			erofs_err("compression level %d is not supported for %s",
122*33b1fccfSAndroid Build Coastguard Worker 				  compression_level, alg_name);
123*33b1fccfSAndroid Build Coastguard Worker 			return -EINVAL;
124*33b1fccfSAndroid Build Coastguard Worker 		}
125*33b1fccfSAndroid Build Coastguard Worker 
126*33b1fccfSAndroid Build Coastguard Worker 		if (erofs_algs[i].c->setdictsize) {
127*33b1fccfSAndroid Build Coastguard Worker 			ret = erofs_algs[i].c->setdictsize(c, dict_size);
128*33b1fccfSAndroid Build Coastguard Worker 			if (ret) {
129*33b1fccfSAndroid Build Coastguard Worker 				erofs_err("failed to set dict size %u for %s",
130*33b1fccfSAndroid Build Coastguard Worker 					  dict_size, alg_name);
131*33b1fccfSAndroid Build Coastguard Worker 				return ret;
132*33b1fccfSAndroid Build Coastguard Worker 			}
133*33b1fccfSAndroid Build Coastguard Worker 		} else if (dict_size) {
134*33b1fccfSAndroid Build Coastguard Worker 			erofs_err("dict size is not supported for %s",
135*33b1fccfSAndroid Build Coastguard Worker 				  alg_name);
136*33b1fccfSAndroid Build Coastguard Worker 			return -EINVAL;
137*33b1fccfSAndroid Build Coastguard Worker 		}
138*33b1fccfSAndroid Build Coastguard Worker 
139*33b1fccfSAndroid Build Coastguard Worker 		ret = erofs_algs[i].c->init(c);
140*33b1fccfSAndroid Build Coastguard Worker 		if (ret)
141*33b1fccfSAndroid Build Coastguard Worker 			return ret;
142*33b1fccfSAndroid Build Coastguard Worker 
143*33b1fccfSAndroid Build Coastguard Worker 		if (!ret) {
144*33b1fccfSAndroid Build Coastguard Worker 			c->alg = &erofs_algs[i];
145*33b1fccfSAndroid Build Coastguard Worker 			return 0;
146*33b1fccfSAndroid Build Coastguard Worker 		}
147*33b1fccfSAndroid Build Coastguard Worker 	}
148*33b1fccfSAndroid Build Coastguard Worker 	erofs_err("Cannot find a valid compressor %s", alg_name);
149*33b1fccfSAndroid Build Coastguard Worker 	return ret;
150*33b1fccfSAndroid Build Coastguard Worker }
151*33b1fccfSAndroid Build Coastguard Worker 
erofs_compressor_exit(struct erofs_compress * c)152*33b1fccfSAndroid Build Coastguard Worker int erofs_compressor_exit(struct erofs_compress *c)
153*33b1fccfSAndroid Build Coastguard Worker {
154*33b1fccfSAndroid Build Coastguard Worker 	if (c->alg && c->alg->c->exit)
155*33b1fccfSAndroid Build Coastguard Worker 		return c->alg->c->exit(c);
156*33b1fccfSAndroid Build Coastguard Worker 	return 0;
157*33b1fccfSAndroid Build Coastguard Worker }
158*33b1fccfSAndroid Build Coastguard Worker 
erofs_compressor_reset(struct erofs_compress * c)159*33b1fccfSAndroid Build Coastguard Worker void erofs_compressor_reset(struct erofs_compress *c)
160*33b1fccfSAndroid Build Coastguard Worker {
161*33b1fccfSAndroid Build Coastguard Worker 	if (c->alg && c->alg->c->reset)
162*33b1fccfSAndroid Build Coastguard Worker 		c->alg->c->reset(c);
163*33b1fccfSAndroid Build Coastguard Worker }
164