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.c175
1 files changed, 70 insertions, 105 deletions
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index 1e559fba7bdf..3098c92402fd 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,8 +579,8 @@ 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; 585 int ret;
586 586
@@ -596,7 +596,7 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file,
596 case HDIO_GET_ACOUSTIC: 596 case HDIO_GET_ACOUSTIC:
597 case HDIO_GET_ADDRESS: 597 case HDIO_GET_ADDRESS:
598 case HDIO_GET_BUSSTATE: 598 case HDIO_GET_BUSSTATE:
599 return compat_hdio_ioctl(inode, file, disk, cmd, arg); 599 return compat_hdio_ioctl(bdev, mode, cmd, arg);
600 case FDSETPRM32: 600 case FDSETPRM32:
601 case FDDEFPRM32: 601 case FDDEFPRM32:
602 case FDGETPRM32: 602 case FDGETPRM32:
@@ -606,11 +606,11 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file,
606 case FDPOLLDRVSTAT32: 606 case FDPOLLDRVSTAT32:
607 case FDGETFDCSTAT32: 607 case FDGETFDCSTAT32:
608 case FDWERRORGET32: 608 case FDWERRORGET32:
609 return compat_fd_ioctl(inode, file, disk, cmd, arg); 609 return compat_fd_ioctl(bdev, mode, cmd, arg);
610 case CDROMREADAUDIO: 610 case CDROMREADAUDIO:
611 return compat_cdrom_read_audio(inode, file, disk, cmd, arg); 611 return compat_cdrom_read_audio(bdev, mode, cmd, arg);
612 case CDROM_SEND_PACKET: 612 case CDROM_SEND_PACKET:
613 return compat_cdrom_generic_command(inode, file, disk, cmd, arg); 613 return compat_cdrom_generic_command(bdev, mode, cmd, arg);
614 614
615 /* 615 /*
616 * No handler required for the ones below, we just need to 616 * No handler required for the ones below, we just need to
@@ -679,55 +679,49 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file,
679 case DVD_WRITE_STRUCT: 679 case DVD_WRITE_STRUCT:
680 case DVD_AUTH: 680 case DVD_AUTH:
681 arg = (unsigned long)compat_ptr(arg); 681 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; 682 break;
706 default: 683 default:
707 /* unknown ioctl number */ 684 /* unknown ioctl number */
708 return -ENOIOCTLCMD; 685 return -ENOIOCTLCMD;
709 } 686 }
710 687
711 if (disk->fops->unlocked_ioctl) 688 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} 689}
723 690
724static int compat_blkdev_locked_ioctl(struct inode *inode, struct file *file, 691/* Most of the generic ioctls are handled in the normal fallback path.
725 struct block_device *bdev, 692 This assumes the blkdev's low level compat_ioctl always returns
726 unsigned cmd, unsigned long arg) 693 ENOIOCTLCMD for unknown ioctls. */
694long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
727{ 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;
728 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;
729 706
730 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(bdev, mode, cmd,
719 (unsigned long)compat_ptr(arg));
720 case BLKBSZSET_32:
721 return blkdev_ioctl(bdev, mode, BLKBSZSET,
722 (unsigned long)compat_ptr(arg));
723 case BLKPG:
724 return compat_blkpg_ioctl(bdev, mode, cmd, compat_ptr(arg));
731 case BLKRAGET: 725 case BLKRAGET:
732 case BLKFRAGET: 726 case BLKFRAGET:
733 if (!arg) 727 if (!arg)
@@ -753,65 +747,36 @@ static int compat_blkdev_locked_ioctl(struct inode *inode, struct file *file,
753 bdi = blk_get_backing_dev_info(bdev); 747 bdi = blk_get_backing_dev_info(bdev);
754 if (bdi == NULL) 748 if (bdi == NULL)
755 return -ENOTTY; 749 return -ENOTTY;
750 lock_kernel();
756 bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; 751 bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
752 unlock_kernel();
757 return 0; 753 return 0;
758 case BLKGETSIZE: 754 case BLKGETSIZE:
759 if ((bdev->bd_inode->i_size >> 9) > ~0UL) 755 size = bdev->bd_inode->i_size;
756 if ((size >> 9) > ~0UL)
760 return -EFBIG; 757 return -EFBIG;
761 return compat_put_ulong(arg, bdev->bd_inode->i_size >> 9); 758 return compat_put_ulong(arg, size >> 9);
762 759
763 case BLKGETSIZE64_32: 760 case BLKGETSIZE64_32:
764 return compat_put_u64(arg, bdev->bd_inode->i_size); 761 return compat_put_u64(arg, bdev->bd_inode->i_size);
765 762
766 case BLKTRACESETUP32: 763 case BLKTRACESETUP32:
767 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;
768 case BLKTRACESTART: /* compatible */ 768 case BLKTRACESTART: /* compatible */
769 case BLKTRACESTOP: /* compatible */ 769 case BLKTRACESTOP: /* compatible */
770 case BLKTRACETEARDOWN: /* compatible */ 770 case BLKTRACETEARDOWN: /* compatible */
771 return blk_trace_ioctl(bdev, cmd, compat_ptr(arg)); 771 lock_kernel();
772 } 772 ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg));
773 return -ENOIOCTLCMD; 773 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; 774 return ret;
815 775 default:
816 return compat_blkdev_driver_ioctl(inode, file, disk, 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 }
817} 782}