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 <crypto/acompress.h> 19 #include <linux/highmem.h> 20 #include "ubifs.h" 21 22 /* Fake description object for the "none" compressor */ 23 static struct ubifs_compressor none_compr = { 24 .compr_type = UBIFS_COMPR_NONE, 25 .name = "none", 26 .capi_name = "", 27 }; 28 29 #ifdef CONFIG_UBIFS_FS_LZO 30 static struct ubifs_compressor lzo_compr = { 31 .compr_type = UBIFS_COMPR_LZO, 32 .name = "lzo", 33 .capi_name = "lzo", 34 }; 35 #else 36 static struct ubifs_compressor lzo_compr = { 37 .compr_type = UBIFS_COMPR_LZO, 38 .name = "lzo", 39 }; 40 #endif 41 42 #ifdef CONFIG_UBIFS_FS_ZLIB 43 static struct ubifs_compressor zlib_compr = { 44 .compr_type = UBIFS_COMPR_ZLIB, 45 .name = "zlib", 46 .capi_name = "deflate", 47 }; 48 #else 49 static struct ubifs_compressor zlib_compr = { 50 .compr_type = UBIFS_COMPR_ZLIB, 51 .name = "zlib", 52 }; 53 #endif 54 55 #ifdef CONFIG_UBIFS_FS_ZSTD 56 static struct ubifs_compressor zstd_compr = { 57 .compr_type = UBIFS_COMPR_ZSTD, 58 .name = "zstd", 59 .capi_name = "zstd", 60 }; 61 #else 62 static struct ubifs_compressor zstd_compr = { 63 .compr_type = UBIFS_COMPR_ZSTD, 64 .name = "zstd", 65 }; 66 #endif 67 68 /* All UBIFS compressors */ 69 struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT]; 70 71 static int ubifs_compress_req(const struct ubifs_info *c, 72 struct acomp_req *req, 73 void *out_buf, int *out_len, 74 const char *compr_name) 75 { 76 struct crypto_wait wait; 77 int in_len = req->slen; 78 int dlen = *out_len; 79 int err; 80 81 dlen = min(dlen, in_len - UBIFS_MIN_COMPRESS_DIFF); 82 83 crypto_init_wait(&wait); 84 acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 85 crypto_req_done, &wait); 86 acomp_request_set_dst_dma(req, out_buf, dlen); 87 err = crypto_acomp_compress(req); 88 err = crypto_wait_req(err, &wait); 89 *out_len = req->dlen; 90 acomp_request_free(req); 91 92 return err; 93 } 94 95 /** 96 * ubifs_compress - compress data. 97 * @c: UBIFS file-system description object 98 * @in_buf: data to compress 99 * @in_len: length of the data to compress 100 * @out_buf: output buffer where compressed data should be stored 101 * @out_len: output buffer length is returned here 102 * @compr_type: type of compression to use on enter, actually used compression 103 * type on exit 104 * 105 * This function compresses input buffer @in_buf of length @in_len and stores 106 * the result in the output buffer @out_buf and the resulting length in 107 * @out_len. If the input buffer does not compress, it is just copied to the 108 * @out_buf. The same happens if @compr_type is %UBIFS_COMPR_NONE or if 109 * compression error occurred. 110 * 111 * Note, if the input buffer was not compressed, it is copied to the output 112 * buffer and %UBIFS_COMPR_NONE is returned in @compr_type. 113 */ 114 void ubifs_compress(const struct ubifs_info *c, const void *in_buf, 115 int in_len, void *out_buf, int *out_len, int *compr_type) 116 { 117 int err; 118 struct ubifs_compressor *compr = ubifs_compressors[*compr_type]; 119 120 if (*compr_type == UBIFS_COMPR_NONE) 121 goto no_compr; 122 123 /* If the input data is small, do not even try to compress it */ 124 if (in_len < UBIFS_MIN_COMPR_LEN) 125 goto no_compr; 126 127 { 128 ACOMP_REQUEST_ALLOC(req, compr->cc, GFP_NOFS | __GFP_NOWARN); 129 130 acomp_request_set_src_dma(req, in_buf, in_len); 131 err = ubifs_compress_req(c, req, out_buf, out_len, compr->name); 132 } 133 134 if (err) 135 goto no_compr; 136 137 return; 138 139 no_compr: 140 memcpy(out_buf, in_buf, in_len); 141 *out_len = in_len; 142 *compr_type = UBIFS_COMPR_NONE; 143 } 144 145 /** 146 * ubifs_compress_folio - compress folio. 147 * @c: UBIFS file-system description object 148 * @in_folio: data to compress 149 * @in_offset: offset into @in_folio 150 * @in_len: length of the data to compress 151 * @out_buf: output buffer where compressed data should be stored 152 * @out_len: output buffer length is returned here 153 * @compr_type: type of compression to use on enter, actually used compression 154 * type on exit 155 * 156 * This function compresses input folio @in_folio of length @in_len and 157 * stores the result in the output buffer @out_buf and the resulting length 158 * in @out_len. If the input buffer does not compress, it is just copied 159 * to the @out_buf. The same happens if @compr_type is %UBIFS_COMPR_NONE 160 * or if compression error occurred. 161 * 162 * Note, if the input buffer was not compressed, it is copied to the output 163 * buffer and %UBIFS_COMPR_NONE is returned in @compr_type. 164 */ 165 void ubifs_compress_folio(const struct ubifs_info *c, struct folio *in_folio, 166 size_t in_offset, int in_len, void *out_buf, 167 int *out_len, int *compr_type) 168 { 169 int err; 170 struct ubifs_compressor *compr = ubifs_compressors[*compr_type]; 171 172 if (*compr_type == UBIFS_COMPR_NONE) 173 goto no_compr; 174 175 /* If the input data is small, do not even try to compress it */ 176 if (in_len < UBIFS_MIN_COMPR_LEN) 177 goto no_compr; 178 179 { 180 ACOMP_REQUEST_ALLOC(req, compr->cc, GFP_NOFS | __GFP_NOWARN); 181 182 acomp_request_set_src_folio(req, in_folio, in_offset, in_len); 183 err = ubifs_compress_req(c, req, out_buf, out_len, compr->name); 184 } 185 186 if (err) 187 goto no_compr; 188 189 return; 190 191 no_compr: 192 memcpy_from_folio(out_buf, in_folio, in_offset, in_len); 193 *out_len = in_len; 194 *compr_type = UBIFS_COMPR_NONE; 195 } 196 197 static int ubifs_decompress_req(const struct ubifs_info *c, 198 struct acomp_req *req, 199 const void *in_buf, int in_len, int *out_len, 200 const char *compr_name) 201 { 202 struct crypto_wait wait; 203 int err; 204 205 crypto_init_wait(&wait); 206 acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 207 crypto_req_done, &wait); 208 acomp_request_set_src_dma(req, in_buf, in_len); 209 err = crypto_acomp_decompress(req); 210 err = crypto_wait_req(err, &wait); 211 *out_len = req->dlen; 212 213 if (err) 214 ubifs_err(c, "cannot decompress %d bytes, compressor %s, error %d", 215 in_len, compr_name, err); 216 217 acomp_request_free(req); 218 219 return err; 220 } 221 222 /** 223 * ubifs_decompress - decompress data. 224 * @c: UBIFS file-system description object 225 * @in_buf: data to decompress 226 * @in_len: length of the data to decompress 227 * @out_buf: output buffer where decompressed data should 228 * @out_len: output length is returned here 229 * @compr_type: type of compression 230 * 231 * This function decompresses data from buffer @in_buf into buffer @out_buf. 232 * The length of the uncompressed data is returned in @out_len. This functions 233 * returns %0 on success or a negative error code on failure. 234 */ 235 int ubifs_decompress(const struct ubifs_info *c, const void *in_buf, 236 int in_len, void *out_buf, int *out_len, int compr_type) 237 { 238 struct ubifs_compressor *compr; 239 240 if (unlikely(compr_type < 0 || compr_type >= UBIFS_COMPR_TYPES_CNT)) { 241 ubifs_err(c, "invalid compression type %d", compr_type); 242 return -EINVAL; 243 } 244 245 compr = ubifs_compressors[compr_type]; 246 247 if (unlikely(!compr->capi_name)) { 248 ubifs_err(c, "%s compression is not compiled in", compr->name); 249 return -EINVAL; 250 } 251 252 if (compr_type == UBIFS_COMPR_NONE) { 253 memcpy(out_buf, in_buf, in_len); 254 *out_len = in_len; 255 return 0; 256 } 257 258 { 259 ACOMP_REQUEST_ALLOC(req, compr->cc, GFP_NOFS | __GFP_NOWARN); 260 261 acomp_request_set_dst_dma(req, out_buf, *out_len); 262 return ubifs_decompress_req(c, req, in_buf, in_len, out_len, 263 compr->name); 264 } 265 } 266 267 /** 268 * ubifs_decompress_folio - decompress folio. 269 * @c: UBIFS file-system description object 270 * @in_buf: data to decompress 271 * @in_len: length of the data to decompress 272 * @out_folio: output folio where decompressed data should 273 * @out_offset: offset into @out_folio 274 * @out_len: output length is returned here 275 * @compr_type: type of compression 276 * 277 * This function decompresses data from buffer @in_buf into folio 278 * @out_folio. The length of the uncompressed data is returned in 279 * @out_len. This functions returns %0 on success or a negative error 280 * code on failure. 281 */ 282 int ubifs_decompress_folio(const struct ubifs_info *c, const void *in_buf, 283 int in_len, struct folio *out_folio, 284 size_t out_offset, int *out_len, int compr_type) 285 { 286 struct ubifs_compressor *compr; 287 288 if (unlikely(compr_type < 0 || compr_type >= UBIFS_COMPR_TYPES_CNT)) { 289 ubifs_err(c, "invalid compression type %d", compr_type); 290 return -EINVAL; 291 } 292 293 compr = ubifs_compressors[compr_type]; 294 295 if (unlikely(!compr->capi_name)) { 296 ubifs_err(c, "%s compression is not compiled in", compr->name); 297 return -EINVAL; 298 } 299 300 if (compr_type == UBIFS_COMPR_NONE) { 301 memcpy_to_folio(out_folio, out_offset, in_buf, in_len); 302 *out_len = in_len; 303 return 0; 304 } 305 306 { 307 ACOMP_REQUEST_ALLOC(req, compr->cc, GFP_NOFS | __GFP_NOWARN); 308 309 acomp_request_set_dst_folio(req, out_folio, out_offset, 310 *out_len); 311 return ubifs_decompress_req(c, req, in_buf, in_len, out_len, 312 compr->name); 313 } 314 } 315 316 /** 317 * compr_init - initialize a compressor. 318 * @compr: compressor description object 319 * 320 * This function initializes the requested compressor and returns zero in case 321 * of success or a negative error code in case of failure. 322 */ 323 static int __init compr_init(struct ubifs_compressor *compr) 324 { 325 if (compr->capi_name) { 326 compr->cc = crypto_alloc_acomp(compr->capi_name, 0, 0); 327 if (IS_ERR(compr->cc)) { 328 pr_err("UBIFS error (pid %d): cannot initialize compressor %s, error %ld", 329 current->pid, compr->name, PTR_ERR(compr->cc)); 330 return PTR_ERR(compr->cc); 331 } 332 } 333 334 ubifs_compressors[compr->compr_type] = compr; 335 return 0; 336 } 337 338 /** 339 * compr_exit - de-initialize a compressor. 340 * @compr: compressor description object 341 */ 342 static void compr_exit(struct ubifs_compressor *compr) 343 { 344 if (compr->capi_name) 345 crypto_free_acomp(compr->cc); 346 } 347 348 /** 349 * ubifs_compressors_init - initialize UBIFS compressors. 350 * 351 * This function initializes the compressor which were compiled in. Returns 352 * zero in case of success and a negative error code in case of failure. 353 */ 354 int __init ubifs_compressors_init(void) 355 { 356 int err; 357 358 err = compr_init(&lzo_compr); 359 if (err) 360 return err; 361 362 err = compr_init(&zstd_compr); 363 if (err) 364 goto out_lzo; 365 366 err = compr_init(&zlib_compr); 367 if (err) 368 goto out_zstd; 369 370 ubifs_compressors[UBIFS_COMPR_NONE] = &none_compr; 371 return 0; 372 373 out_zstd: 374 compr_exit(&zstd_compr); 375 out_lzo: 376 compr_exit(&lzo_compr); 377 return err; 378 } 379 380 /** 381 * ubifs_compressors_exit - de-initialize UBIFS compressors. 382 */ 383 void ubifs_compressors_exit(void) 384 { 385 compr_exit(&lzo_compr); 386 compr_exit(&zlib_compr); 387 compr_exit(&zstd_compr); 388 } 389