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