x86/mce: Make mce_chrdev_ops 'static const'
Arjan would like to make struct file_operations const, but mce-inject directly writes to the mce_chrdev_ops to install its write handler. In an ideal world mce-inject would have its own character device, but we have a sizable legacy of test scripts that hardwire "/dev/mcelog", so it would be painful to switch to a separate device now. Instead, this patch switches to a stub function in the mce code, with a registration helper that mce-inject can call when it is loaded. Note that this would also allow for a sane process to allow mce-inject to be unloaded again (with an unregister function, and appropriate module_{get,put}() calls), but that is left for potential future patches. Reported-by: Arjan van de Ven <arjan@linux.intel.com> Signed-off-by: Tony Luck <tony.luck@intel.com> Link: http://lkml.kernel.org/r/4eb2e1971326651a3b@agluck-desktop.sc.intel.com Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
@ -201,7 +201,10 @@ int mce_notify_irq(void);
|
|||||||
void mce_notify_process(void);
|
void mce_notify_process(void);
|
||||||
|
|
||||||
DECLARE_PER_CPU(struct mce, injectm);
|
DECLARE_PER_CPU(struct mce, injectm);
|
||||||
extern struct file_operations mce_chrdev_ops;
|
|
||||||
|
extern void register_mce_write_callback(ssize_t (*)(struct file *filp,
|
||||||
|
const char __user *ubuf,
|
||||||
|
size_t usize, loff_t *off));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exception handler
|
* Exception handler
|
||||||
|
@ -208,7 +208,7 @@ static int inject_init(void)
|
|||||||
if (!alloc_cpumask_var(&mce_inject_cpumask, GFP_KERNEL))
|
if (!alloc_cpumask_var(&mce_inject_cpumask, GFP_KERNEL))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
printk(KERN_INFO "Machine check injector initialized\n");
|
printk(KERN_INFO "Machine check injector initialized\n");
|
||||||
mce_chrdev_ops.write = mce_write;
|
register_mce_write_callback(mce_write);
|
||||||
register_nmi_handler(NMI_LOCAL, mce_raise_notify, 0,
|
register_nmi_handler(NMI_LOCAL, mce_raise_notify, 0,
|
||||||
"mce_notify");
|
"mce_notify");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1634,16 +1634,35 @@ static long mce_chrdev_ioctl(struct file *f, unsigned int cmd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Modified in mce-inject.c, so not static or const */
|
static ssize_t (*mce_write)(struct file *filp, const char __user *ubuf,
|
||||||
struct file_operations mce_chrdev_ops = {
|
size_t usize, loff_t *off);
|
||||||
|
|
||||||
|
void register_mce_write_callback(ssize_t (*fn)(struct file *filp,
|
||||||
|
const char __user *ubuf,
|
||||||
|
size_t usize, loff_t *off))
|
||||||
|
{
|
||||||
|
mce_write = fn;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(register_mce_write_callback);
|
||||||
|
|
||||||
|
ssize_t mce_chrdev_write(struct file *filp, const char __user *ubuf,
|
||||||
|
size_t usize, loff_t *off)
|
||||||
|
{
|
||||||
|
if (mce_write)
|
||||||
|
return mce_write(filp, ubuf, usize, off);
|
||||||
|
else
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations mce_chrdev_ops = {
|
||||||
.open = mce_chrdev_open,
|
.open = mce_chrdev_open,
|
||||||
.release = mce_chrdev_release,
|
.release = mce_chrdev_release,
|
||||||
.read = mce_chrdev_read,
|
.read = mce_chrdev_read,
|
||||||
|
.write = mce_chrdev_write,
|
||||||
.poll = mce_chrdev_poll,
|
.poll = mce_chrdev_poll,
|
||||||
.unlocked_ioctl = mce_chrdev_ioctl,
|
.unlocked_ioctl = mce_chrdev_ioctl,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(mce_chrdev_ops);
|
|
||||||
|
|
||||||
static struct miscdevice mce_chrdev_device = {
|
static struct miscdevice mce_chrdev_device = {
|
||||||
MISC_MCELOG_MINOR,
|
MISC_MCELOG_MINOR,
|
||||||
|
Reference in New Issue
Block a user