linux/fs/pstore/inode.c
<<
>>
Prefs
   1/*
   2 * Persistent Storage - ramfs parts.
   3 *
   4 * Copyright (C) 2010 Intel Corporation <tony.luck@intel.com>
   5 *
   6 *  This program is free software; you can redistribute it and/or modify
   7 *  it under the terms of the GNU General Public License version 2 as
   8 *  published by the Free Software Foundation.
   9 *
  10 *  This program is distributed in the hope that it will be useful,
  11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 *  GNU General Public License for more details.
  14 *
  15 *  You should have received a copy of the GNU General Public License
  16 *  along with this program; if not, write to the Free Software
  17 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18 */
  19
  20#include <linux/module.h>
  21#include <linux/fs.h>
  22#include <linux/fsnotify.h>
  23#include <linux/pagemap.h>
  24#include <linux/highmem.h>
  25#include <linux/time.h>
  26#include <linux/init.h>
  27#include <linux/list.h>
  28#include <linux/string.h>
  29#include <linux/mount.h>
  30#include <linux/seq_file.h>
  31#include <linux/ramfs.h>
  32#include <linux/parser.h>
  33#include <linux/sched.h>
  34#include <linux/magic.h>
  35#include <linux/pstore.h>
  36#include <linux/slab.h>
  37#include <linux/spinlock.h>
  38#include <linux/uaccess.h>
  39
  40#include "internal.h"
  41
  42#define PSTORE_NAMELEN  64
  43
  44static DEFINE_SPINLOCK(allpstore_lock);
  45static LIST_HEAD(allpstore);
  46
  47struct pstore_private {
  48        struct list_head list;
  49        struct pstore_record *record;
  50        size_t total_size;
  51};
  52
  53struct pstore_ftrace_seq_data {
  54        const void *ptr;
  55        size_t off;
  56        size_t size;
  57};
  58
  59#define REC_SIZE sizeof(struct pstore_ftrace_record)
  60
  61static void free_pstore_private(struct pstore_private *private)
  62{
  63        if (!private)
  64                return;
  65        if (private->record) {
  66                kfree(private->record->buf);
  67                kfree(private->record);
  68        }
  69        kfree(private);
  70}
  71
  72static void *pstore_ftrace_seq_start(struct seq_file *s, loff_t *pos)
  73{
  74        struct pstore_private *ps = s->private;
  75        struct pstore_ftrace_seq_data *data;
  76
  77        data = kzalloc(sizeof(*data), GFP_KERNEL);
  78        if (!data)
  79                return NULL;
  80
  81        data->off = ps->total_size % REC_SIZE;
  82        data->off += *pos * REC_SIZE;
  83        if (data->off + REC_SIZE > ps->total_size) {
  84                kfree(data);
  85                return NULL;
  86        }
  87
  88        return data;
  89
  90}
  91
  92static void pstore_ftrace_seq_stop(struct seq_file *s, void *v)
  93{
  94        kfree(v);
  95}
  96
  97static void *pstore_ftrace_seq_next(struct seq_file *s, void *v, loff_t *pos)
  98{
  99        struct pstore_private *ps = s->private;
 100        struct pstore_ftrace_seq_data *data = v;
 101
 102        data->off += REC_SIZE;
 103        if (data->off + REC_SIZE > ps->total_size)
 104                return NULL;
 105
 106        (*pos)++;
 107        return data;
 108}
 109
 110static int pstore_ftrace_seq_show(struct seq_file *s, void *v)
 111{
 112        struct pstore_private *ps = s->private;
 113        struct pstore_ftrace_seq_data *data = v;
 114        struct pstore_ftrace_record *rec;
 115
 116        rec = (struct pstore_ftrace_record *)(ps->record->buf + data->off);
 117
 118        seq_printf(s, "CPU:%d ts:%llu %08lx  %08lx  %ps <- %pS\n",
 119                   pstore_ftrace_decode_cpu(rec),
 120                   pstore_ftrace_read_timestamp(rec),
 121                   rec->ip, rec->parent_ip, (void *)rec->ip,
 122                   (void *)rec->parent_ip);
 123
 124        return 0;
 125}
 126
 127static const struct seq_operations pstore_ftrace_seq_ops = {
 128        .start  = pstore_ftrace_seq_start,
 129        .next   = pstore_ftrace_seq_next,
 130        .stop   = pstore_ftrace_seq_stop,
 131        .show   = pstore_ftrace_seq_show,
 132};
 133
 134static ssize_t pstore_file_read(struct file *file, char __user *userbuf,
 135                                                size_t count, loff_t *ppos)
 136{
 137        struct seq_file *sf = file->private_data;
 138        struct pstore_private *ps = sf->private;
 139
 140        if (ps->record->type == PSTORE_TYPE_FTRACE)
 141                return seq_read(file, userbuf, count, ppos);
 142        return simple_read_from_buffer(userbuf, count, ppos,
 143                                       ps->record->buf, ps->total_size);
 144}
 145
 146static int pstore_file_open(struct inode *inode, struct file *file)
 147{
 148        struct pstore_private *ps = inode->i_private;
 149        struct seq_file *sf;
 150        int err;
 151        const struct seq_operations *sops = NULL;
 152
 153        if (ps->record->type == PSTORE_TYPE_FTRACE)
 154                sops = &pstore_ftrace_seq_ops;
 155
 156        err = seq_open(file, sops);
 157        if (err < 0)
 158                return err;
 159
 160        sf = file->private_data;
 161        sf->private = ps;
 162
 163        return 0;
 164}
 165
 166static loff_t pstore_file_llseek(struct file *file, loff_t off, int whence)
 167{
 168        struct seq_file *sf = file->private_data;
 169
 170        if (sf->op)
 171                return seq_lseek(file, off, whence);
 172        return default_llseek(file, off, whence);
 173}
 174
 175static const struct file_operations pstore_file_operations = {
 176        .open           = pstore_file_open,
 177        .read           = pstore_file_read,
 178        .llseek         = pstore_file_llseek,
 179        .release        = seq_release,
 180};
 181
 182/*
 183 * When a file is unlinked from our file system we call the
 184 * platform driver to erase the record from persistent store.
 185 */
 186static int pstore_unlink(struct inode *dir, struct dentry *dentry)
 187{
 188        struct pstore_private *p = d_inode(dentry)->i_private;
 189        struct pstore_record *record = p->record;
 190
 191        if (!record->psi->erase)
 192                return -EPERM;
 193
 194        mutex_lock(&record->psi->read_mutex);
 195        record->psi->erase(record);
 196        mutex_unlock(&record->psi->read_mutex);
 197
 198        return simple_unlink(dir, dentry);
 199}
 200
 201static void pstore_evict_inode(struct inode *inode)
 202{
 203        struct pstore_private   *p = inode->i_private;
 204        unsigned long           flags;
 205
 206        clear_inode(inode);
 207        if (p) {
 208                spin_lock_irqsave(&allpstore_lock, flags);
 209                list_del(&p->list);
 210                spin_unlock_irqrestore(&allpstore_lock, flags);
 211                free_pstore_private(p);
 212        }
 213}
 214
 215static const struct inode_operations pstore_dir_inode_operations = {
 216        .lookup         = simple_lookup,
 217        .unlink         = pstore_unlink,
 218};
 219
 220static struct inode *pstore_get_inode(struct super_block *sb)
 221{
 222        struct inode *inode = new_inode(sb);
 223        if (inode) {
 224                inode->i_ino = get_next_ino();
 225                inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
 226        }
 227        return inode;
 228}
 229
 230enum {
 231        Opt_kmsg_bytes, Opt_err
 232};
 233
 234static const match_table_t tokens = {
 235        {Opt_kmsg_bytes, "kmsg_bytes=%u"},
 236        {Opt_err, NULL}
 237};
 238
 239static void parse_options(char *options)
 240{
 241        char            *p;
 242        substring_t     args[MAX_OPT_ARGS];
 243        int             option;
 244
 245        if (!options)
 246                return;
 247
 248        while ((p = strsep(&options, ",")) != NULL) {
 249                int token;
 250
 251                if (!*p)
 252                        continue;
 253
 254                token = match_token(p, tokens, args);
 255                switch (token) {
 256                case Opt_kmsg_bytes:
 257                        if (!match_int(&args[0], &option))
 258                                pstore_set_kmsg_bytes(option);
 259                        break;
 260                }
 261        }
 262}
 263
 264/*
 265 * Display the mount options in /proc/mounts.
 266 */
 267static int pstore_show_options(struct seq_file *m, struct dentry *root)
 268{
 269        if (kmsg_bytes != PSTORE_DEFAULT_KMSG_BYTES)
 270                seq_printf(m, ",kmsg_bytes=%lu", kmsg_bytes);
 271        return 0;
 272}
 273
 274static int pstore_remount(struct super_block *sb, int *flags, char *data)
 275{
 276        sync_filesystem(sb);
 277        parse_options(data);
 278
 279        return 0;
 280}
 281
 282static const struct super_operations pstore_ops = {
 283        .statfs         = simple_statfs,
 284        .drop_inode     = generic_delete_inode,
 285        .evict_inode    = pstore_evict_inode,
 286        .remount_fs     = pstore_remount,
 287        .show_options   = pstore_show_options,
 288};
 289
 290static struct super_block *pstore_sb;
 291
 292bool pstore_is_mounted(void)
 293{
 294        return pstore_sb != NULL;
 295}
 296
 297/*
 298 * Make a regular file in the root directory of our file system.
 299 * Load it up with "size" bytes of data from "buf".
 300 * Set the mtime & ctime to the date that this record was originally stored.
 301 */
 302int pstore_mkfile(struct dentry *root, struct pstore_record *record)
 303{
 304        struct dentry           *dentry;
 305        struct inode            *inode;
 306        int                     rc = 0;
 307        char                    name[PSTORE_NAMELEN];
 308        struct pstore_private   *private, *pos;
 309        unsigned long           flags;
 310        size_t                  size = record->size + record->ecc_notice_size;
 311
 312        WARN_ON(!inode_is_locked(d_inode(root)));
 313
 314        spin_lock_irqsave(&allpstore_lock, flags);
 315        list_for_each_entry(pos, &allpstore, list) {
 316                if (pos->record->type == record->type &&
 317                    pos->record->id == record->id &&
 318                    pos->record->psi == record->psi) {
 319                        rc = -EEXIST;
 320                        break;
 321                }
 322        }
 323        spin_unlock_irqrestore(&allpstore_lock, flags);
 324        if (rc)
 325                return rc;
 326
 327        rc = -ENOMEM;
 328        inode = pstore_get_inode(root->d_sb);
 329        if (!inode)
 330                goto fail;
 331        inode->i_mode = S_IFREG | 0444;
 332        inode->i_fop = &pstore_file_operations;
 333        private = kzalloc(sizeof(*private), GFP_KERNEL);
 334        if (!private)
 335                goto fail_alloc;
 336        private->record = record;
 337
 338        switch (record->type) {
 339        case PSTORE_TYPE_DMESG:
 340                scnprintf(name, sizeof(name), "dmesg-%s-%llu%s",
 341                          record->psi->name, record->id,
 342                          record->compressed ? ".enc.z" : "");
 343                break;
 344        case PSTORE_TYPE_CONSOLE:
 345                scnprintf(name, sizeof(name), "console-%s-%llu",
 346                          record->psi->name, record->id);
 347                break;
 348        case PSTORE_TYPE_FTRACE:
 349                scnprintf(name, sizeof(name), "ftrace-%s-%llu",
 350                          record->psi->name, record->id);
 351                break;
 352        case PSTORE_TYPE_MCE:
 353                scnprintf(name, sizeof(name), "mce-%s-%llu",
 354                          record->psi->name, record->id);
 355                break;
 356        case PSTORE_TYPE_PPC_RTAS:
 357                scnprintf(name, sizeof(name), "rtas-%s-%llu",
 358                          record->psi->name, record->id);
 359                break;
 360        case PSTORE_TYPE_PPC_OF:
 361                scnprintf(name, sizeof(name), "powerpc-ofw-%s-%llu",
 362                          record->psi->name, record->id);
 363                break;
 364        case PSTORE_TYPE_PPC_COMMON:
 365                scnprintf(name, sizeof(name), "powerpc-common-%s-%llu",
 366                          record->psi->name, record->id);
 367                break;
 368        case PSTORE_TYPE_PMSG:
 369                scnprintf(name, sizeof(name), "pmsg-%s-%llu",
 370                          record->psi->name, record->id);
 371                break;
 372        case PSTORE_TYPE_PPC_OPAL:
 373                scnprintf(name, sizeof(name), "powerpc-opal-%s-%llu",
 374                          record->psi->name, record->id);
 375                break;
 376        case PSTORE_TYPE_UNKNOWN:
 377                scnprintf(name, sizeof(name), "unknown-%s-%llu",
 378                          record->psi->name, record->id);
 379                break;
 380        default:
 381                scnprintf(name, sizeof(name), "type%d-%s-%llu",
 382                          record->type, record->psi->name, record->id);
 383                break;
 384        }
 385
 386        dentry = d_alloc_name(root, name);
 387        if (!dentry)
 388                goto fail_private;
 389
 390        inode->i_size = private->total_size = size;
 391
 392        inode->i_private = private;
 393
 394        if (record->time.tv_sec)
 395                inode->i_mtime = inode->i_ctime = record->time;
 396
 397        d_add(dentry, inode);
 398
 399        spin_lock_irqsave(&allpstore_lock, flags);
 400        list_add(&private->list, &allpstore);
 401        spin_unlock_irqrestore(&allpstore_lock, flags);
 402
 403        return 0;
 404
 405fail_private:
 406        free_pstore_private(private);
 407fail_alloc:
 408        iput(inode);
 409
 410fail:
 411        return rc;
 412}
 413
 414/*
 415 * Read all the records from the persistent store. Create
 416 * files in our filesystem.  Don't warn about -EEXIST errors
 417 * when we are re-scanning the backing store looking to add new
 418 * error records.
 419 */
 420void pstore_get_records(int quiet)
 421{
 422        struct pstore_info *psi = psinfo;
 423        struct dentry *root;
 424
 425        if (!psi || !pstore_sb)
 426                return;
 427
 428        root = pstore_sb->s_root;
 429
 430        inode_lock(d_inode(root));
 431        pstore_get_backend_records(psi, root, quiet);
 432        inode_unlock(d_inode(root));
 433}
 434
 435static int pstore_fill_super(struct super_block *sb, void *data, int silent)
 436{
 437        struct inode *inode;
 438
 439        pstore_sb = sb;
 440
 441        sb->s_maxbytes          = MAX_LFS_FILESIZE;
 442        sb->s_blocksize         = PAGE_SIZE;
 443        sb->s_blocksize_bits    = PAGE_SHIFT;
 444        sb->s_magic             = PSTOREFS_MAGIC;
 445        sb->s_op                = &pstore_ops;
 446        sb->s_time_gran         = 1;
 447
 448        parse_options(data);
 449
 450        inode = pstore_get_inode(sb);
 451        if (inode) {
 452                inode->i_mode = S_IFDIR | 0750;
 453                inode->i_op = &pstore_dir_inode_operations;
 454                inode->i_fop = &simple_dir_operations;
 455                inc_nlink(inode);
 456        }
 457        sb->s_root = d_make_root(inode);
 458        if (!sb->s_root)
 459                return -ENOMEM;
 460
 461        pstore_get_records(0);
 462
 463        return 0;
 464}
 465
 466static struct dentry *pstore_mount(struct file_system_type *fs_type,
 467        int flags, const char *dev_name, void *data)
 468{
 469        return mount_single(fs_type, flags, data, pstore_fill_super);
 470}
 471
 472static void pstore_kill_sb(struct super_block *sb)
 473{
 474        kill_litter_super(sb);
 475        pstore_sb = NULL;
 476}
 477
 478static struct file_system_type pstore_fs_type = {
 479        .owner          = THIS_MODULE,
 480        .name           = "pstore",
 481        .mount          = pstore_mount,
 482        .kill_sb        = pstore_kill_sb,
 483};
 484
 485static int __init init_pstore_fs(void)
 486{
 487        int err;
 488
 489        pstore_choose_compression();
 490
 491        /* Create a convenient mount point for people to access pstore */
 492        err = sysfs_create_mount_point(fs_kobj, "pstore");
 493        if (err)
 494                goto out;
 495
 496        err = register_filesystem(&pstore_fs_type);
 497        if (err < 0)
 498                sysfs_remove_mount_point(fs_kobj, "pstore");
 499
 500out:
 501        return err;
 502}
 503module_init(init_pstore_fs)
 504
 505static void __exit exit_pstore_fs(void)
 506{
 507        unregister_filesystem(&pstore_fs_type);
 508        sysfs_remove_mount_point(fs_kobj, "pstore");
 509}
 510module_exit(exit_pstore_fs)
 511
 512MODULE_AUTHOR("Tony Luck <tony.luck@intel.com>");
 513MODULE_LICENSE("GPL");
 514