Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 257253
b: refs/heads/master
c: 93b62c3
h: refs/heads/master
i:
  257251: 33ee776
v: v3
  • Loading branch information
Hidetoshi Seto authored and Borislav Petkov committed Jun 16, 2011
1 parent 8c86f68 commit c2ef0f3
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 37 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 559faa6be143b8aa7a07b12f618d29fbc1c8eb0d
refs/heads/master: 93b62c3cf59d44850cbe9f04d58da08930e3fb0b
77 changes: 41 additions & 36 deletions trunk/arch/x86/kernel/cpu/mcheck/mce.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@

#include "mce-internal.h"

static DEFINE_MUTEX(mce_read_mutex);
static DEFINE_MUTEX(mce_chrdev_read_mutex);

#define rcu_dereference_check_mce(p) \
rcu_dereference_index_check((p), \
rcu_read_lock_sched_held() || \
lockdep_is_held(&mce_read_mutex))
lockdep_is_held(&mce_chrdev_read_mutex))

#define CREATE_TRACE_POINTS
#include <trace/events/mce.h>
Expand Down Expand Up @@ -90,7 +90,8 @@ static unsigned long mce_need_notify;
static char mce_helper[128];
static char *mce_helper_argv[2] = { mce_helper, NULL };

static DECLARE_WAIT_QUEUE_HEAD(mce_wait);
static DECLARE_WAIT_QUEUE_HEAD(mce_chrdev_wait);

static DEFINE_PER_CPU(struct mce, mces_seen);
static int cpu_missing;

Expand Down Expand Up @@ -1159,7 +1160,8 @@ int mce_notify_irq(void)
clear_thread_flag(TIF_MCE_NOTIFY);

if (test_and_clear_bit(0, &mce_need_notify)) {
wake_up_interruptible(&mce_wait);
/* wake processes polling /dev/mcelog */
wake_up_interruptible(&mce_chrdev_wait);

/*
* There is no risk of missing notifications because
Expand Down Expand Up @@ -1423,40 +1425,41 @@ void __cpuinit mcheck_cpu_init(struct cpuinfo_x86 *c)
}

/*
* Character device to read and clear the MCE log.
* mce_chrdev: Character device /dev/mcelog to read and clear the MCE log.
*/

static DEFINE_SPINLOCK(mce_state_lock);
static int open_count; /* #times opened */
static int open_exclu; /* already open exclusive? */
static DEFINE_SPINLOCK(mce_chrdev_state_lock);
static int mce_chrdev_open_count; /* #times opened */
static int mce_chrdev_open_exclu; /* already open exclusive? */

static int mce_open(struct inode *inode, struct file *file)
static int mce_chrdev_open(struct inode *inode, struct file *file)
{
spin_lock(&mce_state_lock);
spin_lock(&mce_chrdev_state_lock);

if (open_exclu || (open_count && (file->f_flags & O_EXCL))) {
spin_unlock(&mce_state_lock);
if (mce_chrdev_open_exclu ||
(mce_chrdev_open_count && (file->f_flags & O_EXCL))) {
spin_unlock(&mce_chrdev_state_lock);

return -EBUSY;
}

if (file->f_flags & O_EXCL)
open_exclu = 1;
open_count++;
mce_chrdev_open_exclu = 1;
mce_chrdev_open_count++;

spin_unlock(&mce_state_lock);
spin_unlock(&mce_chrdev_state_lock);

return nonseekable_open(inode, file);
}

static int mce_release(struct inode *inode, struct file *file)
static int mce_chrdev_release(struct inode *inode, struct file *file)
{
spin_lock(&mce_state_lock);
spin_lock(&mce_chrdev_state_lock);

open_count--;
open_exclu = 0;
mce_chrdev_open_count--;
mce_chrdev_open_exclu = 0;

spin_unlock(&mce_state_lock);
spin_unlock(&mce_chrdev_state_lock);

return 0;
}
Expand Down Expand Up @@ -1505,8 +1508,8 @@ static int __mce_read_apei(char __user **ubuf, size_t usize)
return 0;
}

static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize,
loff_t *off)
static ssize_t mce_chrdev_read(struct file *filp, char __user *ubuf,
size_t usize, loff_t *off)
{
char __user *buf = ubuf;
unsigned long *cpu_tsc;
Expand All @@ -1517,7 +1520,7 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize,
if (!cpu_tsc)
return -ENOMEM;

mutex_lock(&mce_read_mutex);
mutex_lock(&mce_chrdev_read_mutex);

if (!mce_apei_read_done) {
err = __mce_read_apei(&buf, usize);
Expand Down Expand Up @@ -1582,23 +1585,24 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize,
err = -EFAULT;

out:
mutex_unlock(&mce_read_mutex);
mutex_unlock(&mce_chrdev_read_mutex);
kfree(cpu_tsc);

return err ? err : buf - ubuf;
}

static unsigned int mce_poll(struct file *file, poll_table *wait)
static unsigned int mce_chrdev_poll(struct file *file, poll_table *wait)
{
poll_wait(file, &mce_wait, wait);
poll_wait(file, &mce_chrdev_wait, wait);
if (rcu_access_index(mcelog.next))
return POLLIN | POLLRDNORM;
if (!mce_apei_read_done && apei_check_mce())
return POLLIN | POLLRDNORM;
return 0;
}

static long mce_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
static long mce_chrdev_ioctl(struct file *f, unsigned int cmd,
unsigned long arg)
{
int __user *p = (int __user *)arg;

Expand Down Expand Up @@ -1626,16 +1630,16 @@ static long mce_ioctl(struct file *f, unsigned int cmd, unsigned long arg)

/* Modified in mce-inject.c, so not static or const */
struct file_operations mce_chrdev_ops = {
.open = mce_open,
.release = mce_release,
.read = mce_read,
.poll = mce_poll,
.unlocked_ioctl = mce_ioctl,
.llseek = no_llseek,
.open = mce_chrdev_open,
.release = mce_chrdev_release,
.read = mce_chrdev_read,
.poll = mce_chrdev_poll,
.unlocked_ioctl = mce_chrdev_ioctl,
.llseek = no_llseek,
};
EXPORT_SYMBOL_GPL(mce_chrdev_ops);

static struct miscdevice mce_log_device = {
static struct miscdevice mce_chrdev_device = {
MISC_MCELOG_MINOR,
"mcelog",
&mce_chrdev_ops,
Expand Down Expand Up @@ -2107,11 +2111,12 @@ static __init int mcheck_init_device(void)

register_syscore_ops(&mce_syscore_ops);
register_hotcpu_notifier(&mce_cpu_notifier);
misc_register(&mce_log_device);

/* register character device /dev/mcelog */
misc_register(&mce_chrdev_device);

return err;
}

device_initcall(mcheck_init_device);

/*
Expand Down

0 comments on commit c2ef0f3

Please sign in to comment.