Signed-off-by: Andrew Morton --- 25-akpm/fs/ioctl.c | 35 +++++++++++++++++++++++------------ 25-akpm/include/linux/fs.h | 5 ++++- 2 files changed, 27 insertions(+), 13 deletions(-) diff -puN fs/ioctl.c~unlocked_ioctl fs/ioctl.c --- 25/fs/ioctl.c~unlocked_ioctl 2004-12-09 22:58:40.324038136 -0800 +++ 25-akpm/fs/ioctl.c 2004-12-09 22:59:30.425421568 -0800 @@ -35,7 +35,6 @@ asmlinkage long sys_ioctl(unsigned int f } inode = filp->f_dentry->d_inode; - lock_kernel(); switch (cmd) { case FIOCLEX: set_close_on_exec(fd, 1); @@ -52,30 +51,33 @@ asmlinkage long sys_ioctl(unsigned int f if(O_NONBLOCK != O_NDELAY) flag |= O_NDELAY; #endif + lock_kernel(); if (on) filp->f_flags |= flag; else filp->f_flags &= ~flag; + unlock_kernel(); goto done; case FIOASYNC: if ((error = get_user(on, (int __user *)arg)) != 0) goto done; flag = on ? FASYNC : 0; - /* Did FASYNC state change ? */ + lock_kernel(); if ((flag ^ filp->f_flags) & FASYNC) { + /* FASYNC state changed */ if (filp->f_op && filp->f_op->fasync) error = filp->f_op->fasync(fd, filp, on); else error = -ENOTTY; } - if (error != 0) - goto done; - - if (on) - filp->f_flags |= FASYNC; - else - filp->f_flags &= ~FASYNC; + if (error == 0) { + if (on) + filp->f_flags |= FASYNC; + else + filp->f_flags &= ~FASYNC; + } + unlock_kernel(); goto done; case FIOQSIZE: error = -ENOTTY; @@ -107,7 +109,9 @@ asmlinkage long sys_ioctl(unsigned int f if ((error = get_user(block, p))) goto done; + lock_kernel(); res = mapping->a_ops->bmap(mapping, block); + unlock_kernel(); error = put_user(res, p); goto done; } @@ -130,10 +134,17 @@ asmlinkage long sys_ioctl(unsigned int f } error = -ENOTTY; - if (filp->f_op && filp->f_op->ioctl) - error = filp->f_op->ioctl(inode, filp, cmd, arg); + if (filp->f_op) { + if (filp->f_op->unlocked_ioctl) { + error = filp->f_op->unlocked_ioctl(inode, filp, + cmd, arg); + } else if (filp->f_op->ioctl) { + lock_kernel(); + error = filp->f_op->ioctl(inode, filp, cmd, arg); + unlock_kernel(); + } + } done: - unlock_kernel(); fput(filp); out: return error; diff -puN include/linux/fs.h~unlocked_ioctl include/linux/fs.h --- 25/include/linux/fs.h~unlocked_ioctl 2004-12-09 22:58:40.326037832 -0800 +++ 25-akpm/include/linux/fs.h 2004-12-09 22:58:40.332036920 -0800 @@ -921,7 +921,10 @@ struct file_operations { ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t); 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 (*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 *); _