xref: /OK3568_Linux_fs/kernel/fs/ubifs/compress.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * This file is part of UBIFS.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2006-2008 Nokia Corporation.
6*4882a593Smuzhiyun  * Copyright (C) 2006, 2007 University of Szeged, Hungary
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * Authors: Adrian Hunter
9*4882a593Smuzhiyun  *          Artem Bityutskiy (Битюцкий Артём)
10*4882a593Smuzhiyun  *          Zoltan Sogor
11*4882a593Smuzhiyun  */
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun /*
14*4882a593Smuzhiyun  * This file provides a single place to access to compression and
15*4882a593Smuzhiyun  * decompression.
16*4882a593Smuzhiyun  */
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun #include <linux/crypto.h>
19*4882a593Smuzhiyun #include "ubifs.h"
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun /* Fake description object for the "none" compressor */
22*4882a593Smuzhiyun static struct ubifs_compressor none_compr = {
23*4882a593Smuzhiyun 	.compr_type = UBIFS_COMPR_NONE,
24*4882a593Smuzhiyun 	.name = "none",
25*4882a593Smuzhiyun 	.capi_name = "",
26*4882a593Smuzhiyun };
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #ifdef CONFIG_UBIFS_FS_LZO
29*4882a593Smuzhiyun static DEFINE_MUTEX(lzo_mutex);
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun static struct ubifs_compressor lzo_compr = {
32*4882a593Smuzhiyun 	.compr_type = UBIFS_COMPR_LZO,
33*4882a593Smuzhiyun 	.comp_mutex = &lzo_mutex,
34*4882a593Smuzhiyun 	.name = "lzo",
35*4882a593Smuzhiyun 	.capi_name = "lzo",
36*4882a593Smuzhiyun };
37*4882a593Smuzhiyun #else
38*4882a593Smuzhiyun static struct ubifs_compressor lzo_compr = {
39*4882a593Smuzhiyun 	.compr_type = UBIFS_COMPR_LZO,
40*4882a593Smuzhiyun 	.name = "lzo",
41*4882a593Smuzhiyun };
42*4882a593Smuzhiyun #endif
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun #ifdef CONFIG_UBIFS_FS_ZLIB
45*4882a593Smuzhiyun static DEFINE_MUTEX(deflate_mutex);
46*4882a593Smuzhiyun static DEFINE_MUTEX(inflate_mutex);
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun static struct ubifs_compressor zlib_compr = {
49*4882a593Smuzhiyun 	.compr_type = UBIFS_COMPR_ZLIB,
50*4882a593Smuzhiyun 	.comp_mutex = &deflate_mutex,
51*4882a593Smuzhiyun 	.decomp_mutex = &inflate_mutex,
52*4882a593Smuzhiyun 	.name = "zlib",
53*4882a593Smuzhiyun 	.capi_name = "deflate",
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun #else
56*4882a593Smuzhiyun static struct ubifs_compressor zlib_compr = {
57*4882a593Smuzhiyun 	.compr_type = UBIFS_COMPR_ZLIB,
58*4882a593Smuzhiyun 	.name = "zlib",
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun #endif
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun #ifdef CONFIG_UBIFS_FS_ZSTD
63*4882a593Smuzhiyun static DEFINE_MUTEX(zstd_enc_mutex);
64*4882a593Smuzhiyun static DEFINE_MUTEX(zstd_dec_mutex);
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun static struct ubifs_compressor zstd_compr = {
67*4882a593Smuzhiyun 	.compr_type = UBIFS_COMPR_ZSTD,
68*4882a593Smuzhiyun 	.comp_mutex = &zstd_enc_mutex,
69*4882a593Smuzhiyun 	.decomp_mutex = &zstd_dec_mutex,
70*4882a593Smuzhiyun 	.name = "zstd",
71*4882a593Smuzhiyun 	.capi_name = "zstd",
72*4882a593Smuzhiyun };
73*4882a593Smuzhiyun #else
74*4882a593Smuzhiyun static struct ubifs_compressor zstd_compr = {
75*4882a593Smuzhiyun 	.compr_type = UBIFS_COMPR_ZSTD,
76*4882a593Smuzhiyun 	.name = "zstd",
77*4882a593Smuzhiyun };
78*4882a593Smuzhiyun #endif
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun /* All UBIFS compressors */
81*4882a593Smuzhiyun struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun /**
84*4882a593Smuzhiyun  * ubifs_compress - compress data.
85*4882a593Smuzhiyun  * @in_buf: data to compress
86*4882a593Smuzhiyun  * @in_len: length of the data to compress
87*4882a593Smuzhiyun  * @out_buf: output buffer where compressed data should be stored
88*4882a593Smuzhiyun  * @out_len: output buffer length is returned here
89*4882a593Smuzhiyun  * @compr_type: type of compression to use on enter, actually used compression
90*4882a593Smuzhiyun  *              type on exit
91*4882a593Smuzhiyun  *
92*4882a593Smuzhiyun  * This function compresses input buffer @in_buf of length @in_len and stores
93*4882a593Smuzhiyun  * the result in the output buffer @out_buf and the resulting length in
94*4882a593Smuzhiyun  * @out_len. If the input buffer does not compress, it is just copied to the
95*4882a593Smuzhiyun  * @out_buf. The same happens if @compr_type is %UBIFS_COMPR_NONE or if
96*4882a593Smuzhiyun  * compression error occurred.
97*4882a593Smuzhiyun  *
98*4882a593Smuzhiyun  * Note, if the input buffer was not compressed, it is copied to the output
99*4882a593Smuzhiyun  * buffer and %UBIFS_COMPR_NONE is returned in @compr_type.
100*4882a593Smuzhiyun  */
ubifs_compress(const struct ubifs_info * c,const void * in_buf,int in_len,void * out_buf,int * out_len,int * compr_type)101*4882a593Smuzhiyun void ubifs_compress(const struct ubifs_info *c, const void *in_buf,
102*4882a593Smuzhiyun 		    int in_len, void *out_buf, int *out_len, int *compr_type)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun 	int err;
105*4882a593Smuzhiyun 	struct ubifs_compressor *compr = ubifs_compressors[*compr_type];
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	if (*compr_type == UBIFS_COMPR_NONE)
108*4882a593Smuzhiyun 		goto no_compr;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	/* If the input data is small, do not even try to compress it */
111*4882a593Smuzhiyun 	if (in_len < UBIFS_MIN_COMPR_LEN)
112*4882a593Smuzhiyun 		goto no_compr;
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	if (compr->comp_mutex)
115*4882a593Smuzhiyun 		mutex_lock(compr->comp_mutex);
116*4882a593Smuzhiyun 	err = crypto_comp_compress(compr->cc, in_buf, in_len, out_buf,
117*4882a593Smuzhiyun 				   (unsigned int *)out_len);
118*4882a593Smuzhiyun 	if (compr->comp_mutex)
119*4882a593Smuzhiyun 		mutex_unlock(compr->comp_mutex);
120*4882a593Smuzhiyun 	if (unlikely(err)) {
121*4882a593Smuzhiyun 		ubifs_warn(c, "cannot compress %d bytes, compressor %s, error %d, leave data uncompressed",
122*4882a593Smuzhiyun 			   in_len, compr->name, err);
123*4882a593Smuzhiyun 		goto no_compr;
124*4882a593Smuzhiyun 	}
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	/*
127*4882a593Smuzhiyun 	 * If the data compressed only slightly, it is better to leave it
128*4882a593Smuzhiyun 	 * uncompressed to improve read speed.
129*4882a593Smuzhiyun 	 */
130*4882a593Smuzhiyun 	if (in_len - *out_len < UBIFS_MIN_COMPRESS_DIFF)
131*4882a593Smuzhiyun 		goto no_compr;
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	return;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun no_compr:
136*4882a593Smuzhiyun 	memcpy(out_buf, in_buf, in_len);
137*4882a593Smuzhiyun 	*out_len = in_len;
138*4882a593Smuzhiyun 	*compr_type = UBIFS_COMPR_NONE;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun /**
142*4882a593Smuzhiyun  * ubifs_decompress - decompress data.
143*4882a593Smuzhiyun  * @in_buf: data to decompress
144*4882a593Smuzhiyun  * @in_len: length of the data to decompress
145*4882a593Smuzhiyun  * @out_buf: output buffer where decompressed data should
146*4882a593Smuzhiyun  * @out_len: output length is returned here
147*4882a593Smuzhiyun  * @compr_type: type of compression
148*4882a593Smuzhiyun  *
149*4882a593Smuzhiyun  * This function decompresses data from buffer @in_buf into buffer @out_buf.
150*4882a593Smuzhiyun  * The length of the uncompressed data is returned in @out_len. This functions
151*4882a593Smuzhiyun  * returns %0 on success or a negative error code on failure.
152*4882a593Smuzhiyun  */
ubifs_decompress(const struct ubifs_info * c,const void * in_buf,int in_len,void * out_buf,int * out_len,int compr_type)153*4882a593Smuzhiyun int ubifs_decompress(const struct ubifs_info *c, const void *in_buf,
154*4882a593Smuzhiyun 		     int in_len, void *out_buf, int *out_len, int compr_type)
155*4882a593Smuzhiyun {
156*4882a593Smuzhiyun 	int err;
157*4882a593Smuzhiyun 	struct ubifs_compressor *compr;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	if (unlikely(compr_type < 0 || compr_type >= UBIFS_COMPR_TYPES_CNT)) {
160*4882a593Smuzhiyun 		ubifs_err(c, "invalid compression type %d", compr_type);
161*4882a593Smuzhiyun 		return -EINVAL;
162*4882a593Smuzhiyun 	}
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	compr = ubifs_compressors[compr_type];
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	if (unlikely(!compr->capi_name)) {
167*4882a593Smuzhiyun 		ubifs_err(c, "%s compression is not compiled in", compr->name);
168*4882a593Smuzhiyun 		return -EINVAL;
169*4882a593Smuzhiyun 	}
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	if (compr_type == UBIFS_COMPR_NONE) {
172*4882a593Smuzhiyun 		memcpy(out_buf, in_buf, in_len);
173*4882a593Smuzhiyun 		*out_len = in_len;
174*4882a593Smuzhiyun 		return 0;
175*4882a593Smuzhiyun 	}
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	if (compr->decomp_mutex)
178*4882a593Smuzhiyun 		mutex_lock(compr->decomp_mutex);
179*4882a593Smuzhiyun 	err = crypto_comp_decompress(compr->cc, in_buf, in_len, out_buf,
180*4882a593Smuzhiyun 				     (unsigned int *)out_len);
181*4882a593Smuzhiyun 	if (compr->decomp_mutex)
182*4882a593Smuzhiyun 		mutex_unlock(compr->decomp_mutex);
183*4882a593Smuzhiyun 	if (err)
184*4882a593Smuzhiyun 		ubifs_err(c, "cannot decompress %d bytes, compressor %s, error %d",
185*4882a593Smuzhiyun 			  in_len, compr->name, err);
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	return err;
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun /**
191*4882a593Smuzhiyun  * compr_init - initialize a compressor.
192*4882a593Smuzhiyun  * @compr: compressor description object
193*4882a593Smuzhiyun  *
194*4882a593Smuzhiyun  * This function initializes the requested compressor and returns zero in case
195*4882a593Smuzhiyun  * of success or a negative error code in case of failure.
196*4882a593Smuzhiyun  */
compr_init(struct ubifs_compressor * compr)197*4882a593Smuzhiyun static int __init compr_init(struct ubifs_compressor *compr)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun 	if (compr->capi_name) {
200*4882a593Smuzhiyun 		compr->cc = crypto_alloc_comp(compr->capi_name, 0, 0);
201*4882a593Smuzhiyun 		if (IS_ERR(compr->cc)) {
202*4882a593Smuzhiyun 			pr_err("UBIFS error (pid %d): cannot initialize compressor %s, error %ld",
203*4882a593Smuzhiyun 			       current->pid, compr->name, PTR_ERR(compr->cc));
204*4882a593Smuzhiyun 			return PTR_ERR(compr->cc);
205*4882a593Smuzhiyun 		}
206*4882a593Smuzhiyun 	}
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	ubifs_compressors[compr->compr_type] = compr;
209*4882a593Smuzhiyun 	return 0;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun /**
213*4882a593Smuzhiyun  * compr_exit - de-initialize a compressor.
214*4882a593Smuzhiyun  * @compr: compressor description object
215*4882a593Smuzhiyun  */
compr_exit(struct ubifs_compressor * compr)216*4882a593Smuzhiyun static void compr_exit(struct ubifs_compressor *compr)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun 	if (compr->capi_name)
219*4882a593Smuzhiyun 		crypto_free_comp(compr->cc);
220*4882a593Smuzhiyun 	return;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun /**
224*4882a593Smuzhiyun  * ubifs_compressors_init - initialize UBIFS compressors.
225*4882a593Smuzhiyun  *
226*4882a593Smuzhiyun  * This function initializes the compressor which were compiled in. Returns
227*4882a593Smuzhiyun  * zero in case of success and a negative error code in case of failure.
228*4882a593Smuzhiyun  */
ubifs_compressors_init(void)229*4882a593Smuzhiyun int __init ubifs_compressors_init(void)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun 	int err;
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	err = compr_init(&lzo_compr);
234*4882a593Smuzhiyun 	if (err)
235*4882a593Smuzhiyun 		return err;
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	err = compr_init(&zstd_compr);
238*4882a593Smuzhiyun 	if (err)
239*4882a593Smuzhiyun 		goto out_lzo;
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	err = compr_init(&zlib_compr);
242*4882a593Smuzhiyun 	if (err)
243*4882a593Smuzhiyun 		goto out_zstd;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	ubifs_compressors[UBIFS_COMPR_NONE] = &none_compr;
246*4882a593Smuzhiyun 	return 0;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun out_zstd:
249*4882a593Smuzhiyun 	compr_exit(&zstd_compr);
250*4882a593Smuzhiyun out_lzo:
251*4882a593Smuzhiyun 	compr_exit(&lzo_compr);
252*4882a593Smuzhiyun 	return err;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun /**
256*4882a593Smuzhiyun  * ubifs_compressors_exit - de-initialize UBIFS compressors.
257*4882a593Smuzhiyun  */
ubifs_compressors_exit(void)258*4882a593Smuzhiyun void ubifs_compressors_exit(void)
259*4882a593Smuzhiyun {
260*4882a593Smuzhiyun 	compr_exit(&lzo_compr);
261*4882a593Smuzhiyun 	compr_exit(&zlib_compr);
262*4882a593Smuzhiyun 	compr_exit(&zstd_compr);
263*4882a593Smuzhiyun }
264