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
  99bool pstore_cannot_block_path(enum kmsg_dump_reason reason)
 100{
 101        /*
 102         * In case of NMI path, pstore shouldn't be blocked
 103         * regardless of reason.
 104         */
 105        if (in_nmi())
 106                return true;
 107
 108        switch (reason) {
 109        /* In panic case, other cpus are stopped by smp_send_stop(). */
 110        case KMSG_DUMP_PANIC:
 111        /* Emergency restart shouldn't be blocked by spin lock. */
 112        case KMSG_DUMP_EMERG:
 113                return true;
 114        default:
 115                return false;
 116        }
 117}
 118EXPORT_SYMBOL_GPL(pstore_cannot_block_path);
 119
 120/*
 121 * callback from kmsg_dump. (s2,l2) has the most recently
 122 * written bytes, older bytes are in (s1,l1). Save as much
 123 * as we can from the end of the buffer.
 124 */
 125static void pstore_dump(struct kmsg_dumper *dumper,
 126                        enum kmsg_dump_reason reason)
 127{
 128        unsigned long   total = 0;
 129        const char      *why;
 130        u64             id;
 131        unsigned int    part = 1;
 132        unsigned long   flags = 0;
 133        int             is_locked = 0;
 134        int             ret;
 135
 136        why = get_reason_str(reason);
 137
 138        if (pstore_cannot_block_path(reason)) {
 139                is_locked = spin_trylock_irqsave(&psinfo->buf_lock, flags);
 140                if (!is_locked) {
 141                        pr_err("pstore dump routine blocked in %s path, may corrupt error record\n"
 142                                       , in_nmi() ? "NMI" : why);
 143                }
 144        } else
 145                spin_lock_irqsave(&psinfo->buf_lock, flags);
 146        oopscount++;
 147        while (total < kmsg_bytes) {
 148                char *dst;
 149                unsigned long size;
 150                int hsize;
 151                size_t len;
 152
 153                dst = psinfo->buf;
 154                hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part);
 155                size = psinfo->bufsize - hsize;
 156                dst += hsize;
 157
 158                if (!kmsg_dump_get_buffer(dumper, true, dst, size, &len))
 159                        break;
 160
 161                ret = psinfo->write(PSTORE_TYPE_DMESG, reason, &id, part,
 162                                    oopscount, hsize + len, psinfo);
 163                if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted())
 164                        pstore_new_entry = 1;
 165
 166                total += hsize + len;
 167                part++;
 168        }
 169        if (pstore_cannot_block_path(reason)) {
 170                if (is_locked)
 171                        spin_unlock_irqrestore(&psinfo->buf_lock, flags);
 172        } else
 173                spin_unlock_irqrestore(&psinfo->buf_lock, flags);
 174}
 175
 176static struct kmsg_dumper pstore_dumper = {
 177        .dump = pstore_dump,
 178};
 179
 180#ifdef CONFIG_PSTORE_CONSOLE
 181static void pstore_console_write(struct console *con, const char *s, unsigned c)
 182{
 183        const char *e = s + c;
 184
 185        while (s < e) {
 186                unsigned long flags;
 187                u64 id;
 188
 189                if (c > psinfo->bufsize)
 190                        c = psinfo->bufsize;
 191
 192                if (oops_in_progress) {
 193                        if (!spin_trylock_irqsave(&psinfo->buf_lock, flags))
 194                                break;
 195                } else {
 196                        spin_lock_irqsave(&psinfo->buf_lock, flags);
 197                }
 198                memcpy(psinfo->buf, s, c);
 199                psinfo->write(PSTORE_TYPE_CONSOLE, 0, &id, 0, 0, c, psinfo);
 200                spin_unlock_irqrestore(&psinfo->buf_lock, flags);
 201                s += c;
 202                c = e - s;
 203        }
 204}
 205
 206static struct console pstore_console = {
 207        .name   = "pstore",
 208        .write  = pstore_console_write,
 209        .flags  = CON_PRINTBUFFER | CON_ENABLED | CON_ANYTIME,
 210        .index  = -1,
 211};
 212
 213static void pstore_register_console(void)
 214{
 215        register_console(&pstore_console);
 216}
 217#else
 218static void pstore_register_console(void) {}
 219#endif
 220
 221static int pstore_write_compat(enum pstore_type_id type,
 222                               enum kmsg_dump_reason reason,
 223                               u64 *id, unsigned int part, int count,
 224                               size_t size, struct pstore_info *psi)
 225{
 226        return psi->write_buf(type, reason, id, part, psinfo->buf, size, psi);
 227}
 228
 229/*
 230 * platform specific persistent storage driver registers with
 231 * us here. If pstore is already mounted, call the platform
 232 * read function right away to populate the file system. If not
 233 * then the pstore mount code will call us later to fill out
 234 * the file system.
 235 *
 236 * Register with kmsg_dump to save last part of console log on panic.
 237 */
 238int pstore_register(struct pstore_info *psi)
 239{
 240        struct module *owner = psi->owner;
 241
 242        spin_lock(&pstore_lock);
 243        if (psinfo) {
 244                spin_unlock(&pstore_lock);
 245                return -EBUSY;
 246        }
 247
 248        if (backend && strcmp(backend, psi->name)) {
 249                spin_unlock(&pstore_lock);
 250                return -EINVAL;
 251        }
 252
 253        if (!psi->write)
 254                psi->write = pstore_write_compat;
 255        psinfo = psi;
 256        mutex_init(&psinfo->read_mutex);
 257        spin_unlock(&pstore_lock);
 258
 259        if (owner && !try_module_get(owner)) {
 260                psinfo = NULL;
 261                return -EINVAL;
 262        }
 263
 264        if (pstore_is_mounted())
 265                pstore_get_records(0);
 266
 267        kmsg_dump_register(&pstore_dumper);
 268        pstore_register_console();
 269        pstore_register_ftrace();
 270
 271        if (pstore_update_ms >= 0) {
 272                pstore_timer.expires = jiffies +
 273                        msecs_to_jiffies(pstore_update_ms);
 274                add_timer(&pstore_timer);
 275        }
 276
 277        return 0;
 278}
 279EXPORT_SYMBOL_GPL(pstore_register);
 280
 281/*
 282 * Read all the records from the persistent store. Create
 283 * files in our filesystem.  Don't warn about -EEXIST errors
 284 * when we are re-scanning the backing store looking to add new
 285 * error records.
 286 */
 287void pstore_get_records(int quiet)
 288{
 289        struct pstore_info *psi = psinfo;
 290        char                    *buf = NULL;
 291        ssize_t                 size;
 292        u64                     id;
 293        int                     count;
 294        enum pstore_type_id     type;
 295        struct timespec         time;
 296        int                     failed = 0, rc;
 297
 298        if (!psi)
 299                return;
 300
 301        mutex_lock(&psi->read_mutex);
 302        if (psi->open && psi->open(psi))
 303                goto out;
 304
 305        while ((size = psi->read(&id, &type, &count, &time, &buf, psi)) > 0) {
 306                rc = pstore_mkfile(type, psi->name, id, count, buf,
 307                                  (size_t)size, time, psi);
 308                kfree(buf);
 309                buf = NULL;
 310                if (rc && (rc != -EEXIST || !quiet))
 311                        failed++;
 312        }
 313        if (psi->close)
 314                psi->close(psi);
 315out:
 316        mutex_unlock(&psi->read_mutex);
 317
 318        if (failed)
 319                printk(KERN_WARNING "pstore: failed to load %d record(s) from '%s'\n",
 320                       failed, psi->name);
 321}
 322
 323static void pstore_dowork(struct work_struct *work)
 324{
 325        pstore_get_records(1);
 326}
 327
 328static void pstore_timefunc(unsigned long dummy)
 329{
 330        if (pstore_new_entry) {
 331                pstore_new_entry = 0;
 332                schedule_work(&pstore_work);
 333        }
 334
 335        mod_timer(&pstore_timer, jiffies + msecs_to_jiffies(pstore_update_ms));
 336}
 337
 338module_param(backend, charp, 0444);
 339MODULE_PARM_DESC(backend, "Pstore backend to use");
 340
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.