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