From 633a08b81206122469365b4c72eaeb71f04f2cb4 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 29 Aug 2007 20:34:12 -0400 Subject: [PATCH] introduce __blkdev_driver_ioctl() Analog of blkdev_driver_ioctl() with sane arguments. For now uses fake struct file, by the end of the series it won't and blkdev_driver_ioctl() will become a wrapper around it. Signed-off-by: Al Viro --- block/ioctl.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'block/ioctl.c') diff --git a/block/ioctl.c b/block/ioctl.c index 38bee321e1f..9a26ace6d04 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -283,6 +283,37 @@ int blkdev_driver_ioctl(struct inode *inode, struct file *file, } EXPORT_SYMBOL_GPL(blkdev_driver_ioctl); +int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, + unsigned cmd, unsigned long arg) +{ + struct gendisk *disk = bdev->bd_disk; + int ret; + /* you bet it'll go away by the end of patch series */ + struct file fake_file = {}; + struct dentry fake_dentry = {}; + fake_file.f_mode = mode; + fake_file.f_path.dentry = &fake_dentry; + fake_dentry.d_inode = bdev->bd_inode; + + if (disk->fops->unlocked_ioctl) + return disk->fops->unlocked_ioctl(&fake_file, cmd, arg); + + if (disk->fops->ioctl) { + lock_kernel(); + ret = disk->fops->ioctl(bdev->bd_inode, &fake_file, cmd, arg); + unlock_kernel(); + return ret; + } + + return -ENOTTY; +} +/* + * For the record: _GPL here is only because somebody decided to slap it + * on the previous export. Sheer idiocy, since it wasn't copyrightable + * at all and could be open-coded without any exports by anybody who cares. + */ +EXPORT_SYMBOL_GPL(__blkdev_driver_ioctl); + /* * always keep this in sync with compat_blkdev_ioctl() and * compat_blkdev_locked_ioctl() -- cgit From d4430d62fa77208824a37fe6f85ab2831d274769 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 2 Mar 2008 09:09:22 -0500 Subject: [PATCH] beginning of methods conversion To keep the size of changesets sane we split the switch by drivers; to keep the damn thing bisectable we do the following: 1) rename the affected methods, add ones with correct prototypes, make (few) callers handle both. That's this changeset. 2) for each driver convert to new methods. *ALL* drivers are converted in this series. 3) kill the old (renamed) methods. Note that it _is_ a flagday; all in-tree drivers are converted and by the end of this series no trace of old methods remain. The only reason why we do that this way is to keep the damn thing bisectable and allow per-driver debugging if anything goes wrong. New methods: open(bdev, mode) release(disk, mode) ioctl(bdev, mode, cmd, arg) /* Called without BKL */ compat_ioctl(bdev, mode, cmd, arg) locked_ioctl(bdev, mode, cmd, arg) /* Called with BKL, legacy */ Signed-off-by: Al Viro --- block/ioctl.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) (limited to 'block/ioctl.c') diff --git a/block/ioctl.c b/block/ioctl.c index 9a26ace6d04..01ff463bc80 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -269,17 +269,24 @@ 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); + fmode_t mode = 0; + if (file) { + mode = file->f_mode; + if (file->f_flags & O_NDELAY) + mode |= FMODE_NDELAY_NOW; + } + + if (disk->fops->__unlocked_ioctl) + return disk->fops->__unlocked_ioctl(file, cmd, arg); - if (disk->fops->ioctl) { + if (disk->fops->__ioctl) { lock_kernel(); - ret = disk->fops->ioctl(inode, file, cmd, arg); + ret = disk->fops->__ioctl(inode, file, cmd, arg); unlock_kernel(); return ret; } - return -ENOTTY; + return __blkdev_driver_ioctl(inode->i_bdev, mode, cmd, arg); } EXPORT_SYMBOL_GPL(blkdev_driver_ioctl); @@ -295,12 +302,22 @@ int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, fake_file.f_path.dentry = &fake_dentry; fake_dentry.d_inode = bdev->bd_inode; - if (disk->fops->unlocked_ioctl) - return disk->fops->unlocked_ioctl(&fake_file, cmd, arg); + if (disk->fops->__unlocked_ioctl) + return disk->fops->__unlocked_ioctl(&fake_file, cmd, arg); + + if (disk->fops->__ioctl) { + lock_kernel(); + ret = disk->fops->__ioctl(bdev->bd_inode, &fake_file, cmd, arg); + unlock_kernel(); + return ret; + } + + if (disk->fops->ioctl) + return disk->fops->ioctl(bdev, mode, cmd, arg); - if (disk->fops->ioctl) { + if (disk->fops->locked_ioctl) { lock_kernel(); - ret = disk->fops->ioctl(bdev->bd_inode, &fake_file, cmd, arg); + ret = disk->fops->locked_ioctl(bdev, mode, cmd, arg); unlock_kernel(); return ret; } -- cgit From 90b8f2824ce68dd87d304641a1d5a048dfff39f5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 2 Mar 2008 10:43:36 -0500 Subject: [PATCH] end of methods switch: remove the old ones Signed-off-by: Al Viro --- block/ioctl.c | 26 -------------------------- 1 file changed, 26 deletions(-) (limited to 'block/ioctl.c') diff --git a/block/ioctl.c b/block/ioctl.c index 01ff463bc80..0db89f95b15 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -276,16 +276,6 @@ int blkdev_driver_ioctl(struct inode *inode, struct file *file, mode |= FMODE_NDELAY_NOW; } - 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 __blkdev_driver_ioctl(inode->i_bdev, mode, cmd, arg); } EXPORT_SYMBOL_GPL(blkdev_driver_ioctl); @@ -295,22 +285,6 @@ int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, { struct gendisk *disk = bdev->bd_disk; int ret; - /* you bet it'll go away by the end of patch series */ - struct file fake_file = {}; - struct dentry fake_dentry = {}; - fake_file.f_mode = mode; - fake_file.f_path.dentry = &fake_dentry; - fake_dentry.d_inode = bdev->bd_inode; - - if (disk->fops->__unlocked_ioctl) - return disk->fops->__unlocked_ioctl(&fake_file, cmd, arg); - - if (disk->fops->__ioctl) { - lock_kernel(); - ret = disk->fops->__ioctl(bdev->bd_inode, &fake_file, cmd, arg); - unlock_kernel(); - return ret; - } if (disk->fops->ioctl) return disk->fops->ioctl(bdev, mode, cmd, arg); -- cgit From e436fdae70a31102d2be32969b80fe8545edebd9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 18 Sep 2008 03:38:12 -0400 Subject: [PATCH] get rid of blkdev_driver_ioctl() convert remaining callers to __blkdev_driver_ioctl() Signed-off-by: Al Viro --- block/ioctl.c | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) (limited to 'block/ioctl.c') diff --git a/block/ioctl.c b/block/ioctl.c index 0db89f95b15..b4e0abed1b4 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -265,21 +265,6 @@ static int blkdev_locked_ioctl(struct file *file, struct block_device *bdev, return -ENOIOCTLCMD; } -int blkdev_driver_ioctl(struct inode *inode, struct file *file, - struct gendisk *disk, unsigned cmd, unsigned long arg) -{ - int ret; - fmode_t mode = 0; - if (file) { - mode = file->f_mode; - if (file->f_flags & O_NDELAY) - mode |= FMODE_NDELAY_NOW; - } - - return __blkdev_driver_ioctl(inode->i_bdev, mode, cmd, arg); -} -EXPORT_SYMBOL_GPL(blkdev_driver_ioctl); - int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long arg) { @@ -315,13 +300,19 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, struct block_device *bdev = inode->i_bdev; struct gendisk *disk = bdev->bd_disk; int ret, n; + fmode_t mode = 0; + if (file) { + mode = file->f_mode; + if (file->f_flags & O_NDELAY) + mode |= FMODE_NDELAY_NOW; + } switch(cmd) { case BLKFLSBUF: if (!capable(CAP_SYS_ADMIN)) return -EACCES; - ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg); + ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg); /* -EINVAL to handle old uncorrected drivers */ if (ret != -EINVAL && ret != -ENOTTY) return ret; @@ -333,7 +324,7 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, return 0; case BLKROSET: - ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg); + ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg); /* -EINVAL to handle old uncorrected drivers */ if (ret != -EINVAL && ret != -ENOTTY) return ret; @@ -349,7 +340,7 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, case BLKDISCARD: { uint64_t range[2]; - if (!(file->f_mode & FMODE_WRITE)) + if (!(mode & FMODE_WRITE)) return -EBADF; if (copy_from_user(range, (void __user *)arg, sizeof(range))) @@ -387,6 +378,6 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, if (ret != -ENOIOCTLCMD) return ret; - return blkdev_driver_ioctl(inode, file, disk, cmd, arg); + ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg); } EXPORT_SYMBOL_GPL(blkdev_ioctl); -- cgit From 45048d0961cdbf7ddfba906797ad8cb42489e070 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 18 Sep 2008 15:53:24 -0400 Subject: [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: Al Viro --- block/ioctl.c | 142 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 70 insertions(+), 72 deletions(-) (limited to 'block/ioctl.c') diff --git a/block/ioctl.c b/block/ioctl.c index b4e0abed1b4..bd214cb37f2 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -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); -- cgit From 6af3a56e1dd4d95836a47214e5c60d5b749a5501 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 19 Sep 2008 03:08:13 -0400 Subject: [PATCH] get rid of struct file use in blkdev_ioctl() BLKBSZSET We need to do bd_claim() only if file hadn't been opened with O_EXCL and then we have no need to use file itself as owner. Signed-off-by: Al Viro --- block/ioctl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'block/ioctl.c') diff --git a/block/ioctl.c b/block/ioctl.c index bd214cb37f2..14b7f2c1066 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -343,10 +343,11 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, return -EINVAL; if (get_user(n, (int __user *) arg)) return -EFAULT; - if (bd_claim(bdev, file) < 0) + if (!(mode & FMODE_EXCL) && bd_claim(bdev, &bdev) < 0) return -EBUSY; ret = set_blocksize(bdev, n); - bd_release(bdev); + if (!(mode & FMODE_EXCL)) + bd_release(bdev); return ret; case BLKPG: lock_kernel(); -- cgit From 56b26add02b4bdea81d5e0ebda60db1fe3311ad4 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 19 Sep 2008 03:17:36 -0400 Subject: [PATCH] kill the rest of struct file propagation in block ioctls Now we can switch blkdev_ioctl() block_device/mode Signed-off-by: Al Viro --- block/ioctl.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'block/ioctl.c') diff --git a/block/ioctl.c b/block/ioctl.c index 14b7f2c1066..c832d639b6e 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -230,20 +230,13 @@ EXPORT_SYMBOL_GPL(__blkdev_driver_ioctl); * always keep this in sync with compat_blkdev_ioctl() and * compat_blkdev_locked_ioctl() */ -int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, +int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long arg) { - 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) { - mode = file->f_mode; - if (file->f_flags & O_NDELAY) - mode |= FMODE_NDELAY_NOW; - } switch(cmd) { case BLKFLSBUF: -- cgit