Commit 45048d09 authored by Al Viro's avatar Al Viro Committed by Al Viro

[PATCH] get rid of blkdev_locked_ioctl()

Most of that stuff doesn't need BKL at all; expand in the (only) caller,
merge the switch into one there and leave BKL only around the stuff that
might actually need it.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent e436fdae
......@@ -688,12 +688,40 @@ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
return __blkdev_driver_ioctl(bdev, mode, cmd, arg);
}
static int compat_blkdev_locked_ioctl(struct block_device *bdev,
unsigned cmd, unsigned long arg)
/* Most of the generic ioctls are handled in the normal fallback path.
This assumes the blkdev's low level compat_ioctl always returns
ENOIOCTLCMD for unknown ioctls. */
long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
int ret = -ENOIOCTLCMD;
struct inode *inode = file->f_mapping->host;
struct block_device *bdev = inode->i_bdev;
struct gendisk *disk = bdev->bd_disk;
fmode_t mode = file->f_mode;
struct backing_dev_info *bdi;
loff_t size;
if (file->f_flags & O_NDELAY)
mode |= FMODE_NDELAY_NOW;
switch (cmd) {
case HDIO_GETGEO:
return compat_hdio_getgeo(disk, bdev, compat_ptr(arg));
case BLKFLSBUF:
case BLKROSET:
case BLKDISCARD:
/*
* the ones below are implemented in blkdev_locked_ioctl,
* but we call blkdev_ioctl, which gets the lock for us
*/
case BLKRRPART:
return blkdev_ioctl(inode, file, cmd,
(unsigned long)compat_ptr(arg));
case BLKBSZSET_32:
return blkdev_ioctl(inode, file, BLKBSZSET,
(unsigned long)compat_ptr(arg));
case BLKPG:
return compat_blkpg_ioctl(inode, file, cmd, compat_ptr(arg));
case BLKRAGET:
case BLKFRAGET:
if (!arg)
......@@ -719,67 +747,36 @@ static int compat_blkdev_locked_ioctl(struct block_device *bdev,
bdi = blk_get_backing_dev_info(bdev);
if (bdi == NULL)
return -ENOTTY;
lock_kernel();
bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
unlock_kernel();
return 0;
case BLKGETSIZE:
if ((bdev->bd_inode->i_size >> 9) > ~0UL)
size = bdev->bd_inode->i_size;
if ((size >> 9) > ~0UL)
return -EFBIG;
return compat_put_ulong(arg, bdev->bd_inode->i_size >> 9);
return compat_put_ulong(arg, size >> 9);
case BLKGETSIZE64_32:
return compat_put_u64(arg, bdev->bd_inode->i_size);
case BLKTRACESETUP32:
return compat_blk_trace_setup(bdev, compat_ptr(arg));
lock_kernel();
ret = compat_blk_trace_setup(bdev, compat_ptr(arg));
unlock_kernel();
return ret;
case BLKTRACESTART: /* compatible */
case BLKTRACESTOP: /* compatible */
case BLKTRACETEARDOWN: /* compatible */
return blk_trace_ioctl(bdev, cmd, compat_ptr(arg));
}
return -ENOIOCTLCMD;
}
/* Most of the generic ioctls are handled in the normal fallback path.
This assumes the blkdev's low level compat_ioctl always returns
ENOIOCTLCMD for unknown ioctls. */
long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
int ret = -ENOIOCTLCMD;
struct inode *inode = file->f_mapping->host;
struct block_device *bdev = inode->i_bdev;
struct gendisk *disk = bdev->bd_disk;
fmode_t mode = file->f_mode;
if (file->f_flags & O_NDELAY)
mode |= FMODE_NDELAY_NOW;
switch (cmd) {
case HDIO_GETGEO:
return compat_hdio_getgeo(disk, bdev, compat_ptr(arg));
case BLKFLSBUF:
case BLKROSET:
case BLKDISCARD:
/*
* the ones below are implemented in blkdev_locked_ioctl,
* but we call blkdev_ioctl, which gets the lock for us
*/
case BLKRRPART:
return blkdev_ioctl(inode, file, cmd,
(unsigned long)compat_ptr(arg));
case BLKBSZSET_32:
return blkdev_ioctl(inode, file, BLKBSZSET,
(unsigned long)compat_ptr(arg));
case BLKPG:
return compat_blkpg_ioctl(inode, file, cmd, compat_ptr(arg));
}
lock_kernel();
ret = compat_blkdev_locked_ioctl(bdev, cmd, arg);
unlock_kernel();
if (ret == -ENOIOCTLCMD && disk->fops->compat_ioctl)
ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg);
if (ret != -ENOIOCTLCMD)
lock_kernel();
ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg));
unlock_kernel();
return ret;
return compat_blkdev_driver_ioctl(bdev, mode, cmd, arg);
default:
if (disk->fops->compat_ioctl)
ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg);
if (ret == -ENOIOCTLCMD)
ret = compat_blkdev_driver_ioctl(bdev, mode, cmd, arg);
return ret;
}
}
......@@ -201,70 +201,6 @@ static int put_u64(unsigned long arg, u64 val)
return put_user(val, (u64 __user *)arg);
}
static int blkdev_locked_ioctl(struct file *file, struct block_device *bdev,
unsigned cmd, unsigned long arg)
{
struct backing_dev_info *bdi;
int ret, n;
switch (cmd) {
case BLKRAGET:
case BLKFRAGET:
if (!arg)
return -EINVAL;
bdi = blk_get_backing_dev_info(bdev);
if (bdi == NULL)
return -ENOTTY;
return put_long(arg, (bdi->ra_pages * PAGE_CACHE_SIZE) / 512);
case BLKROGET:
return put_int(arg, bdev_read_only(bdev) != 0);
case BLKBSZGET: /* get the logical block size (cf. BLKSSZGET) */
return put_int(arg, block_size(bdev));
case BLKSSZGET: /* get block device hardware sector size */
return put_int(arg, bdev_hardsect_size(bdev));
case BLKSECTGET:
return put_ushort(arg, bdev_get_queue(bdev)->max_sectors);
case BLKRASET:
case BLKFRASET:
if(!capable(CAP_SYS_ADMIN))
return -EACCES;
bdi = blk_get_backing_dev_info(bdev);
if (bdi == NULL)
return -ENOTTY;
bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
return 0;
case BLKBSZSET:
/* set the logical block size */
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
if (!arg)
return -EINVAL;
if (get_user(n, (int __user *) arg))
return -EFAULT;
if (bd_claim(bdev, file) < 0)
return -EBUSY;
ret = set_blocksize(bdev, n);
bd_release(bdev);
return ret;
case BLKPG:
return blkpg_ioctl(bdev, (struct blkpg_ioctl_arg __user *) arg);
case BLKRRPART:
return blkdev_reread_part(bdev);
case BLKGETSIZE:
if ((bdev->bd_inode->i_size >> 9) > ~0UL)
return -EFBIG;
return put_ulong(arg, bdev->bd_inode->i_size >> 9);
case BLKGETSIZE64:
return put_u64(arg, bdev->bd_inode->i_size);
case BLKTRACESTART:
case BLKTRACESTOP:
case BLKTRACESETUP:
case BLKTRACETEARDOWN:
return blk_trace_ioctl(bdev, cmd, (char __user *) arg);
}
return -ENOIOCTLCMD;
}
int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
unsigned cmd, unsigned long arg)
{
......@@ -299,6 +235,8 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
{
struct block_device *bdev = inode->i_bdev;
struct gendisk *disk = bdev->bd_disk;
struct backing_dev_info *bdi;
loff_t size;
int ret, n;
fmode_t mode = 0;
if (file) {
......@@ -370,14 +308,74 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
return -EFAULT;
return 0;
}
}
lock_kernel();
ret = blkdev_locked_ioctl(file, bdev, cmd, arg);
unlock_kernel();
if (ret != -ENOIOCTLCMD)
case BLKRAGET:
case BLKFRAGET:
if (!arg)
return -EINVAL;
bdi = blk_get_backing_dev_info(bdev);
if (bdi == NULL)
return -ENOTTY;
return put_long(arg, (bdi->ra_pages * PAGE_CACHE_SIZE) / 512);
case BLKROGET:
return put_int(arg, bdev_read_only(bdev) != 0);
case BLKBSZGET: /* get the logical block size (cf. BLKSSZGET) */
return put_int(arg, block_size(bdev));
case BLKSSZGET: /* get block device hardware sector size */
return put_int(arg, bdev_hardsect_size(bdev));
case BLKSECTGET:
return put_ushort(arg, bdev_get_queue(bdev)->max_sectors);
case BLKRASET:
case BLKFRASET:
if(!capable(CAP_SYS_ADMIN))
return -EACCES;
bdi = blk_get_backing_dev_info(bdev);
if (bdi == NULL)
return -ENOTTY;
lock_kernel();
bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
unlock_kernel();
return 0;
case BLKBSZSET:
/* set the logical block size */
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
if (!arg)
return -EINVAL;
if (get_user(n, (int __user *) arg))
return -EFAULT;
if (bd_claim(bdev, file) < 0)
return -EBUSY;
ret = set_blocksize(bdev, n);
bd_release(bdev);
return ret;
ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg);
case BLKPG:
lock_kernel();
ret = blkpg_ioctl(bdev, (struct blkpg_ioctl_arg __user *) arg);
unlock_kernel();
break;
case BLKRRPART:
lock_kernel();
ret = blkdev_reread_part(bdev);
unlock_kernel();
break;
case BLKGETSIZE:
size = bdev->bd_inode->i_size;
if ((size >> 9) > ~0UL)
return -EFBIG;
return put_ulong(arg, size >> 9);
case BLKGETSIZE64:
return put_u64(arg, bdev->bd_inode->i_size);
case BLKTRACESTART:
case BLKTRACESTOP:
case BLKTRACESETUP:
case BLKTRACETEARDOWN:
lock_kernel();
ret = blk_trace_ioctl(bdev, cmd, (char __user *) arg);
unlock_kernel();
break;
default:
ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg);
}
return ret;
}
EXPORT_SYMBOL_GPL(blkdev_ioctl);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment