blob: c238ab8ba31d6139a9b19c087e6041d3e1b8dffc [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>
Arnd Bergmann58eb5b672018-03-15 16:34:08 +010031#if IS_ENABLED(CONFIG_PSTORE_LZO_COMPRESS)
Geliang Tang8cfc8dd2016-02-18 22:04:22 +080032#include <linux/lzo.h>
33#endif
Arnd Bergmann58eb5b672018-03-15 16:34:08 +010034#if IS_ENABLED(CONFIG_PSTORE_LZ4_COMPRESS) || IS_ENABLED(CONFIG_PSTORE_LZ4HC_COMPRESS)
Geliang Tang8cfc8dd2016-02-18 22:04:22 +080035#include <linux/lz4.h>
36#endif
Geliang Tangcb3bee02018-03-09 18:51:07 +080037#include <linux/crypto.h>
Tony Luckca01d6d2010-12-28 14:25:21 -080038#include <linux/string.h>
Luck, Tony6dda9262011-08-11 15:14:39 -070039#include <linux/timer.h>
Tony Luckca01d6d2010-12-28 14:25:21 -080040#include <linux/slab.h>
41#include <linux/uaccess.h>
Anton Vorontsova3f5f072012-05-26 06:20:28 -070042#include <linux/jiffies.h>
Luck, Tony6dda9262011-08-11 15:14:39 -070043#include <linux/workqueue.h>
Tony Luckca01d6d2010-12-28 14:25:21 -080044
45#include "internal.h"
46
47/*
Luck, Tony6dda9262011-08-11 15:14:39 -070048 * We defer making "oops" entries appear in pstore - see
49 * whether the system is actually still running well enough
50 * to let someone see the entry
51 */
Anton Vorontsov521f72882012-05-26 06:20:29 -070052static int pstore_update_ms = -1;
Anton Vorontsova3f5f072012-05-26 06:20:28 -070053module_param_named(update_ms, pstore_update_ms, int, 0600);
54MODULE_PARM_DESC(update_ms, "milliseconds before pstore updates its content "
Anton Vorontsov521f72882012-05-26 06:20:29 -070055 "(default is -1, which means runtime updates are disabled; "
56 "enabling this option is not safe, it may lead to further "
57 "corruption on Oopses)");
Luck, Tony6dda9262011-08-11 15:14:39 -070058
59static int pstore_new_entry;
60
Kees Cook24ed9602017-08-28 11:28:21 -070061static void pstore_timefunc(struct timer_list *);
Kees Cook1d27e3e2017-10-04 16:27:04 -070062static DEFINE_TIMER(pstore_timer, pstore_timefunc);
Luck, Tony6dda9262011-08-11 15:14:39 -070063
64static void pstore_dowork(struct work_struct *);
65static DECLARE_WORK(pstore_work, pstore_dowork);
66
67/*
Tony Luckca01d6d2010-12-28 14:25:21 -080068 * pstore_lock just protects "psinfo" during
69 * calls to pstore_register()
70 */
71static DEFINE_SPINLOCK(pstore_lock);
Anton Vorontsov060287b2012-07-09 17:10:41 -070072struct pstore_info *psinfo;
Tony Luckca01d6d2010-12-28 14:25:21 -080073
Matthew Garrettdee28e72011-07-21 16:57:55 -040074static char *backend;
Kees Cookfe1d4752018-03-06 15:57:38 -080075static char *compress =
76#ifdef CONFIG_PSTORE_COMPRESS_DEFAULT
77 CONFIG_PSTORE_COMPRESS_DEFAULT;
78#else
79 NULL;
80#endif
Matthew Garrettdee28e72011-07-21 16:57:55 -040081
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -070082/* Compression parameters */
Geliang Tangcb3bee02018-03-09 18:51:07 +080083static struct crypto_comp *tfm;
Geliang Tang8cfc8dd2016-02-18 22:04:22 +080084
85struct pstore_zbackend {
Geliang Tangcb3bee02018-03-09 18:51:07 +080086 int (*zbufsize)(size_t size);
Geliang Tang8cfc8dd2016-02-18 22:04:22 +080087 const char *name;
88};
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -070089
90static char *big_oops_buf;
91static size_t big_oops_buf_sz;
92
Luck, Tony366f7e72011-03-18 15:33:43 -070093/* How much of the console log to snapshot */
David Howells349d7432017-07-05 16:24:34 +010094unsigned long kmsg_bytes = PSTORE_DEFAULT_KMSG_BYTES;
Tony Luckca01d6d2010-12-28 14:25:21 -080095
Luck, Tony366f7e72011-03-18 15:33:43 -070096void pstore_set_kmsg_bytes(int bytes)
Tony Luckca01d6d2010-12-28 14:25:21 -080097{
Luck, Tony366f7e72011-03-18 15:33:43 -070098 kmsg_bytes = bytes;
Tony Luckca01d6d2010-12-28 14:25:21 -080099}
100
Tony Luckca01d6d2010-12-28 14:25:21 -0800101/* Tag each group of saved records with a sequence number */
102static int oopscount;
103
Seiji Aguchi381b8722012-03-16 15:36:59 -0700104static const char *get_reason_str(enum kmsg_dump_reason reason)
105{
106 switch (reason) {
107 case KMSG_DUMP_PANIC:
108 return "Panic";
109 case KMSG_DUMP_OOPS:
110 return "Oops";
111 case KMSG_DUMP_EMERG:
112 return "Emergency";
113 case KMSG_DUMP_RESTART:
114 return "Restart";
115 case KMSG_DUMP_HALT:
116 return "Halt";
117 case KMSG_DUMP_POWEROFF:
118 return "Poweroff";
119 default:
120 return "Unknown";
121 }
122}
Tony Luck9f6af272011-03-22 16:01:49 -0700123
Seiji Aguchi9f244e92013-01-11 18:09:41 +0000124bool pstore_cannot_block_path(enum kmsg_dump_reason reason)
125{
126 /*
127 * In case of NMI path, pstore shouldn't be blocked
128 * regardless of reason.
129 */
130 if (in_nmi())
131 return true;
132
133 switch (reason) {
134 /* In panic case, other cpus are stopped by smp_send_stop(). */
135 case KMSG_DUMP_PANIC:
136 /* Emergency restart shouldn't be blocked by spin lock. */
137 case KMSG_DUMP_EMERG:
138 return true;
139 default:
140 return false;
141 }
142}
143EXPORT_SYMBOL_GPL(pstore_cannot_block_path);
144
Arnd Bergmann58eb5b672018-03-15 16:34:08 +0100145#if IS_ENABLED(CONFIG_PSTORE_DEFLATE_COMPRESS)
Geliang Tangcb3bee02018-03-09 18:51:07 +0800146static int zbufsize_deflate(size_t size)
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700147{
Aruna Balakrishnaiah7de8fe22013-09-11 10:57:41 -0700148 size_t cmpr;
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700149
Geliang Tangcb3bee02018-03-09 18:51:07 +0800150 switch (size) {
Aruna Balakrishnaiah7de8fe22013-09-11 10:57:41 -0700151 /* buffer range for efivars */
152 case 1000 ... 2000:
153 cmpr = 56;
154 break;
155 case 2001 ... 3000:
156 cmpr = 54;
157 break;
158 case 3001 ... 3999:
159 cmpr = 52;
160 break;
161 /* buffer range for nvram, erst */
162 case 4000 ... 10000:
163 cmpr = 45;
164 break;
165 default:
166 cmpr = 60;
167 break;
168 }
169
Geliang Tangcb3bee02018-03-09 18:51:07 +0800170 return (size * 100) / cmpr;
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800171}
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800172#endif
173
Arnd Bergmann58eb5b672018-03-15 16:34:08 +0100174#if IS_ENABLED(CONFIG_PSTORE_LZO_COMPRESS)
Geliang Tangcb3bee02018-03-09 18:51:07 +0800175static int zbufsize_lzo(size_t size)
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800176{
Geliang Tangcb3bee02018-03-09 18:51:07 +0800177 return lzo1x_worst_compress(size);
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800178}
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800179#endif
180
Arnd Bergmann58eb5b672018-03-15 16:34:08 +0100181#if IS_ENABLED(CONFIG_PSTORE_LZ4_COMPRESS) || IS_ENABLED(CONFIG_PSTORE_LZ4HC_COMPRESS)
Geliang Tangcb3bee02018-03-09 18:51:07 +0800182static int zbufsize_lz4(size_t size)
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800183{
Geliang Tangcb3bee02018-03-09 18:51:07 +0800184 return LZ4_compressBound(size);
Geliang Tang239b7162018-02-13 14:40:39 +0800185}
Geliang Tang239b7162018-02-13 14:40:39 +0800186#endif
187
Arnd Bergmann58eb5b672018-03-15 16:34:08 +0100188#if IS_ENABLED(CONFIG_PSTORE_842_COMPRESS)
Geliang Tangcb3bee02018-03-09 18:51:07 +0800189static int zbufsize_842(size_t size)
Geliang Tang239b7162018-02-13 14:40:39 +0800190{
Kees Cook55597402018-03-06 15:15:24 -0800191 return size;
Geliang Tang239b7162018-02-13 14:40:39 +0800192}
Kees Cookfe1d4752018-03-06 15:57:38 -0800193#endif
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800194
Kees Cookfe1d4752018-03-06 15:57:38 -0800195static const struct pstore_zbackend *zbackend __ro_after_init;
196
197static const struct pstore_zbackend zbackends[] = {
Arnd Bergmann58eb5b672018-03-15 16:34:08 +0100198#if IS_ENABLED(CONFIG_PSTORE_DEFLATE_COMPRESS)
Kees Cookfe1d4752018-03-06 15:57:38 -0800199 {
Geliang Tangcb3bee02018-03-09 18:51:07 +0800200 .zbufsize = zbufsize_deflate,
201 .name = "deflate",
Kees Cookfe1d4752018-03-06 15:57:38 -0800202 },
203#endif
Arnd Bergmann58eb5b672018-03-15 16:34:08 +0100204#if IS_ENABLED(CONFIG_PSTORE_LZO_COMPRESS)
Kees Cookfe1d4752018-03-06 15:57:38 -0800205 {
Geliang Tangcb3bee02018-03-09 18:51:07 +0800206 .zbufsize = zbufsize_lzo,
Kees Cookfe1d4752018-03-06 15:57:38 -0800207 .name = "lzo",
208 },
209#endif
Arnd Bergmann58eb5b672018-03-15 16:34:08 +0100210#if IS_ENABLED(CONFIG_PSTORE_LZ4_COMPRESS)
Kees Cookfe1d4752018-03-06 15:57:38 -0800211 {
Geliang Tangcb3bee02018-03-09 18:51:07 +0800212 .zbufsize = zbufsize_lz4,
Kees Cookfe1d4752018-03-06 15:57:38 -0800213 .name = "lz4",
214 },
215#endif
Arnd Bergmann58eb5b672018-03-15 16:34:08 +0100216#if IS_ENABLED(CONFIG_PSTORE_LZ4HC_COMPRESS)
Kees Cookfe1d4752018-03-06 15:57:38 -0800217 {
Geliang Tangcb3bee02018-03-09 18:51:07 +0800218 .zbufsize = zbufsize_lz4,
Kees Cookfe1d4752018-03-06 15:57:38 -0800219 .name = "lz4hc",
220 },
221#endif
Arnd Bergmann58eb5b672018-03-15 16:34:08 +0100222#if IS_ENABLED(CONFIG_PSTORE_842_COMPRESS)
Kees Cookfe1d4752018-03-06 15:57:38 -0800223 {
Geliang Tangcb3bee02018-03-09 18:51:07 +0800224 .zbufsize = zbufsize_842,
Kees Cookfe1d4752018-03-06 15:57:38 -0800225 .name = "842",
226 },
227#endif
228 { }
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800229};
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800230
231static int pstore_compress(const void *in, void *out,
Geliang Tangcb3bee02018-03-09 18:51:07 +0800232 unsigned int inlen, unsigned int outlen)
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800233{
Geliang Tangcb3bee02018-03-09 18:51:07 +0800234 int ret;
235
236 ret = crypto_comp_compress(tfm, in, inlen, out, &outlen);
237 if (ret) {
238 pr_err("crypto_comp_compress failed, ret = %d!\n", ret);
239 return ret;
240 }
241
242 return outlen;
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800243}
244
Geliang Tangcb3bee02018-03-09 18:51:07 +0800245static int pstore_decompress(void *in, void *out,
246 unsigned int inlen, unsigned int outlen)
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800247{
Geliang Tangcb3bee02018-03-09 18:51:07 +0800248 int ret;
249
250 ret = crypto_comp_decompress(tfm, in, inlen, out, &outlen);
251 if (ret) {
252 pr_err("crypto_comp_decompress failed, ret = %d!\n", ret);
253 return ret;
254 }
255
256 return outlen;
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800257}
258
259static void allocate_buf_for_compression(void)
260{
Tobias Regnerye698aaf2018-04-06 09:25:17 +0200261 if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS) || !zbackend)
Geliang Tangcb3bee02018-03-09 18:51:07 +0800262 return;
263
264 if (!crypto_has_comp(zbackend->name, 0, 0)) {
265 pr_err("No %s compression\n", zbackend->name);
266 return;
267 }
268
269 big_oops_buf_sz = zbackend->zbufsize(psinfo->bufsize);
270 if (big_oops_buf_sz <= 0)
271 return;
272
273 big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
274 if (!big_oops_buf) {
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800275 pr_err("allocate compression buffer error!\n");
Geliang Tangcb3bee02018-03-09 18:51:07 +0800276 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;
Geliang Tang8cfc8dd2016-02-18 22:04:22 +0800285 }
286}
287
288static void free_buf_for_compression(void)
289{
Tobias Regnerye698aaf2018-04-06 09:25:17 +0200290 if (IS_ENABLED(CONFIG_PSTORE_COMPRESS) && !IS_ERR_OR_NULL(tfm))
Geliang Tangcb3bee02018-03-09 18:51:07 +0800291 crypto_free_comp(tfm);
292 kfree(big_oops_buf);
293 big_oops_buf = NULL;
294 big_oops_buf_sz = 0;
Geliang Tangee1d2672015-10-20 00:39:03 -0700295}
296
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700297/*
298 * Called when compression fails, since the printk buffer
299 * would be fetched for compression calling it again when
300 * compression fails would have moved the iterator of
301 * printk buffer which results in fetching old contents.
302 * Copy the recent messages from big_oops_buf to psinfo->buf
303 */
304static size_t copy_kmsg_to_buffer(int hsize, size_t len)
305{
306 size_t total_len;
307 size_t diff;
308
309 total_len = hsize + len;
310
311 if (total_len > psinfo->bufsize) {
312 diff = total_len - psinfo->bufsize + hsize;
313 memcpy(psinfo->buf, big_oops_buf, hsize);
314 memcpy(psinfo->buf + hsize, big_oops_buf + diff,
315 psinfo->bufsize - hsize);
316 total_len = psinfo->bufsize;
317 } else
318 memcpy(psinfo->buf, big_oops_buf, total_len);
319
320 return total_len;
321}
322
Kees Cooke581ca82017-05-19 15:10:31 -0700323void pstore_record_init(struct pstore_record *record,
324 struct pstore_info *psinfo)
325{
326 memset(record, 0, sizeof(*record));
327
328 record->psi = psinfo;
Kees Cookc7f3c5952017-05-19 15:29:10 -0700329
330 /* Report zeroed timestamp if called before timekeeping has resumed. */
Kees Cook7aaa8222018-05-14 15:50:52 -0700331 record->time = ns_to_timespec64(ktime_get_real_fast_ns());
Kees Cooke581ca82017-05-19 15:10:31 -0700332}
333
Tony Luckca01d6d2010-12-28 14:25:21 -0800334/*
335 * callback from kmsg_dump. (s2,l2) has the most recently
336 * written bytes, older bytes are in (s1,l1). Save as much
337 * as we can from the end of the buffer.
338 */
339static void pstore_dump(struct kmsg_dumper *dumper,
Kay Sieverse2ae7152012-06-15 14:07:51 +0200340 enum kmsg_dump_reason reason)
Tony Luckca01d6d2010-12-28 14:25:21 -0800341{
Kay Sieverse2ae7152012-06-15 14:07:51 +0200342 unsigned long total = 0;
Seiji Aguchi381b8722012-03-16 15:36:59 -0700343 const char *why;
Matthew Garrettb94fdd02011-07-21 16:57:54 -0400344 unsigned int part = 1;
Don Zickusabd4d552011-08-12 10:54:51 -0700345 unsigned long flags = 0;
Namhyung Kim98e44fda2016-05-18 21:00:05 +0900346 int is_locked;
Kay Sieverse2ae7152012-06-15 14:07:51 +0200347 int ret;
Tony Luckca01d6d2010-12-28 14:25:21 -0800348
Seiji Aguchi381b8722012-03-16 15:36:59 -0700349 why = get_reason_str(reason);
Tony Luck9f6af272011-03-22 16:01:49 -0700350
Seiji Aguchi9f244e92013-01-11 18:09:41 +0000351 if (pstore_cannot_block_path(reason)) {
352 is_locked = spin_trylock_irqsave(&psinfo->buf_lock, flags);
353 if (!is_locked) {
354 pr_err("pstore dump routine blocked in %s path, may corrupt error record\n"
355 , in_nmi() ? "NMI" : why);
Li Pengcheng959217c2016-11-05 10:15:59 +0800356 return;
Seiji Aguchi9f244e92013-01-11 18:09:41 +0000357 }
Namhyung Kim98e44fda2016-05-18 21:00:05 +0900358 } else {
Don Zickusabd4d552011-08-12 10:54:51 -0700359 spin_lock_irqsave(&psinfo->buf_lock, flags);
Namhyung Kim98e44fda2016-05-18 21:00:05 +0900360 is_locked = 1;
361 }
Tony Luckca01d6d2010-12-28 14:25:21 -0800362 oopscount++;
363 while (total < kmsg_bytes) {
Kay Sieverse2ae7152012-06-15 14:07:51 +0200364 char *dst;
Kees Cook76cc9582017-03-03 23:28:53 -0800365 size_t dst_size;
366 int header_size;
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700367 int zipped_len = -1;
Kees Cook76cc9582017-03-03 23:28:53 -0800368 size_t dump_size;
Kees Cooke581ca82017-05-19 15:10:31 -0700369 struct pstore_record record;
370
371 pstore_record_init(&record, psinfo);
372 record.type = PSTORE_TYPE_DMESG;
373 record.count = oopscount;
374 record.reason = reason;
375 record.part = part;
376 record.buf = psinfo->buf;
Kay Sieverse2ae7152012-06-15 14:07:51 +0200377
Konstantin Khlebnikovf0e2efc2015-05-21 09:26:19 -0700378 if (big_oops_buf && is_locked) {
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700379 dst = big_oops_buf;
Kees Cook76cc9582017-03-03 23:28:53 -0800380 dst_size = big_oops_buf_sz;
Namhyung Kim235f6d12016-05-18 21:00:06 +0900381 } else {
382 dst = psinfo->buf;
Kees Cook76cc9582017-03-03 23:28:53 -0800383 dst_size = psinfo->bufsize;
Namhyung Kim235f6d12016-05-18 21:00:06 +0900384 }
Tony Luckca01d6d2010-12-28 14:25:21 -0800385
Kees Cook76cc9582017-03-03 23:28:53 -0800386 /* Write dump header. */
387 header_size = snprintf(dst, dst_size, "%s#%d Part%u\n", why,
388 oopscount, part);
389 dst_size -= header_size;
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700390
Kees Cook76cc9582017-03-03 23:28:53 -0800391 /* Write dump contents. */
392 if (!kmsg_dump_get_buffer(dumper, true, dst + header_size,
393 dst_size, &dump_size))
Namhyung Kim235f6d12016-05-18 21:00:06 +0900394 break;
395
396 if (big_oops_buf && is_locked) {
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700397 zipped_len = pstore_compress(dst, psinfo->buf,
Kees Cook76cc9582017-03-03 23:28:53 -0800398 header_size + dump_size,
399 psinfo->bufsize);
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700400
401 if (zipped_len > 0) {
Kees Cook76cc9582017-03-03 23:28:53 -0800402 record.compressed = true;
403 record.size = zipped_len;
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700404 } else {
Kees Cook76cc9582017-03-03 23:28:53 -0800405 record.size = copy_kmsg_to_buffer(header_size,
406 dump_size);
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700407 }
408 } else {
Kees Cook76cc9582017-03-03 23:28:53 -0800409 record.size = header_size + dump_size;
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700410 }
Tony Luckca01d6d2010-12-28 14:25:21 -0800411
Kees Cook76cc9582017-03-03 23:28:53 -0800412 ret = psinfo->write(&record);
Chen Gongb238b8f2011-10-12 09:17:24 -0700413 if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted())
Luck, Tony6dda9262011-08-11 15:14:39 -0700414 pstore_new_entry = 1;
Kay Sieverse2ae7152012-06-15 14:07:51 +0200415
Kees Cook76cc9582017-03-03 23:28:53 -0800416 total += record.size;
Matthew Garrett56280682011-07-21 16:57:53 -0400417 part++;
Tony Luckca01d6d2010-12-28 14:25:21 -0800418 }
Namhyung Kim98e44fda2016-05-18 21:00:05 +0900419 if (is_locked)
Don Zickusabd4d552011-08-12 10:54:51 -0700420 spin_unlock_irqrestore(&psinfo->buf_lock, flags);
Tony Luckca01d6d2010-12-28 14:25:21 -0800421}
422
423static struct kmsg_dumper pstore_dumper = {
424 .dump = pstore_dump,
425};
426
Geliang Tang306e5c22015-10-31 23:23:15 +0800427/*
428 * Register with kmsg_dump to save last part of console log on panic.
429 */
Geliang Tang18730412015-10-20 00:39:02 -0700430static void pstore_register_kmsg(void)
431{
432 kmsg_dump_register(&pstore_dumper);
433}
434
Geliang Tangee1d2672015-10-20 00:39:03 -0700435static void pstore_unregister_kmsg(void)
436{
437 kmsg_dump_unregister(&pstore_dumper);
438}
439
Anton Vorontsovf29e5952012-05-26 06:20:19 -0700440#ifdef CONFIG_PSTORE_CONSOLE
441static void pstore_console_write(struct console *con, const char *s, unsigned c)
442{
443 const char *e = s + c;
444
445 while (s < e) {
Kees Cooke581ca82017-05-19 15:10:31 -0700446 struct pstore_record record;
Anton Vorontsovf29e5952012-05-26 06:20:19 -0700447 unsigned long flags;
448
Kees Cooke581ca82017-05-19 15:10:31 -0700449 pstore_record_init(&record, psinfo);
450 record.type = PSTORE_TYPE_CONSOLE;
451
Anton Vorontsovf29e5952012-05-26 06:20:19 -0700452 if (c > psinfo->bufsize)
453 c = psinfo->bufsize;
Chuansheng Liu80c9d032012-09-18 01:43:44 +0800454
455 if (oops_in_progress) {
456 if (!spin_trylock_irqsave(&psinfo->buf_lock, flags))
457 break;
458 } else {
459 spin_lock_irqsave(&psinfo->buf_lock, flags);
460 }
Kees Cookb10b4712017-03-05 00:27:54 -0800461 record.buf = (char *)s;
462 record.size = c;
Kees Cook4c9ec212017-03-05 22:41:10 -0800463 psinfo->write(&record);
Anton Vorontsovf29e5952012-05-26 06:20:19 -0700464 spin_unlock_irqrestore(&psinfo->buf_lock, flags);
465 s += c;
466 c = e - s;
467 }
468}
469
470static struct console pstore_console = {
471 .name = "pstore",
472 .write = pstore_console_write,
473 .flags = CON_PRINTBUFFER | CON_ENABLED | CON_ANYTIME,
474 .index = -1,
475};
476
477static void pstore_register_console(void)
478{
479 register_console(&pstore_console);
480}
Geliang Tangee1d2672015-10-20 00:39:03 -0700481
482static void pstore_unregister_console(void)
483{
484 unregister_console(&pstore_console);
485}
Anton Vorontsovf29e5952012-05-26 06:20:19 -0700486#else
487static void pstore_register_console(void) {}
Geliang Tangee1d2672015-10-20 00:39:03 -0700488static void pstore_unregister_console(void) {}
Anton Vorontsovf29e5952012-05-26 06:20:19 -0700489#endif
490
Kees Cook4c9ec212017-03-05 22:41:10 -0800491static int pstore_write_user_compat(struct pstore_record *record,
492 const char __user *buf)
Mark Salyzyn5bf6d1b2016-09-01 08:13:46 -0700493{
Kees Cook30800d92017-03-07 13:57:11 -0800494 int ret = 0;
Mark Salyzyn5bf6d1b2016-09-01 08:13:46 -0700495
Kees Cook30800d92017-03-07 13:57:11 -0800496 if (record->buf)
497 return -EINVAL;
Mark Salyzyn5bf6d1b2016-09-01 08:13:46 -0700498
Geliang Tang077090a2017-04-29 09:45:16 +0800499 record->buf = memdup_user(buf, record->size);
Hirofumi Nakagawadfd6fa32017-09-26 03:21:27 +0900500 if (IS_ERR(record->buf)) {
Geliang Tang077090a2017-04-29 09:45:16 +0800501 ret = PTR_ERR(record->buf);
Kees Cook30800d92017-03-07 13:57:11 -0800502 goto out;
Mark Salyzyn5bf6d1b2016-09-01 08:13:46 -0700503 }
Kees Cook30800d92017-03-07 13:57:11 -0800504
505 ret = record->psi->write(record);
506
Kees Cook30800d92017-03-07 13:57:11 -0800507 kfree(record->buf);
Geliang Tang077090a2017-04-29 09:45:16 +0800508out:
Kees Cook30800d92017-03-07 13:57:11 -0800509 record->buf = NULL;
510
511 return unlikely(ret < 0) ? ret : record->size;
Mark Salyzyn5bf6d1b2016-09-01 08:13:46 -0700512}
513
Tony Luckca01d6d2010-12-28 14:25:21 -0800514/*
515 * platform specific persistent storage driver registers with
516 * us here. If pstore is already mounted, call the platform
517 * read function right away to populate the file system. If not
518 * then the pstore mount code will call us later to fill out
519 * the file system.
Tony Luckca01d6d2010-12-28 14:25:21 -0800520 */
521int pstore_register(struct pstore_info *psi)
522{
523 struct module *owner = psi->owner;
524
Kees Cook0d7cd092017-03-03 12:11:40 -0800525 if (backend && strcmp(backend, psi->name)) {
526 pr_warn("ignoring unexpected backend '%s'\n", psi->name);
Lenny Szubowicz8e48b1a2013-06-28 17:11:33 -0400527 return -EPERM;
Kees Cook0d7cd092017-03-03 12:11:40 -0800528 }
Lenny Szubowicz8e48b1a2013-06-28 17:11:33 -0400529
Kees Cook4c9ec212017-03-05 22:41:10 -0800530 /* Sanity check flags. */
531 if (!psi->flags) {
532 pr_warn("backend '%s' must support at least one frontend\n",
533 psi->name);
534 return -EINVAL;
535 }
536
537 /* Check for required functions. */
538 if (!psi->read || !psi->write) {
539 pr_warn("backend '%s' must implement read() and write()\n",
540 psi->name);
541 return -EINVAL;
542 }
543
Tony Luckca01d6d2010-12-28 14:25:21 -0800544 spin_lock(&pstore_lock);
545 if (psinfo) {
Kees Cook0d7cd092017-03-03 12:11:40 -0800546 pr_warn("backend '%s' already loaded: ignoring '%s'\n",
547 psinfo->name, psi->name);
Tony Luckca01d6d2010-12-28 14:25:21 -0800548 spin_unlock(&pstore_lock);
549 return -EBUSY;
550 }
Matthew Garrettdee28e72011-07-21 16:57:55 -0400551
Kees Cook4c9ec212017-03-05 22:41:10 -0800552 if (!psi->write_user)
553 psi->write_user = pstore_write_user_compat;
Tony Luckca01d6d2010-12-28 14:25:21 -0800554 psinfo = psi;
Kees Cookf6f82852011-11-17 12:58:07 -0800555 mutex_init(&psinfo->read_mutex);
Tony Luckca01d6d2010-12-28 14:25:21 -0800556 spin_unlock(&pstore_lock);
557
558 if (owner && !try_module_get(owner)) {
559 psinfo = NULL;
560 return -EINVAL;
561 }
562
Aruna Balakrishnaiahb0aad7a2013-08-16 13:53:10 -0700563 allocate_buf_for_compression();
564
Tony Luckca01d6d2010-12-28 14:25:21 -0800565 if (pstore_is_mounted())
Luck, Tony6dda9262011-08-11 15:14:39 -0700566 pstore_get_records(0);
Tony Luckca01d6d2010-12-28 14:25:21 -0800567
Namhyung Kimc950fd62016-07-28 00:08:25 +0900568 if (psi->flags & PSTORE_FLAGS_DMESG)
569 pstore_register_kmsg();
570 if (psi->flags & PSTORE_FLAGS_CONSOLE)
Luck, Tonydf36ac12013-12-18 15:17:10 -0800571 pstore_register_console();
Namhyung Kimc950fd62016-07-28 00:08:25 +0900572 if (psi->flags & PSTORE_FLAGS_FTRACE)
Luck, Tonydf36ac12013-12-18 15:17:10 -0800573 pstore_register_ftrace();
Namhyung Kimc950fd62016-07-28 00:08:25 +0900574 if (psi->flags & PSTORE_FLAGS_PMSG)
Mark Salyzyn9d5438f2015-01-16 16:01:10 -0800575 pstore_register_pmsg();
Tony Luckca01d6d2010-12-28 14:25:21 -0800576
Kees Cook6330d552017-03-06 12:42:12 -0800577 /* Start watching for new records, if desired. */
Anton Vorontsova3f5f072012-05-26 06:20:28 -0700578 if (pstore_update_ms >= 0) {
579 pstore_timer.expires = jiffies +
580 msecs_to_jiffies(pstore_update_ms);
581 add_timer(&pstore_timer);
582 }
Luck, Tony6dda9262011-08-11 15:14:39 -0700583
Wang Long42222c22015-05-21 09:34:22 -0700584 /*
585 * Update the module parameter backend, so it is visible
586 * through /sys/module/pstore/parameters/backend
587 */
588 backend = psi->name;
589
Fabian Frederickef748852014-06-06 14:37:31 -0700590 pr_info("Registered %s as persistent store backend\n", psi->name);
Lenny Szubowicz8e48b1a2013-06-28 17:11:33 -0400591
Kees Cook1344dd82017-03-03 17:45:38 -0800592 module_put(owner);
593
Tony Luckca01d6d2010-12-28 14:25:21 -0800594 return 0;
595}
596EXPORT_SYMBOL_GPL(pstore_register);
597
Geliang Tangee1d2672015-10-20 00:39:03 -0700598void pstore_unregister(struct pstore_info *psi)
599{
Kees Cook6330d552017-03-06 12:42:12 -0800600 /* Stop timer and make sure all work has finished. */
601 pstore_update_ms = -1;
602 del_timer_sync(&pstore_timer);
603 flush_work(&pstore_work);
604
Namhyung Kimc950fd62016-07-28 00:08:25 +0900605 if (psi->flags & PSTORE_FLAGS_PMSG)
Kees Cooka1db8062016-05-19 10:59:03 -0400606 pstore_unregister_pmsg();
Namhyung Kimc950fd62016-07-28 00:08:25 +0900607 if (psi->flags & PSTORE_FLAGS_FTRACE)
Kees Cooka1db8062016-05-19 10:59:03 -0400608 pstore_unregister_ftrace();
Namhyung Kimc950fd62016-07-28 00:08:25 +0900609 if (psi->flags & PSTORE_FLAGS_CONSOLE)
Kees Cooka1db8062016-05-19 10:59:03 -0400610 pstore_unregister_console();
Namhyung Kimc950fd62016-07-28 00:08:25 +0900611 if (psi->flags & PSTORE_FLAGS_DMESG)
612 pstore_unregister_kmsg();
Geliang Tangee1d2672015-10-20 00:39:03 -0700613
614 free_buf_for_compression();
615
616 psinfo = NULL;
617 backend = NULL;
618}
619EXPORT_SYMBOL_GPL(pstore_unregister);
620
Kees Cook634f8f52017-03-03 17:35:25 -0800621static void decompress_record(struct pstore_record *record)
622{
623 int unzipped_len;
Kees Cook7e8cc8d2017-03-04 22:28:46 -0800624 char *decompressed;
Kees Cook634f8f52017-03-03 17:35:25 -0800625
Ankit Kumar4a16d1c2017-05-23 11:16:52 +0530626 if (!record->compressed)
627 return;
628
Kees Cook634f8f52017-03-03 17:35:25 -0800629 /* Only PSTORE_TYPE_DMESG support compression. */
Ankit Kumar4a16d1c2017-05-23 11:16:52 +0530630 if (record->type != PSTORE_TYPE_DMESG) {
Kees Cook634f8f52017-03-03 17:35:25 -0800631 pr_warn("ignored compressed record type %d\n", record->type);
632 return;
633 }
634
635 /* No compression method has created the common buffer. */
636 if (!big_oops_buf) {
637 pr_warn("no decompression buffer allocated\n");
638 return;
639 }
640
641 unzipped_len = pstore_decompress(record->buf, big_oops_buf,
642 record->size, big_oops_buf_sz);
Kees Cook7e8cc8d2017-03-04 22:28:46 -0800643 if (unzipped_len <= 0) {
Kees Cook634f8f52017-03-03 17:35:25 -0800644 pr_err("decompression failed: %d\n", unzipped_len);
Kees Cook7e8cc8d2017-03-04 22:28:46 -0800645 return;
646 }
647
648 /* Build new buffer for decompressed contents. */
649 decompressed = kmalloc(unzipped_len + record->ecc_notice_size,
650 GFP_KERNEL);
651 if (!decompressed) {
652 pr_err("decompression ran out of memory\n");
653 return;
654 }
655 memcpy(decompressed, big_oops_buf, unzipped_len);
656
657 /* Append ECC notice to decompressed buffer. */
658 memcpy(decompressed + unzipped_len, record->buf + record->size,
659 record->ecc_notice_size);
660
661 /* Swap out compresed contents with decompressed contents. */
662 kfree(record->buf);
663 record->buf = decompressed;
664 record->size = unzipped_len;
665 record->compressed = false;
Kees Cook634f8f52017-03-03 17:35:25 -0800666}
667
Tony Luckca01d6d2010-12-28 14:25:21 -0800668/*
Kees Cook3a7d2fd2017-04-27 15:53:21 -0700669 * Read all the records from one persistent store backend. Create
Luck, Tony6dda9262011-08-11 15:14:39 -0700670 * files in our filesystem. Don't warn about -EEXIST errors
671 * when we are re-scanning the backing store looking to add new
672 * error records.
Tony Luckca01d6d2010-12-28 14:25:21 -0800673 */
Kees Cook3a7d2fd2017-04-27 15:53:21 -0700674void pstore_get_backend_records(struct pstore_info *psi,
675 struct dentry *root, int quiet)
Tony Luckca01d6d2010-12-28 14:25:21 -0800676{
Kees Cook2a2b0ac2017-03-04 22:57:26 -0800677 int failed = 0;
Kees Cook656de422017-05-16 12:03:31 -0700678 unsigned int stop_loop = 65536;
Tony Luckca01d6d2010-12-28 14:25:21 -0800679
Kees Cook3a7d2fd2017-04-27 15:53:21 -0700680 if (!psi || !root)
Tony Luckca01d6d2010-12-28 14:25:21 -0800681 return;
682
Kees Cookf6f82852011-11-17 12:58:07 -0800683 mutex_lock(&psi->read_mutex);
Kees Cook2174f6d2011-11-18 13:49:00 -0800684 if (psi->open && psi->open(psi))
Chen Gong06cf91b2011-05-16 11:00:27 -0700685 goto out;
686
Kees Cook1dfff7d2017-03-04 22:46:41 -0800687 /*
688 * Backend callback read() allocates record.buf. decompress_record()
689 * may reallocate record.buf. On success, pstore_mkfile() will keep
690 * the record.buf, so free it only on failure.
691 */
Kees Cook656de422017-05-16 12:03:31 -0700692 for (; stop_loop; stop_loop--) {
Kees Cook2a2b0ac2017-03-04 22:57:26 -0800693 struct pstore_record *record;
694 int rc;
695
696 record = kzalloc(sizeof(*record), GFP_KERNEL);
697 if (!record) {
698 pr_err("out of memory creating record\n");
699 break;
700 }
Kees Cooke581ca82017-05-19 15:10:31 -0700701 pstore_record_init(record, psi);
Kees Cook2a2b0ac2017-03-04 22:57:26 -0800702
703 record->size = psi->read(record);
704
705 /* No more records left in backend? */
Douglas Andersonf6525b92017-05-30 15:50:38 -0700706 if (record->size <= 0) {
707 kfree(record);
Kees Cook2a2b0ac2017-03-04 22:57:26 -0800708 break;
Douglas Andersonf6525b92017-05-30 15:50:38 -0700709 }
Kees Cook2a2b0ac2017-03-04 22:57:26 -0800710
711 decompress_record(record);
Kees Cook3a7d2fd2017-04-27 15:53:21 -0700712 rc = pstore_mkfile(root, record);
Kees Cook1dfff7d2017-03-04 22:46:41 -0800713 if (rc) {
Kees Cook83f70f02017-03-04 23:12:24 -0800714 /* pstore_mkfile() did not take record, so free it. */
Kees Cook2a2b0ac2017-03-04 22:57:26 -0800715 kfree(record->buf);
Kees Cook83f70f02017-03-04 23:12:24 -0800716 kfree(record);
Kees Cook1dfff7d2017-03-04 22:46:41 -0800717 if (rc != -EEXIST || !quiet)
718 failed++;
719 }
Tony Luckca01d6d2010-12-28 14:25:21 -0800720 }
Kees Cook2174f6d2011-11-18 13:49:00 -0800721 if (psi->close)
722 psi->close(psi);
Chen Gong06cf91b2011-05-16 11:00:27 -0700723out:
Kees Cookf6f82852011-11-17 12:58:07 -0800724 mutex_unlock(&psi->read_mutex);
Tony Luckca01d6d2010-12-28 14:25:21 -0800725
726 if (failed)
Kees Cook656de422017-05-16 12:03:31 -0700727 pr_warn("failed to create %d record(s) from '%s'\n",
Fabian Frederickef748852014-06-06 14:37:31 -0700728 failed, psi->name);
Kees Cook656de422017-05-16 12:03:31 -0700729 if (!stop_loop)
730 pr_err("looping? Too many records seen from '%s'\n",
731 psi->name);
Tony Luckca01d6d2010-12-28 14:25:21 -0800732}
733
Luck, Tony6dda9262011-08-11 15:14:39 -0700734static void pstore_dowork(struct work_struct *work)
735{
736 pstore_get_records(1);
737}
738
Kees Cook24ed9602017-08-28 11:28:21 -0700739static void pstore_timefunc(struct timer_list *unused)
Luck, Tony6dda9262011-08-11 15:14:39 -0700740{
741 if (pstore_new_entry) {
742 pstore_new_entry = 0;
743 schedule_work(&pstore_work);
744 }
745
Kees Cook6330d552017-03-06 12:42:12 -0800746 if (pstore_update_ms >= 0)
747 mod_timer(&pstore_timer,
748 jiffies + msecs_to_jiffies(pstore_update_ms));
Luck, Tony6dda9262011-08-11 15:14:39 -0700749}
750
Kees Cookfe1d4752018-03-06 15:57:38 -0800751void __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
Matthew Garrettdee28e72011-07-21 16:57:55 -0400770module_param(backend, charp, 0444);
771MODULE_PARM_DESC(backend, "Pstore backend to use");