Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+49 −52
Original line number Original line Diff line number Diff line
@@ -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);
	return __blkdev_driver_ioctl(bdev, mode, cmd, arg);
}
}


static int compat_blkdev_locked_ioctl(struct block_device *bdev,
/* Most of the generic ioctls are handled in the normal fallback path.
				unsigned cmd, unsigned long arg)
   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;
	struct backing_dev_info *bdi;
	loff_t size;

	if (file->f_flags & O_NDELAY)
		mode |= FMODE_NDELAY_NOW;


	switch (cmd) {
	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 BLKRAGET:
	case BLKFRAGET:
	case BLKFRAGET:
		if (!arg)
		if (!arg)
@@ -719,67 +747,36 @@ static int compat_blkdev_locked_ioctl(struct block_device *bdev,
		bdi = blk_get_backing_dev_info(bdev);
		bdi = blk_get_backing_dev_info(bdev);
		if (bdi == NULL)
		if (bdi == NULL)
			return -ENOTTY;
			return -ENOTTY;
		lock_kernel();
		bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
		bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
		unlock_kernel();
		return 0;
		return 0;
	case BLKGETSIZE:
	case BLKGETSIZE:
		if ((bdev->bd_inode->i_size >> 9) > ~0UL)
		size = bdev->bd_inode->i_size;
		if ((size >> 9) > ~0UL)
			return -EFBIG;
			return -EFBIG;
		return compat_put_ulong(arg, bdev->bd_inode->i_size >> 9);
		return compat_put_ulong(arg, size >> 9);


	case BLKGETSIZE64_32:
	case BLKGETSIZE64_32:
		return compat_put_u64(arg, bdev->bd_inode->i_size);
		return compat_put_u64(arg, bdev->bd_inode->i_size);


	case BLKTRACESETUP32:
	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 BLKTRACESTART: /* compatible */
	case BLKTRACESTOP:  /* compatible */
	case BLKTRACESTOP:  /* compatible */
	case BLKTRACETEARDOWN: /* 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();
		lock_kernel();
	ret = compat_blkdev_locked_ioctl(bdev, cmd, arg);
		ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg));
		unlock_kernel();
		unlock_kernel();
	if (ret == -ENOIOCTLCMD && disk->fops->compat_ioctl)
		return ret;
	default:
		if (disk->fops->compat_ioctl)
			ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg);
			ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg);

		if (ret == -ENOIOCTLCMD)
	if (ret != -ENOIOCTLCMD)
			ret = compat_blkdev_driver_ioctl(bdev, mode, cmd, arg);
		return ret;
		return ret;

	}
	return compat_blkdev_driver_ioctl(bdev, mode, cmd, arg);
}
}
+70 −72
Original line number Original line Diff line number Diff line
@@ -201,70 +201,6 @@ static int put_u64(unsigned long arg, u64 val)
	return put_user(val, (u64 __user *)arg);
	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,
int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
			unsigned cmd, unsigned long arg)
			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 block_device *bdev = inode->i_bdev;
	struct gendisk *disk = bdev->bd_disk;
	struct gendisk *disk = bdev->bd_disk;
	struct backing_dev_info *bdi;
	loff_t size;
	int ret, n;
	int ret, n;
	fmode_t mode = 0;
	fmode_t mode = 0;
	if (file) {
	if (file) {
@@ -370,14 +308,74 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
			return -EFAULT;
			return -EFAULT;
		return 0;
		return 0;
	}
	}
	}
	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();
		lock_kernel();
	ret = blkdev_locked_ioctl(file, bdev, cmd, arg);
		bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
		unlock_kernel();
		unlock_kernel();
	if (ret != -ENOIOCTLCMD)
		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;
		return ret;

	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);
		ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg);
	}
	}
	return ret;
}
EXPORT_SYMBOL_GPL(blkdev_ioctl);
EXPORT_SYMBOL_GPL(blkdev_ioctl);