cregit-Linux how code gets into the kernel

Release 4.11 drivers/acpi/apei/erst-dbg.c

/*
 * APEI Error Record Serialization Table debug support
 *
 * ERST is a way provided by APEI to save and retrieve hardware error
 * information to and from a persistent store. This file provide the
 * debugging/testing support for ERST kernel support and firmware
 * implementation.
 *
 * Copyright 2010 Intel Corp.
 *   Author: Huang Ying <ying.huang@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.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#include <acpi/apei.h>
#include <linux/miscdevice.h>

#include "apei-internal.h"


#define ERST_DBG_PFX			"ERST DBG: "


#define ERST_DBG_RECORD_LEN_MAX		0x4000


static void *erst_dbg_buf;

static unsigned int erst_dbg_buf_len;

/* Prevent erst_dbg_read/write from being invoked concurrently */
static DEFINE_MUTEX(erst_dbg_mutex);


static int erst_dbg_open(struct inode *inode, struct file *file) { int rc, *pos; if (erst_disable) return -ENODEV; pos = (int *)&file->private_data; rc = erst_get_record_id_begin(pos); if (rc) return rc; return nonseekable_open(inode, file); }

Contributors

PersonTokensPropCommitsCommitProp
Huang Ying63100.00%2100.00%
Total63100.00%2100.00%


static int erst_dbg_release(struct inode *inode, struct file *file) { erst_get_record_id_end(); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Huang Ying22100.00%1100.00%
Total22100.00%1100.00%


static long erst_dbg_ioctl(struct file *f, unsigned int cmd, unsigned long arg) { int rc; u64 record_id; u32 record_count; switch (cmd) { case APEI_ERST_CLEAR_RECORD: rc = copy_from_user(&record_id, (void __user *)arg, sizeof(record_id)); if (rc) return -EFAULT; return erst_clear(record_id); case APEI_ERST_GET_RECORD_COUNT: rc = erst_get_record_count(); if (rc < 0) return rc; record_count = rc; rc = put_user(record_count, (u32 __user *)arg); if (rc) return rc; return 0; default: return -ENOTTY; } }

Contributors

PersonTokensPropCommitsCommitProp
Huang Ying121100.00%1100.00%
Total121100.00%1100.00%


static ssize_t erst_dbg_read(struct file *filp, char __user *ubuf, size_t usize, loff_t *off) { int rc, *pos; ssize_t len = 0; u64 id; if (*off) return -EINVAL; if (mutex_lock_interruptible(&erst_dbg_mutex) != 0) return -EINTR; pos = (int *)&filp->private_data; retry_next: rc = erst_get_record_id_next(pos, &id); if (rc) goto out; /* no more record */ if (id == APEI_ERST_INVALID_RECORD_ID) { /* * If the persistent store is empty initially, the function * 'erst_read' below will return "-ENOENT" value. This causes * 'retry_next' label is entered again. The returned value * should be zero indicating the read operation is EOF. */ len = 0; goto out; } retry: rc = len = erst_read(id, erst_dbg_buf, erst_dbg_buf_len); /* The record may be cleared by others, try read next record */ if (rc == -ENOENT) goto retry_next; if (rc < 0) goto out; if (len > ERST_DBG_RECORD_LEN_MAX) { pr_warning(ERST_DBG_PFX "Record (ID: 0x%llx) length is too long: %zd\n", id, len); rc = -EIO; goto out; } if (len > erst_dbg_buf_len) { void *p; rc = -ENOMEM; p = kmalloc(len, GFP_KERNEL); if (!p) goto out; kfree(erst_dbg_buf); erst_dbg_buf = p; erst_dbg_buf_len = len; goto retry; } rc = -EINVAL; if (len > usize) goto out; rc = -EFAULT; if (copy_to_user(ubuf, erst_dbg_buf, len)) goto out; rc = 0; out: mutex_unlock(&erst_dbg_mutex); return rc ? rc : len; }

Contributors

PersonTokensPropCommitsCommitProp
Huang Ying26397.41%375.00%
Adrian Huang72.59%125.00%
Total270100.00%4100.00%


static ssize_t erst_dbg_write(struct file *filp, const char __user *ubuf, size_t usize, loff_t *off) { int rc; struct cper_record_header *rcd; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (usize > ERST_DBG_RECORD_LEN_MAX) { pr_err(ERST_DBG_PFX "Too long record to be written\n"); return -EINVAL; } if (mutex_lock_interruptible(&erst_dbg_mutex)) return -EINTR; if (usize > erst_dbg_buf_len) { void *p; rc = -ENOMEM; p = kmalloc(usize, GFP_KERNEL); if (!p) goto out; kfree(erst_dbg_buf); erst_dbg_buf = p; erst_dbg_buf_len = usize; } rc = copy_from_user(erst_dbg_buf, ubuf, usize); if (rc) { rc = -EFAULT; goto out; } rcd = erst_dbg_buf; rc = -EINVAL; if (rcd->record_length != usize) goto out; rc = erst_write(erst_dbg_buf); out: mutex_unlock(&erst_dbg_mutex); return rc < 0 ? rc : usize; }

Contributors

PersonTokensPropCommitsCommitProp
Huang Ying190100.00%2100.00%
Total190100.00%2100.00%

static const struct file_operations erst_dbg_ops = { .owner = THIS_MODULE, .open = erst_dbg_open, .release = erst_dbg_release, .read = erst_dbg_read, .write = erst_dbg_write, .unlocked_ioctl = erst_dbg_ioctl, .llseek = no_llseek, }; static struct miscdevice erst_dbg_dev = { .minor = MISC_DYNAMIC_MINOR, .name = "erst_dbg", .fops = &erst_dbg_ops, };
static __init int erst_dbg_init(void) { if (erst_disable) { pr_info(ERST_DBG_PFX "ERST support is disabled.\n"); return -ENODEV; } return misc_register(&erst_dbg_dev); }

Contributors

PersonTokensPropCommitsCommitProp
Huang Ying32100.00%2100.00%
Total32100.00%2100.00%


static __exit void erst_dbg_exit(void) { misc_deregister(&erst_dbg_dev); kfree(erst_dbg_buf); }

Contributors

PersonTokensPropCommitsCommitProp
Huang Ying20100.00%1100.00%
Total20100.00%1100.00%

module_init(erst_dbg_init); module_exit(erst_dbg_exit); MODULE_AUTHOR("Huang Ying"); MODULE_DESCRIPTION("APEI Error Record Serialization Table debug support"); MODULE_LICENSE("GPL");

Overall Contributors

PersonTokensPropCommitsCommitProp
Huang Ying83998.36%450.00%
Adrian Huang70.82%112.50%
Arnd Bergmann50.59%112.50%
Jarkko Nikula10.12%112.50%
Chen Gong10.12%112.50%
Total853100.00%8100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.