]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/x86_64/kernel/mce.c
x86_64: O_EXCL on /dev/mcelog
[linux-2.6-omap-h63xx.git] / arch / x86_64 / kernel / mce.c
index a14375dd54252d1ca6405e1f28a4e7246ae3cbbe..77fee481be4fbcdb456fb83c6ea9aeaae58fb84b 100644 (file)
@@ -174,7 +174,7 @@ static void do_mce_trigger(void)
        if (events != atomic_read(&mce_logged) && trigger[0]) {
                /* Small race window, but should be harmless.  */
                atomic_set(&mce_logged, events);
-               call_usermodehelper(trigger, trigger_argv, NULL, -1);
+               call_usermodehelper(trigger, trigger_argv, NULL, UMH_NO_WAIT);
        }
 }
 
@@ -465,6 +465,40 @@ void __cpuinit mcheck_init(struct cpuinfo_x86 *c)
  * Character device 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 int mce_open(struct inode *inode, struct file *file)
+{
+       spin_lock(&mce_state_lock);
+
+       if (open_exclu || (open_count && (file->f_flags & O_EXCL))) {
+               spin_unlock(&mce_state_lock);
+               return -EBUSY;
+       }
+
+       if (file->f_flags & O_EXCL)
+               open_exclu = 1;
+       open_count++;
+
+       spin_unlock(&mce_state_lock);
+
+       return 0;
+}
+
+static int mce_release(struct inode *inode, struct file *file)
+{
+       spin_lock(&mce_state_lock);
+
+       open_count--;
+       open_exclu = 0;
+
+       spin_unlock(&mce_state_lock);
+
+       return 0;
+}
+
 static void collect_tscs(void *data) 
 { 
        unsigned long *cpu_tsc = (unsigned long *)data;
@@ -497,15 +531,17 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, loff
        for (i = 0; i < next; i++) {            
                unsigned long start = jiffies;
                while (!mcelog.entry[i].finished) {
-                       if (!time_before(jiffies, start + 2)) {
+                       if (time_after_eq(jiffies, start + 2)) {
                                memset(mcelog.entry + i,0, sizeof(struct mce));
-                               continue;
+                               goto timeout;
                        }
                        cpu_relax();
                }
                smp_rmb();
                err |= copy_to_user(buf, mcelog.entry + i, sizeof(struct mce));
                buf += sizeof(struct mce); 
+ timeout:
+               ;
        } 
 
        memset(mcelog.entry, 0, next * sizeof(struct mce));
@@ -553,6 +589,8 @@ static int mce_ioctl(struct inode *i, struct file *f,unsigned int cmd, unsigned
 }
 
 static const struct file_operations mce_chrdev_ops = {
+       .open = mce_open,
+       .release = mce_release,
        .read = mce_read,
        .ioctl = mce_ioctl,
 };