aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-04-06 17:59:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-06 17:59:01 -0400
commit69824bcc4b4e1427ac18a76057d592ec9028f2fe (patch)
tree98abb9aa0f80004cb742600c072e323b24264728
parent3b54765cca23152ec0cc254b75c877c10f6e2870 (diff)
parent58eb5b6707477ff458db3ee522aac317da719e2a (diff)
Merge tag 'pstore-v4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
Pull pstore updates from Kees Cook: "This cycle was almost entirely improvements to the pstore compression options, noted below: - Add lz4hc and 842 to pstore compression options (Geliang Tang) - Refactor to use crypto compression API (Geliang Tang) - Fix up Kconfig dependencies for compression (Arnd Bergmann) - Allow for run-time compression selection - Remove stack VLA usage" * tag 'pstore-v4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: pstore: fix crypto dependencies pstore: Use crypto compress API pstore/ram: Do not use stack VLA for parity workspace pstore: Select compression at runtime pstore: Avoid size casts for 842 compression pstore: Add lz4hc and 842 compression support
-rw-r--r--fs/pstore/Kconfig101
-rw-r--r--fs/pstore/inode.c2
-rw-r--r--fs/pstore/internal.h3
-rw-r--r--fs/pstore/platform.c372
-rw-r--r--fs/pstore/ram.c2
-rw-r--r--fs/pstore/ram_core.c29
-rw-r--r--include/linux/pstore_ram.h1
7 files changed, 226 insertions, 284 deletions
diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig
index b42e5bd6d8ff..09c19ef91526 100644
--- a/fs/pstore/Kconfig
+++ b/fs/pstore/Kconfig
@@ -1,5 +1,6 @@
1config PSTORE 1config PSTORE
2 tristate "Persistent store support" 2 tristate "Persistent store support"
3 select CRYPTO if PSTORE_COMPRESS
3 default n 4 default n
4 help 5 help
5 This option enables generic access to platform level 6 This option enables generic access to platform level
@@ -12,35 +13,89 @@ config PSTORE
12 If you don't have a platform persistent store driver, 13 If you don't have a platform persistent store driver,
13 say N. 14 say N.
14 15
15choice 16config PSTORE_DEFLATE_COMPRESS
16 prompt "Choose compression algorithm" 17 tristate "DEFLATE (ZLIB) compression"
17 depends on PSTORE 18 default y
18 default PSTORE_ZLIB_COMPRESS 19 depends on PSTORE
19 help 20 select CRYPTO_DEFLATE
20 This option chooses compression algorithm. 21 help
21 22 This option enables DEFLATE (also known as ZLIB) compression
22config PSTORE_ZLIB_COMPRESS 23 algorithm support.
23 bool "ZLIB"
24 select ZLIB_DEFLATE
25 select ZLIB_INFLATE
26 help
27 This option enables ZLIB compression algorithm support.
28 24
29config PSTORE_LZO_COMPRESS 25config PSTORE_LZO_COMPRESS
30 bool "LZO" 26 tristate "LZO compression"
31 select LZO_COMPRESS 27 depends on PSTORE
32 select LZO_DECOMPRESS 28 select CRYPTO_LZO
33 help 29 help
34 This option enables LZO compression algorithm support. 30 This option enables LZO compression algorithm support.
35 31
36config PSTORE_LZ4_COMPRESS 32config PSTORE_LZ4_COMPRESS
37 bool "LZ4" 33 tristate "LZ4 compression"
38 select LZ4_COMPRESS 34 depends on PSTORE
39 select LZ4_DECOMPRESS 35 select CRYPTO_LZ4
40 help 36 help
41 This option enables LZ4 compression algorithm support. 37 This option enables LZ4 compression algorithm support.
38
39config PSTORE_LZ4HC_COMPRESS
40 tristate "LZ4HC compression"
41 depends on PSTORE
42 select CRYPTO_LZ4HC
43 help
44 This option enables LZ4HC (high compression) mode algorithm.
45
46config PSTORE_842_COMPRESS
47 bool "842 compression"
48 depends on PSTORE
49 select CRYPTO_842
50 help
51 This option enables 842 compression algorithm support.
52
53config PSTORE_COMPRESS
54 def_bool y
55 depends on PSTORE
56 depends on PSTORE_DEFLATE_COMPRESS || PSTORE_LZO_COMPRESS || \
57 PSTORE_LZ4_COMPRESS || PSTORE_LZ4HC_COMPRESS || \
58 PSTORE_842_COMPRESS
59
60choice
61 prompt "Default pstore compression algorithm"
62 depends on PSTORE_COMPRESS
63 help
64 This option chooses the default active compression algorithm.
65 This change be changed at boot with "pstore.compress=..." on
66 the kernel command line.
67
68 Currently, pstore has support for 5 compression algorithms:
69 deflate, lzo, lz4, lz4hc and 842.
70
71 The default compression algorithm is deflate.
72
73 config PSTORE_DEFLATE_COMPRESS_DEFAULT
74 bool "deflate" if PSTORE_DEFLATE_COMPRESS
75
76 config PSTORE_LZO_COMPRESS_DEFAULT
77 bool "lzo" if PSTORE_LZO_COMPRESS
78
79 config PSTORE_LZ4_COMPRESS_DEFAULT
80 bool "lz4" if PSTORE_LZ4_COMPRESS
81
82 config PSTORE_LZ4HC_COMPRESS_DEFAULT
83 bool "lz4hc" if PSTORE_LZ4HC_COMPRESS
84
85 config PSTORE_842_COMPRESS_DEFAULT
86 bool "842" if PSTORE_842_COMPRESS
87
42endchoice 88endchoice
43 89
90config PSTORE_COMPRESS_DEFAULT
91 string
92 depends on PSTORE_COMPRESS
93 default "deflate" if PSTORE_DEFLATE_COMPRESS_DEFAULT
94 default "lzo" if PSTORE_LZO_COMPRESS_DEFAULT
95 default "lz4" if PSTORE_LZ4_COMPRESS_DEFAULT
96 default "lz4hc" if PSTORE_LZ4HC_COMPRESS_DEFAULT
97 default "842" if PSTORE_842_COMPRESS_DEFAULT
98
44config PSTORE_CONSOLE 99config PSTORE_CONSOLE
45 bool "Log kernel console messages" 100 bool "Log kernel console messages"
46 depends on PSTORE 101 depends on PSTORE
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index d814723fb27d..5fcb845b9fec 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -486,6 +486,8 @@ static int __init init_pstore_fs(void)
486{ 486{
487 int err; 487 int err;
488 488
489 pstore_choose_compression();
490
489 /* Create a convenient mount point for people to access pstore */ 491 /* Create a convenient mount point for people to access pstore */
490 err = sysfs_create_mount_point(fs_kobj, "pstore"); 492 err = sysfs_create_mount_point(fs_kobj, "pstore");
491 if (err) 493 if (err)
diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h
index c029314478fa..fb767e28aeb2 100644
--- a/fs/pstore/internal.h
+++ b/fs/pstore/internal.h
@@ -37,4 +37,7 @@ extern bool pstore_is_mounted(void);
37extern void pstore_record_init(struct pstore_record *record, 37extern void pstore_record_init(struct pstore_record *record,
38 struct pstore_info *psi); 38 struct pstore_info *psi);
39 39
40/* Called during module_init() */
41extern void __init pstore_choose_compression(void);
42
40#endif 43#endif
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index c3129b131e4d..1143ef351c58 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -28,15 +28,13 @@
28#include <linux/console.h> 28#include <linux/console.h>
29#include <linux/module.h> 29#include <linux/module.h>
30#include <linux/pstore.h> 30#include <linux/pstore.h>
31#ifdef CONFIG_PSTORE_ZLIB_COMPRESS 31#if IS_ENABLED(CONFIG_PSTORE_LZO_COMPRESS)
32#include <linux/zlib.h>
33#endif
34#ifdef CONFIG_PSTORE_LZO_COMPRESS
35#include <linux/lzo.h> 32#include <linux/lzo.h>
36#endif 33#endif
37#ifdef CONFIG_PSTORE_LZ4_COMPRESS 34#if IS_ENABLED(CONFIG_PSTORE_LZ4_COMPRESS) || IS_ENABLED(CONFIG_PSTORE_LZ4HC_COMPRESS)
38#include <linux/lz4.h> 35#include <linux/lz4.h>
39#endif 36#endif
37#include <linux/crypto.h>
40#include <linux/string.h> 38#include <linux/string.h>
41#include <linux/timer.h> 39#include <linux/timer.h>
42#include <linux/slab.h> 40#include <linux/slab.h>
@@ -74,23 +72,18 @@ static DEFINE_SPINLOCK(pstore_lock);
74struct pstore_info *psinfo; 72struct pstore_info *psinfo;
75 73
76static char *backend; 74static char *backend;
77 75static char *compress =
78/* Compression parameters */ 76#ifdef CONFIG_PSTORE_COMPRESS_DEFAULT
79#ifdef CONFIG_PSTORE_ZLIB_COMPRESS 77 CONFIG_PSTORE_COMPRESS_DEFAULT;
80#define COMPR_LEVEL 6
81#define WINDOW_BITS 12
82#define MEM_LEVEL 4
83static struct z_stream_s stream;
84#else 78#else
85static unsigned char *workspace; 79 NULL;
86#endif 80#endif
87 81
88struct pstore_zbackend { 82/* Compression parameters */
89 int (*compress)(const void *in, void *out, size_t inlen, size_t outlen); 83static struct crypto_comp *tfm;
90 int (*decompress)(void *in, void *out, size_t inlen, size_t outlen);
91 void (*allocate)(void);
92 void (*free)(void);
93 84
85struct pstore_zbackend {
86 int (*zbufsize)(size_t size);
94 const char *name; 87 const char *name;
95}; 88};
96 89
@@ -149,77 +142,12 @@ bool pstore_cannot_block_path(enum kmsg_dump_reason reason)
149} 142}
150EXPORT_SYMBOL_GPL(pstore_cannot_block_path); 143EXPORT_SYMBOL_GPL(pstore_cannot_block_path);
151 144
152#ifdef CONFIG_PSTORE_ZLIB_COMPRESS 145#if IS_ENABLED(CONFIG_PSTORE_DEFLATE_COMPRESS)
153/* Derived from logfs_compress() */ 146static int zbufsize_deflate(size_t size)
154static int compress_zlib(const void *in, void *out, size_t inlen, size_t outlen)
155{
156 int err, ret;
157
158 ret = -EIO;
159 err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
160 MEM_LEVEL, Z_DEFAULT_STRATEGY);
161 if (err != Z_OK)
162 goto error;
163
164 stream.next_in = in;
165 stream.avail_in = inlen;
166 stream.total_in = 0;
167 stream.next_out = out;
168 stream.avail_out = outlen;
169 stream.total_out = 0;
170
171 err = zlib_deflate(&stream, Z_FINISH);
172 if (err != Z_STREAM_END)
173 goto error;
174
175 err = zlib_deflateEnd(&stream);
176 if (err != Z_OK)
177 goto error;
178
179 if (stream.total_out >= stream.total_in)
180 goto error;
181
182 ret = stream.total_out;
183error:
184 return ret;
185}
186
187/* Derived from logfs_uncompress */
188static int decompress_zlib(void *in, void *out, size_t inlen, size_t outlen)
189{ 147{
190 int err, ret;
191
192 ret = -EIO;
193 err = zlib_inflateInit2(&stream, WINDOW_BITS);
194 if (err != Z_OK)
195 goto error;
196
197 stream.next_in = in;
198 stream.avail_in = inlen;
199 stream.total_in = 0;
200 stream.next_out = out;
201 stream.avail_out = outlen;
202 stream.total_out = 0;
203
204 err = zlib_inflate(&stream, Z_FINISH);
205 if (err != Z_STREAM_END)
206 goto error;
207
208 err = zlib_inflateEnd(&stream);
209 if (err != Z_OK)
210 goto error;
211
212 ret = stream.total_out;
213error:
214 return ret;
215}
216
217static void allocate_zlib(void)
218{
219 size_t size;
220 size_t cmpr; 148 size_t cmpr;
221 149
222 switch (psinfo->bufsize) { 150 switch (size) {
223 /* buffer range for efivars */ 151 /* buffer range for efivars */
224 case 1000 ... 2000: 152 case 1000 ... 2000:
225 cmpr = 56; 153 cmpr = 56;
@@ -239,212 +167,131 @@ static void allocate_zlib(void)
239 break; 167 break;
240 } 168 }
241 169
242 big_oops_buf_sz = (psinfo->bufsize * 100) / cmpr; 170 return (size * 100) / cmpr;
243 big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
244 if (big_oops_buf) {
245 size = max(zlib_deflate_workspacesize(WINDOW_BITS, MEM_LEVEL),
246 zlib_inflate_workspacesize());
247 stream.workspace = kmalloc(size, GFP_KERNEL);
248 if (!stream.workspace) {
249 pr_err("No memory for compression workspace; skipping compression\n");
250 kfree(big_oops_buf);
251 big_oops_buf = NULL;
252 }
253 } else {
254 pr_err("No memory for uncompressed data; skipping compression\n");
255 stream.workspace = NULL;
256 }
257
258} 171}
259
260static void free_zlib(void)
261{
262 kfree(stream.workspace);
263 stream.workspace = NULL;
264 kfree(big_oops_buf);
265 big_oops_buf = NULL;
266 big_oops_buf_sz = 0;
267}
268
269static const struct pstore_zbackend backend_zlib = {
270 .compress = compress_zlib,
271 .decompress = decompress_zlib,
272 .allocate = allocate_zlib,
273 .free = free_zlib,
274 .name = "zlib",
275};
276#endif 172#endif
277 173
278#ifdef CONFIG_PSTORE_LZO_COMPRESS 174#if IS_ENABLED(CONFIG_PSTORE_LZO_COMPRESS)
279static int compress_lzo(const void *in, void *out, size_t inlen, size_t outlen) 175static int zbufsize_lzo(size_t size)
280{ 176{
281 int ret; 177 return lzo1x_worst_compress(size);
282
283 ret = lzo1x_1_compress(in, inlen, out, &outlen, workspace);
284 if (ret != LZO_E_OK) {
285 pr_err("lzo_compress error, ret = %d!\n", ret);
286 return -EIO;
287 }
288
289 return outlen;
290} 178}
179#endif
291 180
292static int decompress_lzo(void *in, void *out, size_t inlen, size_t outlen) 181#if IS_ENABLED(CONFIG_PSTORE_LZ4_COMPRESS) || IS_ENABLED(CONFIG_PSTORE_LZ4HC_COMPRESS)
182static int zbufsize_lz4(size_t size)
293{ 183{
294 int ret; 184 return LZ4_compressBound(size);
295
296 ret = lzo1x_decompress_safe(in, inlen, out, &outlen);
297 if (ret != LZO_E_OK) {
298 pr_err("lzo_decompress error, ret = %d!\n", ret);
299 return -EIO;
300 }
301
302 return outlen;
303} 185}
186#endif
304 187
305static void allocate_lzo(void) 188#if IS_ENABLED(CONFIG_PSTORE_842_COMPRESS)
189static int zbufsize_842(size_t size)
306{ 190{
307 big_oops_buf_sz = lzo1x_worst_compress(psinfo->bufsize); 191 return size;
308 big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
309 if (big_oops_buf) {
310 workspace = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
311 if (!workspace) {
312 pr_err("No memory for compression workspace; skipping compression\n");
313 kfree(big_oops_buf);
314 big_oops_buf = NULL;
315 }
316 } else {
317 pr_err("No memory for uncompressed data; skipping compression\n");
318 workspace = NULL;
319 }
320} 192}
193#endif
321 194
322static void free_lzo(void) 195static const struct pstore_zbackend *zbackend __ro_after_init;
323{
324 kfree(workspace);
325 kfree(big_oops_buf);
326 big_oops_buf = NULL;
327 big_oops_buf_sz = 0;
328}
329 196
330static const struct pstore_zbackend backend_lzo = { 197static const struct pstore_zbackend zbackends[] = {
331 .compress = compress_lzo, 198#if IS_ENABLED(CONFIG_PSTORE_DEFLATE_COMPRESS)
332 .decompress = decompress_lzo, 199 {
333 .allocate = allocate_lzo, 200 .zbufsize = zbufsize_deflate,
334 .free = free_lzo, 201 .name = "deflate",
335 .name = "lzo", 202 },
336}; 203#endif
204#if IS_ENABLED(CONFIG_PSTORE_LZO_COMPRESS)
205 {
206 .zbufsize = zbufsize_lzo,
207 .name = "lzo",
208 },
209#endif
210#if IS_ENABLED(CONFIG_PSTORE_LZ4_COMPRESS)
211 {
212 .zbufsize = zbufsize_lz4,
213 .name = "lz4",
214 },
337#endif 215#endif
216#if IS_ENABLED(CONFIG_PSTORE_LZ4HC_COMPRESS)
217 {
218 .zbufsize = zbufsize_lz4,
219 .name = "lz4hc",
220 },
221#endif
222#if IS_ENABLED(CONFIG_PSTORE_842_COMPRESS)
223 {
224 .zbufsize = zbufsize_842,
225 .name = "842",
226 },
227#endif
228 { }
229};
338 230
339#ifdef CONFIG_PSTORE_LZ4_COMPRESS 231static int pstore_compress(const void *in, void *out,
340static int compress_lz4(const void *in, void *out, size_t inlen, size_t outlen) 232 unsigned int inlen, unsigned int outlen)
341{ 233{
342 int ret; 234 int ret;
343 235
344 ret = LZ4_compress_default(in, out, inlen, outlen, workspace); 236 ret = crypto_comp_compress(tfm, in, inlen, out, &outlen);
345 if (!ret) { 237 if (ret) {
346 pr_err("LZ4_compress_default error; compression failed!\n"); 238 pr_err("crypto_comp_compress failed, ret = %d!\n", ret);
347 return -EIO; 239 return ret;
348 } 240 }
349 241
350 return ret; 242 return outlen;
351} 243}
352 244
353static int decompress_lz4(void *in, void *out, size_t inlen, size_t outlen) 245static int pstore_decompress(void *in, void *out,
246 unsigned int inlen, unsigned int outlen)
354{ 247{
355 int ret; 248 int ret;
356 249
357 ret = LZ4_decompress_safe(in, out, inlen, outlen); 250 ret = crypto_comp_decompress(tfm, in, inlen, out, &outlen);
358 if (ret < 0) { 251 if (ret) {
359 /* 252 pr_err("crypto_comp_decompress failed, ret = %d!\n", ret);
360 * LZ4_decompress_safe will return an error code 253 return ret;
361 * (< 0) if decompression failed
362 */
363 pr_err("LZ4_decompress_safe error, ret = %d!\n", ret);
364 return -EIO;
365 } 254 }
366 255
367 return ret; 256 return outlen;
368}
369
370static void allocate_lz4(void)
371{
372 big_oops_buf_sz = LZ4_compressBound(psinfo->bufsize);
373 big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
374 if (big_oops_buf) {
375 workspace = kmalloc(LZ4_MEM_COMPRESS, GFP_KERNEL);
376 if (!workspace) {
377 pr_err("No memory for compression workspace; skipping compression\n");
378 kfree(big_oops_buf);
379 big_oops_buf = NULL;
380 }
381 } else {
382 pr_err("No memory for uncompressed data; skipping compression\n");
383 workspace = NULL;
384 }
385} 257}
386 258
387static void free_lz4(void) 259static void allocate_buf_for_compression(void)
388{ 260{
389 kfree(workspace); 261 if (!zbackend)
390 kfree(big_oops_buf); 262 return;
391 big_oops_buf = NULL;
392 big_oops_buf_sz = 0;
393}
394
395static const struct pstore_zbackend backend_lz4 = {
396 .compress = compress_lz4,
397 .decompress = decompress_lz4,
398 .allocate = allocate_lz4,
399 .free = free_lz4,
400 .name = "lz4",
401};
402#endif
403
404static const struct pstore_zbackend *zbackend =
405#if defined(CONFIG_PSTORE_ZLIB_COMPRESS)
406 &backend_zlib;
407#elif defined(CONFIG_PSTORE_LZO_COMPRESS)
408 &backend_lzo;
409#elif defined(CONFIG_PSTORE_LZ4_COMPRESS)
410 &backend_lz4;
411#else
412 NULL;
413#endif
414 263
415static int pstore_compress(const void *in, void *out, 264 if (!crypto_has_comp(zbackend->name, 0, 0)) {
416 size_t inlen, size_t outlen) 265 pr_err("No %s compression\n", zbackend->name);
417{ 266 return;
418 if (zbackend) 267 }
419 return zbackend->compress(in, out, inlen, outlen);
420 else
421 return -EIO;
422}
423 268
424static int pstore_decompress(void *in, void *out, size_t inlen, size_t outlen) 269 big_oops_buf_sz = zbackend->zbufsize(psinfo->bufsize);
425{ 270 if (big_oops_buf_sz <= 0)
426 if (zbackend) 271 return;
427 return zbackend->decompress(in, out, inlen, outlen);
428 else
429 return -EIO;
430}
431 272
432static void allocate_buf_for_compression(void) 273 big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
433{ 274 if (!big_oops_buf) {
434 if (zbackend) {
435 pr_info("using %s compression\n", zbackend->name);
436 zbackend->allocate();
437 } else {
438 pr_err("allocate compression buffer error!\n"); 275 pr_err("allocate compression buffer error!\n");
276 return;
277 }
278
279 tfm = crypto_alloc_comp(zbackend->name, 0, 0);
280 if (IS_ERR_OR_NULL(tfm)) {
281 kfree(big_oops_buf);
282 big_oops_buf = NULL;
283 pr_err("crypto_alloc_comp() failed!\n");
284 return;
439 } 285 }
440} 286}
441 287
442static void free_buf_for_compression(void) 288static void free_buf_for_compression(void)
443{ 289{
444 if (zbackend) 290 if (!IS_ERR_OR_NULL(tfm))
445 zbackend->free(); 291 crypto_free_comp(tfm);
446 else 292 kfree(big_oops_buf);
447 pr_err("free compression buffer error!\n"); 293 big_oops_buf = NULL;
294 big_oops_buf_sz = 0;
448} 295}
449 296
450/* 297/*
@@ -901,5 +748,24 @@ static void pstore_timefunc(struct timer_list *unused)
901 jiffies + msecs_to_jiffies(pstore_update_ms)); 748 jiffies + msecs_to_jiffies(pstore_update_ms));
902} 749}
903 750
751void __init pstore_choose_compression(void)
752{
753 const struct pstore_zbackend *step;
754
755 if (!compress)
756 return;
757
758 for (step = zbackends; step->name; step++) {
759 if (!strcmp(compress, step->name)) {
760 zbackend = step;
761 pr_info("using %s compression\n", zbackend->name);
762 return;
763 }
764 }
765}
766
767module_param(compress, charp, 0444);
768MODULE_PARM_DESC(compress, "Pstore compression to use");
769
904module_param(backend, charp, 0444); 770module_param(backend, charp, 0444);
905MODULE_PARM_DESC(backend, "Pstore backend to use"); 771MODULE_PARM_DESC(backend, "Pstore backend to use");
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 7125b398d312..49b2bc114868 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -938,7 +938,7 @@ static int __init ramoops_init(void)
938 ramoops_register_dummy(); 938 ramoops_register_dummy();
939 return platform_driver_register(&ramoops_driver); 939 return platform_driver_register(&ramoops_driver);
940} 940}
941postcore_initcall(ramoops_init); 941late_initcall(ramoops_init);
942 942
943static void __exit ramoops_exit(void) 943static void __exit ramoops_exit(void)
944{ 944{
diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c
index e11672aa4575..951a14edcf51 100644
--- a/fs/pstore/ram_core.c
+++ b/fs/pstore/ram_core.c
@@ -98,24 +98,23 @@ static void notrace persistent_ram_encode_rs8(struct persistent_ram_zone *prz,
98 uint8_t *data, size_t len, uint8_t *ecc) 98 uint8_t *data, size_t len, uint8_t *ecc)
99{ 99{
100 int i; 100 int i;
101 uint16_t par[prz->ecc_info.ecc_size];
102 101
103 /* Initialize the parity buffer */ 102 /* Initialize the parity buffer */
104 memset(par, 0, sizeof(par)); 103 memset(prz->ecc_info.par, 0,
105 encode_rs8(prz->rs_decoder, data, len, par, 0); 104 prz->ecc_info.ecc_size * sizeof(prz->ecc_info.par[0]));
105 encode_rs8(prz->rs_decoder, data, len, prz->ecc_info.par, 0);
106 for (i = 0; i < prz->ecc_info.ecc_size; i++) 106 for (i = 0; i < prz->ecc_info.ecc_size; i++)
107 ecc[i] = par[i]; 107 ecc[i] = prz->ecc_info.par[i];
108} 108}
109 109
110static int persistent_ram_decode_rs8(struct persistent_ram_zone *prz, 110static int persistent_ram_decode_rs8(struct persistent_ram_zone *prz,
111 void *data, size_t len, uint8_t *ecc) 111 void *data, size_t len, uint8_t *ecc)
112{ 112{
113 int i; 113 int i;
114 uint16_t par[prz->ecc_info.ecc_size];
115 114
116 for (i = 0; i < prz->ecc_info.ecc_size; i++) 115 for (i = 0; i < prz->ecc_info.ecc_size; i++)
117 par[i] = ecc[i]; 116 prz->ecc_info.par[i] = ecc[i];
118 return decode_rs8(prz->rs_decoder, data, par, len, 117 return decode_rs8(prz->rs_decoder, data, prz->ecc_info.par, len,
119 NULL, 0, NULL, 0, NULL); 118 NULL, 0, NULL, 0, NULL);
120} 119}
121 120
@@ -228,6 +227,15 @@ static int persistent_ram_init_ecc(struct persistent_ram_zone *prz,
228 return -EINVAL; 227 return -EINVAL;
229 } 228 }
230 229
230 /* allocate workspace instead of using stack VLA */
231 prz->ecc_info.par = kmalloc_array(prz->ecc_info.ecc_size,
232 sizeof(*prz->ecc_info.par),
233 GFP_KERNEL);
234 if (!prz->ecc_info.par) {
235 pr_err("cannot allocate ECC parity workspace\n");
236 return -ENOMEM;
237 }
238
231 prz->corrected_bytes = 0; 239 prz->corrected_bytes = 0;
232 prz->bad_blocks = 0; 240 prz->bad_blocks = 0;
233 241
@@ -514,6 +522,13 @@ void persistent_ram_free(struct persistent_ram_zone *prz)
514 } 522 }
515 prz->vaddr = NULL; 523 prz->vaddr = NULL;
516 } 524 }
525 if (prz->rs_decoder) {
526 free_rs(prz->rs_decoder);
527 prz->rs_decoder = NULL;
528 }
529 kfree(prz->ecc_info.par);
530 prz->ecc_info.par = NULL;
531
517 persistent_ram_free_old(prz); 532 persistent_ram_free_old(prz);
518 kfree(prz); 533 kfree(prz);
519} 534}
diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h
index 9395f06e8372..e6d226464838 100644
--- a/include/linux/pstore_ram.h
+++ b/include/linux/pstore_ram.h
@@ -39,6 +39,7 @@ struct persistent_ram_ecc_info {
39 int ecc_size; 39 int ecc_size;
40 int symsize; 40 int symsize;
41 int poly; 41 int poly;
42 uint16_t *par;
42}; 43};
43 44
44struct persistent_ram_zone { 45struct persistent_ram_zone {