Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/fs/erofs/decompressor_crypto.c
26278 views
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
183