Skip to content

Commit

Permalink
x86_64: O_EXCL on /dev/mcelog
Browse files Browse the repository at this point in the history
Background:
 /dev/mcelog is a clear-on-read interface.  It is currently possible for
 multiple users to open and read() the device.  Users are protected from
 each other during any one read, but not across reads.

Description:
 This patch adds support for O_EXCL to /dev/mcelog.  If a user opens the
 device with O_EXCL, no other user may open the device (EBUSY).  Likewise,
 any user that tries to open the device with O_EXCL while another user has
 the device will fail (EBUSY).

Result:
 Applications can get exclusive access to /dev/mcelog.  Applications that
 do not care will be unchanged.

Alternatives:
 A simpler choice would be to only allow one open() at all, regardless of
 O_EXCL.

Testing:
 I wrote an application that opens /dev/mcelog with O_EXCL and observed
 that any other app that tried to open /dev/mcelog would fail until the
 exclusive app had closed the device.

Caveats:
 None.

Signed-off-by: Tim Hockin <thockin@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Tim Hockin authored and Linus Torvalds committed Jul 22, 2007
1 parent a5ba797 commit f528e7b
Showing 1 changed file with 36 additions and 0 deletions.
36 changes: 36 additions & 0 deletions arch/x86_64/kernel/mce.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -555,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,
};
Expand Down

0 comments on commit f528e7b

Please sign in to comment.