compress.c 10 KB

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