summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2010-05-07 14:27:06 +1000
committerStephen Rothwell <sfr@canb.auug.org.au>2010-05-07 14:27:06 +1000
commit699a982fb31962ccd338396fc6fa91e89753c639 (patch)
treeabd4afe687b1ccdda37d2b907d06ce1b136f48e9
parent30b013aefde4c1778d9975ef5ca4f80c50e4cd69 (diff)
parentd48af88be21a0f1e3217cda95e820aed88ae0bcb (diff)
Merge remote branch 'bkl-procfs/bkl/procfs'
-rw-r--r--drivers/char/i8k.c53
-rw-r--r--drivers/isdn/divert/divert_procfs.c90
-rw-r--r--fs/proc/base.c10
-rw-r--r--fs/proc/inode.c4
-rw-r--r--fs/proc/kcore.c1
-rw-r--r--fs/proc/kmsg.c1
-rw-r--r--fs/proc/vmcore.c1
-rw-r--r--net/sunrpc/cache.c18
8 files changed, 122 insertions, 56 deletions
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
index fc8cf7ac7f2b..85f8893ca08a 100644
--- a/drivers/char/i8k.c
+++ b/drivers/char/i8k.c
@@ -23,6 +23,7 @@
#include <linux/seq_file.h>
#include <linux/dmi.h>
#include <linux/capability.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -82,8 +83,7 @@ module_param(fan_mult, int, 0);
MODULE_PARM_DESC(fan_mult, "Factor to multiply fan speed with");
static int i8k_open_fs(struct inode *inode, struct file *file);
-static int i8k_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long);
+static long i8k_ioctl(struct file *, unsigned int, unsigned long);
static const struct file_operations i8k_fops = {
.owner = THIS_MODULE,
@@ -91,7 +91,7 @@ static const struct file_operations i8k_fops = {
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
- .ioctl = i8k_ioctl,
+ .unlocked_ioctl = i8k_ioctl,
};
struct smm_regs {
@@ -307,8 +307,7 @@ static int i8k_get_dell_signature(int req_fn)
return regs.eax == 1145651527 && regs.edx == 1145392204 ? 0 : -1;
}
-static int i8k_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
- unsigned long arg)
+static long i8k_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
{
int val = 0;
int speed;
@@ -318,6 +317,9 @@ static int i8k_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
if (!argp)
return -EINVAL;
+ /* Pushed down from procfs ioctl handler */
+ lock_kernel();
+
switch (cmd) {
case I8K_BIOS_VERSION:
val = i8k_get_bios_version();
@@ -341,57 +343,78 @@ static int i8k_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
break;
case I8K_GET_SPEED:
- if (copy_from_user(&val, argp, sizeof(int)))
+ if (copy_from_user(&val, argp, sizeof(int))) {
+ unlock_kernel();
return -EFAULT;
+ }
val = i8k_get_fan_speed(val);
break;
case I8K_GET_FAN:
- if (copy_from_user(&val, argp, sizeof(int)))
+ if (copy_from_user(&val, argp, sizeof(int))) {
+ unlock_kernel();
return -EFAULT;
+ }
val = i8k_get_fan_status(val);
break;
case I8K_SET_FAN:
- if (restricted && !capable(CAP_SYS_ADMIN))
+ if (restricted && !capable(CAP_SYS_ADMIN)) {
+ unlock_kernel();
return -EPERM;
+ }
- if (copy_from_user(&val, argp, sizeof(int)))
+ if (copy_from_user(&val, argp, sizeof(int))) {
+ unlock_kernel();
return -EFAULT;
+ }
- if (copy_from_user(&speed, argp + 1, sizeof(int)))
+ if (copy_from_user(&speed, argp + 1, sizeof(int))) {
+ unlock_kernel();
return -EFAULT;
+ }
val = i8k_set_fan(val, speed);
break;
default:
+ unlock_kernel();
return -EINVAL;
}
- if (val < 0)
- return val;
+ if (val < 0) {
+ unlock_kernel();
+ return -val;
+ }
switch (cmd) {
case I8K_BIOS_VERSION:
- if (copy_to_user(argp, &val, 4))
+ if (copy_to_user(argp, &val, 4)) {
+ unlock_kernel();
return -EFAULT;
+ }
break;
case I8K_MACHINE_ID:
- if (copy_to_user(argp, buff, 16))
+ if (copy_to_user(argp, buff, 16)) {
+ unlock_kernel();
return -EFAULT;
+ }
break;
default:
- if (copy_to_user(argp, &val, sizeof(int)))
+ if (copy_to_user(argp, &val, sizeof(int))) {
+ unlock_kernel();
return -EFAULT;
+ }
break;
}
+ unlock_kernel();
+
return 0;
}
diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c
index 9f49d9065791..ec595cf4ce6b 100644
--- a/drivers/isdn/divert/divert_procfs.c
+++ b/drivers/isdn/divert/divert_procfs.c
@@ -20,6 +20,7 @@
#include <linux/sched.h>
#include <linux/isdnif.h>
#include <net/net_namespace.h>
+#include <linux/smp_lock.h>
#include "isdn_divert.h"
@@ -177,18 +178,20 @@ isdn_divert_close(struct inode *ino, struct file *filep)
/*********/
/* IOCTL */
/*********/
-static int
-isdn_divert_ioctl(struct inode *inode, struct file *file,
- uint cmd, ulong arg)
+static long isdn_divert_ioctl(struct file *file, uint cmd, ulong arg)
{
divert_ioctl dioctl;
- int i;
unsigned long flags;
divert_rule *rulep;
char *cp;
- if (copy_from_user(&dioctl, (void __user *) arg, sizeof(dioctl)))
+ /* Pushed down from procfs ioctl handler */
+ lock_kernel();
+
+ if (copy_from_user(&dioctl, (void __user *) arg, sizeof(dioctl))) {
+ unlock_kernel();
return -EFAULT;
+ }
switch (cmd) {
case IIOCGETVER:
@@ -196,65 +199,84 @@ isdn_divert_ioctl(struct inode *inode, struct file *file,
break;
case IIOCGETDRV:
- if ((dioctl.getid.drvid = divert_if.name_to_drv(dioctl.getid.drvnam)) < 0)
- return (-EINVAL);
+ if ((dioctl.getid.drvid = divert_if.name_to_drv(dioctl.getid.drvnam)) < 0) {
+ unlock_kernel();
+ return -EINVAL;
+ }
break;
case IIOCGETNAM:
cp = divert_if.drv_to_name(dioctl.getid.drvid);
- if (!cp)
- return (-EINVAL);
- if (!*cp)
- return (-EINVAL);
+ if (!cp || !*cp) {
+ unlock_kernel();
+ return -EINVAL;
+ }
strcpy(dioctl.getid.drvnam, cp);
break;
case IIOCGETRULE:
- if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx)))
- return (-EINVAL);
+ if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx))) {
+ unlock_kernel();
+ return -EINVAL;
+ }
dioctl.getsetrule.rule = *rulep; /* copy data */
break;
case IIOCMODRULE:
- if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx)))
- return (-EINVAL);
- spin_lock_irqsave(&divert_lock, flags);
+ if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx))) {
+ unlock_kernel();
+ return -EINVAL;
+ }
+ spin_lock_irqsave(&divert_lock, flags);
*rulep = dioctl.getsetrule.rule; /* copy data */
spin_unlock_irqrestore(&divert_lock, flags);
- return (0); /* no copy required */
- break;
+
+ unlock_kernel();
+ return 0; /* no copy required */
case IIOCINSRULE:
- return (insertrule(dioctl.getsetrule.ruleidx, &dioctl.getsetrule.rule));
- break;
+ unlock_kernel();
+ return insertrule(dioctl.getsetrule.ruleidx, &dioctl.getsetrule.rule);
case IIOCDELRULE:
- return (deleterule(dioctl.getsetrule.ruleidx));
- break;
+ unlock_kernel();
+ return deleterule(dioctl.getsetrule.ruleidx);
case IIOCDODFACT:
- return (deflect_extern_action(dioctl.fwd_ctrl.subcmd,
- dioctl.fwd_ctrl.callid,
- dioctl.fwd_ctrl.to_nr));
+ unlock_kernel();
+ return deflect_extern_action(dioctl.fwd_ctrl.subcmd,
+ dioctl.fwd_ctrl.callid,
+ dioctl.fwd_ctrl.to_nr);
case IIOCDOCFACT:
case IIOCDOCFDIS:
- case IIOCDOCFINT:
- if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid))
- return (-EINVAL); /* invalid driver */
- if ((i = cf_command(dioctl.cf_ctrl.drvid,
+ case IIOCDOCFINT: {
+ long err;
+
+ if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid)) {
+ unlock_kernel();
+ return -EINVAL; /* invalid driver */
+ }
+ err = cf_command(dioctl.cf_ctrl.drvid,
(cmd == IIOCDOCFACT) ? 1 : (cmd == IIOCDOCFDIS) ? 0 : 2,
dioctl.cf_ctrl.cfproc,
dioctl.cf_ctrl.msn,
dioctl.cf_ctrl.service,
dioctl.cf_ctrl.fwd_nr,
- &dioctl.cf_ctrl.procid)))
- return (i);
+ &dioctl.cf_ctrl.procid);
+ if (err) {
+ unlock_kernel();
+ return err;
+ }
break;
+ }
default:
- return (-EINVAL);
- } /* switch cmd */
+ unlock_kernel();
+ return -EINVAL;
+ }
+
+ unlock_kernel();
return copy_to_user((void __user *)arg, &dioctl, sizeof(dioctl)) ? -EFAULT : 0;
} /* isdn_divert_ioctl */
@@ -265,7 +287,7 @@ static const struct file_operations isdn_fops =
.read = isdn_divert_read,
.write = isdn_divert_write,
.poll = isdn_divert_poll,
- .ioctl = isdn_divert_ioctl,
+ .unlocked_ioctl = isdn_divert_ioctl,
.open = isdn_divert_open,
.release = isdn_divert_close,
};
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 8418fcc0a6ab..c7f9f23449dc 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -730,6 +730,7 @@ out_no_task:
static const struct file_operations proc_info_file_operations = {
.read = proc_info_read,
+ .llseek = generic_file_llseek,
};
static int proc_single_show(struct seq_file *m, void *v)
@@ -987,6 +988,7 @@ out_no_task:
static const struct file_operations proc_environ_operations = {
.read = environ_read,
+ .llseek = generic_file_llseek,
};
static ssize_t oom_adjust_read(struct file *file, char __user *buf,
@@ -1060,6 +1062,7 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
static const struct file_operations proc_oom_adjust_operations = {
.read = oom_adjust_read,
.write = oom_adjust_write,
+ .llseek = generic_file_llseek,
};
#ifdef CONFIG_AUDITSYSCALL
@@ -1131,6 +1134,7 @@ out_free_page:
static const struct file_operations proc_loginuid_operations = {
.read = proc_loginuid_read,
.write = proc_loginuid_write,
+ .llseek = generic_file_llseek,
};
static ssize_t proc_sessionid_read(struct file * file, char __user * buf,
@@ -1151,6 +1155,7 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf,
static const struct file_operations proc_sessionid_operations = {
.read = proc_sessionid_read,
+ .llseek = generic_file_llseek,
};
#endif
@@ -1202,6 +1207,7 @@ static ssize_t proc_fault_inject_write(struct file * file,
static const struct file_operations proc_fault_inject_operations = {
.read = proc_fault_inject_read,
.write = proc_fault_inject_write,
+ .llseek = generic_file_llseek,
};
#endif
@@ -1943,7 +1949,7 @@ static ssize_t proc_fdinfo_read(struct file *file, char __user *buf,
}
static const struct file_operations proc_fdinfo_file_operations = {
- .open = nonseekable_open,
+ .open = nonseekable_open,
.read = proc_fdinfo_read,
};
@@ -2227,6 +2233,7 @@ out_no_task:
static const struct file_operations proc_pid_attr_operations = {
.read = proc_pid_attr_read,
.write = proc_pid_attr_write,
+ .llseek = generic_file_llseek,
};
static const struct pid_entry attr_dir_stuff[] = {
@@ -2347,6 +2354,7 @@ static ssize_t proc_coredump_filter_write(struct file *file,
static const struct file_operations proc_coredump_filter_operations = {
.read = proc_coredump_filter_read,
.write = proc_coredump_filter_write,
+ .llseek = generic_file_llseek,
};
#endif
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index d35b23238fb1..aea8502e58a3 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -232,9 +232,9 @@ static long proc_reg_unlocked_ioctl(struct file *file, unsigned int cmd, unsigne
if (rv == -ENOIOCTLCMD)
rv = -EINVAL;
} else if (ioctl) {
- lock_kernel();
+ WARN_ONCE(1, "Procfs ioctl handlers must use unlocked_ioctl, "
+ "%pf will be called without the Bkl held\n", ioctl);
rv = ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
- unlock_kernel();
}
pde_users_dec(pde);
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index 19979a2ce272..c837a77351be 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -558,6 +558,7 @@ static int open_kcore(struct inode *inode, struct file *filp)
static const struct file_operations proc_kcore_operations = {
.read = read_kcore,
.open = open_kcore,
+ .llseek = generic_file_llseek,
};
#ifdef CONFIG_MEMORY_HOTPLUG
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c
index cfe90a48a6e8..bd4b5a740ff1 100644
--- a/fs/proc/kmsg.c
+++ b/fs/proc/kmsg.c
@@ -53,6 +53,7 @@ static const struct file_operations proc_kmsg_operations = {
.poll = kmsg_poll,
.open = kmsg_open,
.release = kmsg_release,
+ .llseek = generic_file_llseek,
};
static int __init proc_kmsg_init(void)
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index 9fbc99ec799a..91c817ff02c3 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -163,6 +163,7 @@ static ssize_t read_vmcore(struct file *file, char __user *buffer,
static const struct file_operations proc_vmcore_operations = {
.read = read_vmcore,
+ .llseek = generic_file_llseek,
};
static struct vmcore* __init get_new_element(void)
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index a3f340c8b79a..7170635687ab 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -28,6 +28,7 @@
#include <linux/workqueue.h>
#include <linux/mutex.h>
#include <linux/pagemap.h>
+#include <linux/smp_lock.h>
#include <asm/ioctls.h>
#include <linux/sunrpc/types.h>
#include <linux/sunrpc/cache.h>
@@ -1344,12 +1345,21 @@ static unsigned int cache_poll_procfs(struct file *filp, poll_table *wait)
return cache_poll(filp, wait, cd);
}
-static int cache_ioctl_procfs(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static long cache_ioctl_procfs(struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
+ long ret;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct cache_detail *cd = PDE(inode)->data;
- return cache_ioctl(inode, filp, cmd, arg, cd);
+ /* Pushed down from procfs ioctl handler */
+ lock_kernel();
+
+ ret = cache_ioctl(inode, filp, cmd, arg, cd);
+
+ unlock_kernel();
+
+ return ret;
}
static int cache_open_procfs(struct inode *inode, struct file *filp)
@@ -1372,7 +1382,7 @@ static const struct file_operations cache_file_operations_procfs = {
.read = cache_read_procfs,
.write = cache_write_procfs,
.poll = cache_poll_procfs,
- .ioctl = cache_ioctl_procfs, /* for FIONREAD */
+ .unlocked_ioctl = cache_ioctl_procfs, /* for FIONREAD */
.open = cache_open_procfs,
.release = cache_release_procfs,
};