decompressor_crypto.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. #include <linux/scatterlist.h>
  3. #include <crypto/acompress.h>
  4. #include "compress.h"
  5. static int __z_erofs_crypto_decompress(struct z_erofs_decompress_req *rq,
  6. struct crypto_acomp *tfm)
  7. {
  8. struct sg_table st_src, st_dst;
  9. struct acomp_req *req;
  10. struct crypto_wait wait;
  11. const char *reason;
  12. u8 *headpage;
  13. int ret;
  14. headpage = kmap_local_page(*rq->in);
  15. reason = z_erofs_fixup_insize(rq, headpage + rq->pageofs_in,
  16. min_t(unsigned int, rq->inputsize,
  17. rq->sb->s_blocksize - rq->pageofs_in));
  18. kunmap_local(headpage);
  19. if (reason)
  20. return IS_ERR(reason) ? PTR_ERR(reason) : -EFSCORRUPTED;
  21. req = acomp_request_alloc(tfm);
  22. if (!req)
  23. return -ENOMEM;
  24. ret = sg_alloc_table_from_pages_segment(&st_src, rq->in, rq->inpages,
  25. rq->pageofs_in, rq->inputsize, UINT_MAX, GFP_KERNEL);
  26. if (ret < 0)
  27. goto failed_src_alloc;
  28. ret = sg_alloc_table_from_pages_segment(&st_dst, rq->out, rq->outpages,
  29. rq->pageofs_out, rq->outputsize, UINT_MAX, GFP_KERNEL);
  30. if (ret < 0)
  31. goto failed_dst_alloc;
  32. acomp_request_set_params(req, st_src.sgl,
  33. st_dst.sgl, rq->inputsize, rq->outputsize);
  34. crypto_init_wait(&wait);
  35. acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
  36. crypto_req_done, &wait);
  37. ret = crypto_wait_req(crypto_acomp_decompress(req), &wait);
  38. if (ret) {
  39. erofs_err(rq->sb, "failed to decompress %d in[%u, %u] out[%u]",
  40. ret, rq->inputsize, rq->pageofs_in, rq->outputsize);
  41. ret = -EIO;
  42. }
  43. sg_free_table(&st_dst);
  44. failed_dst_alloc:
  45. sg_free_table(&st_src);
  46. failed_src_alloc:
  47. acomp_request_free(req);
  48. return ret;
  49. }
  50. struct z_erofs_crypto_engine {
  51. char *crypto_name;
  52. struct crypto_acomp *tfm;
  53. };
  54. static struct z_erofs_crypto_engine *z_erofs_crypto[Z_EROFS_COMPRESSION_MAX] = {
  55. [Z_EROFS_COMPRESSION_LZ4] = (struct z_erofs_crypto_engine[]) {
  56. {},
  57. },
  58. [Z_EROFS_COMPRESSION_LZMA] = (struct z_erofs_crypto_engine[]) {
  59. {},
  60. },
  61. [Z_EROFS_COMPRESSION_DEFLATE] = (struct z_erofs_crypto_engine[]) {
  62. { .crypto_name = "qat_deflate", },
  63. {},
  64. },
  65. [Z_EROFS_COMPRESSION_ZSTD] = (struct z_erofs_crypto_engine[]) {
  66. {},
  67. },
  68. };
  69. static DECLARE_RWSEM(z_erofs_crypto_rwsem);
  70. static struct crypto_acomp *z_erofs_crypto_get_engine(int alg)
  71. {
  72. struct z_erofs_crypto_engine *e;
  73. for (e = z_erofs_crypto[alg]; e->crypto_name; ++e)
  74. if (e->tfm)
  75. return e->tfm;
  76. return NULL;
  77. }
  78. int z_erofs_crypto_decompress(struct z_erofs_decompress_req *rq,
  79. struct page **pgpl)
  80. {
  81. struct crypto_acomp *tfm;
  82. int i, err;
  83. down_read(&z_erofs_crypto_rwsem);
  84. tfm = z_erofs_crypto_get_engine(rq->alg);
  85. if (!tfm) {
  86. err = -EOPNOTSUPP;
  87. goto out;
  88. }
  89. for (i = 0; i < rq->outpages; i++) {
  90. struct page *const page = rq->out[i];
  91. struct page *victim;
  92. if (!page) {
  93. victim = __erofs_allocpage(pgpl, rq->gfp, true);
  94. if (!victim) {
  95. err = -ENOMEM;
  96. goto out;
  97. }
  98. set_page_private(victim, Z_EROFS_SHORTLIVED_PAGE);
  99. rq->out[i] = victim;
  100. }
  101. }
  102. err = __z_erofs_crypto_decompress(rq, tfm);
  103. out:
  104. up_read(&z_erofs_crypto_rwsem);
  105. return err;
  106. }
  107. int z_erofs_crypto_enable_engine(const char *name, int len)
  108. {
  109. struct z_erofs_crypto_engine *e;
  110. struct crypto_acomp *tfm;
  111. int alg;
  112. down_write(&z_erofs_crypto_rwsem);
  113. for (alg = 0; alg < Z_EROFS_COMPRESSION_MAX; ++alg) {
  114. for (e = z_erofs_crypto[alg]; e->crypto_name; ++e) {
  115. if (!strncmp(name, e->crypto_name, len)) {
  116. if (e->tfm)
  117. break;
  118. tfm = crypto_alloc_acomp(e->crypto_name, 0, 0);
  119. if (IS_ERR(tfm)) {
  120. up_write(&z_erofs_crypto_rwsem);
  121. return -EOPNOTSUPP;
  122. }
  123. e->tfm = tfm;
  124. break;
  125. }
  126. }
  127. }
  128. up_write(&z_erofs_crypto_rwsem);
  129. return 0;
  130. }
  131. void z_erofs_crypto_disable_all_engines(void)
  132. {
  133. struct z_erofs_crypto_engine *e;
  134. int alg;
  135. down_write(&z_erofs_crypto_rwsem);
  136. for (alg = 0; alg < Z_EROFS_COMPRESSION_MAX; ++alg) {
  137. for (e = z_erofs_crypto[alg]; e->crypto_name; ++e) {
  138. if (!e->tfm)
  139. continue;
  140. crypto_free_acomp(e->tfm);
  141. e->tfm = NULL;
  142. }
  143. }
  144. up_write(&z_erofs_crypto_rwsem);
  145. }
  146. int z_erofs_crypto_show_engines(char *buf, int size, char sep)
  147. {
  148. struct z_erofs_crypto_engine *e;
  149. int alg, len = 0;
  150. for (alg = 0; alg < Z_EROFS_COMPRESSION_MAX; ++alg) {
  151. for (e = z_erofs_crypto[alg]; e->crypto_name; ++e) {
  152. if (!e->tfm)
  153. continue;
  154. len += scnprintf(buf + len, size - len, "%s%c",
  155. e->crypto_name, sep);
  156. }
  157. }
  158. return len;
  159. }