compat_ioctl.c revision b3087cc4f31a66c8c7b63419e913ed9d34145f10
1f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/blkdev.h>
2f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/blkpg.h>
3f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/blktrace_api.h>
4f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/cdrom.h>
5f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/compat.h>
6f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/elevator.h>
7f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/fd.h>
8f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/hdreg.h>
9f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/syscalls.h>
10f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/smp_lock.h>
11f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/types.h>
12f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/uaccess.h>
13f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann
14f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmannstatic int compat_put_ushort(unsigned long arg, unsigned short val)
15f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann{
16f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	return put_user(val, (unsigned short __user *)compat_ptr(arg));
17f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann}
18f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann
19f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmannstatic int compat_put_int(unsigned long arg, int val)
20f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann{
21f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	return put_user(val, (compat_int_t __user *)compat_ptr(arg));
22f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann}
23f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann
24f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmannstatic int compat_put_long(unsigned long arg, long val)
25f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann{
26f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	return put_user(val, (compat_long_t __user *)compat_ptr(arg));
27f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann}
28f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann
29f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmannstatic int compat_put_ulong(unsigned long arg, compat_ulong_t val)
30f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann{
31f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	return put_user(val, (compat_ulong_t __user *)compat_ptr(arg));
32f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann}
33f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann
34f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmannstatic int compat_put_u64(unsigned long arg, u64 val)
35f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann{
36f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	return put_user(val, (compat_u64 __user *)compat_ptr(arg));
37f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann}
38f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann
399617db085c119879cd371e3212806a15596e121aArnd Bergmannstruct compat_hd_geometry {
409617db085c119879cd371e3212806a15596e121aArnd Bergmann	unsigned char heads;
419617db085c119879cd371e3212806a15596e121aArnd Bergmann	unsigned char sectors;
429617db085c119879cd371e3212806a15596e121aArnd Bergmann	unsigned short cylinders;
439617db085c119879cd371e3212806a15596e121aArnd Bergmann	u32 start;
449617db085c119879cd371e3212806a15596e121aArnd Bergmann};
459617db085c119879cd371e3212806a15596e121aArnd Bergmann
469617db085c119879cd371e3212806a15596e121aArnd Bergmannstatic int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev,
479617db085c119879cd371e3212806a15596e121aArnd Bergmann			struct compat_hd_geometry __user *ugeo)
489617db085c119879cd371e3212806a15596e121aArnd Bergmann{
499617db085c119879cd371e3212806a15596e121aArnd Bergmann	struct hd_geometry geo;
509617db085c119879cd371e3212806a15596e121aArnd Bergmann	int ret;
519617db085c119879cd371e3212806a15596e121aArnd Bergmann
529617db085c119879cd371e3212806a15596e121aArnd Bergmann	if (!ugeo)
539617db085c119879cd371e3212806a15596e121aArnd Bergmann		return -EINVAL;
549617db085c119879cd371e3212806a15596e121aArnd Bergmann	if (!disk->fops->getgeo)
559617db085c119879cd371e3212806a15596e121aArnd Bergmann		return -ENOTTY;
569617db085c119879cd371e3212806a15596e121aArnd Bergmann
579617db085c119879cd371e3212806a15596e121aArnd Bergmann	/*
589617db085c119879cd371e3212806a15596e121aArnd Bergmann	 * We need to set the startsect first, the driver may
599617db085c119879cd371e3212806a15596e121aArnd Bergmann	 * want to override it.
609617db085c119879cd371e3212806a15596e121aArnd Bergmann	 */
619617db085c119879cd371e3212806a15596e121aArnd Bergmann	geo.start = get_start_sect(bdev);
629617db085c119879cd371e3212806a15596e121aArnd Bergmann	ret = disk->fops->getgeo(bdev, &geo);
639617db085c119879cd371e3212806a15596e121aArnd Bergmann	if (ret)
649617db085c119879cd371e3212806a15596e121aArnd Bergmann		return ret;
659617db085c119879cd371e3212806a15596e121aArnd Bergmann
669617db085c119879cd371e3212806a15596e121aArnd Bergmann	ret = copy_to_user(ugeo, &geo, 4);
679617db085c119879cd371e3212806a15596e121aArnd Bergmann	ret |= __put_user(geo.start, &ugeo->start);
689617db085c119879cd371e3212806a15596e121aArnd Bergmann	if (ret)
699617db085c119879cd371e3212806a15596e121aArnd Bergmann		ret = -EFAULT;
709617db085c119879cd371e3212806a15596e121aArnd Bergmann
719617db085c119879cd371e3212806a15596e121aArnd Bergmann	return ret;
729617db085c119879cd371e3212806a15596e121aArnd Bergmann}
739617db085c119879cd371e3212806a15596e121aArnd Bergmann
749617db085c119879cd371e3212806a15596e121aArnd Bergmannstatic int compat_hdio_ioctl(struct inode *inode, struct file *file,
759617db085c119879cd371e3212806a15596e121aArnd Bergmann		struct gendisk *disk, unsigned int cmd, unsigned long arg)
769617db085c119879cd371e3212806a15596e121aArnd Bergmann{
779617db085c119879cd371e3212806a15596e121aArnd Bergmann	mm_segment_t old_fs = get_fs();
789617db085c119879cd371e3212806a15596e121aArnd Bergmann	unsigned long kval;
799617db085c119879cd371e3212806a15596e121aArnd Bergmann	unsigned int __user *uvp;
809617db085c119879cd371e3212806a15596e121aArnd Bergmann	int error;
819617db085c119879cd371e3212806a15596e121aArnd Bergmann
829617db085c119879cd371e3212806a15596e121aArnd Bergmann	set_fs(KERNEL_DS);
839617db085c119879cd371e3212806a15596e121aArnd Bergmann	error = blkdev_driver_ioctl(inode, file, disk,
849617db085c119879cd371e3212806a15596e121aArnd Bergmann				cmd, (unsigned long)(&kval));
859617db085c119879cd371e3212806a15596e121aArnd Bergmann	set_fs(old_fs);
869617db085c119879cd371e3212806a15596e121aArnd Bergmann
879617db085c119879cd371e3212806a15596e121aArnd Bergmann	if (error == 0) {
889617db085c119879cd371e3212806a15596e121aArnd Bergmann		uvp = compat_ptr(arg);
899617db085c119879cd371e3212806a15596e121aArnd Bergmann		if (put_user(kval, uvp))
909617db085c119879cd371e3212806a15596e121aArnd Bergmann			error = -EFAULT;
919617db085c119879cd371e3212806a15596e121aArnd Bergmann	}
929617db085c119879cd371e3212806a15596e121aArnd Bergmann	return error;
939617db085c119879cd371e3212806a15596e121aArnd Bergmann}
949617db085c119879cd371e3212806a15596e121aArnd Bergmann
95b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmannstruct compat_cdrom_read_audio {
96b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	union cdrom_addr	addr;
97b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	u8			addr_format;
98b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	compat_int_t		nframes;
99b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	compat_caddr_t		buf;
100b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann};
101b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann
102b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmannstruct compat_cdrom_generic_command {
103b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	unsigned char	cmd[CDROM_PACKET_SIZE];
104b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	compat_caddr_t	buffer;
105b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	compat_uint_t	buflen;
106b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	compat_int_t	stat;
107b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	compat_caddr_t	sense;
108b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	unsigned char	data_direction;
109b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	compat_int_t	quiet;
110b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	compat_int_t	timeout;
111b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	compat_caddr_t	reserved[1];
112b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann};
113b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann
114b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmannstatic int compat_cdrom_read_audio(struct inode *inode, struct file *file,
115b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann		struct gendisk *disk, unsigned int cmd, unsigned long arg)
116b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann{
117b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	struct cdrom_read_audio __user *cdread_audio;
118b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	struct compat_cdrom_read_audio __user *cdread_audio32;
119b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	__u32 data;
120b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	void __user *datap;
121b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann
122b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	cdread_audio = compat_alloc_user_space(sizeof(*cdread_audio));
123b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	cdread_audio32 = compat_ptr(arg);
124b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann
125b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	if (copy_in_user(&cdread_audio->addr,
126b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann			 &cdread_audio32->addr,
127b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann			 (sizeof(*cdread_audio32) -
128b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann			  sizeof(compat_caddr_t))))
129b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann		return -EFAULT;
130b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann
131b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	if (get_user(data, &cdread_audio32->buf))
132b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann		return -EFAULT;
133b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	datap = compat_ptr(data);
134b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	if (put_user(datap, &cdread_audio->buf))
135b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann		return -EFAULT;
136b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann
137b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	return blkdev_driver_ioctl(inode, file, disk, cmd,
138b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann			(unsigned long)cdread_audio);
139b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann}
140b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann
141b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmannstatic int compat_cdrom_generic_command(struct inode *inode, struct file *file,
142b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann		struct gendisk *disk, unsigned int cmd, unsigned long arg)
143b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann{
144b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	struct cdrom_generic_command __user *cgc;
145b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	struct compat_cdrom_generic_command __user *cgc32;
146b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	u32 data;
147b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	unsigned char dir;
148b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	int itmp;
149b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann
150b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	cgc = compat_alloc_user_space(sizeof(*cgc));
151b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	cgc32 = compat_ptr(arg);
152b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann
153b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	if (copy_in_user(&cgc->cmd, &cgc32->cmd, sizeof(cgc->cmd)) ||
154b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	    get_user(data, &cgc32->buffer) ||
155b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	    put_user(compat_ptr(data), &cgc->buffer) ||
156b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	    copy_in_user(&cgc->buflen, &cgc32->buflen,
157b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann			 (sizeof(unsigned int) + sizeof(int))) ||
158b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	    get_user(data, &cgc32->sense) ||
159b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	    put_user(compat_ptr(data), &cgc->sense) ||
160b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	    get_user(dir, &cgc32->data_direction) ||
161b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	    put_user(dir, &cgc->data_direction) ||
162b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	    get_user(itmp, &cgc32->quiet) ||
163b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	    put_user(itmp, &cgc->quiet) ||
164b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	    get_user(itmp, &cgc32->timeout) ||
165b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	    put_user(itmp, &cgc->timeout) ||
166b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	    get_user(data, &cgc32->reserved[0]) ||
167b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	    put_user(compat_ptr(data), &cgc->reserved[0]))
168b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann		return -EFAULT;
169b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann
170b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	return blkdev_driver_ioctl(inode, file, disk, cmd, (unsigned long)cgc);
171b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann}
172b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann
17318cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmannstruct compat_blkpg_ioctl_arg {
17418cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann	compat_int_t op;
17518cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann	compat_int_t flags;
17618cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann	compat_int_t datalen;
17718cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann	compat_caddr_t data;
17818cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann};
17918cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann
18018cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmannstatic int compat_blkpg_ioctl(struct inode *inode, struct file *file,
18118cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann		unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32)
18218cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann{
18318cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann	struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a));
18418cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann	compat_caddr_t udata;
18518cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann	compat_int_t n;
18618cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann	int err;
18718cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann
18818cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann	err = get_user(n, &ua32->op);
18918cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann	err |= put_user(n, &a->op);
19018cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann	err |= get_user(n, &ua32->flags);
19118cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann	err |= put_user(n, &a->flags);
19218cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann	err |= get_user(n, &ua32->datalen);
19318cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann	err |= put_user(n, &a->datalen);
19418cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann	err |= get_user(udata, &ua32->data);
19518cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann	err |= put_user(compat_ptr(udata), &a->data);
19618cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann	if (err)
19718cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann		return err;
19818cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann
19918cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann	return blkdev_ioctl(inode, file, cmd, (unsigned long)a);
20018cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann}
20118cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann
202f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#define BLKBSZGET_32		_IOR(0x12, 112, int)
203f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#define BLKBSZSET_32		_IOW(0x12, 113, int)
204f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#define BLKGETSIZE64_32		_IOR(0x12, 114, int)
205f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann
206171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmannstruct compat_blk_user_trace_setup {
207171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	char name[32];
208171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	u16 act_mask;
209171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	u32 buf_size;
210171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	u32 buf_nr;
211171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	compat_u64 start_lba;
212171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	compat_u64 end_lba;
213171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	u32 pid;
214171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann};
215171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann#define BLKTRACESETUP32 _IOWR(0x12, 115, struct compat_blk_user_trace_setup)
216171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann
217171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmannstatic int compat_blk_trace_setup(struct block_device *bdev, char __user *arg)
218171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann{
219171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	struct blk_user_trace_setup buts;
220171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	struct compat_blk_user_trace_setup cbuts;
221171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	struct request_queue *q;
222171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	int ret;
223171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann
224171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	q = bdev_get_queue(bdev);
225171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	if (!q)
226171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann		return -ENXIO;
227171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann
228171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	if (copy_from_user(&cbuts, arg, sizeof(cbuts)))
229171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann		return -EFAULT;
230171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann
231171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	buts = (struct blk_user_trace_setup) {
232171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann		.act_mask = cbuts.act_mask,
233171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann		.buf_size = cbuts.buf_size,
234171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann		.buf_nr = cbuts.buf_nr,
235171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann		.start_lba = cbuts.start_lba,
236171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann		.end_lba = cbuts.end_lba,
237171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann		.pid = cbuts.pid,
238171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	};
239171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	memcpy(&buts.name, &cbuts.name, 32);
240171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann
241171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	mutex_lock(&bdev->bd_mutex);
242171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	ret = do_blk_trace_setup(q, bdev, &buts);
243171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	mutex_unlock(&bdev->bd_mutex);
244171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	if (ret)
245171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann		return ret;
246171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann
247171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	if (copy_to_user(arg, &buts.name, 32))
248171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann		return -EFAULT;
249171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann
250171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	return 0;
251171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann}
252171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann
2537199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmannstatic int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file,
2547199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann			struct gendisk *disk, unsigned cmd, unsigned long arg)
2557199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann{
2567199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	int ret;
2577199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann
2587199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	switch (arg) {
2599617db085c119879cd371e3212806a15596e121aArnd Bergmann	case HDIO_GET_UNMASKINTR:
2609617db085c119879cd371e3212806a15596e121aArnd Bergmann	case HDIO_GET_MULTCOUNT:
2619617db085c119879cd371e3212806a15596e121aArnd Bergmann	case HDIO_GET_KEEPSETTINGS:
2629617db085c119879cd371e3212806a15596e121aArnd Bergmann	case HDIO_GET_32BIT:
2639617db085c119879cd371e3212806a15596e121aArnd Bergmann	case HDIO_GET_NOWERR:
2649617db085c119879cd371e3212806a15596e121aArnd Bergmann	case HDIO_GET_DMA:
2659617db085c119879cd371e3212806a15596e121aArnd Bergmann	case HDIO_GET_NICE:
2669617db085c119879cd371e3212806a15596e121aArnd Bergmann	case HDIO_GET_WCACHE:
2679617db085c119879cd371e3212806a15596e121aArnd Bergmann	case HDIO_GET_ACOUSTIC:
2689617db085c119879cd371e3212806a15596e121aArnd Bergmann	case HDIO_GET_ADDRESS:
2699617db085c119879cd371e3212806a15596e121aArnd Bergmann	case HDIO_GET_BUSSTATE:
2709617db085c119879cd371e3212806a15596e121aArnd Bergmann		return compat_hdio_ioctl(inode, file, disk, cmd, arg);
271b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	case CDROMREADAUDIO:
272b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann		return compat_cdrom_read_audio(inode, file, disk, cmd, arg);
273b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann	case CDROM_SEND_PACKET:
274b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann		return compat_cdrom_generic_command(inode, file, disk, cmd, arg);
275b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann
2767199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	/*
2777199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	 * No handler required for the ones below, we just need to
2787199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	 * convert arg to a 64 bit pointer.
2797199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	 */
2807199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case BLKSECTSET:
2817199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	/*
2827199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	 * 0x03 -- HD/IDE ioctl's used by hdparm and friends.
2837199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	 *         Some need translations, these do not.
2847199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	 */
2857199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case HDIO_GET_IDENTITY:
2867199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case HDIO_DRIVE_TASK:
2877199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case HDIO_DRIVE_CMD:
2887199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case HDIO_SCAN_HWIF:
2897199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	/* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */
2907199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case 0x330:
2917199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	/* 0x02 -- Floppy ioctls */
2927199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case FDMSGON:
2937199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case FDMSGOFF:
2947199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case FDSETEMSGTRESH:
2957199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case FDFLUSH:
2967199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case FDWERRORCLR:
2977199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case FDSETMAXERRS:
2987199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case FDGETMAXERRS:
2997199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case FDGETDRVTYP:
3007199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case FDEJECT:
3017199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case FDCLRPRM:
3027199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case FDFMTBEG:
3037199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case FDFMTEND:
3047199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case FDRESET:
3057199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case FDTWADDLE:
3067199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case FDFMTTRK:
3077199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case FDRAWCMD:
3087199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	/* CDROM stuff */
3097199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMPAUSE:
3107199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMRESUME:
3117199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMPLAYMSF:
3127199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMPLAYTRKIND:
3137199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMREADTOCHDR:
3147199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMREADTOCENTRY:
3157199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMSTOP:
3167199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMSTART:
3177199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMEJECT:
3187199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMVOLCTRL:
3197199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMSUBCHNL:
3207199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMMULTISESSION:
3217199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROM_GET_MCN:
3227199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMRESET:
3237199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMVOLREAD:
3247199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMSEEK:
3257199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMPLAYBLK:
3267199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMCLOSETRAY:
3277199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROM_DISC_STATUS:
3287199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROM_CHANGER_NSLOTS:
3297199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROM_GET_CAPABILITY:
3307199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	/* Ignore cdrom.h about these next 5 ioctls, they absolutely do
3317199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	 * not take a struct cdrom_read, instead they take a struct cdrom_msf
3327199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	 * which is compatible.
3337199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	 */
3347199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMREADMODE2:
3357199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMREADMODE1:
3367199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMREADRAW:
3377199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMREADCOOKED:
3387199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMREADALL:
3397199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	/* DVD ioctls */
3407199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case DVD_READ_STRUCT:
3417199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case DVD_WRITE_STRUCT:
3427199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case DVD_AUTH:
3437199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann		arg = (unsigned long)compat_ptr(arg);
3447199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	/* These intepret arg as an unsigned long, not as a pointer,
3457199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	 * so we must not do compat_ptr() conversion. */
3467199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case HDIO_SET_MULTCOUNT:
3477199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case HDIO_SET_UNMASKINTR:
3487199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case HDIO_SET_KEEPSETTINGS:
3497199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case HDIO_SET_32BIT:
3507199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case HDIO_SET_NOWERR:
3517199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case HDIO_SET_DMA:
3527199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case HDIO_SET_PIO_MODE:
3537199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case HDIO_SET_NICE:
3547199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case HDIO_SET_WCACHE:
3557199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case HDIO_SET_ACOUSTIC:
3567199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case HDIO_SET_BUSSTATE:
3577199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case HDIO_SET_ADDRESS:
3587199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROMEJECT_SW:
3597199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROM_SET_OPTIONS:
3607199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROM_CLEAR_OPTIONS:
3617199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROM_SELECT_SPEED:
3627199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROM_SELECT_DISC:
3637199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROM_MEDIA_CHANGED:
3647199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROM_DRIVE_STATUS:
3657199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROM_LOCKDOOR:
3667199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	case CDROM_DEBUG:
3677199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann		break;
3687199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	default:
3697199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann		/* unknown ioctl number */
3707199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann		return -ENOIOCTLCMD;
3717199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	}
3727199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann
3737199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	if (disk->fops->unlocked_ioctl)
3747199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann		return disk->fops->unlocked_ioctl(file, cmd, arg);
3757199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann
3767199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	if (disk->fops->ioctl) {
3777199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann		lock_kernel();
3787199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann		ret = disk->fops->ioctl(inode, file, cmd, arg);
3797199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann		unlock_kernel();
3807199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann		return ret;
3817199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	}
3827199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann
3837199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	return -ENOTTY;
3847199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann}
3857199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann
386f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmannstatic int compat_blkdev_locked_ioctl(struct inode *inode, struct file *file,
387f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann				struct block_device *bdev,
388f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann				unsigned cmd, unsigned long arg)
389f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann{
390f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	struct backing_dev_info *bdi;
391f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann
392f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	switch (cmd) {
393f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	case BLKRAGET:
394f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	case BLKFRAGET:
395f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann		if (!arg)
396f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann			return -EINVAL;
397f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann		bdi = blk_get_backing_dev_info(bdev);
398f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann		if (bdi == NULL)
399f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann			return -ENOTTY;
400f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann		return compat_put_long(arg,
401f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann				       (bdi->ra_pages * PAGE_CACHE_SIZE) / 512);
402f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	case BLKROGET: /* compatible */
403f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann		return compat_put_int(arg, bdev_read_only(bdev) != 0);
404f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */
405f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann		return compat_put_int(arg, block_size(bdev));
406f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	case BLKSSZGET: /* get block device hardware sector size */
407f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann		return compat_put_int(arg, bdev_hardsect_size(bdev));
408f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	case BLKSECTGET:
409f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann		return compat_put_ushort(arg,
410f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann					 bdev_get_queue(bdev)->max_sectors);
411f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	case BLKRASET: /* compatible, but no compat_ptr (!) */
412f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	case BLKFRASET:
413f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann		if (!capable(CAP_SYS_ADMIN))
414f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann			return -EACCES;
415f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann		bdi = blk_get_backing_dev_info(bdev);
416f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann		if (bdi == NULL)
417f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann			return -ENOTTY;
418f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann		bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
419f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann		return 0;
420f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	case BLKGETSIZE:
421f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann		if ((bdev->bd_inode->i_size >> 9) > ~0UL)
422f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann			return -EFBIG;
423f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann		return compat_put_ulong(arg, bdev->bd_inode->i_size >> 9);
424f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann
425f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	case BLKGETSIZE64_32:
426f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann		return compat_put_u64(arg, bdev->bd_inode->i_size);
427171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann
428171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	case BLKTRACESETUP32:
429171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann		return compat_blk_trace_setup(bdev, compat_ptr(arg));
430171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	case BLKTRACESTART: /* compatible */
431171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	case BLKTRACESTOP:  /* compatible */
432171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann	case BLKTRACETEARDOWN: /* compatible */
433171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann		return blk_trace_ioctl(bdev, cmd, compat_ptr(arg));
434f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	}
435f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	return -ENOIOCTLCMD;
436f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann}
437f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann
438f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann/* Most of the generic ioctls are handled in the normal fallback path.
439f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann   This assumes the blkdev's low level compat_ioctl always returns
440f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann   ENOIOCTLCMD for unknown ioctls. */
441f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmannlong compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
442f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann{
443f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	int ret = -ENOIOCTLCMD;
444f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	struct inode *inode = file->f_mapping->host;
445f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	struct block_device *bdev = inode->i_bdev;
446f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	struct gendisk *disk = bdev->bd_disk;
447f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann
448f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	switch (cmd) {
4499617db085c119879cd371e3212806a15596e121aArnd Bergmann	case HDIO_GETGEO:
4509617db085c119879cd371e3212806a15596e121aArnd Bergmann		return compat_hdio_getgeo(disk, bdev, compat_ptr(arg));
451f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	case BLKFLSBUF:
452f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	case BLKROSET:
453f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	/*
454f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	 * the ones below are implemented in blkdev_locked_ioctl,
455f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	 * but we call blkdev_ioctl, which gets the lock for us
456f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	 */
457f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	case BLKRRPART:
458f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann		return blkdev_ioctl(inode, file, cmd,
459f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann				(unsigned long)compat_ptr(arg));
460f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	case BLKBSZSET_32:
461f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann		return blkdev_ioctl(inode, file, BLKBSZSET,
462f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann				(unsigned long)compat_ptr(arg));
46318cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann	case BLKPG:
46418cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann		return compat_blkpg_ioctl(inode, file, cmd, compat_ptr(arg));
465f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	}
466f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann
467f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	lock_kernel();
468f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	ret = compat_blkdev_locked_ioctl(inode, file, bdev, cmd, arg);
469f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	/* FIXME: why do we assume -> compat_ioctl needs the BKL? */
470f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	if (ret == -ENOIOCTLCMD && disk->fops->compat_ioctl)
471f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann		ret = disk->fops->compat_ioctl(file, cmd, arg);
472f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann	unlock_kernel();
473f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann
4747199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	if (ret != -ENOIOCTLCMD)
4757199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann		return ret;
4767199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann
4777199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann	return compat_blkdev_driver_ioctl(inode, file, disk, cmd, arg);
478f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann}
479