brintos

brintos / linux-shallow public Read only

0
0
Text · 18.4 KiB · f56b066 Raw
766 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Persistent Storage - platform driver interface parts.4 *5 * Copyright (C) 2007-2008 Google, Inc.6 * Copyright (C) 2010 Intel Corporation <tony.luck@intel.com>7 */8 9#define pr_fmt(fmt) "pstore: " fmt10 11#include <linux/atomic.h>12#include <linux/types.h>13#include <linux/errno.h>14#include <linux/init.h>15#include <linux/kmsg_dump.h>16#include <linux/console.h>17#include <linux/mm.h>18#include <linux/module.h>19#include <linux/pstore.h>20#include <linux/string.h>21#include <linux/timer.h>22#include <linux/slab.h>23#include <linux/uaccess.h>24#include <linux/jiffies.h>25#include <linux/vmalloc.h>26#include <linux/workqueue.h>27#include <linux/zlib.h>28 29#include "internal.h"30 31/*32 * We defer making "oops" entries appear in pstore - see33 * whether the system is actually still running well enough34 * to let someone see the entry35 */36static int pstore_update_ms = -1;37module_param_named(update_ms, pstore_update_ms, int, 0600);38MODULE_PARM_DESC(update_ms, "milliseconds before pstore updates its content "39		 "(default is -1, which means runtime updates are disabled; "40		 "enabling this option may not be safe; it may lead to further "41		 "corruption on Oopses)");42 43/* Names should be in the same order as the enum pstore_type_id */44static const char * const pstore_type_names[] = {45	"dmesg",46	"mce",47	"console",48	"ftrace",49	"rtas",50	"powerpc-ofw",51	"powerpc-common",52	"pmsg",53	"powerpc-opal",54};55 56static int pstore_new_entry;57 58static void pstore_timefunc(struct timer_list *);59static DEFINE_TIMER(pstore_timer, pstore_timefunc);60 61static void pstore_dowork(struct work_struct *);62static DECLARE_WORK(pstore_work, pstore_dowork);63 64/*65 * psinfo_lock protects "psinfo" during calls to66 * pstore_register(), pstore_unregister(), and67 * the filesystem mount/unmount routines.68 */69static DEFINE_MUTEX(psinfo_lock);70struct pstore_info *psinfo;71 72static char *backend;73module_param(backend, charp, 0444);74MODULE_PARM_DESC(backend, "specific backend to use");75 76/*77 * pstore no longer implements compression via the crypto API, and only78 * supports zlib deflate compression implemented using the zlib library79 * interface. This removes additional complexity which is hard to justify for a80 * diagnostic facility that has to operate in conditions where the system may81 * have become unstable. Zlib deflate is comparatively small in terms of code82 * size, and compresses ASCII text comparatively well. In terms of compression83 * speed, deflate is not the best performer but for recording the log output on84 * a kernel panic, this is not considered critical.85 *86 * The only remaining arguments supported by the compress= module parameter are87 * 'deflate' and 'none'. To retain compatibility with existing installations,88 * all other values are logged and replaced with 'deflate'.89 */90static char *compress = "deflate";91module_param(compress, charp, 0444);92MODULE_PARM_DESC(compress, "compression to use");93 94/* How much of the kernel log to snapshot */95unsigned long kmsg_bytes = CONFIG_PSTORE_DEFAULT_KMSG_BYTES;96module_param(kmsg_bytes, ulong, 0444);97MODULE_PARM_DESC(kmsg_bytes, "amount of kernel log to snapshot (in bytes)");98 99static void *compress_workspace;100 101/*102 * Compression is only used for dmesg output, which consists of low-entropy103 * ASCII text, and so we can assume worst-case 60%.104 */105#define DMESG_COMP_PERCENT	60106 107static char *big_oops_buf;108static size_t max_compressed_size;109 110void pstore_set_kmsg_bytes(int bytes)111{112	kmsg_bytes = bytes;113}114 115/* Tag each group of saved records with a sequence number */116static int	oopscount;117 118const char *pstore_type_to_name(enum pstore_type_id type)119{120	BUILD_BUG_ON(ARRAY_SIZE(pstore_type_names) != PSTORE_TYPE_MAX);121 122	if (WARN_ON_ONCE(type >= PSTORE_TYPE_MAX))123		return "unknown";124 125	return pstore_type_names[type];126}127EXPORT_SYMBOL_GPL(pstore_type_to_name);128 129enum pstore_type_id pstore_name_to_type(const char *name)130{131	int i;132 133	for (i = 0; i < PSTORE_TYPE_MAX; i++) {134		if (!strcmp(pstore_type_names[i], name))135			return i;136	}137 138	return PSTORE_TYPE_MAX;139}140EXPORT_SYMBOL_GPL(pstore_name_to_type);141 142static void pstore_timer_kick(void)143{144	if (pstore_update_ms < 0)145		return;146 147	mod_timer(&pstore_timer, jiffies + msecs_to_jiffies(pstore_update_ms));148}149 150static bool pstore_cannot_block_path(enum kmsg_dump_reason reason)151{152	/*153	 * In case of NMI path, pstore shouldn't be blocked154	 * regardless of reason.155	 */156	if (in_nmi())157		return true;158 159	switch (reason) {160	/* In panic case, other cpus are stopped by smp_send_stop(). */161	case KMSG_DUMP_PANIC:162	/*163	 * Emergency restart shouldn't be blocked by spinning on164	 * pstore_info::buf_lock.165	 */166	case KMSG_DUMP_EMERG:167		return true;168	default:169		return false;170	}171}172 173static int pstore_compress(const void *in, void *out,174			   unsigned int inlen, unsigned int outlen)175{176	struct z_stream_s zstream = {177		.next_in	= in,178		.avail_in	= inlen,179		.next_out	= out,180		.avail_out	= outlen,181		.workspace	= compress_workspace,182	};183	int ret;184 185	if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS))186		return -EINVAL;187 188	ret = zlib_deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,189				-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);190	if (ret != Z_OK)191		return -EINVAL;192 193	ret = zlib_deflate(&zstream, Z_FINISH);194	if (ret != Z_STREAM_END)195		return -EINVAL;196 197	ret = zlib_deflateEnd(&zstream);198	if (ret != Z_OK)199		pr_warn_once("zlib_deflateEnd() failed: %d\n", ret);200 201	return zstream.total_out;202}203 204static void allocate_buf_for_compression(void)205{206	size_t compressed_size;207	char *buf;208 209	/* Skip if not built-in or compression disabled. */210	if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS) || !compress ||211	    !strcmp(compress, "none")) {212		compress = NULL;213		return;214	}215 216	if (strcmp(compress, "deflate")) {217		pr_err("Unsupported compression '%s', falling back to deflate\n",218		       compress);219		compress = "deflate";220	}221 222	/*223	 * The compression buffer only needs to be as large as the maximum224	 * uncompressed record size, since any record that would be expanded by225	 * compression is just stored uncompressed.226	 */227	compressed_size = (psinfo->bufsize * 100) / DMESG_COMP_PERCENT;228	buf = kvzalloc(compressed_size, GFP_KERNEL);229	if (!buf) {230		pr_err("Failed %zu byte compression buffer allocation for: %s\n",231		       psinfo->bufsize, compress);232		return;233	}234 235	compress_workspace =236		vmalloc(zlib_deflate_workspacesize(MAX_WBITS, DEF_MEM_LEVEL));237	if (!compress_workspace) {238		pr_err("Failed to allocate zlib deflate workspace\n");239		kvfree(buf);240		return;241	}242 243	/* A non-NULL big_oops_buf indicates compression is available. */244	big_oops_buf = buf;245	max_compressed_size = compressed_size;246 247	pr_info("Using crash dump compression: %s\n", compress);248}249 250static void free_buf_for_compression(void)251{252	if (IS_ENABLED(CONFIG_PSTORE_COMPRESS) && compress_workspace) {253		vfree(compress_workspace);254		compress_workspace = NULL;255	}256 257	kvfree(big_oops_buf);258	big_oops_buf = NULL;259	max_compressed_size = 0;260}261 262void pstore_record_init(struct pstore_record *record,263			struct pstore_info *psinfo)264{265	memset(record, 0, sizeof(*record));266 267	record->psi = psinfo;268 269	/* Report zeroed timestamp if called before timekeeping has resumed. */270	record->time = ns_to_timespec64(ktime_get_real_fast_ns());271}272 273/*274 * callback from kmsg_dump. Save as much as we can (up to kmsg_bytes) from the275 * end of the buffer.276 */277static void pstore_dump(struct kmsg_dumper *dumper,278			struct kmsg_dump_detail *detail)279{280	struct kmsg_dump_iter iter;281	unsigned long	total = 0;282	const char	*why;283	unsigned int	part = 1;284	unsigned long	flags = 0;285	int		saved_ret = 0;286	int		ret;287 288	why = kmsg_dump_reason_str(detail->reason);289 290	if (pstore_cannot_block_path(detail->reason)) {291		if (!raw_spin_trylock_irqsave(&psinfo->buf_lock, flags)) {292			pr_err("dump skipped in %s path because of concurrent dump\n",293					in_nmi() ? "NMI" : why);294			return;295		}296	} else {297		raw_spin_lock_irqsave(&psinfo->buf_lock, flags);298	}299 300	kmsg_dump_rewind(&iter);301 302	oopscount++;303	while (total < kmsg_bytes) {304		char *dst;305		size_t dst_size;306		int header_size;307		int zipped_len = -1;308		size_t dump_size;309		struct pstore_record record;310 311		pstore_record_init(&record, psinfo);312		record.type = PSTORE_TYPE_DMESG;313		record.count = oopscount;314		record.reason = detail->reason;315		record.part = part;316		record.buf = psinfo->buf;317 318		dst = big_oops_buf ?: psinfo->buf;319		dst_size = max_compressed_size ?: psinfo->bufsize;320 321		/* Write dump header. */322		header_size = snprintf(dst, dst_size, "%s#%d Part%u\n", why,323				 oopscount, part);324		dst_size -= header_size;325 326		/* Write dump contents. */327		if (!kmsg_dump_get_buffer(&iter, true, dst + header_size,328					  dst_size, &dump_size))329			break;330 331		if (big_oops_buf) {332			zipped_len = pstore_compress(dst, psinfo->buf,333						header_size + dump_size,334						psinfo->bufsize);335 336			if (zipped_len > 0) {337				record.compressed = true;338				record.size = zipped_len;339			} else {340				/*341				 * Compression failed, so the buffer is most342				 * likely filled with binary data that does not343				 * compress as well as ASCII text. Copy as much344				 * of the uncompressed data as possible into345				 * the pstore record, and discard the rest.346				 */347				record.size = psinfo->bufsize;348				memcpy(psinfo->buf, dst, psinfo->bufsize);349			}350		} else {351			record.size = header_size + dump_size;352		}353 354		ret = psinfo->write(&record);355		if (ret == 0 && detail->reason == KMSG_DUMP_OOPS) {356			pstore_new_entry = 1;357			pstore_timer_kick();358		} else {359			/* Preserve only the first non-zero returned value. */360			if (!saved_ret)361				saved_ret = ret;362		}363 364		total += record.size;365		part++;366	}367	raw_spin_unlock_irqrestore(&psinfo->buf_lock, flags);368 369	if (saved_ret) {370		pr_err_once("backend (%s) writing error (%d)\n", psinfo->name,371			    saved_ret);372	}373}374 375static struct kmsg_dumper pstore_dumper = {376	.dump = pstore_dump,377};378 379/*380 * Register with kmsg_dump to save last part of console log on panic.381 */382static void pstore_register_kmsg(void)383{384	kmsg_dump_register(&pstore_dumper);385}386 387static void pstore_unregister_kmsg(void)388{389	kmsg_dump_unregister(&pstore_dumper);390}391 392#ifdef CONFIG_PSTORE_CONSOLE393static void pstore_console_write(struct console *con, const char *s, unsigned c)394{395	struct pstore_record record;396 397	if (!c)398		return;399 400	pstore_record_init(&record, psinfo);401	record.type = PSTORE_TYPE_CONSOLE;402 403	record.buf = (char *)s;404	record.size = c;405	psinfo->write(&record);406}407 408static struct console pstore_console = {409	.write	= pstore_console_write,410	.index	= -1,411};412 413static void pstore_register_console(void)414{415	/* Show which backend is going to get console writes. */416	strscpy(pstore_console.name, psinfo->name,417		sizeof(pstore_console.name));418	/*419	 * Always initialize flags here since prior unregister_console()420	 * calls may have changed settings (specifically CON_ENABLED).421	 */422	pstore_console.flags = CON_PRINTBUFFER | CON_ENABLED | CON_ANYTIME;423	register_console(&pstore_console);424}425 426static void pstore_unregister_console(void)427{428	unregister_console(&pstore_console);429}430#else431static void pstore_register_console(void) {}432static void pstore_unregister_console(void) {}433#endif434 435static int pstore_write_user_compat(struct pstore_record *record,436				    const char __user *buf)437{438	int ret = 0;439 440	if (record->buf)441		return -EINVAL;442 443	record->buf = vmemdup_user(buf, record->size);444	if (IS_ERR(record->buf)) {445		ret = PTR_ERR(record->buf);446		goto out;447	}448 449	ret = record->psi->write(record);450 451	kvfree(record->buf);452out:453	record->buf = NULL;454 455	return unlikely(ret < 0) ? ret : record->size;456}457 458/*459 * platform specific persistent storage driver registers with460 * us here. If pstore is already mounted, call the platform461 * read function right away to populate the file system. If not462 * then the pstore mount code will call us later to fill out463 * the file system.464 */465int pstore_register(struct pstore_info *psi)466{467	char *new_backend;468 469	if (backend && strcmp(backend, psi->name)) {470		pr_warn("backend '%s' already in use: ignoring '%s'\n",471			backend, psi->name);472		return -EBUSY;473	}474 475	/* Sanity check flags. */476	if (!psi->flags) {477		pr_warn("backend '%s' must support at least one frontend\n",478			psi->name);479		return -EINVAL;480	}481 482	/* Check for required functions. */483	if (!psi->read || !psi->write) {484		pr_warn("backend '%s' must implement read() and write()\n",485			psi->name);486		return -EINVAL;487	}488 489	new_backend = kstrdup(psi->name, GFP_KERNEL);490	if (!new_backend)491		return -ENOMEM;492 493	mutex_lock(&psinfo_lock);494	if (psinfo) {495		pr_warn("backend '%s' already loaded: ignoring '%s'\n",496			psinfo->name, psi->name);497		mutex_unlock(&psinfo_lock);498		kfree(new_backend);499		return -EBUSY;500	}501 502	if (!psi->write_user)503		psi->write_user = pstore_write_user_compat;504	psinfo = psi;505	mutex_init(&psinfo->read_mutex);506	raw_spin_lock_init(&psinfo->buf_lock);507 508	if (psi->flags & PSTORE_FLAGS_DMESG)509		allocate_buf_for_compression();510 511	pstore_get_records(0);512 513	if (psi->flags & PSTORE_FLAGS_DMESG) {514		pstore_dumper.max_reason = psinfo->max_reason;515		pstore_register_kmsg();516	}517	if (psi->flags & PSTORE_FLAGS_CONSOLE)518		pstore_register_console();519	if (psi->flags & PSTORE_FLAGS_FTRACE)520		pstore_register_ftrace();521	if (psi->flags & PSTORE_FLAGS_PMSG)522		pstore_register_pmsg();523 524	/* Start watching for new records, if desired. */525	pstore_timer_kick();526 527	/*528	 * Update the module parameter backend, so it is visible529	 * through /sys/module/pstore/parameters/backend530	 */531	backend = new_backend;532 533	pr_info("Registered %s as persistent store backend\n", psi->name);534 535	mutex_unlock(&psinfo_lock);536	return 0;537}538EXPORT_SYMBOL_GPL(pstore_register);539 540void pstore_unregister(struct pstore_info *psi)541{542	/* It's okay to unregister nothing. */543	if (!psi)544		return;545 546	mutex_lock(&psinfo_lock);547 548	/* Only one backend can be registered at a time. */549	if (WARN_ON(psi != psinfo)) {550		mutex_unlock(&psinfo_lock);551		return;552	}553 554	/* Unregister all callbacks. */555	if (psi->flags & PSTORE_FLAGS_PMSG)556		pstore_unregister_pmsg();557	if (psi->flags & PSTORE_FLAGS_FTRACE)558		pstore_unregister_ftrace();559	if (psi->flags & PSTORE_FLAGS_CONSOLE)560		pstore_unregister_console();561	if (psi->flags & PSTORE_FLAGS_DMESG)562		pstore_unregister_kmsg();563 564	/* Stop timer and make sure all work has finished. */565	del_timer_sync(&pstore_timer);566	flush_work(&pstore_work);567 568	/* Remove all backend records from filesystem tree. */569	pstore_put_backend_records(psi);570 571	free_buf_for_compression();572 573	psinfo = NULL;574	kfree(backend);575	backend = NULL;576 577	pr_info("Unregistered %s as persistent store backend\n", psi->name);578	mutex_unlock(&psinfo_lock);579}580EXPORT_SYMBOL_GPL(pstore_unregister);581 582static void decompress_record(struct pstore_record *record,583			      struct z_stream_s *zstream)584{585	int ret;586	int unzipped_len;587	char *unzipped, *workspace;588	size_t max_uncompressed_size;589 590	if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS) || !record->compressed)591		return;592 593	/* Only PSTORE_TYPE_DMESG support compression. */594	if (record->type != PSTORE_TYPE_DMESG) {595		pr_warn("ignored compressed record type %d\n", record->type);596		return;597	}598 599	/* Missing compression buffer means compression was not initialized. */600	if (!zstream->workspace) {601		pr_warn("no decompression method initialized!\n");602		return;603	}604 605	ret = zlib_inflateReset(zstream);606	if (ret != Z_OK) {607		pr_err("zlib_inflateReset() failed, ret = %d!\n", ret);608		return;609	}610 611	/* Allocate enough space to hold max decompression and ECC. */612	max_uncompressed_size = 3 * psinfo->bufsize;613	workspace = kvzalloc(max_uncompressed_size + record->ecc_notice_size,614			     GFP_KERNEL);615	if (!workspace)616		return;617 618	zstream->next_in	= record->buf;619	zstream->avail_in	= record->size;620	zstream->next_out	= workspace;621	zstream->avail_out	= max_uncompressed_size;622 623	ret = zlib_inflate(zstream, Z_FINISH);624	if (ret != Z_STREAM_END) {625		pr_err_ratelimited("zlib_inflate() failed, ret = %d!\n", ret);626		kvfree(workspace);627		return;628	}629 630	unzipped_len = zstream->total_out;631 632	/* Append ECC notice to decompressed buffer. */633	memcpy(workspace + unzipped_len, record->buf + record->size,634	       record->ecc_notice_size);635 636	/* Copy decompressed contents into an minimum-sized allocation. */637	unzipped = kvmemdup(workspace, unzipped_len + record->ecc_notice_size,638			    GFP_KERNEL);639	kvfree(workspace);640	if (!unzipped)641		return;642 643	/* Swap out compressed contents with decompressed contents. */644	kvfree(record->buf);645	record->buf = unzipped;646	record->size = unzipped_len;647	record->compressed = false;648}649 650/*651 * Read all the records from one persistent store backend. Create652 * files in our filesystem.  Don't warn about -EEXIST errors653 * when we are re-scanning the backing store looking to add new654 * error records.655 */656void pstore_get_backend_records(struct pstore_info *psi,657				struct dentry *root, int quiet)658{659	int failed = 0;660	unsigned int stop_loop = 65536;661	struct z_stream_s zstream = {};662 663	if (!psi || !root)664		return;665 666	if (IS_ENABLED(CONFIG_PSTORE_COMPRESS) && compress) {667		zstream.workspace = kvmalloc(zlib_inflate_workspacesize(),668					     GFP_KERNEL);669		zlib_inflateInit2(&zstream, -DEF_WBITS);670	}671 672	mutex_lock(&psi->read_mutex);673	if (psi->open && psi->open(psi))674		goto out;675 676	/*677	 * Backend callback read() allocates record.buf. decompress_record()678	 * may reallocate record.buf. On success, pstore_mkfile() will keep679	 * the record.buf, so free it only on failure.680	 */681	for (; stop_loop; stop_loop--) {682		struct pstore_record *record;683		int rc;684 685		record = kzalloc(sizeof(*record), GFP_KERNEL);686		if (!record) {687			pr_err("out of memory creating record\n");688			break;689		}690		pstore_record_init(record, psi);691 692		record->size = psi->read(record);693 694		/* No more records left in backend? */695		if (record->size <= 0) {696			kfree(record);697			break;698		}699 700		decompress_record(record, &zstream);701		rc = pstore_mkfile(root, record);702		if (rc) {703			/* pstore_mkfile() did not take record, so free it. */704			kvfree(record->buf);705			kfree(record->priv);706			kfree(record);707			if (rc != -EEXIST || !quiet)708				failed++;709		}710	}711	if (psi->close)712		psi->close(psi);713out:714	mutex_unlock(&psi->read_mutex);715 716	if (IS_ENABLED(CONFIG_PSTORE_COMPRESS) && compress) {717		if (zlib_inflateEnd(&zstream) != Z_OK)718			pr_warn("zlib_inflateEnd() failed\n");719		kvfree(zstream.workspace);720	}721 722	if (failed)723		pr_warn("failed to create %d record(s) from '%s'\n",724			failed, psi->name);725	if (!stop_loop)726		pr_err("looping? Too many records seen from '%s'\n",727			psi->name);728}729 730static void pstore_dowork(struct work_struct *work)731{732	pstore_get_records(1);733}734 735static void pstore_timefunc(struct timer_list *unused)736{737	if (pstore_new_entry) {738		pstore_new_entry = 0;739		schedule_work(&pstore_work);740	}741 742	pstore_timer_kick();743}744 745static int __init pstore_init(void)746{747	int ret;748 749	ret = pstore_init_fs();750	if (ret)751		free_buf_for_compression();752 753	return ret;754}755late_initcall(pstore_init);756 757static void __exit pstore_exit(void)758{759	pstore_exit_fs();760}761module_exit(pstore_exit)762 763MODULE_AUTHOR("Tony Luck <tony.luck@intel.com>");764MODULE_DESCRIPTION("Persistent Storage - platform driver interface");765MODULE_LICENSE("GPL");766