2525
2626#include "compress.h"
2727
28- #define SCOMP_SCRATCH_SIZE 65400
29-
3028struct scomp_scratch {
3129 spinlock_t lock ;
3230 union {
3331 void * src ;
3432 unsigned long saddr ;
3533 };
36- void * dst ;
3734};
3835
3936static DEFINE_PER_CPU (struct scomp_scratch , scomp_scratch ) = {
@@ -78,29 +75,20 @@ static void crypto_scomp_free_scratches(void)
7875 scratch = per_cpu_ptr (& scomp_scratch , i );
7976
8077 free_page (scratch -> saddr );
81- kvfree (scratch -> dst );
8278 scratch -> src = NULL ;
83- scratch -> dst = NULL ;
8479 }
8580}
8681
8782static int scomp_alloc_scratch (struct scomp_scratch * scratch , int cpu )
8883{
8984 int node = cpu_to_node (cpu );
9085 struct page * page ;
91- void * mem ;
9286
93- mem = kvmalloc_node (SCOMP_SCRATCH_SIZE , GFP_KERNEL , node );
94- if (!mem )
95- return - ENOMEM ;
9687 page = alloc_pages_node (node , GFP_KERNEL , 0 );
97- if (!page ) {
98- kvfree (mem );
88+ if (!page )
9989 return - ENOMEM ;
100- }
10190 spin_lock_bh (& scratch -> lock );
10291 scratch -> src = page_address (page );
103- scratch -> dst = mem ;
10492 spin_unlock_bh (& scratch -> lock );
10593 return 0 ;
10694}
@@ -181,6 +169,8 @@ static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
181169{
182170 struct crypto_acomp * tfm = crypto_acomp_reqtfm (req );
183171 struct crypto_scomp * * tfm_ctx = acomp_tfm_ctx (tfm );
172+ bool src_isvirt = acomp_request_src_isvirt (req );
173+ bool dst_isvirt = acomp_request_dst_isvirt (req );
184174 struct crypto_scomp * scomp = * tfm_ctx ;
185175 struct crypto_acomp_stream * stream ;
186176 struct scomp_scratch * scratch ;
@@ -200,13 +190,33 @@ static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
200190 if (!req -> dst || !dlen )
201191 return - EINVAL ;
202192
203- stream = crypto_acomp_lock_stream_bh (& crypto_scomp_alg (scomp )-> streams );
204- scratch = scomp_lock_scratch ();
193+ if (dst_isvirt )
194+ dst = req -> dvirt ;
195+ else {
196+ if (acomp_request_dst_isfolio (req )) {
197+ dpage = folio_page (req -> dfolio , 0 );
198+ doff = req -> doff ;
199+ } else if (dlen <= req -> dst -> length ) {
200+ dpage = sg_page (req -> dst );
201+ doff = req -> dst -> offset ;
202+ } else
203+ return - ENOSYS ;
204+
205+ dpage = nth_page (dpage , doff / PAGE_SIZE );
206+ doff = offset_in_page (doff );
207+
208+ n = dlen / PAGE_SIZE ;
209+ n += (offset_in_page (dlen ) + doff - 1 ) / PAGE_SIZE ;
210+ if (PageHighMem (dpage + n ) &&
211+ size_add (doff , dlen ) > PAGE_SIZE )
212+ return - ENOSYS ;
213+ dst = kmap_local_page (dpage ) + doff ;
214+ }
205215
206- if (acomp_request_src_isvirt ( req ) )
216+ if (src_isvirt )
207217 src = req -> svirt ;
208218 else {
209- src = scratch -> src ;
219+ src = NULL ;
210220 do {
211221 if (acomp_request_src_isfolio (req )) {
212222 spage = folio_page (req -> sfolio , 0 );
@@ -227,57 +237,39 @@ static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
227237 break ;
228238 src = kmap_local_page (spage ) + soff ;
229239 } while (0 );
230-
231- if (src == scratch -> src )
232- memcpy_from_sglist (scratch -> src , req -> src , 0 , slen );
233240 }
234241
235- if (acomp_request_dst_isvirt (req ))
236- dst = req -> dvirt ;
237- else {
238- unsigned int max = SCOMP_SCRATCH_SIZE ;
242+ stream = crypto_acomp_lock_stream_bh (& crypto_scomp_alg (scomp )-> streams );
239243
240- dst = scratch -> dst ;
241- do {
242- if (acomp_request_dst_isfolio (req )) {
243- dpage = folio_page (req -> dfolio , 0 );
244- doff = req -> doff ;
245- } else if (dlen <= req -> dst -> length ) {
246- dpage = sg_page (req -> dst );
247- doff = req -> dst -> offset ;
248- } else
249- break ;
244+ if (!src_isvirt && !src ) {
245+ const u8 * src ;
250246
251- dpage = nth_page (dpage , doff / PAGE_SIZE );
252- doff = offset_in_page (doff );
247+ scratch = scomp_lock_scratch ();
248+ src = scratch -> src ;
249+ memcpy_from_sglist (scratch -> src , req -> src , 0 , slen );
253250
254- n = dlen / PAGE_SIZE ;
255- n += (offset_in_page (dlen ) + doff - 1 ) / PAGE_SIZE ;
256- if (PageHighMem (dpage + n ) &&
257- size_add (doff , dlen ) > PAGE_SIZE )
258- break ;
259- dst = kmap_local_page (dpage ) + doff ;
260- max = dlen ;
261- } while (0 );
262- dlen = min (dlen , max );
263- }
251+ if (dir )
252+ ret = crypto_scomp_compress (scomp , src , slen ,
253+ dst , & dlen , stream -> ctx );
254+ else
255+ ret = crypto_scomp_decompress (scomp , src , slen ,
256+ dst , & dlen , stream -> ctx );
264257
265- if (dir )
258+ scomp_unlock_scratch (scratch );
259+ } else if (dir )
266260 ret = crypto_scomp_compress (scomp , src , slen ,
267261 dst , & dlen , stream -> ctx );
268262 else
269263 ret = crypto_scomp_decompress (scomp , src , slen ,
270264 dst , & dlen , stream -> ctx );
271265
272- if (dst == scratch -> dst )
273- memcpy_to_sglist (req -> dst , 0 , dst , dlen );
274-
275- scomp_unlock_scratch (scratch );
276266 crypto_acomp_unlock_stream_bh (stream );
277267
278268 req -> dlen = dlen ;
279269
280- if (!acomp_request_dst_isvirt (req ) && dst != scratch -> dst ) {
270+ if (!src_isvirt && src )
271+ kunmap_local (src );
272+ if (!dst_isvirt ) {
281273 kunmap_local (dst );
282274 dlen += doff ;
283275 for (;;) {
@@ -288,8 +280,6 @@ static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
288280 dpage = nth_page (dpage , 1 );
289281 }
290282 }
291- if (!acomp_request_src_isvirt (req ) && src != scratch -> src )
292- kunmap_local (src );
293283
294284 return ret ;
295285}
0 commit comments