~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/lib/decompress_unzstd.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /lib/decompress_unzstd.c (Version linux-6.12-rc7) and /lib/decompress_unzstd.c (Version linux-2.6.32.71)


  1 // SPDX-License-Identifier: GPL-2.0                 1 
  2                                                   
  3 /*                                                
  4  * Important notes about in-place decompressio    
  5  *                                                
  6  * At least on x86, the kernel is decompressed    
  7  * is placed to the end of the output buffer,     
  8  * most of the compressed data. There must be     
  9  * guarantee that the write position is always    
 10  *                                                
 11  * The safety margin for ZSTD with a 128 KB bl    
 12  * Note that the margin with ZSTD is bigger th    
 13  *                                                
 14  * The worst case for in-place decompression i    
 15  * the file is compressed extremely well, and     
 16  * uncompressible. Thus, we must look for wors    
 17  * compressor is encoding uncompressible data.    
 18  *                                                
 19  * The structure of the .zst file in case of a    
 20  * Maximum sizes (as bytes) of the fields are     
 21  *                                                
 22  *    Frame Header: (18)                          
 23  *    Blocks: (N)                                 
 24  *    Checksum: (4)                               
 25  *                                                
 26  * The frame header and checksum overhead is a    
 27  *                                                
 28  * ZSTD stores the data in blocks. Each block     
 29  * a 3 bytes. After the block header, there is    
 30  * The maximum uncompressed size of the payloa    
 31  * uncompressed size of the payload is never l    
 32  * (excluding the block header).                  
 33  *                                                
 34  * The assumption, that the uncompressed size     
 35  * smaller than the payload itself, is valid o    
 36  * the payload as a whole. It is possible that    
 37  * the decompressor consumes more input than i    
 38  * the worst case for this would be tricky. In    
 39  * let's simply make sure that the decompresso    
 40  * of the payload which it is currently readin    
 41  *                                                
 42  * Now we have enough information to calculate    
 43  *   - 22 bytes for the .zst file format heade    
 44  *   - 3 bytes per every 128 KiB of uncompress    
 45  *     block); and                                
 46  *   - 128 KiB (biggest possible zstd block si    
 47  *     decompressor never overwrites anything     
 48  *     reading.                                   
 49  *                                                
 50  * We get the following formula:                  
 51  *                                                
 52  *    safety_margin = 22 + uncompressed_size *    
 53  *                 <= 22 + (uncompressed_size     
 54  */                                               
 55                                                   
 56 /*                                                
 57  * Preboot environments #include "path/to/deco    
 58  * All of the source files we depend on must b    
 59  * zstd's only source dependency is xxhash, wh    
 60  * dependencies.                                  
 61  *                                                
 62  * When UNZSTD_PREBOOT is defined we declare _    
 63  * used for kernel decompression, instead of u    
 64  *                                                
 65  * Define __DISABLE_EXPORTS in preboot environ    
 66  * from xxhash and zstd from being exported by    
 67  */                                               
 68 #ifdef STATIC                                     
 69 # define UNZSTD_PREBOOT                           
 70 # include "xxhash.c"                              
 71 # include "zstd/decompress_sources.h"             
 72 #else                                             
 73 #include <linux/decompress/unzstd.h>              
 74 #endif                                            
 75                                                   
 76 #include <linux/decompress/mm.h>                  
 77 #include <linux/kernel.h>                         
 78 #include <linux/zstd.h>                           
 79                                                   
 80 /* 128MB is the maximum window size supported     
 81 #define ZSTD_WINDOWSIZE_MAX     (1 << ZSTD_WIN    
 82 /*                                                
 83  * Size of the input and output buffers in mul    
 84  * Pick a larger size because it isn't used du    
 85  * since that is single pass, and we have to a    
 86  * zstd's window anyway. The larger size speed    
 87  */                                               
 88 #define ZSTD_IOBUF_SIZE         (1 << 17)         
 89                                                   
 90 static int INIT handle_zstd_error(size_t ret,     
 91 {                                                 
 92         const zstd_error_code err = zstd_get_e    
 93                                                   
 94         if (!zstd_is_error(ret))                  
 95                 return 0;                         
 96                                                   
 97         /*                                        
 98          * zstd_get_error_name() cannot be use    
 99          * not a const char *                     
100          */                                       
101         switch (err) {                            
102         case ZSTD_error_memory_allocation:        
103                 error("ZSTD decompressor ran o    
104                 break;                            
105         case ZSTD_error_prefix_unknown:           
106                 error("Input is not in the ZST    
107                 break;                            
108         case ZSTD_error_dstSize_tooSmall:         
109         case ZSTD_error_corruption_detected:      
110         case ZSTD_error_checksum_wrong:           
111                 error("ZSTD-compressed data is    
112                 break;                            
113         default:                                  
114                 error("ZSTD-compressed data is    
115                 break;                            
116         }                                         
117         return -1;                                
118 }                                                 
119                                                   
120 /*                                                
121  * Handle the case where we have the entire in    
122  * We can allocate less memory (no circular bu    
123  * and avoid some memcpy() calls.                 
124  */                                               
125 static int INIT decompress_single(const u8 *in    
126                                   long out_len    
127                                   void (*error    
128 {                                                 
129         const size_t wksp_size = zstd_dctx_wor    
130         void *wksp = large_malloc(wksp_size);     
131         zstd_dctx *dctx = zstd_init_dctx(wksp,    
132         int err;                                  
133         size_t ret;                               
134                                                   
135         if (dctx == NULL) {                       
136                 error("Out of memory while all    
137                 err = -1;                         
138                 goto out;                         
139         }                                         
140         /*                                        
141          * Find out how large the frame actual    
142          * the end of the frame that zstd_deco    
143          */                                       
144         ret = zstd_find_frame_compressed_size(    
145         err = handle_zstd_error(ret, error);      
146         if (err)                                  
147                 goto out;                         
148         in_len = (long)ret;                       
149                                                   
150         ret = zstd_decompress_dctx(dctx, out_b    
151         err = handle_zstd_error(ret, error);      
152         if (err)                                  
153                 goto out;                         
154                                                   
155         if (in_pos != NULL)                       
156                 *in_pos = in_len;                 
157                                                   
158         err = 0;                                  
159 out:                                              
160         if (wksp != NULL)                         
161                 large_free(wksp);                 
162         return err;                               
163 }                                                 
164                                                   
165 static int INIT __unzstd(unsigned char *in_buf    
166                          long (*fill)(void*, u    
167                          long (*flush)(void*,     
168                          unsigned char *out_bu    
169                          long *in_pos,            
170                          void (*error)(char *x    
171 {                                                 
172         zstd_in_buffer in;                        
173         zstd_out_buffer out;                      
174         zstd_frame_header header;                 
175         void *in_allocated = NULL;                
176         void *out_allocated = NULL;               
177         void *wksp = NULL;                        
178         size_t wksp_size;                         
179         zstd_dstream *dstream;                    
180         int err;                                  
181         size_t ret;                               
182                                                   
183         /*                                        
184          * ZSTD decompression code won't be ha    
185          * that its end address overflows. Whe    
186          * it as big as possible without havin    
187          */                                       
188         if (out_len == 0)                         
189                 out_len = UINTPTR_MAX - (uintp    
190                                                   
191         if (fill == NULL && flush == NULL)        
192                 /*                                
193                  * We can decompress faster an    
194                  * single chunk.                  
195                  */                               
196                 return decompress_single(in_bu    
197                                          in_po    
198                                                   
199         /*                                        
200          * If in_buf is not provided, we must     
201          * a large enough buffer. If it is pro    
202          * ZSTD_IOBUF_SIZE large.                 
203          */                                       
204         if (in_buf == NULL) {                     
205                 in_allocated = large_malloc(ZS    
206                 if (in_allocated == NULL) {       
207                         error("Out of memory w    
208                         err = -1;                 
209                         goto out;                 
210                 }                                 
211                 in_buf = in_allocated;            
212                 in_len = 0;                       
213         }                                         
214         /* Read the first chunk, since we need    
215         if (fill != NULL)                         
216                 in_len = fill(in_buf, ZSTD_IOB    
217         if (in_len < 0) {                         
218                 error("ZSTD-compressed data is    
219                 err = -1;                         
220                 goto out;                         
221         }                                         
222         /* Set the first non-empty input buffe    
223         in.src = in_buf;                          
224         in.pos = 0;                               
225         in.size = in_len;                         
226         /* Allocate the output buffer if we ar    
227         if (flush != NULL) {                      
228                 out_allocated = large_malloc(Z    
229                 if (out_allocated == NULL) {      
230                         error("Out of memory w    
231                         err = -1;                 
232                         goto out;                 
233                 }                                 
234                 out_buf = out_allocated;          
235                 out_len = ZSTD_IOBUF_SIZE;        
236         }                                         
237         /* Set the output buffer. */              
238         out.dst = out_buf;                        
239         out.pos = 0;                              
240         out.size = out_len;                       
241                                                   
242         /*                                        
243          * We need to know the window size to     
244          * Since we are streaming, we need to     
245          * window. The window size varies from    
246          * (8 MB), so it is important to use t    
247          * waste memory when it is smaller.       
248          */                                       
249         ret = zstd_get_frame_header(&header, i    
250         err = handle_zstd_error(ret, error);      
251         if (err)                                  
252                 goto out;                         
253         if (ret != 0) {                           
254                 error("ZSTD-compressed data ha    
255                 err = -1;                         
256                 goto out;                         
257         }                                         
258         if (header.windowSize > ZSTD_WINDOWSIZ    
259                 error("ZSTD-compressed data ha    
260                 err = -1;                         
261                 goto out;                         
262         }                                         
263                                                   
264         /*                                        
265          * Allocate the zstd_dstream now that     
266          * required.                              
267          */                                       
268         wksp_size = zstd_dstream_workspace_bou    
269         wksp = large_malloc(wksp_size);           
270         dstream = zstd_init_dstream(header.win    
271         if (dstream == NULL) {                    
272                 error("Out of memory while all    
273                 err = -1;                         
274                 goto out;                         
275         }                                         
276                                                   
277         /*                                        
278          * Decompression loop:                    
279          * Read more data if necessary (error     
280          * Call the decompression function, wh    
281          * Flush any data produced if using fl    
282          */                                       
283         if (in_pos != NULL)                       
284                 *in_pos = 0;                      
285         do {                                      
286                 /*                                
287                  * If we need to reload data,     
288                  * try to get more data, or we    
289                  */                               
290                 if (in.pos == in.size) {          
291                         if (in_pos != NULL)       
292                                 *in_pos += in.    
293                         in_len = fill ? fill(i    
294                         if (in_len < 0) {         
295                                 error("ZSTD-co    
296                                 err = -1;         
297                                 goto out;         
298                         }                         
299                         in.pos = 0;               
300                         in.size = in_len;         
301                 }                                 
302                 /* Returns zero when the frame    
303                 ret = zstd_decompress_stream(d    
304                 err = handle_zstd_error(ret, e    
305                 if (err)                          
306                         goto out;                 
307                 /* Flush all of the data produ    
308                 if (flush != NULL && out.pos >    
309                         if (out.pos != flush(o    
310                                 error("Failed     
311                                 err = -1;         
312                                 goto out;         
313                         }                         
314                         out.pos = 0;              
315                 }                                 
316         } while (ret != 0);                       
317                                                   
318         if (in_pos != NULL)                       
319                 *in_pos += in.pos;                
320                                                   
321         err = 0;                                  
322 out:                                              
323         if (in_allocated != NULL)                 
324                 large_free(in_allocated);         
325         if (out_allocated != NULL)                
326                 large_free(out_allocated);        
327         if (wksp != NULL)                         
328                 large_free(wksp);                 
329         return err;                               
330 }                                                 
331                                                   
332 #ifndef UNZSTD_PREBOOT                            
333 STATIC int INIT unzstd(unsigned char *buf, lon    
334                        long (*fill)(void*, uns    
335                        long (*flush)(void*, un    
336                        unsigned char *out_buf,    
337                        long *pos,                 
338                        void (*error)(char *x))    
339 {                                                 
340         return __unzstd(buf, len, fill, flush,    
341 }                                                 
342 #else                                             
343 STATIC int INIT __decompress(unsigned char *bu    
344                              long (*fill)(void    
345                              long (*flush)(voi    
346                              unsigned char *ou    
347                              long *pos,           
348                              void (*error)(cha    
349 {                                                 
350         return __unzstd(buf, len, fill, flush,    
351 }                                                 
352 #endif                                            
353                                                   

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php