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