From: Mike Werner <werner@sgi.com>
To: linux-kernel@vger.kernel.org
Subject: [RFC]Add an unlocked_ioctl file operation
Date: Tue, 7 Dec 2004 12:11:41 -0800 [thread overview]
Message-ID: <200412071211.41468.werner@sgi.com> (raw)
Per Andi Kleen's suggestion.
# This is a BitKeeper generated diff -Nru style patch.
#
# Run Lindent on ioctl.c
# Add an ioctl path which does not take the BKL.
#
diff -Nru a/fs/ioctl.c b/fs/ioctl.c
--- a/fs/ioctl.c 2004-12-07 11:53:59 -08:00
+++ b/fs/ioctl.c 2004-12-07 11:53:59 -08:00
@@ -16,15 +16,15 @@
#include <asm/uaccess.h>
#include <asm/ioctls.h>
-static int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
+static int file_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int error;
int block;
- struct inode * inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_dentry->d_inode;
int __user *p = (int __user *)arg;
switch (cmd) {
- case FIBMAP:
+ case FIBMAP:
{
struct address_space *mapping = filp->f_mapping;
int res;
@@ -39,101 +39,113 @@
res = mapping->a_ops->bmap(mapping, block);
return put_user(res, p);
}
- case FIGETBSZ:
- if (inode->i_sb == NULL)
- return -EBADF;
- return put_user(inode->i_sb->s_blocksize, p);
- case FIONREAD:
- return put_user(i_size_read(inode) - filp->f_pos, p);
+ case FIGETBSZ:
+ if (inode->i_sb == NULL)
+ return -EBADF;
+ return put_user(inode->i_sb->s_blocksize, p);
+ case FIONREAD:
+ return put_user(i_size_read(inode) - filp->f_pos, p);
}
if (filp->f_op && filp->f_op->ioctl)
return filp->f_op->ioctl(inode, filp, cmd, arg);
return -ENOTTY;
}
-
asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long
arg)
-{
- struct file * filp;
+{
+ struct file *filp;
unsigned int flag;
int on, error = -EBADF;
-
+ int locked = 1;
filp = fget(fd);
if (!filp)
goto out;
error = security_file_ioctl(filp, cmd, arg);
if (error) {
- fput(filp);
- goto out;
- }
+ fput(filp);
+ goto out;
+ }
+
+ if (filp->f_op && filp->f_op->unlocked_ioctl)
+ locked = 0;
+ else
+ lock_kernel();
- lock_kernel();
switch (cmd) {
- case FIOCLEX:
- set_close_on_exec(fd, 1);
- break;
+ case FIOCLEX:
+ set_close_on_exec(fd, 1);
+ break;
+
+ case FIONCLEX:
+ set_close_on_exec(fd, 0);
+ break;
- case FIONCLEX:
- set_close_on_exec(fd, 0);
+ case FIONBIO:
+ if ((error = get_user(on, (int __user *)arg)) != 0)
break;
-
- case FIONBIO:
- if ((error = get_user(on, (int __user *)arg)) != 0)
- break;
- flag = O_NONBLOCK;
+ flag = O_NONBLOCK;
#ifdef __sparc__
- /* SunOS compatibility item. */
- if(O_NONBLOCK != O_NDELAY)
- flag |= O_NDELAY;
+ /* SunOS compatibility item. */
+ if (O_NONBLOCK != O_NDELAY)
+ flag |= O_NDELAY;
#endif
- if (on)
- filp->f_flags |= flag;
- else
- filp->f_flags &= ~flag;
- break;
-
- case FIOASYNC:
- if ((error = get_user(on, (int __user *)arg)) != 0)
- break;
- flag = on ? FASYNC : 0;
-
- /* Did FASYNC state change ? */
- if ((flag ^ filp->f_flags) & FASYNC) {
- if (filp->f_op && filp->f_op->fasync)
- error = filp->f_op->fasync(fd, filp, on);
- else error = -ENOTTY;
- }
- if (error != 0)
- break;
+ if (on)
+ filp->f_flags |= flag;
+ else
+ filp->f_flags &= ~flag;
+ break;
- if (on)
- filp->f_flags |= FASYNC;
- else
- filp->f_flags &= ~FASYNC;
+ case FIOASYNC:
+ if ((error = get_user(on, (int __user *)arg)) != 0)
break;
+ flag = on ? FASYNC : 0;
- case FIOQSIZE:
- if (S_ISDIR(filp->f_dentry->d_inode->i_mode) ||
- S_ISREG(filp->f_dentry->d_inode->i_mode) ||
- S_ISLNK(filp->f_dentry->d_inode->i_mode)) {
- loff_t res = inode_get_bytes(filp->f_dentry->d_inode);
- error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT :
0;
- }
+ /* Did FASYNC state change ? */
+ if ((flag ^ filp->f_flags) & FASYNC) {
+ if (filp->f_op && filp->f_op->fasync)
+ error = filp->f_op->fasync(fd, filp, on);
else
error = -ENOTTY;
+ }
+ if (error != 0)
break;
- default:
+
+ if (on)
+ filp->f_flags |= FASYNC;
+ else
+ filp->f_flags &= ~FASYNC;
+ break;
+
+ case FIOQSIZE:
+ if (S_ISDIR(filp->f_dentry->d_inode->i_mode) ||
+ S_ISREG(filp->f_dentry->d_inode->i_mode) ||
+ S_ISLNK(filp->f_dentry->d_inode->i_mode)) {
+ loff_t res = inode_get_bytes(filp->f_dentry->d_inode);
+ error =
+ copy_to_user((loff_t __user *) arg, &res,
+ sizeof(res)) ? -EFAULT : 0;
+ } else
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->ioctl)
- error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+ break;
+ default:
+ 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:
+ out:
return error;
}
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h 2004-12-07 11:53:59 -08:00
+++ b/include/linux/fs.h 2004-12-07 11:53:59 -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 *);
next reply other threads:[~2004-12-07 20:13 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-12-07 20:11 Mike Werner [this message]
2004-12-07 20:30 ` [RFC]Add an unlocked_ioctl file operation Randy.Dunlap
2004-12-07 21:30 ` Mike Waychison
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200412071211.41468.werner@sgi.com \
--to=werner@sgi.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox