[PATCH 2.6.10-rc3] sys_ioctl: Add an unlocked_ioctl file operation

From: Mike Werner
Date: Wed Dec 08 2004 - 11:48:40 EST


# This is a BitKeeper generated diff -Nru style patch.
#
# Add an unlocked_ioctl file operation
# It assumes if unlocked_ioctl is defined in fops
# then the driver can handle concurrency and
# lock_kernel isn't called.
#
# Signed-off-by: Mike Werner <werner@xxxxxxx>
#
diff -Nru a/fs/ioctl.c b/fs/ioctl.c
--- a/fs/ioctl.c 2004-12-07 16:14:55 -08:00
+++ b/fs/ioctl.c 2004-12-07 16:14:55 -08:00
@@ -16,6 +16,8 @@
#include <asm/uaccess.h>
#include <asm/ioctls.h>

+/* Any additions in file_ioctl need to be added to the lock_kernel filter in sys_ioctl */
+
static int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
{
int error;
@@ -46,7 +48,9 @@
case FIONREAD:
return put_user(i_size_read(inode) - filp->f_pos, p);
}
- if (filp->f_op && filp->f_op->ioctl)
+ if (filp->f_op && filp->f_op->unlocked_ioctl)
+ return filp->f_op->unlocked_ioctl(inode, filp, cmd, arg);
+ else if (filp->f_op && filp->f_op->ioctl)
return filp->f_op->ioctl(inode, filp, cmd, arg);
return -ENOTTY;
}
@@ -56,7 +60,7 @@
{
struct file * filp;
unsigned int flag;
- int on, error = -EBADF;
+ int on, locked, error = -EBADF;

filp = fget(fd);
if (!filp)
@@ -68,7 +72,26 @@
goto out;
}

- lock_kernel();
+ switch (cmd) {
+ case FIOCLEX:
+ case FIONCLEX:
+ case FIONBIO:
+ case FIOASYNC:
+ case FIOQSIZE:
+ case FIBMAP:
+ case FIGETBSZ:
+ case FIONREAD:
+ lock_kernel();
+ locked=1;
+ break;
+ default:
+ locked=0;
+ if (filp->f_op && !filp->f_op->unlocked_ioctl) {
+ lock_kernel();
+ locked=1;
+ }
+ }
+
switch (cmd) {
case FIOCLEX:
set_close_on_exec(fd, 1);
@@ -127,10 +150,13 @@
error = -ENOTTY;
if (S_ISREG(filp->f_dentry->d_inode->i_mode))
error = file_ioctl(filp, cmd, arg);
+ else if (filp->f_op && filp->f_op->unlocked_ioctl)
+ error = filp->f_op->unlocked_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
else if (filp->f_op && filp->f_op->ioctl)
error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
}
- unlock_kernel();
+ if (locked)
+ unlock_kernel();
fput(filp);

out:
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h 2004-12-07 16:14:55 -08:00
+++ b/include/linux/fs.h 2004-12-07 16:14:55 -08:00
@@ -915,6 +915,7 @@
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
+ int (*unlocked_ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/