diff options
Diffstat (limited to 'block/compat_ioctl.c')
-rw-r--r-- | block/compat_ioctl.c | 175 |
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 | ||
74 | static int compat_hdio_ioctl(struct inode *inode, struct file *file, | 74 | static 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 | ||
114 | static int compat_cdrom_read_audio(struct inode *inode, struct file *file, | 114 | static 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 | ||
141 | static int compat_cdrom_generic_command(struct inode *inode, struct file *file, | 141 | static 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 | ||
173 | struct compat_blkpg_ioctl_arg { | 173 | struct 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 | ||
180 | static int compat_blkpg_ioctl(struct inode *inode, struct file *file, | 180 | static 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 | ||
311 | static int compat_fd_ioctl(struct inode *inode, struct file *file, | 311 | static 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 | ||
582 | static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file, | 582 | static 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 | ||
724 | static 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. */ |
694 | long 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. */ | ||
779 | long 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 | } |