@@ -98,7 +98,14 @@ MODULE_PARM_DESC(kmsg_bytes, "amount of kernel log to snapshot (in bytes)");
98
98
99
99
static void * compress_workspace ;
100
100
101
+ /*
102
+ * Compression is only used for dmesg output, which consists of low-entropy
103
+ * ASCII text, and so we can assume worst-case 60%.
104
+ */
105
+ #define DMESG_COMP_PERCENT 60
106
+
101
107
static char * big_oops_buf ;
108
+ static size_t max_compressed_size ;
102
109
103
110
void pstore_set_kmsg_bytes (int bytes )
104
111
{
@@ -196,6 +203,7 @@ static int pstore_compress(const void *in, void *out,
196
203
197
204
static void allocate_buf_for_compression (void )
198
205
{
206
+ size_t compressed_size ;
199
207
char * buf ;
200
208
201
209
/* Skip if not built-in or compression disabled. */
@@ -216,7 +224,8 @@ static void allocate_buf_for_compression(void)
216
224
* uncompressed record size, since any record that would be expanded by
217
225
* compression is just stored uncompressed.
218
226
*/
219
- buf = kvzalloc (psinfo -> bufsize , GFP_KERNEL );
227
+ compressed_size = (psinfo -> bufsize * 100 ) / DMESG_COMP_PERCENT ;
228
+ buf = kvzalloc (compressed_size , GFP_KERNEL );
220
229
if (!buf ) {
221
230
pr_err ("Failed %zu byte compression buffer allocation for: %s\n" ,
222
231
psinfo -> bufsize , compress );
@@ -233,6 +242,7 @@ static void allocate_buf_for_compression(void)
233
242
234
243
/* A non-NULL big_oops_buf indicates compression is available. */
235
244
big_oops_buf = buf ;
245
+ max_compressed_size = compressed_size ;
236
246
237
247
pr_info ("Using crash dump compression: %s\n" , compress );
238
248
}
@@ -246,6 +256,7 @@ static void free_buf_for_compression(void)
246
256
247
257
kvfree (big_oops_buf );
248
258
big_oops_buf = NULL ;
259
+ max_compressed_size = 0 ;
249
260
}
250
261
251
262
void pstore_record_init (struct pstore_record * record ,
@@ -305,7 +316,7 @@ static void pstore_dump(struct kmsg_dumper *dumper,
305
316
record .buf = psinfo -> buf ;
306
317
307
318
dst = big_oops_buf ?: psinfo -> buf ;
308
- dst_size = psinfo -> bufsize ;
319
+ dst_size = max_compressed_size ?: psinfo -> bufsize ;
309
320
310
321
/* Write dump header. */
311
322
header_size = snprintf (dst , dst_size , "%s#%d Part%u\n" , why ,
@@ -326,8 +337,15 @@ static void pstore_dump(struct kmsg_dumper *dumper,
326
337
record .compressed = true;
327
338
record .size = zipped_len ;
328
339
} else {
329
- record .size = header_size + dump_size ;
330
- memcpy (psinfo -> buf , dst , record .size );
340
+ /*
341
+ * Compression failed, so the buffer is most
342
+ * likely filled with binary data that does not
343
+ * compress as well as ASCII text. Copy as much
344
+ * of the uncompressed data as possible into
345
+ * the pstore record, and discard the rest.
346
+ */
347
+ record .size = psinfo -> bufsize ;
348
+ memcpy (psinfo -> buf , dst , psinfo -> bufsize );
331
349
}
332
350
} else {
333
351
record .size = header_size + dump_size ;
@@ -560,6 +578,7 @@ static void decompress_record(struct pstore_record *record,
560
578
int ret ;
561
579
int unzipped_len ;
562
580
char * unzipped , * workspace ;
581
+ size_t max_uncompressed_size ;
563
582
564
583
if (!IS_ENABLED (CONFIG_PSTORE_COMPRESS ) || !record -> compressed )
565
584
return ;
@@ -583,19 +602,20 @@ static void decompress_record(struct pstore_record *record,
583
602
}
584
603
585
604
/* Allocate enough space to hold max decompression and ECC. */
586
- workspace = kvzalloc (psinfo -> bufsize + record -> ecc_notice_size ,
605
+ max_uncompressed_size = 3 * psinfo -> bufsize ;
606
+ workspace = kvzalloc (max_uncompressed_size + record -> ecc_notice_size ,
587
607
GFP_KERNEL );
588
608
if (!workspace )
589
609
return ;
590
610
591
611
zstream -> next_in = record -> buf ;
592
612
zstream -> avail_in = record -> size ;
593
613
zstream -> next_out = workspace ;
594
- zstream -> avail_out = psinfo -> bufsize ;
614
+ zstream -> avail_out = max_uncompressed_size ;
595
615
596
616
ret = zlib_inflate (zstream , Z_FINISH );
597
617
if (ret != Z_STREAM_END ) {
598
- pr_err ("zlib_inflate() failed, ret = %d!\n" , ret );
618
+ pr_err_ratelimited ("zlib_inflate() failed, ret = %d!\n" , ret );
599
619
kvfree (workspace );
600
620
return ;
601
621
}
0 commit comments