linux/fs/pstore/platform.c
<<
>>
Prefs
   1/*
   2 * Persistent Storage - platform driver interface parts.
   3 *
   4 * Copyright (C) 2007-2008 Google, Inc.
   5 * 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
  21#include <linux/atomic.h>
  22#include <linux/types.h>
  23#include <linux/errno.h>
  24#include <linux/init.h>
  25#include <linux/kmsg_dump.h>
  26#include <linux/console.h>
  27#include <linux/module.h>
  28#include <linux/pstore.h>
  29#include <linux/string.h>
  30#include <linux/timer.h>
  31#include <linux/slab.h>
  32#include <linux/uaccess.h>
  33#include <linux/hardirq.h>
  34#include <linux/jiffies.h>
  35#include <linux/workqueue.h>
  36
  37#include "internal.h"
  38
  39/*
  40 * We defer making "oops" entries appear in pstore - see
  41 * whether the system is actually still running well enough
  42 * to let someone see the entry
  43 */
  44static int pstore_update_ms = -1;
  45module_param_named(update_ms, pstore_update_ms, int, 0600);
  46MODULE_PARM_DESC(update_ms, "milliseconds before pstore updates its content "
  47                 "(default is -1, which means runtime updates are disabled; "
  48                 "enabling this option is not safe, it may lead to further "
  49                 "corruption on Oopses)");
  50
  51static int pstore_new_entry;
  52
  53static void pstore_timefunc(unsigned long);
  54static DEFINE_TIMER(pstore_timer, pstore_timefunc, 0, 0);
  55
  56static void pstore_dowork(struct work_struct *);
  57static DECLARE_WORK(pstore_work, pstore_dowork);
  58
  59/*
  60 * pstore_lock just protects "psinfo" during
  61 * calls to pstore_register()
  62 */
  63static DEFINE_SPINLOCK(pstore_lock);
  64struct pstore_info *psinfo;
  65
  66static char *backend;
  67
  68/* How much of the console log to snapshot */
  69static unsigned long kmsg_bytes = 10240;
  70
  71void pstore_set_kmsg_bytes(int bytes)
  72{
  73        kmsg_bytes = bytes;
  74}
  75
  76/* Tag each group of saved records with a sequence number */
  77static int      oopscount;
  78
  79static const char *get_reason_str(enum kmsg_dump_reason reason)
  80{
  81        switch (reason) {
  82        case KMSG_DUMP_PANIC:
  83                return "Panic";
  84        case KMSG_DUMP_OOPS:
  85                return "Oops";
  86        case KMSG_DUMP_EMERG:
  87                return "Emergency";
  88        case KMSG_DUMP_RESTART:
  89                return "Restart";
  90        case KMSG_DUMP_HALT:
  91                return "Halt";
  92        case KMSG_DUMP_POWEROFF:
  93                return "Poweroff";
  94        default:
  95                return "Unknown";
  96        }
  97}
  98
  99/*
 100 * callback from kmsg_dump. (s2,l2) has the most recently
 101 * written bytes, older bytes are in (s1,l1). Save as much
 102 * as we can from the end of the buffer.
 103 */
 104static 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;
 110        unsigned int    part = 1;
 111        unsigned long   flags = 0;
 112        int             is_locked = 0;
 113        int             ret;
 114
 115        why = get_reason_str(reason);
 116
 117        if (in_nmi()) {
 118                is_locked = spin_trylock(&psinfo->buf_lock);
 119                if (!is_locked)
 120                        pr_err("pstore dump routine blocked in NMI, may corrupt error record\n");
 121        } else
 122                spin_lock_irqsave(&psinfo->buf_lock, flags);
 123        oopscount++;
 124        while (total < kmsg_bytes) {
 125                char *dst;
 126                unsigned long size;
 127                int hsize;
 128                size_t len;
 129
 130                dst = psinfo->buf;
 131                hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part);
 132                size = psinfo->bufsize - hsize;
 133                dst += hsize;
 134
 135                if (!kmsg_dump_get_buffer(dumper, true, dst, size, &len))
 136                        break;
 137
 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        if (in_nmi()) {
 147                if (is_locked)
 148                        spin_unlock(&psinfo->buf_lock);
 149        } else
 150                spin_unlock_irqrestore(&psinfo->buf_lock, flags);
 151}
 152
 153static struct kmsg_dumper pstore_dumper = {
 154        .dump = pstore_dump,
 155};
 156
 157#ifdef CONFIG_PSTORE_CONSOLE
 158static void pstore_console_write(struct console *con, const char *s, unsigned c)
 159{
 160        const char *e = s + c;
 161
 162        while (s < e) {
 163                unsigned long flags;
 164                u64 id;
 165
 166                if (c > psinfo->bufsize)
 167                        c = psinfo->bufsize;
 168                spin_lock_irqsave(&psinfo->buf_lock, flags);
 169                memcpy(psinfo->buf, s, c);
 170                psinfo->write(PSTORE_TYPE_CONSOLE, 0, &id, 0, c, psinfo);
 171                spin_unlock_irqrestore(&psinfo->buf_lock, flags);
 172                s += c;
 173                c = e - s;
 174        }
 175}
 176
 177static struct console pstore_console = {
 178        .name   = "pstore",
 179        .write  = pstore_console_write,
 180        .flags  = CON_PRINTBUFFER | CON_ENABLED | CON_ANYTIME,
 181        .index  = -1,
 182};
 183
 184static void pstore_register_console(void)
 185{
 186        register_console(&pstore_console);
 187}
 188#else
 189static void pstore_register_console(void) {}
 190#endif
 191
 192static int pstore_write_compat(enum pstore_type_id type,
 193                               enum kmsg_dump_reason reason,
 194                               u64 *id, unsigned int part,
 195                               size_t size, struct pstore_info *psi)
 196{
 197        return psi->write_buf(type, reason, id, part, psinfo->buf, size, psi);
 198}
 199
 200/*
 201 * platform specific persistent storage driver registers with
 202 * us here. If pstore is already mounted, call the platform
 203 * read function right away to populate the file system. If not
 204 * then the pstore mount code will call us later to fill out
 205 * the file system.
 206 *
 207 * Register with kmsg_dump to save last part of console log on panic.
 208 */
 209int pstore_register(struct pstore_info *psi)
 210{
 211        struct module *owner = psi->owner;
 212
 213        spin_lock(&pstore_lock);
 214        if (psinfo) {
 215                spin_unlock(&pstore_lock);
 216                return -EBUSY;
 217        }
 218
 219        if (backend && strcmp(backend, psi->name)) {
 220                spin_unlock(&pstore_lock);
 221                return -EINVAL;
 222        }
 223
 224        if (!psi->write)
 225                psi->write = pstore_write_compat;
 226        psinfo = psi;
 227        mutex_init(&psinfo->read_mutex);
 228        spin_unlock(&pstore_lock);
 229
 230        if (owner && !try_module_get(owner)) {
 231                psinfo = NULL;
 232                return -EINVAL;
 233        }
 234
 235        if (pstore_is_mounted())
 236                pstore_get_records(0);
 237
 238        kmsg_dump_register(&pstore_dumper);
 239        pstore_register_console();
 240
 241        if (pstore_update_ms >= 0) {
 242                pstore_timer.expires = jiffies +
 243                        msecs_to_jiffies(pstore_update_ms);
 244                add_timer(&pstore_timer);
 245        }
 246
 247        return 0;
 248}
 249EXPORT_SYMBOL_GPL(pstore_register);
 250
 251/*
 252 * Read all the records from the persistent store. Create
 253 * files in our filesystem.  Don't warn about -EEXIST errors
 254 * when we are re-scanning the backing store looking to add new
 255 * error records.
 256 */
 257void pstore_get_records(int quiet)
 258{
 259        struct pstore_info *psi = psinfo;
 260        char                    *buf = NULL;
 261        ssize_t                 size;
 262        u64                     id;
 263        enum pstore_type_id     type;
 264        struct timespec         time;
 265        int                     failed = 0, rc;
 266
 267        if (!psi)
 268                return;
 269
 270        mutex_lock(&psi->read_mutex);
 271        if (psi->open && psi->open(psi))
 272                goto out;
 273
 274        while ((size = psi->read(&id, &type, &time, &buf, psi)) > 0) {
 275                rc = pstore_mkfile(type, psi->name, id, buf, (size_t)size,
 276                                  time, psi);
 277                kfree(buf);
 278                buf = NULL;
 279                if (rc && (rc != -EEXIST || !quiet))
 280                        failed++;
 281        }
 282        if (psi->close)
 283                psi->close(psi);
 284out:
 285        mutex_unlock(&psi->read_mutex);
 286
 287        if (failed)
 288                printk(KERN_WARNING "pstore: failed to load %d record(s) from '%s'\n",
 289                       failed, psi->name);
 290}
 291
 292static void pstore_dowork(struct work_struct *work)
 293{
 294        pstore_get_records(1);
 295}
 296
 297static void pstore_timefunc(unsigned long dummy)
 298{
 299        if (pstore_new_entry) {
 300                pstore_new_entry = 0;
 301                schedule_work(&pstore_work);
 302        }
 303
 304        mod_timer(&pstore_timer, jiffies + msecs_to_jiffies(pstore_update_ms));
 305}
 306
 307module_param(backend, charp, 0444);
 308MODULE_PARM_DESC(backend, "Pstore backend to use");
 309
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.