Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <herbert@gondor.apana.org.au>

+76 -71
-1
crypto/acompress.c
··· 73 73 74 74 acomp->compress = alg->compress; 75 75 acomp->decompress = alg->decompress; 76 - acomp->dst_free = alg->dst_free; 77 76 acomp->reqsize = alg->reqsize; 78 77 79 78 if (alg->exit)
+73 -54
crypto/scompress.c
··· 12 12 #include <crypto/scatterwalk.h> 13 13 #include <linux/cryptouser.h> 14 14 #include <linux/err.h> 15 + #include <linux/highmem.h> 15 16 #include <linux/kernel.h> 16 17 #include <linux/module.h> 18 + #include <linux/overflow.h> 17 19 #include <linux/scatterlist.h> 18 20 #include <linux/seq_file.h> 19 21 #include <linux/slab.h> ··· 25 23 26 24 #include "compress.h" 27 25 26 + #define SCOMP_SCRATCH_SIZE 65400 27 + 28 28 struct scomp_scratch { 29 29 spinlock_t lock; 30 - void *src; 30 + union { 31 + void *src; 32 + unsigned long saddr; 33 + }; 31 34 void *dst; 32 35 }; 33 36 ··· 73 66 for_each_possible_cpu(i) { 74 67 scratch = per_cpu_ptr(&scomp_scratch, i); 75 68 76 - vfree(scratch->src); 69 + free_page(scratch->saddr); 77 70 vfree(scratch->dst); 78 71 scratch->src = NULL; 79 72 scratch->dst = NULL; ··· 86 79 int i; 87 80 88 81 for_each_possible_cpu(i) { 82 + struct page *page; 89 83 void *mem; 90 84 91 85 scratch = per_cpu_ptr(&scomp_scratch, i); 92 86 93 - mem = vmalloc_node(SCOMP_SCRATCH_SIZE, cpu_to_node(i)); 94 - if (!mem) 87 + page = alloc_pages_node(cpu_to_node(i), GFP_KERNEL, 0); 88 + if (!page) 95 89 goto error; 96 - scratch->src = mem; 90 + scratch->src = page_address(page); 97 91 mem = vmalloc_node(SCOMP_SCRATCH_SIZE, cpu_to_node(i)); 98 92 if (!mem) 99 93 goto error; ··· 169 161 170 162 static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir) 171 163 { 164 + struct scomp_scratch *scratch = raw_cpu_ptr(&scomp_scratch); 172 165 struct crypto_acomp *tfm = crypto_acomp_reqtfm(req); 173 - void **tfm_ctx = acomp_tfm_ctx(tfm); 166 + struct crypto_scomp **tfm_ctx = acomp_tfm_ctx(tfm); 174 167 struct crypto_scomp *scomp = *tfm_ctx; 175 168 struct crypto_acomp_stream *stream; 176 - struct scomp_scratch *scratch; 169 + unsigned int slen = req->slen; 170 + unsigned int dlen = req->dlen; 171 + struct page *spage, *dpage; 172 + unsigned int soff, doff; 177 173 void *src, *dst; 178 - unsigned int dlen; 174 + unsigned int n; 179 175 int ret; 180 176 181 - if (!req->src || !req->slen || req->slen > SCOMP_SCRATCH_SIZE) 177 + if (!req->src || !slen) 182 178 return -EINVAL; 183 179 184 - if (req->dst && !req->dlen) 180 + if (!req->dst || !dlen) 185 181 return -EINVAL; 186 182 187 - if (!req->dlen || req->dlen > SCOMP_SCRATCH_SIZE) 188 - req->dlen = SCOMP_SCRATCH_SIZE; 183 + soff = req->src->offset; 184 + spage = nth_page(sg_page(req->src), soff / PAGE_SIZE); 185 + soff = offset_in_page(soff); 189 186 190 - dlen = req->dlen; 191 - 192 - scratch = raw_cpu_ptr(&scomp_scratch); 193 - spin_lock_bh(&scratch->lock); 194 - 195 - if (sg_nents(req->src) == 1 && !PageHighMem(sg_page(req->src))) { 196 - src = page_to_virt(sg_page(req->src)) + req->src->offset; 197 - } else { 198 - scatterwalk_map_and_copy(scratch->src, req->src, 0, 199 - req->slen, 0); 187 + n = slen / PAGE_SIZE; 188 + n += (offset_in_page(slen) + soff - 1) / PAGE_SIZE; 189 + if (slen <= req->src->length && (!PageHighMem(nth_page(spage, n)) || 190 + size_add(soff, slen) <= PAGE_SIZE)) 191 + src = kmap_local_page(spage) + soff; 192 + else 200 193 src = scratch->src; 194 + 195 + doff = req->dst->offset; 196 + dpage = nth_page(sg_page(req->dst), doff / PAGE_SIZE); 197 + doff = offset_in_page(doff); 198 + 199 + n = dlen / PAGE_SIZE; 200 + n += (offset_in_page(dlen) + doff - 1) / PAGE_SIZE; 201 + if (dlen <= req->dst->length && (!PageHighMem(nth_page(dpage, n)) || 202 + size_add(doff, dlen) <= PAGE_SIZE)) 203 + dst = kmap_local_page(dpage) + doff; 204 + else { 205 + if (dlen > SCOMP_SCRATCH_SIZE) 206 + dlen = SCOMP_SCRATCH_SIZE; 207 + dst = scratch->dst; 201 208 } 202 209 203 - if (req->dst && sg_nents(req->dst) == 1 && !PageHighMem(sg_page(req->dst))) 204 - dst = page_to_virt(sg_page(req->dst)) + req->dst->offset; 205 - else 206 - dst = scratch->dst; 210 + spin_lock_bh(&scratch->lock); 211 + 212 + if (src == scratch->src) 213 + memcpy_from_sglist(src, req->src, 0, slen); 207 214 208 215 stream = raw_cpu_ptr(crypto_scomp_alg(scomp)->stream); 209 216 spin_lock(&stream->lock); 210 217 if (dir) 211 - ret = crypto_scomp_compress(scomp, src, req->slen, 212 - dst, &req->dlen, stream->ctx); 218 + ret = crypto_scomp_compress(scomp, src, slen, 219 + dst, &dlen, stream->ctx); 213 220 else 214 - ret = crypto_scomp_decompress(scomp, src, req->slen, 215 - dst, &req->dlen, stream->ctx); 216 - spin_unlock(&stream->lock); 217 - if (!ret) { 218 - if (!req->dst) { 219 - req->dst = sgl_alloc(req->dlen, GFP_ATOMIC, NULL); 220 - if (!req->dst) { 221 - ret = -ENOMEM; 222 - goto out; 223 - } 224 - } else if (req->dlen > dlen) { 225 - ret = -ENOSPC; 226 - goto out; 227 - } 228 - if (dst == scratch->dst) { 229 - scatterwalk_map_and_copy(scratch->dst, req->dst, 0, 230 - req->dlen, 1); 231 - } else { 232 - int nr_pages = DIV_ROUND_UP(req->dst->offset + req->dlen, PAGE_SIZE); 233 - int i; 234 - struct page *dst_page = sg_page(req->dst); 221 + ret = crypto_scomp_decompress(scomp, src, slen, 222 + dst, &dlen, stream->ctx); 235 223 236 - for (i = 0; i < nr_pages; i++) 237 - flush_dcache_page(dst_page + i); 224 + if (dst == scratch->dst) 225 + memcpy_to_sglist(req->dst, 0, dst, dlen); 226 + 227 + spin_unlock(&stream->lock); 228 + spin_unlock_bh(&scratch->lock); 229 + 230 + req->dlen = dlen; 231 + 232 + if (dst != scratch->dst) { 233 + kunmap_local(dst); 234 + dlen += doff; 235 + for (;;) { 236 + flush_dcache_page(dpage); 237 + if (dlen <= PAGE_SIZE) 238 + break; 239 + dlen -= PAGE_SIZE; 240 + dpage = nth_page(dpage, 1); 238 241 } 239 242 } 240 - out: 241 - spin_unlock_bh(&scratch->lock); 243 + if (src != scratch->src) 244 + kunmap_local(src); 245 + 242 246 return ret; 243 247 } 244 248 ··· 297 277 298 278 crt->compress = scomp_acomp_compress; 299 279 crt->decompress = scomp_acomp_decompress; 300 - crt->dst_free = sgl_free; 301 280 302 281 return 0; 303 282 }
+3 -14
include/crypto/acompress.h
··· 18 18 #include <linux/spinlock_types.h> 19 19 #include <linux/types.h> 20 20 21 - #define CRYPTO_ACOMP_ALLOC_OUTPUT 0x00000001 22 - 23 21 /* Set this bit if source is virtual address instead of SG list. */ 24 22 #define CRYPTO_ACOMP_REQ_SRC_VIRT 0x00000002 25 23 ··· 82 84 * 83 85 * @compress: Function performs a compress operation 84 86 * @decompress: Function performs a de-compress operation 85 - * @dst_free: Frees destination buffer if allocated inside the 86 - * algorithm 87 87 * @reqsize: Context size for (de)compression requests 88 88 * @base: Common crypto API algorithm data structure 89 89 */ 90 90 struct crypto_acomp { 91 91 int (*compress)(struct acomp_req *req); 92 92 int (*decompress)(struct acomp_req *req); 93 - void (*dst_free)(struct scatterlist *dst); 94 93 unsigned int reqsize; 95 94 struct crypto_tfm base; 96 95 }; ··· 256 261 crypto_completion_t cmpl, 257 262 void *data) 258 263 { 259 - u32 keep = CRYPTO_ACOMP_ALLOC_OUTPUT | CRYPTO_ACOMP_REQ_SRC_VIRT | 260 - CRYPTO_ACOMP_REQ_SRC_NONDMA | CRYPTO_ACOMP_REQ_DST_VIRT | 261 - CRYPTO_ACOMP_REQ_DST_NONDMA; 264 + u32 keep = CRYPTO_ACOMP_REQ_SRC_VIRT | CRYPTO_ACOMP_REQ_SRC_NONDMA | 265 + CRYPTO_ACOMP_REQ_DST_VIRT | CRYPTO_ACOMP_REQ_DST_NONDMA; 262 266 263 267 req->base.complete = cmpl; 264 268 req->base.data = data; ··· 291 297 req->slen = slen; 292 298 req->dlen = dlen; 293 299 294 - req->base.flags &= ~(CRYPTO_ACOMP_ALLOC_OUTPUT | 295 - CRYPTO_ACOMP_REQ_SRC_VIRT | 300 + req->base.flags &= ~(CRYPTO_ACOMP_REQ_SRC_VIRT | 296 301 CRYPTO_ACOMP_REQ_SRC_NONDMA | 297 302 CRYPTO_ACOMP_REQ_DST_VIRT | 298 303 CRYPTO_ACOMP_REQ_DST_NONDMA); 299 - if (!req->dst) 300 - req->base.flags |= CRYPTO_ACOMP_ALLOC_OUTPUT; 301 304 } 302 305 303 306 /** ··· 394 403 req->dvirt = dst; 395 404 req->dlen = dlen; 396 405 397 - req->base.flags &= ~CRYPTO_ACOMP_ALLOC_OUTPUT; 398 406 req->base.flags &= ~CRYPTO_ACOMP_REQ_DST_NONDMA; 399 407 req->base.flags |= CRYPTO_ACOMP_REQ_DST_VIRT; 400 408 } ··· 414 424 req->dvirt = dst; 415 425 req->dlen = dlen; 416 426 417 - req->base.flags &= ~CRYPTO_ACOMP_ALLOC_OUTPUT; 418 427 req->base.flags |= CRYPTO_ACOMP_REQ_DST_NONDMA; 419 428 req->base.flags |= CRYPTO_ACOMP_REQ_DST_VIRT; 420 429 }
-2
include/crypto/internal/scompress.h
··· 12 12 #include <crypto/acompress.h> 13 13 #include <crypto/algapi.h> 14 14 15 - #define SCOMP_SCRATCH_SIZE 131072 16 - 17 15 struct acomp_req; 18 16 19 17 struct crypto_scomp {