aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/compat_ioctl.c101
-rw-r--r--block/ioctl.c142
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
691static 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. */
694long 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. */
745long 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
204static 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
268int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, 204int __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}
383EXPORT_SYMBOL_GPL(blkdev_ioctl); 381EXPORT_SYMBOL_GPL(blkdev_ioctl);