Skip to content

Commit 2d3553e

Browse files
committed
crypto: scomp - Remove support for some non-trivial SG lists
As the only user of acomp/scomp uses a trivial single-page SG list, remove support for everything else in preprataion for the addition of virtual address support. However, keep support for non-trivial source SG lists as that user is currently jumping through hoops in order to linearise the source data. Limit the source SG linearisation buffer to a single page as that user never goes over that. The only other potential user is also unlikely to exceed that (IPComp) and it can easily do its own linearisation if necessary. Also keep the destination SG linearisation for IPComp. Signed-off-by: Herbert Xu <[email protected]>
1 parent 39a3f23 commit 2d3553e

File tree

4 files changed

+76
-71
lines changed

4 files changed

+76
-71
lines changed

crypto/acompress.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ static int crypto_acomp_init_tfm(struct crypto_tfm *tfm)
7373

7474
acomp->compress = alg->compress;
7575
acomp->decompress = alg->decompress;
76-
acomp->dst_free = alg->dst_free;
7776
acomp->reqsize = alg->reqsize;
7877

7978
if (alg->exit)

crypto/scompress.c

Lines changed: 73 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
#include <crypto/scatterwalk.h>
1313
#include <linux/cryptouser.h>
1414
#include <linux/err.h>
15+
#include <linux/highmem.h>
1516
#include <linux/kernel.h>
1617
#include <linux/module.h>
18+
#include <linux/overflow.h>
1719
#include <linux/scatterlist.h>
1820
#include <linux/seq_file.h>
1921
#include <linux/slab.h>
@@ -23,9 +25,14 @@
2325

2426
#include "compress.h"
2527

28+
#define SCOMP_SCRATCH_SIZE 65400
29+
2630
struct scomp_scratch {
2731
spinlock_t lock;
28-
void *src;
32+
union {
33+
void *src;
34+
unsigned long saddr;
35+
};
2936
void *dst;
3037
};
3138

@@ -66,7 +73,7 @@ static void crypto_scomp_free_scratches(void)
6673
for_each_possible_cpu(i) {
6774
scratch = per_cpu_ptr(&scomp_scratch, i);
6875

69-
vfree(scratch->src);
76+
free_page(scratch->saddr);
7077
vfree(scratch->dst);
7178
scratch->src = NULL;
7279
scratch->dst = NULL;
@@ -79,14 +86,15 @@ static int crypto_scomp_alloc_scratches(void)
7986
int i;
8087

8188
for_each_possible_cpu(i) {
89+
struct page *page;
8290
void *mem;
8391

8492
scratch = per_cpu_ptr(&scomp_scratch, i);
8593

86-
mem = vmalloc_node(SCOMP_SCRATCH_SIZE, cpu_to_node(i));
87-
if (!mem)
94+
page = alloc_pages_node(cpu_to_node(i), GFP_KERNEL, 0);
95+
if (!page)
8896
goto error;
89-
scratch->src = mem;
97+
scratch->src = page_address(page);
9098
mem = vmalloc_node(SCOMP_SCRATCH_SIZE, cpu_to_node(i));
9199
if (!mem)
92100
goto error;
@@ -161,76 +169,88 @@ static int crypto_scomp_init_tfm(struct crypto_tfm *tfm)
161169

162170
static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
163171
{
172+
struct scomp_scratch *scratch = raw_cpu_ptr(&scomp_scratch);
164173
struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
165-
void **tfm_ctx = acomp_tfm_ctx(tfm);
174+
struct crypto_scomp **tfm_ctx = acomp_tfm_ctx(tfm);
166175
struct crypto_scomp *scomp = *tfm_ctx;
167176
struct crypto_acomp_stream *stream;
168-
struct scomp_scratch *scratch;
177+
unsigned int slen = req->slen;
178+
unsigned int dlen = req->dlen;
179+
struct page *spage, *dpage;
180+
unsigned int soff, doff;
169181
void *src, *dst;
170-
unsigned int dlen;
182+
unsigned int n;
171183
int ret;
172184

173-
if (!req->src || !req->slen || req->slen > SCOMP_SCRATCH_SIZE)
185+
if (!req->src || !slen)
174186
return -EINVAL;
175187

176-
if (req->dst && !req->dlen)
188+
if (!req->dst || !dlen)
177189
return -EINVAL;
178190

179-
if (!req->dlen || req->dlen > SCOMP_SCRATCH_SIZE)
180-
req->dlen = SCOMP_SCRATCH_SIZE;
181-
182-
dlen = req->dlen;
191+
soff = req->src->offset;
192+
spage = nth_page(sg_page(req->src), soff / PAGE_SIZE);
193+
soff = offset_in_page(soff);
183194

184-
scratch = raw_cpu_ptr(&scomp_scratch);
185-
spin_lock_bh(&scratch->lock);
186-
187-
if (sg_nents(req->src) == 1 && !PageHighMem(sg_page(req->src))) {
188-
src = page_to_virt(sg_page(req->src)) + req->src->offset;
189-
} else {
190-
scatterwalk_map_and_copy(scratch->src, req->src, 0,
191-
req->slen, 0);
195+
n = slen / PAGE_SIZE;
196+
n += (offset_in_page(slen) + soff - 1) / PAGE_SIZE;
197+
if (slen <= req->src->length && (!PageHighMem(nth_page(spage, n)) ||
198+
size_add(soff, slen) <= PAGE_SIZE))
199+
src = kmap_local_page(spage) + soff;
200+
else
192201
src = scratch->src;
193-
}
194202

195-
if (req->dst && sg_nents(req->dst) == 1 && !PageHighMem(sg_page(req->dst)))
196-
dst = page_to_virt(sg_page(req->dst)) + req->dst->offset;
197-
else
203+
doff = req->dst->offset;
204+
dpage = nth_page(sg_page(req->dst), doff / PAGE_SIZE);
205+
doff = offset_in_page(doff);
206+
207+
n = dlen / PAGE_SIZE;
208+
n += (offset_in_page(dlen) + doff - 1) / PAGE_SIZE;
209+
if (dlen <= req->dst->length && (!PageHighMem(nth_page(dpage, n)) ||
210+
size_add(doff, dlen) <= PAGE_SIZE))
211+
dst = kmap_local_page(dpage) + doff;
212+
else {
213+
if (dlen > SCOMP_SCRATCH_SIZE)
214+
dlen = SCOMP_SCRATCH_SIZE;
198215
dst = scratch->dst;
216+
}
217+
218+
spin_lock_bh(&scratch->lock);
219+
220+
if (src == scratch->src)
221+
memcpy_from_sglist(src, req->src, 0, slen);
199222

200223
stream = raw_cpu_ptr(crypto_scomp_alg(scomp)->stream);
201224
spin_lock(&stream->lock);
202225
if (dir)
203-
ret = crypto_scomp_compress(scomp, src, req->slen,
204-
dst, &req->dlen, stream->ctx);
226+
ret = crypto_scomp_compress(scomp, src, slen,
227+
dst, &dlen, stream->ctx);
205228
else
206-
ret = crypto_scomp_decompress(scomp, src, req->slen,
207-
dst, &req->dlen, stream->ctx);
229+
ret = crypto_scomp_decompress(scomp, src, slen,
230+
dst, &dlen, stream->ctx);
231+
232+
if (dst == scratch->dst)
233+
memcpy_to_sglist(req->dst, 0, dst, dlen);
234+
208235
spin_unlock(&stream->lock);
209-
if (!ret) {
210-
if (!req->dst) {
211-
req->dst = sgl_alloc(req->dlen, GFP_ATOMIC, NULL);
212-
if (!req->dst) {
213-
ret = -ENOMEM;
214-
goto out;
215-
}
216-
} else if (req->dlen > dlen) {
217-
ret = -ENOSPC;
218-
goto out;
219-
}
220-
if (dst == scratch->dst) {
221-
scatterwalk_map_and_copy(scratch->dst, req->dst, 0,
222-
req->dlen, 1);
223-
} else {
224-
int nr_pages = DIV_ROUND_UP(req->dst->offset + req->dlen, PAGE_SIZE);
225-
int i;
226-
struct page *dst_page = sg_page(req->dst);
227-
228-
for (i = 0; i < nr_pages; i++)
229-
flush_dcache_page(dst_page + i);
236+
spin_unlock_bh(&scratch->lock);
237+
238+
req->dlen = dlen;
239+
240+
if (dst != scratch->dst) {
241+
kunmap_local(dst);
242+
dlen += doff;
243+
for (;;) {
244+
flush_dcache_page(dpage);
245+
if (dlen <= PAGE_SIZE)
246+
break;
247+
dlen -= PAGE_SIZE;
248+
dpage = nth_page(dpage, 1);
230249
}
231250
}
232-
out:
233-
spin_unlock_bh(&scratch->lock);
251+
if (src != scratch->src)
252+
kunmap_local(src);
253+
234254
return ret;
235255
}
236256

@@ -277,7 +297,6 @@ int crypto_init_scomp_ops_async(struct crypto_tfm *tfm)
277297

278298
crt->compress = scomp_acomp_compress;
279299
crt->decompress = scomp_acomp_decompress;
280-
crt->dst_free = sgl_free;
281300

282301
return 0;
283302
}

include/crypto/acompress.h

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818
#include <linux/spinlock_types.h>
1919
#include <linux/types.h>
2020

21-
#define CRYPTO_ACOMP_ALLOC_OUTPUT 0x00000001
22-
2321
/* Set this bit if source is virtual address instead of SG list. */
2422
#define CRYPTO_ACOMP_REQ_SRC_VIRT 0x00000002
2523

@@ -84,15 +82,12 @@ struct acomp_req {
8482
*
8583
* @compress: Function performs a compress operation
8684
* @decompress: Function performs a de-compress operation
87-
* @dst_free: Frees destination buffer if allocated inside the
88-
* algorithm
8985
* @reqsize: Context size for (de)compression requests
9086
* @base: Common crypto API algorithm data structure
9187
*/
9288
struct crypto_acomp {
9389
int (*compress)(struct acomp_req *req);
9490
int (*decompress)(struct acomp_req *req);
95-
void (*dst_free)(struct scatterlist *dst);
9691
unsigned int reqsize;
9792
struct crypto_tfm base;
9893
};
@@ -261,9 +256,8 @@ static inline void acomp_request_set_callback(struct acomp_req *req,
261256
crypto_completion_t cmpl,
262257
void *data)
263258
{
264-
u32 keep = CRYPTO_ACOMP_ALLOC_OUTPUT | CRYPTO_ACOMP_REQ_SRC_VIRT |
265-
CRYPTO_ACOMP_REQ_SRC_NONDMA | CRYPTO_ACOMP_REQ_DST_VIRT |
266-
CRYPTO_ACOMP_REQ_DST_NONDMA;
259+
u32 keep = CRYPTO_ACOMP_REQ_SRC_VIRT | CRYPTO_ACOMP_REQ_SRC_NONDMA |
260+
CRYPTO_ACOMP_REQ_DST_VIRT | CRYPTO_ACOMP_REQ_DST_NONDMA;
267261

268262
req->base.complete = cmpl;
269263
req->base.data = data;
@@ -297,13 +291,10 @@ static inline void acomp_request_set_params(struct acomp_req *req,
297291
req->slen = slen;
298292
req->dlen = dlen;
299293

300-
req->base.flags &= ~(CRYPTO_ACOMP_ALLOC_OUTPUT |
301-
CRYPTO_ACOMP_REQ_SRC_VIRT |
294+
req->base.flags &= ~(CRYPTO_ACOMP_REQ_SRC_VIRT |
302295
CRYPTO_ACOMP_REQ_SRC_NONDMA |
303296
CRYPTO_ACOMP_REQ_DST_VIRT |
304297
CRYPTO_ACOMP_REQ_DST_NONDMA);
305-
if (!req->dst)
306-
req->base.flags |= CRYPTO_ACOMP_ALLOC_OUTPUT;
307298
}
308299

309300
/**
@@ -403,7 +394,6 @@ static inline void acomp_request_set_dst_dma(struct acomp_req *req,
403394
req->dvirt = dst;
404395
req->dlen = dlen;
405396

406-
req->base.flags &= ~CRYPTO_ACOMP_ALLOC_OUTPUT;
407397
req->base.flags &= ~CRYPTO_ACOMP_REQ_DST_NONDMA;
408398
req->base.flags |= CRYPTO_ACOMP_REQ_DST_VIRT;
409399
}
@@ -424,7 +414,6 @@ static inline void acomp_request_set_dst_nondma(struct acomp_req *req,
424414
req->dvirt = dst;
425415
req->dlen = dlen;
426416

427-
req->base.flags &= ~CRYPTO_ACOMP_ALLOC_OUTPUT;
428417
req->base.flags |= CRYPTO_ACOMP_REQ_DST_NONDMA;
429418
req->base.flags |= CRYPTO_ACOMP_REQ_DST_VIRT;
430419
}

include/crypto/internal/scompress.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
#include <crypto/acompress.h>
1313
#include <crypto/algapi.h>
1414

15-
#define SCOMP_SCRATCH_SIZE 131072
16-
1715
struct acomp_req;
1816

1917
struct crypto_scomp {

0 commit comments

Comments
 (0)