diff options
-rw-r--r-- | block/compat_ioctl.c | 101 | ||||
-rw-r--r-- | block/ioctl.c | 142 |
2 files changed, 119 insertions, 124 deletions
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 504344d29022..5b3db0640d87 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c | |||
@@ -688,12 +688,40 @@ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, | |||
688 | return __blkdev_driver_ioctl(bdev, mode, cmd, arg); | 688 | return __blkdev_driver_ioctl(bdev, mode, cmd, arg); |
689 | } | 689 | } |
690 | 690 | ||
691 | static int compat_blkdev_locked_ioctl(struct block_device *bdev, | 691 | /* Most of the generic ioctls are handled in the normal fallback path. |
692 | unsigned cmd, unsigned long arg) | 692 | This assumes the blkdev's low level compat_ioctl always returns |
693 | ENOIOCTLCMD for unknown ioctls. */ | ||
694 | long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) | ||
693 | { | 695 | { |
696 | int ret = -ENOIOCTLCMD; | ||
697 | struct inode *inode = file->f_mapping->host; | ||
698 | struct block_device *bdev = inode->i_bdev; | ||
699 | struct gendisk *disk = bdev->bd_disk; | ||
700 | fmode_t mode = file->f_mode; | ||
694 | struct backing_dev_info *bdi; | 701 | struct backing_dev_info *bdi; |
702 | loff_t size; | ||
703 | |||
704 | if (file->f_flags & O_NDELAY) | ||
705 | mode |= FMODE_NDELAY_NOW; | ||
695 | 706 | ||
696 | switch (cmd) { | 707 | switch (cmd) { |
708 | case HDIO_GETGEO: | ||
709 | return compat_hdio_getgeo(disk, bdev, compat_ptr(arg)); | ||
710 | case BLKFLSBUF: | ||
711 | case BLKROSET: | ||
712 | case BLKDISCARD: | ||
713 | /* | ||
714 | * the ones below are implemented in blkdev_locked_ioctl, | ||
715 | * but we call blkdev_ioctl, which gets the lock for us | ||
716 | */ | ||
717 | case BLKRRPART: | ||
718 | return blkdev_ioctl(inode, file, cmd, | ||
719 | (unsigned long)compat_ptr(arg)); | ||
720 | case BLKBSZSET_32: | ||
721 | return blkdev_ioctl(inode, file, BLKBSZSET, | ||
722 | (unsigned long)compat_ptr(arg)); | ||
723 | case BLKPG: | ||
724 | return compat_blkpg_ioctl(inode, file, cmd, compat_ptr(arg)); | ||
697 | case BLKRAGET: | 725 | case BLKRAGET: |
698 | case BLKFRAGET: | 726 | case BLKFRAGET: |
699 | if (!arg) | 727 | if (!arg) |
@@ -719,67 +747,36 @@ static int compat_blkdev_locked_ioctl(struct block_device *bdev, | |||
719 | bdi = blk_get_backing_dev_info(bdev); | 747 | bdi = blk_get_backing_dev_info(bdev); |
720 | if (bdi == NULL) | 748 | if (bdi == NULL) |
721 | return -ENOTTY; | 749 | return -ENOTTY; |
750 | lock_kernel(); | ||
722 | bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; | 751 | bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; |
752 | unlock_kernel(); | ||
723 | return 0; | 753 | return 0; |
724 | case BLKGETSIZE: | 754 | case BLKGETSIZE: |
725 | if ((bdev->bd_inode->i_size >> 9) > ~0UL) | 755 | size = bdev->bd_inode->i_size; |
756 | if ((size >> 9) > ~0UL) | ||
726 | return -EFBIG; | 757 | return -EFBIG; |
727 | return compat_put_ulong(arg, bdev->bd_inode->i_size >> 9); | 758 | return compat_put_ulong(arg, size >> 9); |
728 | 759 | ||
729 | case BLKGETSIZE64_32: | 760 | case BLKGETSIZE64_32: |
730 | return compat_put_u64(arg, bdev->bd_inode->i_size); | 761 | return compat_put_u64(arg, bdev->bd_inode->i_size); |
731 | 762 | ||
732 | case BLKTRACESETUP32: | 763 | case BLKTRACESETUP32: |
733 | return compat_blk_trace_setup(bdev, compat_ptr(arg)); | 764 | lock_kernel(); |
765 | ret = compat_blk_trace_setup(bdev, compat_ptr(arg)); | ||
766 | unlock_kernel(); | ||
767 | return ret; | ||
734 | case BLKTRACESTART: /* compatible */ | 768 | case BLKTRACESTART: /* compatible */ |
735 | case BLKTRACESTOP: /* compatible */ | 769 | case BLKTRACESTOP: /* compatible */ |
736 | case BLKTRACETEARDOWN: /* compatible */ | 770 | case BLKTRACETEARDOWN: /* compatible */ |
737 | return blk_trace_ioctl(bdev, cmd, compat_ptr(arg)); | 771 | lock_kernel(); |
738 | } | 772 | ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg)); |
739 | return -ENOIOCTLCMD; | 773 | unlock_kernel(); |
740 | } | ||
741 | |||
742 | /* Most of the generic ioctls are handled in the normal fallback path. | ||
743 | This assumes the blkdev's low level compat_ioctl always returns | ||
744 | ENOIOCTLCMD for unknown ioctls. */ | ||
745 | long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) | ||
746 | { | ||
747 | int ret = -ENOIOCTLCMD; | ||
748 | struct inode *inode = file->f_mapping->host; | ||
749 | struct block_device *bdev = inode->i_bdev; | ||
750 | struct gendisk *disk = bdev->bd_disk; | ||
751 | fmode_t mode = file->f_mode; | ||
752 | if (file->f_flags & O_NDELAY) | ||
753 | mode |= FMODE_NDELAY_NOW; | ||
754 | |||
755 | switch (cmd) { | ||
756 | case HDIO_GETGEO: | ||
757 | return compat_hdio_getgeo(disk, bdev, compat_ptr(arg)); | ||
758 | case BLKFLSBUF: | ||
759 | case BLKROSET: | ||
760 | case BLKDISCARD: | ||
761 | /* | ||
762 | * the ones below are implemented in blkdev_locked_ioctl, | ||
763 | * but we call blkdev_ioctl, which gets the lock for us | ||
764 | */ | ||
765 | case BLKRRPART: | ||
766 | return blkdev_ioctl(inode, file, cmd, | ||
767 | (unsigned long)compat_ptr(arg)); | ||
768 | case BLKBSZSET_32: | ||
769 | return blkdev_ioctl(inode, file, BLKBSZSET, | ||
770 | (unsigned long)compat_ptr(arg)); | ||
771 | case BLKPG: | ||
772 | return compat_blkpg_ioctl(inode, file, cmd, compat_ptr(arg)); | ||
773 | } | ||
774 | |||
775 | lock_kernel(); | ||
776 | ret = compat_blkdev_locked_ioctl(bdev, cmd, arg); | ||
777 | unlock_kernel(); | ||
778 | if (ret == -ENOIOCTLCMD && disk->fops->compat_ioctl) | ||
779 | ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg); | ||
780 | |||
781 | if (ret != -ENOIOCTLCMD) | ||
782 | return ret; | 774 | return ret; |
783 | 775 | default: | |
784 | return compat_blkdev_driver_ioctl(bdev, mode, cmd, arg); | 776 | if (disk->fops->compat_ioctl) |
777 | ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg); | ||
778 | if (ret == -ENOIOCTLCMD) | ||
779 | ret = compat_blkdev_driver_ioctl(bdev, mode, cmd, arg); | ||
780 | return ret; | ||
781 | } | ||
785 | } | 782 | } |
diff --git a/block/ioctl.c b/block/ioctl.c index b4e0abed1b4b..bd214cb37f2b 100644 --- a/block/ioctl.c +++ b/block/ioctl.c | |||
@@ -201,70 +201,6 @@ static int put_u64(unsigned long arg, u64 val) | |||
201 | return put_user(val, (u64 __user *)arg); | 201 | return put_user(val, (u64 __user *)arg); |
202 | } | 202 | } |
203 | 203 | ||
204 | static int blkdev_locked_ioctl(struct file *file, struct block_device *bdev, | ||
205 | unsigned cmd, unsigned long arg) | ||
206 | { | ||
207 | struct backing_dev_info *bdi; | ||
208 | int ret, n; | ||
209 | |||
210 | switch (cmd) { | ||
211 | case BLKRAGET: | ||
212 | case BLKFRAGET: | ||
213 | if (!arg) | ||
214 | return -EINVAL; | ||
215 | bdi = blk_get_backing_dev_info(bdev); | ||
216 | if (bdi == NULL) | ||
217 | return -ENOTTY; | ||
218 | return put_long(arg, (bdi->ra_pages * PAGE_CACHE_SIZE) / 512); | ||
219 | case BLKROGET: | ||
220 | return put_int(arg, bdev_read_only(bdev) != 0); | ||
221 | case BLKBSZGET: /* get the logical block size (cf. BLKSSZGET) */ | ||
222 | return put_int(arg, block_size(bdev)); | ||
223 | case BLKSSZGET: /* get block device hardware sector size */ | ||
224 | return put_int(arg, bdev_hardsect_size(bdev)); | ||
225 | case BLKSECTGET: | ||
226 | return put_ushort(arg, bdev_get_queue(bdev)->max_sectors); | ||
227 | case BLKRASET: | ||
228 | case BLKFRASET: | ||
229 | if(!capable(CAP_SYS_ADMIN)) | ||
230 | return -EACCES; | ||
231 | bdi = blk_get_backing_dev_info(bdev); | ||
232 | if (bdi == NULL) | ||
233 | return -ENOTTY; | ||
234 | bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; | ||
235 | return 0; | ||
236 | case BLKBSZSET: | ||
237 | /* set the logical block size */ | ||
238 | if (!capable(CAP_SYS_ADMIN)) | ||
239 | return -EACCES; | ||
240 | if (!arg) | ||
241 | return -EINVAL; | ||
242 | if (get_user(n, (int __user *) arg)) | ||
243 | return -EFAULT; | ||
244 | if (bd_claim(bdev, file) < 0) | ||
245 | return -EBUSY; | ||
246 | ret = set_blocksize(bdev, n); | ||
247 | bd_release(bdev); | ||
248 | return ret; | ||
249 | case BLKPG: | ||
250 | return blkpg_ioctl(bdev, (struct blkpg_ioctl_arg __user *) arg); | ||
251 | case BLKRRPART: | ||
252 | return blkdev_reread_part(bdev); | ||
253 | case BLKGETSIZE: | ||
254 | if ((bdev->bd_inode->i_size >> 9) > ~0UL) | ||
255 | return -EFBIG; | ||
256 | return put_ulong(arg, bdev->bd_inode->i_size >> 9); | ||
257 | case BLKGETSIZE64: | ||
258 | return put_u64(arg, bdev->bd_inode->i_size); | ||
259 | case BLKTRACESTART: | ||
260 | case BLKTRACESTOP: | ||
261 | case BLKTRACESETUP: | ||
262 | case BLKTRACETEARDOWN: | ||
263 | return blk_trace_ioctl(bdev, cmd, (char __user *) arg); | ||
264 | } | ||
265 | return -ENOIOCTLCMD; | ||
266 | } | ||
267 | |||
268 | int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, | 204 | int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, |
269 | unsigned cmd, unsigned long arg) | 205 | unsigned cmd, unsigned long arg) |
270 | { | 206 | { |
@@ -299,6 +235,8 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, | |||
299 | { | 235 | { |
300 | struct block_device *bdev = inode->i_bdev; | 236 | struct block_device *bdev = inode->i_bdev; |
301 | struct gendisk *disk = bdev->bd_disk; | 237 | struct gendisk *disk = bdev->bd_disk; |
238 | struct backing_dev_info *bdi; | ||
239 | loff_t size; | ||
302 | int ret, n; | 240 | int ret, n; |
303 | fmode_t mode = 0; | 241 | fmode_t mode = 0; |
304 | if (file) { | 242 | if (file) { |
@@ -370,14 +308,74 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, | |||
370 | return -EFAULT; | 308 | return -EFAULT; |
371 | return 0; | 309 | return 0; |
372 | } | 310 | } |
373 | } | 311 | case BLKRAGET: |
374 | 312 | case BLKFRAGET: | |
375 | lock_kernel(); | 313 | if (!arg) |
376 | ret = blkdev_locked_ioctl(file, bdev, cmd, arg); | 314 | return -EINVAL; |
377 | unlock_kernel(); | 315 | bdi = blk_get_backing_dev_info(bdev); |
378 | if (ret != -ENOIOCTLCMD) | 316 | if (bdi == NULL) |
317 | return -ENOTTY; | ||
318 | return put_long(arg, (bdi->ra_pages * PAGE_CACHE_SIZE) / 512); | ||
319 | case BLKROGET: | ||
320 | return put_int(arg, bdev_read_only(bdev) != 0); | ||
321 | case BLKBSZGET: /* get the logical block size (cf. BLKSSZGET) */ | ||
322 | return put_int(arg, block_size(bdev)); | ||
323 | case BLKSSZGET: /* get block device hardware sector size */ | ||
324 | return put_int(arg, bdev_hardsect_size(bdev)); | ||
325 | case BLKSECTGET: | ||
326 | return put_ushort(arg, bdev_get_queue(bdev)->max_sectors); | ||
327 | case BLKRASET: | ||
328 | case BLKFRASET: | ||
329 | if(!capable(CAP_SYS_ADMIN)) | ||
330 | return -EACCES; | ||
331 | bdi = blk_get_backing_dev_info(bdev); | ||
332 | if (bdi == NULL) | ||
333 | return -ENOTTY; | ||
334 | lock_kernel(); | ||
335 | bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; | ||
336 | unlock_kernel(); | ||
337 | return 0; | ||
338 | case BLKBSZSET: | ||
339 | /* set the logical block size */ | ||
340 | if (!capable(CAP_SYS_ADMIN)) | ||
341 | return -EACCES; | ||
342 | if (!arg) | ||
343 | return -EINVAL; | ||
344 | if (get_user(n, (int __user *) arg)) | ||
345 | return -EFAULT; | ||
346 | if (bd_claim(bdev, file) < 0) | ||
347 | return -EBUSY; | ||
348 | ret = set_blocksize(bdev, n); | ||
349 | bd_release(bdev); | ||
379 | return ret; | 350 | return ret; |
380 | 351 | case BLKPG: | |
381 | ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg); | 352 | lock_kernel(); |
353 | ret = blkpg_ioctl(bdev, (struct blkpg_ioctl_arg __user *) arg); | ||
354 | unlock_kernel(); | ||
355 | break; | ||
356 | case BLKRRPART: | ||
357 | lock_kernel(); | ||
358 | ret = blkdev_reread_part(bdev); | ||
359 | unlock_kernel(); | ||
360 | break; | ||
361 | case BLKGETSIZE: | ||
362 | size = bdev->bd_inode->i_size; | ||
363 | if ((size >> 9) > ~0UL) | ||
364 | return -EFBIG; | ||
365 | return put_ulong(arg, size >> 9); | ||
366 | case BLKGETSIZE64: | ||
367 | return put_u64(arg, bdev->bd_inode->i_size); | ||
368 | case BLKTRACESTART: | ||
369 | case BLKTRACESTOP: | ||
370 | case BLKTRACESETUP: | ||
371 | case BLKTRACETEARDOWN: | ||
372 | lock_kernel(); | ||
373 | ret = blk_trace_ioctl(bdev, cmd, (char __user *) arg); | ||
374 | unlock_kernel(); | ||
375 | break; | ||
376 | default: | ||
377 | ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg); | ||
378 | } | ||
379 | return ret; | ||
382 | } | 380 | } |
383 | EXPORT_SYMBOL_GPL(blkdev_ioctl); | 381 | EXPORT_SYMBOL_GPL(blkdev_ioctl); |