blob: df54dd87598a24588cdeadafa01be33049a0dc32 [file] [log] [blame]
Tony Luckca01d6d2010-12-28 14:25:21 -08001/*
2 * Persistent Storage - platform driver interface parts.
3 *
Anton Vorontsovf29e5952012-05-26 06:20:19 -07004 * Copyright (C) 2007-2008 Google, Inc.
Tony Luckca01d6d2010-12-28 14:25:21 -08005 * Copyright (C) 2010 Intel Corporation <tony.luck@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
Fabian Frederickef748852014-06-06 14:37:31 -070021#define pr_fmt(fmt) "pstore: " fmt
22
Tony Luckca01d6d2010-12-28 14:25:21 -080023#include <linux/atomic.h>
24#include <linux/types.h>
25#include <linux/errno.h>
26#include <linux/init.h>
27#include <linux/kmsg_dump.h>
Anton Vorontsovf29e5952012-05-26 06:20:19 -070028#include <linux/console.h>
Tony Luckca01d6d2010-12-28 14:25:21 -080029#include <linux/module.h>
30#include <linux/pstore.h>
Geliang Tang8cfc8dd2016-02-18 22:04:22 +080031#ifdef CONFIG_PSTORE_ZLIB_COMPRESS
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -070032#include <linux/zlib.h>
Geliang Tang8cfc8dd2016-02-18 22:04:22 +080033#endif
34#ifdef CONFIG_PSTORE_LZO_COMPRESS
35#include <linux/lzo.h>
36#endif
Geliang Tang239b7162018-02-13 14:40:39 +080037#if defined(CONFIG_PSTORE_LZ4_COMPRESS) || defined(CONFIG_PSTORE_LZ4HC_COMPRESS)
Geliang Tang8cfc8dd2016-02-18 22:04:22 +080038#include <linux/lz4.h>
39#endif
Geliang Tang239b7162018-02-13 14:40:39 +080040#ifdef CONFIG_PSTORE_842_COMPRESS
41#include <linux/sw842.h>
42#endif
Tony Luckca01d6d2010-12-28 14:25:21 -080043#include <linux/string.h>
Luck, Tony6dda9262011-08-11 15:14:39 -070044#include <linux/timer.h>
Tony Luckca01d6d2010-12-28 14:25:21 -080045#include <linux/slab.h>
46#include <linux/uaccess.h>
Anton Vorontsova3f5f072012-05-26 06:20:28 -070047#include <linux/jiffies.h>
Luck, Tony6dda9262011-08-11 15:14:39 -070048#include <linux/workqueue.h>
Tony Luckca01d6d2010-12-28 14:25:21 -080049
50#include "internal.h"
51
52/*
Luck, Tony6dda9262011-08-11 15:14:39 -070053 * We defer making "oops" entries appear in pstore - see
54 * whether the system is actually still running well enough
55 * to let someone see the entry
56 */
Anton Vorontsov521f72882012-05-26 06:20:29 -070057static int pstore_update_ms = -1;
Anton Vorontsova3f5f072012-05-26 06:20:28 -070058module_param_named(update_ms, pstore_update_ms, int, 0600);
59MODULE_PARM_DESC(update_ms, "milliseconds before pstore updates its content "
Anton Vorontsov521f72882012-05-26 06:20:29 -070060 "(default is -1, which means runtime updates are disabled; "
61 "enabling this option is not safe, it may lead to further "
62 "corruption on Oopses)");
Luck, Tony6dda9262011-08-11 15:14:39 -070063
64static int pstore_new_entry;
65
Kees Cook24ed9602017-08-28 11:28:21 -070066static void pstore_timefunc(struct timer_list *);
Kees Cook1d27e3e2017-10-04 16:27:04 -070067static DEFINE_TIMER(pstore_timer, pstore_timefunc);
Luck, Tony6dda9262011-08-11 15:14:39 -070068
69static void pstore_dowork(struct work_struct *);
70static DECLARE_WORK(pstore_work, pstore_dowork);
71
72/*
Tony Luckca01d6d2010-12-28 14:25:21 -080073 * pstore_lock just protects "psinfo" during
74 * calls to pstore_register()
75 */
76static DEFINE_SPINLOCK(pstore_lock);
Anton Vorontsov060287b2012-07-09 17:10:41 -070077struct pstore_info *psinfo;
Tony Luckca01d6d2010-12-28 14:25:21 -080078
Matthew Garrettdee28e72011-07-21 16:57:55 -040079static char *backend;
80
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -070081/* Compression parameters */
Geliang Tang8cfc8dd2016-02-18 22:04:22 +080082#ifdef CONFIG_PSTORE_ZLIB_COMPRESS
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -070083#define COMPR_LEVEL 6
84#define WINDOW_BITS 12
85#define MEM_LEVEL 4
86static struct z_stream_s stream;
Geliang Tang8cfc8dd2016-02-18 22:04:22 +080087#else
88static unsigned char *workspace;
89#endif
90
91struct pstore_zbackend {
92 int (*compress)(const void *in, void *out, size_t inlen, size_t outlen);
93 int (*decompress)(void *in, void *out, size_t inlen, size_t outlen);
94 void (*allocate)(void);
95 void (*free)(void);
96
97 const char *name;
98};
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -070099
100static char *big_oops_buf;
101static size_t big_oops_buf_sz;
102
Luck, Tony366f7e72011-03-18 15:33:43 -0700103/* How much of the console log to snapshot */
David Howells349d7432017-07-05 16:24:34 +0100104unsigned long kmsg_bytes = PSTORE_DEFAULT_KMSG_BYTES;
Tony Luckca01d6d2010-12-28 14:25:21 -0800105
Luck, Tony366f7e72011-03-18 15:33:43 -0700106void pstore_set_kmsg_bytes(int bytes)
Tony Luckca01d6d2010-12-28 14:25:21 -0800107{
Luck, Tony366f7e72011-03-18 15:33:43 -0700108 kmsg_bytes = bytes;
Tony Luckca01d6d2010-12-28 14:25:21 -0800109}
110
Tony Luckca01d6d2010-12-28 14:25:21 -0800111/* Tag each group of saved records with a sequence number */
112static int oopscount;
113
Seiji Aguchi381b8722012-03-16 15:36:59 -0700114static const char *get_reason_str(enum kmsg_dump_reason reason)
115{
116 switch (reason) {
117 case KMSG_DUMP_PANIC:
118 return "Panic";
119 case KMSG_DUMP_OOPS:
120 return "Oops";
121 case KMSG_DUMP_EMERG:
122 return "Emergency";
123 case KMSG_DUMP_RESTART:
124 return "Restart";
125 case KMSG_DUMP_HALT:
126 return "Halt";
127 case KMSG_DUMP_POWEROFF:
128 return "Poweroff";
129 default:
130 return "Unknown";
131 }
132}
Tony Luck9f6af272011-03-22 16:01:49 -0700133
Seiji Aguchi9f244e92013-01-11 18:09:41 +0000134bool pstore_cannot_block_path(enum kmsg_dump_reason reason)
135{
136 /*
137 * In case of NMI path, pstore shouldn't be blocked
138 * regardless of reason.
139 */
140 if (in_nmi())
141 return true;
142
143 switch (reason) {
144 /* In panic case, other cpus are stopped by smp_send_stop(). */
145 case KMSG_DUMP_PANIC:
146 /* Emergency restart shouldn't be blocked by spin lock. */
147 case KMSG_DUMP_EMERG:
148 return true;
149 default:
150 return false;
151 }
152}
153EXPORT_SYMBOL_GPL(pstore_cannot_block_path);
154
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800155#ifdef CONFIG_PSTORE_ZLIB_COMPRESS
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700156/* Derived from logfs_compress() */
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800157static int compress_zlib(const void *in, void *out, size_t inlen, size_t outlen)
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700158{
159 int err, ret;
160
161 ret = -EIO;
162 err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
163 MEM_LEVEL, Z_DEFAULT_STRATEGY);
164 if (err != Z_OK)
165 goto error;
166
167 stream.next_in = in;
168 stream.avail_in = inlen;
169 stream.total_in = 0;
170 stream.next_out = out;
171 stream.avail_out = outlen;
172 stream.total_out = 0;
173
174 err = zlib_deflate(&stream, Z_FINISH);
175 if (err != Z_STREAM_END)
176 goto error;
177
178 err = zlib_deflateEnd(&stream);
179 if (err != Z_OK)
180 goto error;
181
182 if (stream.total_out >= stream.total_in)
183 goto error;
184
185 ret = stream.total_out;
186error:
187 return ret;
188}
189
Aruna Balakrishnaiahadb42f52013-08-16 13:53:28 -0700190/* Derived from logfs_uncompress */
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800191static int decompress_zlib(void *in, void *out, size_t inlen, size_t outlen)
Aruna Balakrishnaiahadb42f52013-08-16 13:53:28 -0700192{
193 int err, ret;
194
195 ret = -EIO;
Aruna Balakrishnaiahb61edf82013-09-11 10:58:03 -0700196 err = zlib_inflateInit2(&stream, WINDOW_BITS);
Aruna Balakrishnaiahadb42f52013-08-16 13:53:28 -0700197 if (err != Z_OK)
198 goto error;
199
200 stream.next_in = in;
201 stream.avail_in = inlen;
202 stream.total_in = 0;
203 stream.next_out = out;
204 stream.avail_out = outlen;
205 stream.total_out = 0;
206
207 err = zlib_inflate(&stream, Z_FINISH);
208 if (err != Z_STREAM_END)
209 goto error;
210
211 err = zlib_inflateEnd(&stream);
212 if (err != Z_OK)
213 goto error;
214
215 ret = stream.total_out;
216error:
217 return ret;
218}
219
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800220static void allocate_zlib(void)
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700221{
222 size_t size;
Aruna Balakrishnaiah7de8fe22013-09-11 10:57:41 -0700223 size_t cmpr;
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700224
Aruna Balakrishnaiah7de8fe22013-09-11 10:57:41 -0700225 switch (psinfo->bufsize) {
226 /* buffer range for efivars */
227 case 1000 ... 2000:
228 cmpr = 56;
229 break;
230 case 2001 ... 3000:
231 cmpr = 54;
232 break;
233 case 3001 ... 3999:
234 cmpr = 52;
235 break;
236 /* buffer range for nvram, erst */
237 case 4000 ... 10000:
238 cmpr = 45;
239 break;
240 default:
241 cmpr = 60;
242 break;
243 }
244
245 big_oops_buf_sz = (psinfo->bufsize * 100) / cmpr;
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700246 big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
247 if (big_oops_buf) {
248 size = max(zlib_deflate_workspacesize(WINDOW_BITS, MEM_LEVEL),
249 zlib_inflate_workspacesize());
250 stream.workspace = kmalloc(size, GFP_KERNEL);
251 if (!stream.workspace) {
Fabian Frederickef748852014-06-06 14:37:31 -0700252 pr_err("No memory for compression workspace; skipping compression\n");
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700253 kfree(big_oops_buf);
254 big_oops_buf = NULL;
255 }
256 } else {
Fabian Frederickef748852014-06-06 14:37:31 -0700257 pr_err("No memory for uncompressed data; skipping compression\n");
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700258 stream.workspace = NULL;
259 }
260
261}
262
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800263static void free_zlib(void)
Geliang Tangee1d2672015-10-20 00:39:03 -0700264{
265 kfree(stream.workspace);
266 stream.workspace = NULL;
267 kfree(big_oops_buf);
268 big_oops_buf = NULL;
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800269 big_oops_buf_sz = 0;
270}
271
Bhumika Goyal3faf9352017-02-19 15:07:53 +0530272static const struct pstore_zbackend backend_zlib = {
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800273 .compress = compress_zlib,
274 .decompress = decompress_zlib,
275 .allocate = allocate_zlib,
276 .free = free_zlib,
277 .name = "zlib",
278};
279#endif
280
281#ifdef CONFIG_PSTORE_LZO_COMPRESS
282static int compress_lzo(const void *in, void *out, size_t inlen, size_t outlen)
283{
284 int ret;
285
286 ret = lzo1x_1_compress(in, inlen, out, &outlen, workspace);
287 if (ret != LZO_E_OK) {
288 pr_err("lzo_compress error, ret = %d!\n", ret);
289 return -EIO;
290 }
291
292 return outlen;
293}
294
295static int decompress_lzo(void *in, void *out, size_t inlen, size_t outlen)
296{
297 int ret;
298
299 ret = lzo1x_decompress_safe(in, inlen, out, &outlen);
300 if (ret != LZO_E_OK) {
301 pr_err("lzo_decompress error, ret = %d!\n", ret);
302 return -EIO;
303 }
304
305 return outlen;
306}
307
308static void allocate_lzo(void)
309{
310 big_oops_buf_sz = lzo1x_worst_compress(psinfo->bufsize);
311 big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
312 if (big_oops_buf) {
313 workspace = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
314 if (!workspace) {
315 pr_err("No memory for compression workspace; skipping compression\n");
316 kfree(big_oops_buf);
317 big_oops_buf = NULL;
318 }
319 } else {
320 pr_err("No memory for uncompressed data; skipping compression\n");
321 workspace = NULL;
322 }
323}
324
325static void free_lzo(void)
326{
327 kfree(workspace);
328 kfree(big_oops_buf);
329 big_oops_buf = NULL;
330 big_oops_buf_sz = 0;
331}
332
Bhumika Goyal3faf9352017-02-19 15:07:53 +0530333static const struct pstore_zbackend backend_lzo = {
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800334 .compress = compress_lzo,
335 .decompress = decompress_lzo,
336 .allocate = allocate_lzo,
337 .free = free_lzo,
338 .name = "lzo",
339};
340#endif
341
Geliang Tang239b7162018-02-13 14:40:39 +0800342#if defined(CONFIG_PSTORE_LZ4_COMPRESS) || defined(CONFIG_PSTORE_LZ4HC_COMPRESS)
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800343static int decompress_lz4(void *in, void *out, size_t inlen, size_t outlen)
344{
345 int ret;
346
Sven Schmidtd21b5ff122017-02-24 15:01:22 -0800347 ret = LZ4_decompress_safe(in, out, inlen, outlen);
348 if (ret < 0) {
349 /*
350 * LZ4_decompress_safe will return an error code
351 * (< 0) if decompression failed
352 */
353 pr_err("LZ4_decompress_safe error, ret = %d!\n", ret);
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800354 return -EIO;
355 }
356
Sven Schmidtd21b5ff122017-02-24 15:01:22 -0800357 return ret;
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800358}
359
Geliang Tang239b7162018-02-13 14:40:39 +0800360static void free_lz4(void)
361{
362 kfree(workspace);
363 kfree(big_oops_buf);
364 big_oops_buf = NULL;
365 big_oops_buf_sz = 0;
366}
367#endif
368
369#ifdef CONFIG_PSTORE_LZ4_COMPRESS
370static int compress_lz4(const void *in, void *out, size_t inlen, size_t outlen)
371{
372 int ret;
373
374 ret = LZ4_compress_default(in, out, inlen, outlen, workspace);
375 if (!ret) {
376 pr_err("LZ4_compress_default error; compression failed!\n");
377 return -EIO;
378 }
379
380 return ret;
381}
382
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800383static void allocate_lz4(void)
384{
Sven Schmidtd21b5ff122017-02-24 15:01:22 -0800385 big_oops_buf_sz = LZ4_compressBound(psinfo->bufsize);
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800386 big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
387 if (big_oops_buf) {
388 workspace = kmalloc(LZ4_MEM_COMPRESS, GFP_KERNEL);
389 if (!workspace) {
390 pr_err("No memory for compression workspace; skipping compression\n");
391 kfree(big_oops_buf);
392 big_oops_buf = NULL;
393 }
394 } else {
395 pr_err("No memory for uncompressed data; skipping compression\n");
396 workspace = NULL;
397 }
398}
399
Geliang Tang239b7162018-02-13 14:40:39 +0800400static const struct pstore_zbackend backend_lz4 = {
401 .compress = compress_lz4,
402 .decompress = decompress_lz4,
403 .allocate = allocate_lz4,
404 .free = free_lz4,
405 .name = "lz4",
406};
407#endif
408
409#ifdef CONFIG_PSTORE_LZ4HC_COMPRESS
410static int compress_lz4hc(const void *in, void *out,
411 size_t inlen, size_t outlen)
412{
413 int ret;
414
415 ret = LZ4_compress_HC(in, out, inlen, outlen,
416 LZ4HC_DEFAULT_CLEVEL, workspace);
417 if (!ret) {
418 pr_err("LZ4_compress_HC error; compression failed!\n");
419 return -EIO;
420 }
421
422 return ret;
423}
424
425static void allocate_lz4hc(void)
426{
427 big_oops_buf_sz = LZ4_compressBound(psinfo->bufsize);
428 big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
429 if (big_oops_buf) {
430 workspace = kmalloc(LZ4HC_MEM_COMPRESS, GFP_KERNEL);
431 if (!workspace) {
432 pr_err("No memory for compression workspace; skipping compression\n");
433 kfree(big_oops_buf);
434 big_oops_buf = NULL;
435 }
436 } else {
437 pr_err("No memory for uncompressed data; skipping compression\n");
438 workspace = NULL;
439 }
440}
441
442static const struct pstore_zbackend backend_lz4hc = {
443 .compress = compress_lz4hc,
444 .decompress = decompress_lz4,
445 .allocate = allocate_lz4hc,
446 .free = free_lz4,
447 .name = "lz4hc",
448};
449#endif
450
451#ifdef CONFIG_PSTORE_842_COMPRESS
452static int compress_842(const void *in, void *out, size_t inlen, size_t outlen)
453{
454 int ret;
Kees Cook55597402018-03-06 15:15:24 -0800455 unsigned int size;
Geliang Tang239b7162018-02-13 14:40:39 +0800456
Kees Cook55597402018-03-06 15:15:24 -0800457 if (outlen > UINT_MAX)
458 return -EIO;
459 size = outlen;
460
461 ret = sw842_compress(in, inlen, out, &size, workspace);
Geliang Tang239b7162018-02-13 14:40:39 +0800462 if (ret) {
463 pr_err("sw842_compress error; compression failed!\n");
464 return ret;
465 }
466
Kees Cook55597402018-03-06 15:15:24 -0800467 return size;
Geliang Tang239b7162018-02-13 14:40:39 +0800468}
469
470static int decompress_842(void *in, void *out, size_t inlen, size_t outlen)
471{
472 int ret;
Kees Cook55597402018-03-06 15:15:24 -0800473 unsigned int size;
Geliang Tang239b7162018-02-13 14:40:39 +0800474
Kees Cook55597402018-03-06 15:15:24 -0800475 if (outlen > UINT_MAX)
476 return -EIO;
477 size = outlen;
478
479 ret = sw842_decompress(in, inlen, out, &size);
Geliang Tang239b7162018-02-13 14:40:39 +0800480 if (ret) {
481 pr_err("sw842_decompress error, ret = %d!\n", ret);
482 return ret;
483 }
484
Kees Cook55597402018-03-06 15:15:24 -0800485 return size;
Geliang Tang239b7162018-02-13 14:40:39 +0800486}
487
488static void allocate_842(void)
489{
490 big_oops_buf_sz = psinfo->bufsize;
491 big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
492 if (big_oops_buf) {
493 workspace = kmalloc(SW842_MEM_COMPRESS, GFP_KERNEL);
494 if (!workspace) {
495 kfree(big_oops_buf);
496 big_oops_buf = NULL;
497 }
498 } else {
499 pr_err("No memory for uncompressed data; skipping compression\n");
500 workspace = NULL;
501 }
502}
503
504static void free_842(void)
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800505{
506 kfree(workspace);
507 kfree(big_oops_buf);
508 big_oops_buf = NULL;
509 big_oops_buf_sz = 0;
510}
511
Geliang Tang239b7162018-02-13 14:40:39 +0800512static const struct pstore_zbackend backend_842 = {
513 .compress = compress_842,
514 .decompress = decompress_842,
515 .allocate = allocate_842,
516 .free = free_842,
517 .name = "842",
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800518};
519#endif
520
Bhumika Goyal3faf9352017-02-19 15:07:53 +0530521static const struct pstore_zbackend *zbackend =
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800522#if defined(CONFIG_PSTORE_ZLIB_COMPRESS)
523 &backend_zlib;
524#elif defined(CONFIG_PSTORE_LZO_COMPRESS)
525 &backend_lzo;
526#elif defined(CONFIG_PSTORE_LZ4_COMPRESS)
527 &backend_lz4;
Geliang Tang239b7162018-02-13 14:40:39 +0800528#elif defined(CONFIG_PSTORE_LZ4HC_COMPRESS)
529 &backend_lz4hc;
530#elif defined(CONFIG_PSTORE_842_COMPRESS)
531 &backend_842;
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800532#else
533 NULL;
534#endif
535
536static int pstore_compress(const void *in, void *out,
537 size_t inlen, size_t outlen)
538{
539 if (zbackend)
540 return zbackend->compress(in, out, inlen, outlen);
541 else
542 return -EIO;
543}
544
545static int pstore_decompress(void *in, void *out, size_t inlen, size_t outlen)
546{
547 if (zbackend)
548 return zbackend->decompress(in, out, inlen, outlen);
549 else
550 return -EIO;
551}
552
553static void allocate_buf_for_compression(void)
554{
555 if (zbackend) {
556 pr_info("using %s compression\n", zbackend->name);
557 zbackend->allocate();
558 } else {
559 pr_err("allocate compression buffer error!\n");
560 }
561}
562
563static void free_buf_for_compression(void)
564{
565 if (zbackend)
566 zbackend->free();
567 else
568 pr_err("free compression buffer error!\n");
Geliang Tangee1d2672015-10-20 00:39:03 -0700569}
570
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700571/*
572 * Called when compression fails, since the printk buffer
573 * would be fetched for compression calling it again when
574 * compression fails would have moved the iterator of
575 * printk buffer which results in fetching old contents.
576 * Copy the recent messages from big_oops_buf to psinfo->buf
577 */
578static size_t copy_kmsg_to_buffer(int hsize, size_t len)
579{
580 size_t total_len;
581 size_t diff;
582
583 total_len = hsize + len;
584
585 if (total_len > psinfo->bufsize) {
586 diff = total_len - psinfo->bufsize + hsize;
587 memcpy(psinfo->buf, big_oops_buf, hsize);
588 memcpy(psinfo->buf + hsize, big_oops_buf + diff,
589 psinfo->bufsize - hsize);
590 total_len = psinfo->bufsize;
591 } else
592 memcpy(psinfo->buf, big_oops_buf, total_len);
593
594 return total_len;
595}
596
Kees Cooke581ca82017-05-19 15:10:31 -0700597void pstore_record_init(struct pstore_record *record,
598 struct pstore_info *psinfo)
599{
600 memset(record, 0, sizeof(*record));
601
602 record->psi = psinfo;
Kees Cookc7f3c5952017-05-19 15:29:10 -0700603
604 /* Report zeroed timestamp if called before timekeeping has resumed. */
Arnd Bergmanndf270672017-11-10 16:25:04 +0100605 record->time = ns_to_timespec(ktime_get_real_fast_ns());
Kees Cooke581ca82017-05-19 15:10:31 -0700606}
607
Tony Luckca01d6d2010-12-28 14:25:21 -0800608/*
609 * callback from kmsg_dump. (s2,l2) has the most recently
610 * written bytes, older bytes are in (s1,l1). Save as much
611 * as we can from the end of the buffer.
612 */
613static void pstore_dump(struct kmsg_dumper *dumper,
Kay Sieverse2ae7152012-06-15 14:07:51 +0200614 enum kmsg_dump_reason reason)
Tony Luckca01d6d2010-12-28 14:25:21 -0800615{
Kay Sieverse2ae7152012-06-15 14:07:51 +0200616 unsigned long total = 0;
Seiji Aguchi381b8722012-03-16 15:36:59 -0700617 const char *why;
Matthew Garrettb94fdd02011-07-21 16:57:54 -0400618 unsigned int part = 1;
Don Zickusabd4d552011-08-12 10:54:51 -0700619 unsigned long flags = 0;
Namhyung Kim98e44fda2016-05-18 21:00:05 +0900620 int is_locked;
Kay Sieverse2ae7152012-06-15 14:07:51 +0200621 int ret;
Tony Luckca01d6d2010-12-28 14:25:21 -0800622
Seiji Aguchi381b8722012-03-16 15:36:59 -0700623 why = get_reason_str(reason);
Tony Luck9f6af272011-03-22 16:01:49 -0700624
Seiji Aguchi9f244e92013-01-11 18:09:41 +0000625 if (pstore_cannot_block_path(reason)) {
626 is_locked = spin_trylock_irqsave(&psinfo->buf_lock, flags);
627 if (!is_locked) {
628 pr_err("pstore dump routine blocked in %s path, may corrupt error record\n"
629 , in_nmi() ? "NMI" : why);
Li Pengcheng959217c2016-11-05 10:15:59 +0800630 return;
Seiji Aguchi9f244e92013-01-11 18:09:41 +0000631 }
Namhyung Kim98e44fda2016-05-18 21:00:05 +0900632 } else {
Don Zickusabd4d552011-08-12 10:54:51 -0700633 spin_lock_irqsave(&psinfo->buf_lock, flags);
Namhyung Kim98e44fda2016-05-18 21:00:05 +0900634 is_locked = 1;
635 }
Tony Luckca01d6d2010-12-28 14:25:21 -0800636 oopscount++;
637 while (total < kmsg_bytes) {
Kay Sieverse2ae7152012-06-15 14:07:51 +0200638 char *dst;
Kees Cook76cc9582017-03-03 23:28:53 -0800639 size_t dst_size;
640 int header_size;
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700641 int zipped_len = -1;
Kees Cook76cc9582017-03-03 23:28:53 -0800642 size_t dump_size;
Kees Cooke581ca82017-05-19 15:10:31 -0700643 struct pstore_record record;
644
645 pstore_record_init(&record, psinfo);
646 record.type = PSTORE_TYPE_DMESG;
647 record.count = oopscount;
648 record.reason = reason;
649 record.part = part;
650 record.buf = psinfo->buf;
Kay Sieverse2ae7152012-06-15 14:07:51 +0200651
Konstantin Khlebnikovf0e2efc2015-05-21 09:26:19 -0700652 if (big_oops_buf && is_locked) {
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700653 dst = big_oops_buf;
Kees Cook76cc9582017-03-03 23:28:53 -0800654 dst_size = big_oops_buf_sz;
Namhyung Kim235f6d12016-05-18 21:00:06 +0900655 } else {
656 dst = psinfo->buf;
Kees Cook76cc9582017-03-03 23:28:53 -0800657 dst_size = psinfo->bufsize;
Namhyung Kim235f6d12016-05-18 21:00:06 +0900658 }
Tony Luckca01d6d2010-12-28 14:25:21 -0800659
Kees Cook76cc9582017-03-03 23:28:53 -0800660 /* Write dump header. */
661 header_size = snprintf(dst, dst_size, "%s#%d Part%u\n", why,
662 oopscount, part);
663 dst_size -= header_size;
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700664
Kees Cook76cc9582017-03-03 23:28:53 -0800665 /* Write dump contents. */
666 if (!kmsg_dump_get_buffer(dumper, true, dst + header_size,
667 dst_size, &dump_size))
Namhyung Kim235f6d12016-05-18 21:00:06 +0900668 break;
669
670 if (big_oops_buf && is_locked) {
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700671 zipped_len = pstore_compress(dst, psinfo->buf,
Kees Cook76cc9582017-03-03 23:28:53 -0800672 header_size + dump_size,
673 psinfo->bufsize);
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700674
675 if (zipped_len > 0) {
Kees Cook76cc9582017-03-03 23:28:53 -0800676 record.compressed = true;
677 record.size = zipped_len;
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700678 } else {
Kees Cook76cc9582017-03-03 23:28:53 -0800679 record.size = copy_kmsg_to_buffer(header_size,
680 dump_size);
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700681 }
682 } else {
Kees Cook76cc9582017-03-03 23:28:53 -0800683 record.size = header_size + dump_size;
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700684 }
Tony Luckca01d6d2010-12-28 14:25:21 -0800685
Kees Cook76cc9582017-03-03 23:28:53 -0800686 ret = psinfo->write(&record);
Chen Gongb238b8f2011-10-12 09:17:24 -0700687 if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted())
Luck, Tony6dda9262011-08-11 15:14:39 -0700688 pstore_new_entry = 1;
Kay Sieverse2ae7152012-06-15 14:07:51 +0200689
Kees Cook76cc9582017-03-03 23:28:53 -0800690 total += record.size;
Matthew Garrett56280682011-07-21 16:57:53 -0400691 part++;
Tony Luckca01d6d2010-12-28 14:25:21 -0800692 }
Namhyung Kim98e44fda2016-05-18 21:00:05 +0900693 if (is_locked)
Don Zickusabd4d552011-08-12 10:54:51 -0700694 spin_unlock_irqrestore(&psinfo->buf_lock, flags);
Tony Luckca01d6d2010-12-28 14:25:21 -0800695}
696
697static struct kmsg_dumper pstore_dumper = {
698 .dump = pstore_dump,
699};
700
Geliang Tang306e5c22015-10-31 23:23:15 +0800701/*
702 * Register with kmsg_dump to save last part of console log on panic.
703 */
Geliang Tang18730412015-10-20 00:39:02 -0700704static void pstore_register_kmsg(void)
705{
706 kmsg_dump_register(&pstore_dumper);
707}
708
Geliang Tangee1d2672015-10-20 00:39:03 -0700709static void pstore_unregister_kmsg(void)
710{
711 kmsg_dump_unregister(&pstore_dumper);
712}
713
Anton Vorontsovf29e5952012-05-26 06:20:19 -0700714#ifdef CONFIG_PSTORE_CONSOLE
715static void pstore_console_write(struct console *con, const char *s, unsigned c)
716{
717 const char *e = s + c;
718
719 while (s < e) {
Kees Cooke581ca82017-05-19 15:10:31 -0700720 struct pstore_record record;
Anton Vorontsovf29e5952012-05-26 06:20:19 -0700721 unsigned long flags;
722
Kees Cooke581ca82017-05-19 15:10:31 -0700723 pstore_record_init(&record, psinfo);
724 record.type = PSTORE_TYPE_CONSOLE;
725
Anton Vorontsovf29e5952012-05-26 06:20:19 -0700726 if (c > psinfo->bufsize)
727 c = psinfo->bufsize;
Chuansheng Liu80c9d032012-09-18 01:43:44 +0800728
729 if (oops_in_progress) {
730 if (!spin_trylock_irqsave(&psinfo->buf_lock, flags))
731 break;
732 } else {
733 spin_lock_irqsave(&psinfo->buf_lock, flags);
734 }
Kees Cookb10b4712017-03-05 00:27:54 -0800735 record.buf = (char *)s;
736 record.size = c;
Kees Cook4c9ec212017-03-05 22:41:10 -0800737 psinfo->write(&record);
Anton Vorontsovf29e5952012-05-26 06:20:19 -0700738 spin_unlock_irqrestore(&psinfo->buf_lock, flags);
739 s += c;
740 c = e - s;
741 }
742}
743
744static struct console pstore_console = {
745 .name = "pstore",
746 .write = pstore_console_write,
747 .flags = CON_PRINTBUFFER | CON_ENABLED | CON_ANYTIME,
748 .index = -1,
749};
750
751static void pstore_register_console(void)
752{
753 register_console(&pstore_console);
754}
Geliang Tangee1d2672015-10-20 00:39:03 -0700755
756static void pstore_unregister_console(void)
757{
758 unregister_console(&pstore_console);
759}
Anton Vorontsovf29e5952012-05-26 06:20:19 -0700760#else
761static void pstore_register_console(void) {}
Geliang Tangee1d2672015-10-20 00:39:03 -0700762static void pstore_unregister_console(void) {}
Anton Vorontsovf29e5952012-05-26 06:20:19 -0700763#endif
764
Kees Cook4c9ec212017-03-05 22:41:10 -0800765static int pstore_write_user_compat(struct pstore_record *record,
766 const char __user *buf)
Mark Salyzyn5bf6d1b2016-09-01 08:13:46 -0700767{
Kees Cook30800d92017-03-07 13:57:11 -0800768 int ret = 0;
Mark Salyzyn5bf6d1b2016-09-01 08:13:46 -0700769
Kees Cook30800d92017-03-07 13:57:11 -0800770 if (record->buf)
771 return -EINVAL;
Mark Salyzyn5bf6d1b2016-09-01 08:13:46 -0700772
Geliang Tang077090a2017-04-29 09:45:16 +0800773 record->buf = memdup_user(buf, record->size);
Hirofumi Nakagawadfd6fa32017-09-26 03:21:27 +0900774 if (IS_ERR(record->buf)) {
Geliang Tang077090a2017-04-29 09:45:16 +0800775 ret = PTR_ERR(record->buf);
Kees Cook30800d92017-03-07 13:57:11 -0800776 goto out;
Mark Salyzyn5bf6d1b2016-09-01 08:13:46 -0700777 }
Kees Cook30800d92017-03-07 13:57:11 -0800778
779 ret = record->psi->write(record);
780
Kees Cook30800d92017-03-07 13:57:11 -0800781 kfree(record->buf);
Geliang Tang077090a2017-04-29 09:45:16 +0800782out:
Kees Cook30800d92017-03-07 13:57:11 -0800783 record->buf = NULL;
784
785 return unlikely(ret < 0) ? ret : record->size;
Mark Salyzyn5bf6d1b2016-09-01 08:13:46 -0700786}
787
Tony Luckca01d6d2010-12-28 14:25:21 -0800788/*
789 * platform specific persistent storage driver registers with
790 * us here. If pstore is already mounted, call the platform
791 * read function right away to populate the file system. If not
792 * then the pstore mount code will call us later to fill out
793 * the file system.
Tony Luckca01d6d2010-12-28 14:25:21 -0800794 */
795int pstore_register(struct pstore_info *psi)
796{
797 struct module *owner = psi->owner;
798
Kees Cook0d7cd092017-03-03 12:11:40 -0800799 if (backend && strcmp(backend, psi->name)) {
800 pr_warn("ignoring unexpected backend '%s'\n", psi->name);
Lenny Szubowicz8e48b1a2013-06-28 17:11:33 -0400801 return -EPERM;
Kees Cook0d7cd092017-03-03 12:11:40 -0800802 }
Lenny Szubowicz8e48b1a2013-06-28 17:11:33 -0400803
Kees Cook4c9ec212017-03-05 22:41:10 -0800804 /* Sanity check flags. */
805 if (!psi->flags) {
806 pr_warn("backend '%s' must support at least one frontend\n",
807 psi->name);
808 return -EINVAL;
809 }
810
811 /* Check for required functions. */
812 if (!psi->read || !psi->write) {
813 pr_warn("backend '%s' must implement read() and write()\n",
814 psi->name);
815 return -EINVAL;
816 }
817
Tony Luckca01d6d2010-12-28 14:25:21 -0800818 spin_lock(&pstore_lock);
819 if (psinfo) {
Kees Cook0d7cd092017-03-03 12:11:40 -0800820 pr_warn("backend '%s' already loaded: ignoring '%s'\n",
821 psinfo->name, psi->name);
Tony Luckca01d6d2010-12-28 14:25:21 -0800822 spin_unlock(&pstore_lock);
823 return -EBUSY;
824 }
Matthew Garrettdee28e72011-07-21 16:57:55 -0400825
Kees Cook4c9ec212017-03-05 22:41:10 -0800826 if (!psi->write_user)
827 psi->write_user = pstore_write_user_compat;
Tony Luckca01d6d2010-12-28 14:25:21 -0800828 psinfo = psi;
Kees Cookf6f82852011-11-17 12:58:07 -0800829 mutex_init(&psinfo->read_mutex);
Tony Luckca01d6d2010-12-28 14:25:21 -0800830 spin_unlock(&pstore_lock);
831
832 if (owner && !try_module_get(owner)) {
833 psinfo = NULL;
834 return -EINVAL;
835 }
836
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700837 allocate_buf_for_compression();
838
Tony Luckca01d6d2010-12-28 14:25:21 -0800839 if (pstore_is_mounted())
Luck, Tony6dda9262011-08-11 15:14:39 -0700840 pstore_get_records(0);
Tony Luckca01d6d2010-12-28 14:25:21 -0800841
Namhyung Kimc950fd62016-07-28 00:08:25 +0900842 if (psi->flags & PSTORE_FLAGS_DMESG)
843 pstore_register_kmsg();
844 if (psi->flags & PSTORE_FLAGS_CONSOLE)
Luck, Tonydf36ac12013-12-18 15:17:10 -0800845 pstore_register_console();
Namhyung Kimc950fd62016-07-28 00:08:25 +0900846 if (psi->flags & PSTORE_FLAGS_FTRACE)
Luck, Tonydf36ac12013-12-18 15:17:10 -0800847 pstore_register_ftrace();
Namhyung Kimc950fd62016-07-28 00:08:25 +0900848 if (psi->flags & PSTORE_FLAGS_PMSG)
Mark Salyzyn9d5438f2015-01-16 16:01:10 -0800849 pstore_register_pmsg();
Tony Luckca01d6d2010-12-28 14:25:21 -0800850
Kees Cook6330d552017-03-06 12:42:12 -0800851 /* Start watching for new records, if desired. */
Anton Vorontsova3f5f072012-05-26 06:20:28 -0700852 if (pstore_update_ms >= 0) {
853 pstore_timer.expires = jiffies +
854 msecs_to_jiffies(pstore_update_ms);
855 add_timer(&pstore_timer);
856 }
Luck, Tony6dda9262011-08-11 15:14:39 -0700857
Wang Long42222c22015-05-21 09:34:22 -0700858 /*
859 * Update the module parameter backend, so it is visible
860 * through /sys/module/pstore/parameters/backend
861 */
862 backend = psi->name;
863
Fabian Frederickef748852014-06-06 14:37:31 -0700864 pr_info("Registered %s as persistent store backend\n", psi->name);
Lenny Szubowicz8e48b1a2013-06-28 17:11:33 -0400865
Kees Cook1344dd82017-03-03 17:45:38 -0800866 module_put(owner);
867
Tony Luckca01d6d2010-12-28 14:25:21 -0800868 return 0;
869}
870EXPORT_SYMBOL_GPL(pstore_register);
871
Geliang Tangee1d2672015-10-20 00:39:03 -0700872void pstore_unregister(struct pstore_info *psi)
873{
Kees Cook6330d552017-03-06 12:42:12 -0800874 /* Stop timer and make sure all work has finished. */
875 pstore_update_ms = -1;
876 del_timer_sync(&pstore_timer);
877 flush_work(&pstore_work);
878
Namhyung Kimc950fd62016-07-28 00:08:25 +0900879 if (psi->flags & PSTORE_FLAGS_PMSG)
Kees Cooka1db8062016-05-19 10:59:03 -0400880 pstore_unregister_pmsg();
Namhyung Kimc950fd62016-07-28 00:08:25 +0900881 if (psi->flags & PSTORE_FLAGS_FTRACE)
Kees Cooka1db8062016-05-19 10:59:03 -0400882 pstore_unregister_ftrace();
Namhyung Kimc950fd62016-07-28 00:08:25 +0900883 if (psi->flags & PSTORE_FLAGS_CONSOLE)
Kees Cooka1db8062016-05-19 10:59:03 -0400884 pstore_unregister_console();
Namhyung Kimc950fd62016-07-28 00:08:25 +0900885 if (psi->flags & PSTORE_FLAGS_DMESG)
886 pstore_unregister_kmsg();
Geliang Tangee1d2672015-10-20 00:39:03 -0700887
888 free_buf_for_compression();
889
890 psinfo = NULL;
891 backend = NULL;
892}
893EXPORT_SYMBOL_GPL(pstore_unregister);
894
Kees Cook634f8f52017-03-03 17:35:25 -0800895static void decompress_record(struct pstore_record *record)
896{
897 int unzipped_len;
Kees Cook7e8cc8d2017-03-04 22:28:46 -0800898 char *decompressed;
Kees Cook634f8f52017-03-03 17:35:25 -0800899
Ankit Kumar4a16d1c2017-05-23 11:16:52 +0530900 if (!record->compressed)
901 return;
902
Kees Cook634f8f52017-03-03 17:35:25 -0800903 /* Only PSTORE_TYPE_DMESG support compression. */
Ankit Kumar4a16d1c2017-05-23 11:16:52 +0530904 if (record->type != PSTORE_TYPE_DMESG) {
Kees Cook634f8f52017-03-03 17:35:25 -0800905 pr_warn("ignored compressed record type %d\n", record->type);
906 return;
907 }
908
909 /* No compression method has created the common buffer. */
910 if (!big_oops_buf) {
911 pr_warn("no decompression buffer allocated\n");
912 return;
913 }
914
915 unzipped_len = pstore_decompress(record->buf, big_oops_buf,
916 record->size, big_oops_buf_sz);
Kees Cook7e8cc8d2017-03-04 22:28:46 -0800917 if (unzipped_len <= 0) {
Kees Cook634f8f52017-03-03 17:35:25 -0800918 pr_err("decompression failed: %d\n", unzipped_len);
Kees Cook7e8cc8d2017-03-04 22:28:46 -0800919 return;
920 }
921
922 /* Build new buffer for decompressed contents. */
923 decompressed = kmalloc(unzipped_len + record->ecc_notice_size,
924 GFP_KERNEL);
925 if (!decompressed) {
926 pr_err("decompression ran out of memory\n");
927 return;
928 }
929 memcpy(decompressed, big_oops_buf, unzipped_len);
930
931 /* Append ECC notice to decompressed buffer. */
932 memcpy(decompressed + unzipped_len, record->buf + record->size,
933 record->ecc_notice_size);
934
935 /* Swap out compresed contents with decompressed contents. */
936 kfree(record->buf);
937 record->buf = decompressed;
938 record->size = unzipped_len;
939 record->compressed = false;
Kees Cook634f8f52017-03-03 17:35:25 -0800940}
941
Tony Luckca01d6d2010-12-28 14:25:21 -0800942/*
Kees Cook3a7d2fd2017-04-27 15:53:21 -0700943 * Read all the records from one persistent store backend. Create
Luck, Tony6dda9262011-08-11 15:14:39 -0700944 * files in our filesystem. Don't warn about -EEXIST errors
945 * when we are re-scanning the backing store looking to add new
946 * error records.
Tony Luckca01d6d2010-12-28 14:25:21 -0800947 */
Kees Cook3a7d2fd2017-04-27 15:53:21 -0700948void pstore_get_backend_records(struct pstore_info *psi,
949 struct dentry *root, int quiet)
Tony Luckca01d6d2010-12-28 14:25:21 -0800950{
Kees Cook2a2b0ac2017-03-04 22:57:26 -0800951 int failed = 0;
Kees Cook656de422017-05-16 12:03:31 -0700952 unsigned int stop_loop = 65536;
Tony Luckca01d6d2010-12-28 14:25:21 -0800953
Kees Cook3a7d2fd2017-04-27 15:53:21 -0700954 if (!psi || !root)
Tony Luckca01d6d2010-12-28 14:25:21 -0800955 return;
956
Kees Cookf6f82852011-11-17 12:58:07 -0800957 mutex_lock(&psi->read_mutex);
Kees Cook2174f6d2011-11-18 13:49:00 -0800958 if (psi->open && psi->open(psi))
Chen Gong06cf91b2011-05-16 11:00:27 -0700959 goto out;
960
Kees Cook1dfff7d2017-03-04 22:46:41 -0800961 /*
962 * Backend callback read() allocates record.buf. decompress_record()
963 * may reallocate record.buf. On success, pstore_mkfile() will keep
964 * the record.buf, so free it only on failure.
965 */
Kees Cook656de422017-05-16 12:03:31 -0700966 for (; stop_loop; stop_loop--) {
Kees Cook2a2b0ac2017-03-04 22:57:26 -0800967 struct pstore_record *record;
968 int rc;
969
970 record = kzalloc(sizeof(*record), GFP_KERNEL);
971 if (!record) {
972 pr_err("out of memory creating record\n");
973 break;
974 }
Kees Cooke581ca82017-05-19 15:10:31 -0700975 pstore_record_init(record, psi);
Kees Cook2a2b0ac2017-03-04 22:57:26 -0800976
977 record->size = psi->read(record);
978
979 /* No more records left in backend? */
Douglas Andersonf6525b92017-05-30 15:50:38 -0700980 if (record->size <= 0) {
981 kfree(record);
Kees Cook2a2b0ac2017-03-04 22:57:26 -0800982 break;
Douglas Andersonf6525b92017-05-30 15:50:38 -0700983 }
Kees Cook2a2b0ac2017-03-04 22:57:26 -0800984
985 decompress_record(record);
Kees Cook3a7d2fd2017-04-27 15:53:21 -0700986 rc = pstore_mkfile(root, record);
Kees Cook1dfff7d2017-03-04 22:46:41 -0800987 if (rc) {
Kees Cook83f70f02017-03-04 23:12:24 -0800988 /* pstore_mkfile() did not take record, so free it. */
Kees Cook2a2b0ac2017-03-04 22:57:26 -0800989 kfree(record->buf);
Kees Cook83f70f02017-03-04 23:12:24 -0800990 kfree(record);
Kees Cook1dfff7d2017-03-04 22:46:41 -0800991 if (rc != -EEXIST || !quiet)
992 failed++;
993 }
Tony Luckca01d6d2010-12-28 14:25:21 -0800994 }
Kees Cook2174f6d2011-11-18 13:49:00 -0800995 if (psi->close)
996 psi->close(psi);
Chen Gong06cf91b2011-05-16 11:00:27 -0700997out:
Kees Cookf6f82852011-11-17 12:58:07 -0800998 mutex_unlock(&psi->read_mutex);
Tony Luckca01d6d2010-12-28 14:25:21 -0800999
1000 if (failed)
Kees Cook656de422017-05-16 12:03:31 -07001001 pr_warn("failed to create %d record(s) from '%s'\n",
Fabian Frederickef748852014-06-06 14:37:31 -07001002 failed, psi->name);
Kees Cook656de422017-05-16 12:03:31 -07001003 if (!stop_loop)
1004 pr_err("looping? Too many records seen from '%s'\n",
1005 psi->name);
Tony Luckca01d6d2010-12-28 14:25:21 -08001006}
1007
Luck, Tony6dda9262011-08-11 15:14:39 -07001008static void pstore_dowork(struct work_struct *work)
1009{
1010 pstore_get_records(1);
1011}
1012
Kees Cook24ed9602017-08-28 11:28:21 -07001013static void pstore_timefunc(struct timer_list *unused)
Luck, Tony6dda9262011-08-11 15:14:39 -07001014{
1015 if (pstore_new_entry) {
1016 pstore_new_entry = 0;
1017 schedule_work(&pstore_work);
1018 }
1019
Kees Cook6330d552017-03-06 12:42:12 -08001020 if (pstore_update_ms >= 0)
1021 mod_timer(&pstore_timer,
1022 jiffies + msecs_to_jiffies(pstore_update_ms));
Luck, Tony6dda9262011-08-11 15:14:39 -07001023}
1024
Matthew Garrettdee28e72011-07-21 16:57:55 -04001025module_param(backend, charp, 0444);
1026MODULE_PARM_DESC(backend, "Pstore backend to use");