s390: #ifdefs in compat_ioctls.
Subsystems (3)
PATCH 5/11 s390: #ifdefs in compat_ioctls.
[patch 5/11] s390: #ifdefs in compat_ioctls.
From: Martin Schwidefsky <[email protected]>
Remove superflous #if .. #endif pairs from compat_ioctl.c.
diffstat:
arch/s390/kernel/compat_ioctl.c | 6 ------ 1 files changed, 6 deletions(-)
arch/s390/kernel/compat_ioctl.c +0 -6
@@ -42,7 +42,6 @@ struct ioctl_trans ioctl_start[] = {#include "../../../fs/compat_ioctl.c" /* s390 only ioctls */ -#if defined(CONFIG_DASD ) || defined(CONFIG_DASD_MODULE ) COMPATIBLE_IOCTL(DASDAPIVER) COMPATIBLE_IOCTL(BIODASDDISABLE) COMPATIBLE_IOCTL(BIODASDENABLE)
@@ -59,16 +58,11 @@ COMPATIBLE_IOCTL(BIODASDPRRD) COMPATIBLE_IOCTL(BIODASDPSRD) COMPATIBLE_IOCTL(BIODASDGATTR) COMPATIBLE_IOCTL(BIODASDSATTR) -#if defined(CONFIG_DASD_CMB ) || defined(CONFIG_DASD_CMB_MODULE ) COMPATIBLE_IOCTL(BIODASDCMFENABLE) COMPATIBLE_IOCTL(BIODASDCMFDISABLE) COMPATIBLE_IOCTL(BIODASDREADALLCMB) -#endif -#endif -#if defined(CONFIG_S390_TAPE ) || defined(CONFIG_S390_TAPE_MODULE ) COMPATIBLE_IOCTL(TAPE390_DISPLAY) -#endif /* s390 doesn't need handlers here */ COMPATIBLE_IOCTL(TIOCGSERIAL)
Quoted 5 lines · Martin Schwidefsky
[patch 5/11] s390: #ifdefs in
compat_ioctls.From: Martin Schwidefsky <[email protected]>
Remove superflous #if .. #endif pairs from
compat_ioctl.c.
Actually is there any chance you could just provide ->compat_ioctl handlers in the drivers? All these ioctls are specific to drivers, and it sounds like a rather bad idea to pollute the global has table with them. This is also a good chance to switch the drivers to drop BKL usage in the ioctl path and use the same handler for ->unlocked_ioctl and ->compat_ioctl.
Quoted 5 lines · Christoph Hellwig
Actually is there any chance you could just provide ->compat_ioctl handlers in the drivers? All these ioctls are specific to drivers, and it sounds like a rather bad idea to pollute the global has table with them. This is also a good chance to switch the drivers to drop BKL usage in the ioctl path and use the same handler for ->unlocked_ioctl and ->compat_ioctl.
I just checked and found that block_device_operations don't support unlocked_ioctl() yet. I have hacked up a patch to add that without changing the semantics of blkdev_ioctl(). I have not done thorough testing, but my system is running fine with this applied. Does it look ok to you?
[PATCH] block: add unlocked_ioctl support for block devices
This patch allows block device drivers to convert their ioctl functions to unlocked_ioctl() like character devices and other subsystems. All functions that were called with the BKL held before are still used that way, but I would not be surprised if it could be removed from the ioctl functions in drivers/block/ioctl.c themselves.
As a side note, I found that compat_blkdev_ioctl() acquires the BKL as well, which looks like a bug. I have checked that every user of disk->fops->compat_ioctl() in the current git tree gets the BKL itself, so it could easily be removed from compat_blkdev_ioctl().
--
drivers/block/ioctl.c (mode:100644) +54 -20
@@ -133,11 +133,9 @@ return put_user(val, (u64 __user *)arg); } -int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, - unsigned long arg) +static int blkdev_locked_ioctl(struct file *file, struct block_device *bdev, + unsigned cmd, unsigned long arg) { - struct block_device *bdev = inode->i_bdev; - struct gendisk *disk = bdev->bd_disk; struct backing_dev_info *bdi; int ret, n;
@@ -190,36 +188,72 @@ return put_ulong(arg, bdev->bd_inode->i_size >> 9); case BLKGETSIZE64: return put_u64(arg, bdev->bd_inode->i_size); + } + return -ENOIOCTLCMD; +} + +static int blkdev_driver_ioctl(struct inode *inode, struct file *file, + struct gendisk *disk, unsigned cmd, unsigned long arg) +{ + int ret; + if (disk->fops->unlocked_ioctl) + return disk->fops->unlocked_ioctl(file, cmd, arg); + + if (disk->fops->ioctl) { + lock_kernel(); + ret = disk->fops->ioctl(inode, file, cmd, arg); + unlock_kernel(); + return ret; + } + + return -ENOTTY; +} + +int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, + unsigned long arg) +{ + struct block_device *bdev = inode->i_bdev; + struct gendisk *disk = bdev->bd_disk; + int ret, n; + + switch(cmd) { case BLKFLSBUF: if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (disk->fops->ioctl) { - ret = disk->fops->ioctl(inode, file, cmd, arg); - /* -EINVAL to handle old uncorrected drivers */ - if (ret != -EINVAL && ret != -ENOTTY) - return ret; - } + + ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg); + /* -EINVAL to handle old uncorrected drivers */ + if (ret != -EINVAL && ret != -ENOTTY) + return ret; + + lock_kernel(); fsync_bdev(bdev); invalidate_bdev(bdev, 0); + unlock_kernel(); return 0; + case BLKROSET: - if (disk->fops->ioctl) { - ret = disk->fops->ioctl(inode, file, cmd, arg); - /* -EINVAL to handle old uncorrected drivers */ - if (ret != -EINVAL && ret != -ENOTTY) - return ret; - } + ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg); + /* -EINVAL to handle old uncorrected drivers */ + if (ret != -EINVAL && ret != -ENOTTY) + return ret; if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (get_user(n, (int __user *)(arg))) return -EFAULT; + lock_kernel(); set_device_ro(bdev, n); + unlock_kernel(); return 0; - default: - if (disk->fops->ioctl) - return disk->fops->ioctl(inode, file, cmd, arg); } - return -ENOTTY; + + lock_kernel(); + ret = blkdev_locked_ioctl(file, bdev, cmd, arg); + unlock_kernel(); + if (ret != -ENOIOCTLCMD) + return ret; + + return blkdev_driver_ioctl(inode, file, disk, cmd, arg); } /* Most of the generic ioctls are handled in the normal fallback path.
fs/block_dev.c (mode:100644) +2 -3
@@ -777,8 +777,7 @@ return generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos); } -static int block_ioctl(struct inode *inode, struct file *file, unsigned cmd, - unsigned long arg) +static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg) { return blkdev_ioctl(file->f_mapping->host, file, cmd, arg); }
@@ -803,7 +802,7 @@ .aio_write = blkdev_file_aio_write, .mmap = generic_file_mmap, .fsync = block_fsync, - .ioctl = block_ioctl, + .unlocked_ioctl = block_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = compat_blkdev_ioctl, #endif
include/linux/fs.h (mode:100644) +1 -0
@@ -883,6 +883,7 @@ int (*open) (struct inode *, struct file *); int (*release) (struct inode *, struct file *); int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long); + long (*unlocked_ioctl) (struct file *, unsigned, unsigned long); long (*compat_ioctl) (struct file *, unsigned, unsigned long); int (*media_changed) (struct gendisk *); int (*revalidate_disk) (struct gendisk *);