platform.c 7.4 KB
Newer Older
1 2 3
/*
 * Persistent Storage - platform driver interface parts.
 *
4
 * Copyright (C) 2007-2008 Google, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 * Copyright (C) 2010 Intel Corporation <tony.luck@intel.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <linux/atomic.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kmsg_dump.h>
26
#include <linux/console.h>
27 28 29
#include <linux/module.h>
#include <linux/pstore.h>
#include <linux/string.h>
30
#include <linux/timer.h>
31 32
#include <linux/slab.h>
#include <linux/uaccess.h>
33
#include <linux/hardirq.h>
34
#include <linux/jiffies.h>
35
#include <linux/workqueue.h>
36 37 38

#include "internal.h"

39 40 41 42 43
/*
 * We defer making "oops" entries appear in pstore - see
 * whether the system is actually still running well enough
 * to let someone see the entry
 */
44
static int pstore_update_ms = -1;
45 46
module_param_named(update_ms, pstore_update_ms, int, 0600);
MODULE_PARM_DESC(update_ms, "milliseconds before pstore updates its content "
47 48 49
		 "(default is -1, which means runtime updates are disabled; "
		 "enabling this option is not safe, it may lead to further "
		 "corruption on Oopses)");
50 51 52 53 54 55 56 57 58

static int pstore_new_entry;

static void pstore_timefunc(unsigned long);
static DEFINE_TIMER(pstore_timer, pstore_timefunc, 0, 0);

static void pstore_dowork(struct work_struct *);
static DECLARE_WORK(pstore_work, pstore_dowork);

59 60 61 62 63 64 65
/*
 * pstore_lock just protects "psinfo" during
 * calls to pstore_register()
 */
static DEFINE_SPINLOCK(pstore_lock);
static struct pstore_info *psinfo;

66 67
static char *backend;

68
/* How much of the console log to snapshot */
69 70
static unsigned long kmsg_bytes = 10240;

71
void pstore_set_kmsg_bytes(int bytes)
72
{
73
	kmsg_bytes = bytes;
74 75 76 77 78
}

/* Tag each group of saved records with a sequence number */
static int	oopscount;

79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
static const char *get_reason_str(enum kmsg_dump_reason reason)
{
	switch (reason) {
	case KMSG_DUMP_PANIC:
		return "Panic";
	case KMSG_DUMP_OOPS:
		return "Oops";
	case KMSG_DUMP_EMERG:
		return "Emergency";
	case KMSG_DUMP_RESTART:
		return "Restart";
	case KMSG_DUMP_HALT:
		return "Halt";
	case KMSG_DUMP_POWEROFF:
		return "Poweroff";
	default:
		return "Unknown";
	}
}
T
Tony Luck 已提交
98

99 100 101 102 103 104
/*
 * callback from kmsg_dump. (s2,l2) has the most recently
 * written bytes, older bytes are in (s1,l1). Save as much
 * as we can from the end of the buffer.
 */
static void pstore_dump(struct kmsg_dumper *dumper,
105
			enum kmsg_dump_reason reason)
106
{
107
	unsigned long	total = 0;
108
	const char	*why;
109
	u64		id;
M
Matthew Garrett 已提交
110
	unsigned int	part = 1;
111 112
	unsigned long	flags = 0;
	int		is_locked = 0;
113
	int		ret;
114

115
	why = get_reason_str(reason);
T
Tony Luck 已提交
116

117 118 119 120 121 122
	if (in_nmi()) {
		is_locked = spin_trylock(&psinfo->buf_lock);
		if (!is_locked)
			pr_err("pstore dump routine blocked in NMI, may corrupt error record\n");
	} else
		spin_lock_irqsave(&psinfo->buf_lock, flags);
123 124
	oopscount++;
	while (total < kmsg_bytes) {
125 126 127 128 129
		char *dst;
		unsigned long size;
		int hsize;
		size_t len;

130
		dst = psinfo->buf;
131
		hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part);
132 133 134
		size = psinfo->bufsize - hsize;
		dst += hsize;

135
		if (!kmsg_dump_get_buffer(dumper, true, dst, size, &len))
136 137
			break;

138
		ret = psinfo->write(PSTORE_TYPE_DMESG, reason, &id, part,
139
				    hsize + len, psinfo);
140
		if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted())
141
			pstore_new_entry = 1;
142 143

		total += hsize + len;
144
		part++;
145
	}
146 147 148 149 150
	if (in_nmi()) {
		if (is_locked)
			spin_unlock(&psinfo->buf_lock);
	} else
		spin_unlock_irqrestore(&psinfo->buf_lock, flags);
151 152 153 154 155 156
}

static struct kmsg_dumper pstore_dumper = {
	.dump = pstore_dump,
};

157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
#ifdef CONFIG_PSTORE_CONSOLE
static void pstore_console_write(struct console *con, const char *s, unsigned c)
{
	const char *e = s + c;

	while (s < e) {
		unsigned long flags;

		if (c > psinfo->bufsize)
			c = psinfo->bufsize;
		spin_lock_irqsave(&psinfo->buf_lock, flags);
		memcpy(psinfo->buf, s, c);
		psinfo->write(PSTORE_TYPE_CONSOLE, 0, NULL, 0, c, psinfo);
		spin_unlock_irqrestore(&psinfo->buf_lock, flags);
		s += c;
		c = e - s;
	}
}

static struct console pstore_console = {
	.name	= "pstore",
	.write	= pstore_console_write,
	.flags	= CON_PRINTBUFFER | CON_ENABLED | CON_ANYTIME,
	.index	= -1,
};

static void pstore_register_console(void)
{
	register_console(&pstore_console);
}
#else
static void pstore_register_console(void) {}
#endif

191 192 193 194 195 196 197 198
static int pstore_write_compat(enum pstore_type_id type,
			       enum kmsg_dump_reason reason,
			       u64 *id, unsigned int part,
			       size_t size, struct pstore_info *psi)
{
	return psi->write_buf(type, reason, id, part, psinfo->buf, size, psi);
}

199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
/*
 * platform specific persistent storage driver registers with
 * us here. If pstore is already mounted, call the platform
 * read function right away to populate the file system. If not
 * then the pstore mount code will call us later to fill out
 * the file system.
 *
 * Register with kmsg_dump to save last part of console log on panic.
 */
int pstore_register(struct pstore_info *psi)
{
	struct module *owner = psi->owner;

	spin_lock(&pstore_lock);
	if (psinfo) {
		spin_unlock(&pstore_lock);
		return -EBUSY;
	}
217 218 219 220 221 222

	if (backend && strcmp(backend, psi->name)) {
		spin_unlock(&pstore_lock);
		return -EINVAL;
	}

223 224
	if (!psi->write)
		psi->write = pstore_write_compat;
225
	psinfo = psi;
226
	mutex_init(&psinfo->read_mutex);
227 228 229 230 231 232 233 234
	spin_unlock(&pstore_lock);

	if (owner && !try_module_get(owner)) {
		psinfo = NULL;
		return -EINVAL;
	}

	if (pstore_is_mounted())
235
		pstore_get_records(0);
236 237

	kmsg_dump_register(&pstore_dumper);
238
	pstore_register_console();
239

240 241 242 243 244
	if (pstore_update_ms >= 0) {
		pstore_timer.expires = jiffies +
			msecs_to_jiffies(pstore_update_ms);
		add_timer(&pstore_timer);
	}
245

246 247 248 249 250
	return 0;
}
EXPORT_SYMBOL_GPL(pstore_register);

/*
251 252 253 254
 * Read all the records from the persistent store. Create
 * files in our filesystem.  Don't warn about -EEXIST errors
 * when we are re-scanning the backing store looking to add new
 * error records.
255
 */
256
void pstore_get_records(int quiet)
257 258
{
	struct pstore_info *psi = psinfo;
259
	char			*buf = NULL;
260
	ssize_t			size;
261 262 263
	u64			id;
	enum pstore_type_id	type;
	struct timespec		time;
264
	int			failed = 0, rc;
265 266 267 268

	if (!psi)
		return;

269
	mutex_lock(&psi->read_mutex);
270
	if (psi->open && psi->open(psi))
271 272
		goto out;

273 274
	while ((size = psi->read(&id, &type, &time, &buf, psi)) > 0) {
		rc = pstore_mkfile(type, psi->name, id, buf, (size_t)size,
275
				  time, psi);
276 277
		kfree(buf);
		buf = NULL;
278
		if (rc && (rc != -EEXIST || !quiet))
279 280
			failed++;
	}
281 282
	if (psi->close)
		psi->close(psi);
283
out:
284
	mutex_unlock(&psi->read_mutex);
285 286 287 288 289 290

	if (failed)
		printk(KERN_WARNING "pstore: failed to load %d record(s) from '%s'\n",
		       failed, psi->name);
}

291 292 293 294 295 296 297 298 299 300 301 302
static void pstore_dowork(struct work_struct *work)
{
	pstore_get_records(1);
}

static void pstore_timefunc(unsigned long dummy)
{
	if (pstore_new_entry) {
		pstore_new_entry = 0;
		schedule_work(&pstore_work);
	}

303
	mod_timer(&pstore_timer, jiffies + msecs_to_jiffies(pstore_update_ms));
304 305
}

306 307
module_param(backend, charp, 0444);
MODULE_PARM_DESC(backend, "Pstore backend to use");