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); |
