aboutsummaryrefslogtreecommitdiffstats
path: root/block/compat_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/compat_ioctl.c')
-rw-r--r--block/compat_ioctl.c177
1 files changed, 70 insertions, 107 deletions
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index 1e559fba7bdf..3d3e7a46f38c 100644
--- a/block/compat_ioctl.c
+++ b/block/compat_ioctl.c
@@ -71,8 +71,8 @@ static int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev,
71 return ret; 71 return ret;
72} 72}
73 73
74static int compat_hdio_ioctl(struct inode *inode, struct file *file, 74static int compat_hdio_ioctl(struct block_device *bdev, fmode_t mode,
75 struct gendisk *disk, unsigned int cmd, unsigned long arg) 75 unsigned int cmd, unsigned long arg)
76{ 76{
77 mm_segment_t old_fs = get_fs(); 77 mm_segment_t old_fs = get_fs();
78 unsigned long kval; 78 unsigned long kval;
@@ -80,7 +80,7 @@ static int compat_hdio_ioctl(struct inode *inode, struct file *file,
80 int error; 80 int error;
81 81
82 set_fs(KERNEL_DS); 82 set_fs(KERNEL_DS);
83 error = blkdev_driver_ioctl(inode, file, disk, 83 error = __blkdev_driver_ioctl(bdev, mode,
84 cmd, (unsigned long)(&kval)); 84 cmd, (unsigned long)(&kval));
85 set_fs(old_fs); 85 set_fs(old_fs);
86 86
@@ -111,8 +111,8 @@ struct compat_cdrom_generic_command {
111 compat_caddr_t reserved[1]; 111 compat_caddr_t reserved[1];
112}; 112};
113 113
114static int compat_cdrom_read_audio(struct inode *inode, struct file *file, 114static int compat_cdrom_read_audio(struct block_device *bdev, fmode_t mode,
115 struct gendisk *disk, unsigned int cmd, unsigned long arg) 115 unsigned int cmd, unsigned long arg)
116{ 116{
117 struct cdrom_read_audio __user *cdread_audio; 117 struct cdrom_read_audio __user *cdread_audio;
118 struct compat_cdrom_read_audio __user *cdread_audio32; 118 struct compat_cdrom_read_audio __user *cdread_audio32;
@@ -134,12 +134,12 @@ static int compat_cdrom_read_audio(struct inode *inode, struct file *file,
134 if (put_user(datap, &cdread_audio->buf)) 134 if (put_user(datap, &cdread_audio->buf))
135 return -EFAULT; 135 return -EFAULT;
136 136
137 return blkdev_driver_ioctl(inode, file, disk, cmd, 137 return __blkdev_driver_ioctl(bdev, mode, cmd,
138 (unsigned long)cdread_audio); 138 (unsigned long)cdread_audio);
139} 139}
140 140
141static int compat_cdrom_generic_command(struct inode *inode, struct file *file, 141static int compat_cdrom_generic_command(struct block_device *bdev, fmode_t mode,
142 struct gendisk *disk, unsigned int cmd, unsigned long arg) 142 unsigned int cmd, unsigned long arg)
143{ 143{
144 struct cdrom_generic_command __user *cgc; 144 struct cdrom_generic_command __user *cgc;
145 struct compat_cdrom_generic_command __user *cgc32; 145 struct compat_cdrom_generic_command __user *cgc32;
@@ -167,7 +167,7 @@ static int compat_cdrom_generic_command(struct inode *inode, struct file *file,
167 put_user(compat_ptr(data), &cgc->reserved[0])) 167 put_user(compat_ptr(data), &cgc->reserved[0]))
168 return -EFAULT; 168 return -EFAULT;
169 169
170 return blkdev_driver_ioctl(inode, file, disk, cmd, (unsigned long)cgc); 170 return __blkdev_driver_ioctl(bdev, mode, cmd, (unsigned long)cgc);
171} 171}
172 172
173struct compat_blkpg_ioctl_arg { 173struct compat_blkpg_ioctl_arg {
@@ -177,7 +177,7 @@ struct compat_blkpg_ioctl_arg {
177 compat_caddr_t data; 177 compat_caddr_t data;
178}; 178};
179 179
180static int compat_blkpg_ioctl(struct inode *inode, struct file *file, 180static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode,
181 unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32) 181 unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32)
182{ 182{
183 struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a)); 183 struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a));
@@ -196,7 +196,7 @@ static int compat_blkpg_ioctl(struct inode *inode, struct file *file,
196 if (err) 196 if (err)
197 return err; 197 return err;
198 198
199 return blkdev_ioctl(inode, file, cmd, (unsigned long)a); 199 return blkdev_ioctl(bdev, mode, cmd, (unsigned long)a);
200} 200}
201 201
202#define BLKBSZGET_32 _IOR(0x12, 112, int) 202#define BLKBSZGET_32 _IOR(0x12, 112, int)
@@ -308,8 +308,8 @@ static struct {
308 308
309#define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table) 309#define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table)
310 310
311static int compat_fd_ioctl(struct inode *inode, struct file *file, 311static int compat_fd_ioctl(struct block_device *bdev, fmode_t mode,
312 struct gendisk *disk, unsigned int cmd, unsigned long arg) 312 unsigned int cmd, unsigned long arg)
313{ 313{
314 mm_segment_t old_fs = get_fs(); 314 mm_segment_t old_fs = get_fs();
315 void *karg = NULL; 315 void *karg = NULL;
@@ -413,7 +413,7 @@ static int compat_fd_ioctl(struct inode *inode, struct file *file,
413 return -EINVAL; 413 return -EINVAL;
414 } 414 }
415 set_fs(KERNEL_DS); 415 set_fs(KERNEL_DS);
416 err = blkdev_driver_ioctl(inode, file, disk, kcmd, (unsigned long)karg); 416 err = __blkdev_driver_ioctl(bdev, mode, kcmd, (unsigned long)karg);
417 set_fs(old_fs); 417 set_fs(old_fs);
418 if (err) 418 if (err)
419 goto out; 419 goto out;
@@ -579,11 +579,9 @@ static int compat_blk_trace_setup(struct block_device *bdev, char __user *arg)
579 return 0; 579 return 0;
580} 580}
581 581
582static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file, 582static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
583 struct gendisk *disk, unsigned cmd, unsigned long arg) 583 unsigned cmd, unsigned long arg)
584{ 584{
585 int ret;
586
587 switch (cmd) { 585 switch (cmd) {
588 case HDIO_GET_UNMASKINTR: 586 case HDIO_GET_UNMASKINTR:
589 case HDIO_GET_MULTCOUNT: 587 case HDIO_GET_MULTCOUNT:
@@ -596,7 +594,7 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file,
596 case HDIO_GET_ACOUSTIC: 594 case HDIO_GET_ACOUSTIC:
597 case HDIO_GET_ADDRESS: 595 case HDIO_GET_ADDRESS:
598 case HDIO_GET_BUSSTATE: 596 case HDIO_GET_BUSSTATE:
599 return compat_hdio_ioctl(inode, file, disk, cmd, arg); 597 return compat_hdio_ioctl(bdev, mode, cmd, arg);
600 case FDSETPRM32: 598 case FDSETPRM32:
601 case FDDEFPRM32: 599 case FDDEFPRM32:
602 case FDGETPRM32: 600 case FDGETPRM32:
@@ -606,11 +604,11 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file,
606 case FDPOLLDRVSTAT32: 604 case FDPOLLDRVSTAT32:
607 case FDGETFDCSTAT32: 605 case FDGETFDCSTAT32:
608 case FDWERRORGET32: 606 case FDWERRORGET32:
609 return compat_fd_ioctl(inode, file, disk, cmd, arg); 607 return compat_fd_ioctl(bdev, mode, cmd, arg);
610 case CDROMREADAUDIO: 608 case CDROMREADAUDIO:
611 return compat_cdrom_read_audio(inode, file, disk, cmd, arg); 609 return compat_cdrom_read_audio(bdev, mode, cmd, arg);
612 case CDROM_SEND_PACKET: 610 case CDROM_SEND_PACKET:
613 return compat_cdrom_generic_command(inode, file, disk, cmd, arg); 611 return compat_cdrom_generic_command(bdev, mode, cmd, arg);
614 612
615 /* 613 /*
616 * No handler required for the ones below, we just need to 614 * No handler required for the ones below, we just need to
@@ -679,55 +677,49 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file,
679 case DVD_WRITE_STRUCT: 677 case DVD_WRITE_STRUCT:
680 case DVD_AUTH: 678 case DVD_AUTH:
681 arg = (unsigned long)compat_ptr(arg); 679 arg = (unsigned long)compat_ptr(arg);
682 /* These intepret arg as an unsigned long, not as a pointer,
683 * so we must not do compat_ptr() conversion. */
684 case HDIO_SET_MULTCOUNT:
685 case HDIO_SET_UNMASKINTR:
686 case HDIO_SET_KEEPSETTINGS:
687 case HDIO_SET_32BIT:
688 case HDIO_SET_NOWERR:
689 case HDIO_SET_DMA:
690 case HDIO_SET_PIO_MODE:
691 case HDIO_SET_NICE:
692 case HDIO_SET_WCACHE:
693 case HDIO_SET_ACOUSTIC:
694 case HDIO_SET_BUSSTATE:
695 case HDIO_SET_ADDRESS:
696 case CDROMEJECT_SW:
697 case CDROM_SET_OPTIONS:
698 case CDROM_CLEAR_OPTIONS:
699 case CDROM_SELECT_SPEED:
700 case CDROM_SELECT_DISC:
701 case CDROM_MEDIA_CHANGED:
702 case CDROM_DRIVE_STATUS:
703 case CDROM_LOCKDOOR:
704 case CDROM_DEBUG:
705 break; 680 break;
706 default: 681 default:
707 /* unknown ioctl number */ 682 /* unknown ioctl number */
708 return -ENOIOCTLCMD; 683 return -ENOIOCTLCMD;
709 } 684 }
710 685
711 if (disk->fops->unlocked_ioctl) 686 return __blkdev_driver_ioctl(bdev, mode, cmd, arg);
712 return disk->fops->unlocked_ioctl(file, cmd, arg);
713
714 if (disk->fops->ioctl) {
715 lock_kernel();
716 ret = disk->fops->ioctl(inode, file, cmd, arg);
717 unlock_kernel();
718 return ret;
719 }
720
721 return -ENOTTY;
722} 687}
723 688
724static int compat_blkdev_locked_ioctl(struct inode *inode, struct file *file, 689/* Most of the generic ioctls are handled in the normal fallback path.
725 struct block_device *bdev, 690 This assumes the blkdev's low level compat_ioctl always returns
726 unsigned cmd, unsigned long arg) 691 ENOIOCTLCMD for unknown ioctls. */
692long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
727{ 693{
694 int ret = -ENOIOCTLCMD;
695 struct inode *inode = file->f_mapping->host;
696 struct block_device *bdev = inode->i_bdev;
697 struct gendisk *disk = bdev->bd_disk;
698 fmode_t mode = file->f_mode;
728 struct backing_dev_info *bdi; 699 struct backing_dev_info *bdi;
700 loff_t size;
701
702 if (file->f_flags & O_NDELAY)
703 mode |= FMODE_NDELAY_NOW;
729 704
730 switch (cmd) { 705 switch (cmd) {
706 case HDIO_GETGEO:
707 return compat_hdio_getgeo(disk, bdev, compat_ptr(arg));
708 case BLKFLSBUF:
709 case BLKROSET:
710 case BLKDISCARD:
711 /*
712 * the ones below are implemented in blkdev_locked_ioctl,
713 * but we call blkdev_ioctl, which gets the lock for us
714 */
715 case BLKRRPART:
716 return blkdev_ioctl(bdev, mode, cmd,
717 (unsigned long)compat_ptr(arg));
718 case BLKBSZSET_32:
719 return blkdev_ioctl(bdev, mode, BLKBSZSET,
720 (unsigned long)compat_ptr(arg));
721 case BLKPG:
722 return compat_blkpg_ioctl(bdev, mode, cmd, compat_ptr(arg));
731 case BLKRAGET: 723 case BLKRAGET:
732 case BLKFRAGET: 724 case BLKFRAGET:
733 if (!arg) 725 if (!arg)
@@ -753,65 +745,36 @@ static int compat_blkdev_locked_ioctl(struct inode *inode, struct file *file,
753 bdi = blk_get_backing_dev_info(bdev); 745 bdi = blk_get_backing_dev_info(bdev);
754 if (bdi == NULL) 746 if (bdi == NULL)
755 return -ENOTTY; 747 return -ENOTTY;
748 lock_kernel();
756 bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; 749 bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
750 unlock_kernel();
757 return 0; 751 return 0;
758 case BLKGETSIZE: 752 case BLKGETSIZE:
759 if ((bdev->bd_inode->i_size >> 9) > ~0UL) 753 size = bdev->bd_inode->i_size;
754 if ((size >> 9) > ~0UL)
760 return -EFBIG; 755 return -EFBIG;
761 return compat_put_ulong(arg, bdev->bd_inode->i_size >> 9); 756 return compat_put_ulong(arg, size >> 9);
762 757
763 case BLKGETSIZE64_32: 758 case BLKGETSIZE64_32:
764 return compat_put_u64(arg, bdev->bd_inode->i_size); 759 return compat_put_u64(arg, bdev->bd_inode->i_size);
765 760
766 case BLKTRACESETUP32: 761 case BLKTRACESETUP32:
767 return compat_blk_trace_setup(bdev, compat_ptr(arg)); 762 lock_kernel();
763 ret = compat_blk_trace_setup(bdev, compat_ptr(arg));
764 unlock_kernel();
765 return ret;
768 case BLKTRACESTART: /* compatible */ 766 case BLKTRACESTART: /* compatible */
769 case BLKTRACESTOP: /* compatible */ 767 case BLKTRACESTOP: /* compatible */
770 case BLKTRACETEARDOWN: /* compatible */ 768 case BLKTRACETEARDOWN: /* compatible */
771 return blk_trace_ioctl(bdev, cmd, compat_ptr(arg)); 769 lock_kernel();
772 } 770 ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg));
773 return -ENOIOCTLCMD; 771 unlock_kernel();
774}
775
776/* Most of the generic ioctls are handled in the normal fallback path.
777 This assumes the blkdev's low level compat_ioctl always returns
778 ENOIOCTLCMD for unknown ioctls. */
779long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
780{
781 int ret = -ENOIOCTLCMD;
782 struct inode *inode = file->f_mapping->host;
783 struct block_device *bdev = inode->i_bdev;
784 struct gendisk *disk = bdev->bd_disk;
785
786 switch (cmd) {
787 case HDIO_GETGEO:
788 return compat_hdio_getgeo(disk, bdev, compat_ptr(arg));
789 case BLKFLSBUF:
790 case BLKROSET:
791 case BLKDISCARD:
792 /*
793 * the ones below are implemented in blkdev_locked_ioctl,
794 * but we call blkdev_ioctl, which gets the lock for us
795 */
796 case BLKRRPART:
797 return blkdev_ioctl(inode, file, cmd,
798 (unsigned long)compat_ptr(arg));
799 case BLKBSZSET_32:
800 return blkdev_ioctl(inode, file, BLKBSZSET,
801 (unsigned long)compat_ptr(arg));
802 case BLKPG:
803 return compat_blkpg_ioctl(inode, file, cmd, compat_ptr(arg));
804 }
805
806 lock_kernel();
807 ret = compat_blkdev_locked_ioctl(inode, file, bdev, cmd, arg);
808 /* FIXME: why do we assume -> compat_ioctl needs the BKL? */
809 if (ret == -ENOIOCTLCMD && disk->fops->compat_ioctl)
810 ret = disk->fops->compat_ioctl(file, cmd, arg);
811 unlock_kernel();
812
813 if (ret != -ENOIOCTLCMD)
814 return ret; 772 return ret;
815 773 default:
816 return compat_blkdev_driver_ioctl(inode, file, disk, cmd, arg); 774 if (disk->fops->compat_ioctl)
775 ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg);
776 if (ret == -ENOIOCTLCMD)
777 ret = compat_blkdev_driver_ioctl(bdev, mode, cmd, arg);
778 return ret;
779 }
817} 780}