linux/fs/pstore/pmsg.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright 2014  Google, Inc.
   4 */
   5
   6#include <linux/cdev.h>
   7#include <linux/device.h>
   8#include <linux/fs.h>
   9#include <linux/uaccess.h>
  10#include "internal.h"
  11
  12static DEFINE_MUTEX(pmsg_lock);
  13
  14static ssize_t write_pmsg(struct file *file, const char __user *buf,
  15                          size_t count, loff_t *ppos)
  16{
  17        struct pstore_record record;
  18        int ret;
  19
  20        if (!count)
  21                return 0;
  22
  23        pstore_record_init(&record, psinfo);
  24        record.type = PSTORE_TYPE_PMSG;
  25        record.size = count;
  26
  27        /* check outside lock, page in any data. write_user also checks */
  28        if (!access_ok(buf, count))
  29                return -EFAULT;
  30
  31        mutex_lock(&pmsg_lock);
  32        ret = psinfo->write_user(&record, buf);
  33        mutex_unlock(&pmsg_lock);
  34        return ret ? ret : count;
  35}
  36
  37static const struct file_operations pmsg_fops = {
  38        .owner          = THIS_MODULE,
  39        .llseek         = noop_llseek,
  40        .write          = write_pmsg,
  41};
  42
  43static struct class *pmsg_class;
  44static int pmsg_major;
  45#define PMSG_NAME "pmsg"
  46#undef pr_fmt
  47#define pr_fmt(fmt) PMSG_NAME ": " fmt
  48
  49static char *pmsg_devnode(struct device *dev, umode_t *mode)
  50{
  51        if (mode)
  52                *mode = 0220;
  53        return NULL;
  54}
  55
  56void pstore_register_pmsg(void)
  57{
  58        struct device *pmsg_device;
  59
  60        pmsg_major = register_chrdev(0, PMSG_NAME, &pmsg_fops);
  61        if (pmsg_major < 0) {
  62                pr_err("register_chrdev failed\n");
  63                goto err;
  64        }
  65
  66        pmsg_class = class_create(THIS_MODULE, PMSG_NAME);
  67        if (IS_ERR(pmsg_class)) {
  68                pr_err("device class file already in use\n");
  69                goto err_class;
  70        }
  71        pmsg_class->devnode = pmsg_devnode;
  72
  73        pmsg_device = device_create(pmsg_class, NULL, MKDEV(pmsg_major, 0),
  74                                        NULL, "%s%d", PMSG_NAME, 0);
  75        if (IS_ERR(pmsg_device)) {
  76                pr_err("failed to create device\n");
  77                goto err_device;
  78        }
  79        return;
  80
  81err_device:
  82        class_destroy(pmsg_class);
  83err_class:
  84        unregister_chrdev(pmsg_major, PMSG_NAME);
  85err:
  86        return;
  87}
  88
  89void pstore_unregister_pmsg(void)
  90{
  91        device_destroy(pmsg_class, MKDEV(pmsg_major, 0));
  92        class_destroy(pmsg_class);
  93        unregister_chrdev(pmsg_major, PMSG_NAME);
  94}
  95