aboutsummaryrefslogtreecommitdiffstats
path: root/block/compat_ioctl.c
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2007-10-09 07:23:55 -0400
committerJens Axboe <axboe@carl.home.kernel.dk>2007-10-10 03:26:00 -0400
commit9617db085c119879cd371e3212806a15596e121a (patch)
tree17db98cd2d195105124f1d8a96f249ca073918cd /block/compat_ioctl.c
parent171044d449611c6e5040b37210ff6aba47f33ee4 (diff)
compat_ioctl: move hdio calls to block/compat_ioctl.c
These are common to multiple block drivers, so they should be handled by the block layer. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block/compat_ioctl.c')
-rw-r--r--block/compat_ioctl.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index 219b7e76e8ad..5c6dafaad938 100644
--- a/block/compat_ioctl.c
+++ b/block/compat_ioctl.c
@@ -36,6 +36,62 @@ static int compat_put_u64(unsigned long arg, u64 val)
36 return put_user(val, (compat_u64 __user *)compat_ptr(arg)); 36 return put_user(val, (compat_u64 __user *)compat_ptr(arg));
37} 37}
38 38
39struct compat_hd_geometry {
40 unsigned char heads;
41 unsigned char sectors;
42 unsigned short cylinders;
43 u32 start;
44};
45
46static int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev,
47 struct compat_hd_geometry __user *ugeo)
48{
49 struct hd_geometry geo;
50 int ret;
51
52 if (!ugeo)
53 return -EINVAL;
54 if (!disk->fops->getgeo)
55 return -ENOTTY;
56
57 /*
58 * We need to set the startsect first, the driver may
59 * want to override it.
60 */
61 geo.start = get_start_sect(bdev);
62 ret = disk->fops->getgeo(bdev, &geo);
63 if (ret)
64 return ret;
65
66 ret = copy_to_user(ugeo, &geo, 4);
67 ret |= __put_user(geo.start, &ugeo->start);
68 if (ret)
69 ret = -EFAULT;
70
71 return ret;
72}
73
74static int compat_hdio_ioctl(struct inode *inode, struct file *file,
75 struct gendisk *disk, unsigned int cmd, unsigned long arg)
76{
77 mm_segment_t old_fs = get_fs();
78 unsigned long kval;
79 unsigned int __user *uvp;
80 int error;
81
82 set_fs(KERNEL_DS);
83 error = blkdev_driver_ioctl(inode, file, disk,
84 cmd, (unsigned long)(&kval));
85 set_fs(old_fs);
86
87 if (error == 0) {
88 uvp = compat_ptr(arg);
89 if (put_user(kval, uvp))
90 error = -EFAULT;
91 }
92 return error;
93}
94
39#define BLKBSZGET_32 _IOR(0x12, 112, int) 95#define BLKBSZGET_32 _IOR(0x12, 112, int)
40#define BLKBSZSET_32 _IOW(0x12, 113, int) 96#define BLKBSZSET_32 _IOW(0x12, 113, int)
41#define BLKGETSIZE64_32 _IOR(0x12, 114, int) 97#define BLKGETSIZE64_32 _IOR(0x12, 114, int)
@@ -93,6 +149,18 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file,
93 int ret; 149 int ret;
94 150
95 switch (arg) { 151 switch (arg) {
152 case HDIO_GET_UNMASKINTR:
153 case HDIO_GET_MULTCOUNT:
154 case HDIO_GET_KEEPSETTINGS:
155 case HDIO_GET_32BIT:
156 case HDIO_GET_NOWERR:
157 case HDIO_GET_DMA:
158 case HDIO_GET_NICE:
159 case HDIO_GET_WCACHE:
160 case HDIO_GET_ACOUSTIC:
161 case HDIO_GET_ADDRESS:
162 case HDIO_GET_BUSSTATE:
163 return compat_hdio_ioctl(inode, file, disk, cmd, arg);
96 /* 164 /*
97 * No handler required for the ones below, we just need to 165 * No handler required for the ones below, we just need to
98 * convert arg to a 64 bit pointer. 166 * convert arg to a 64 bit pointer.
@@ -266,6 +334,8 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
266 struct gendisk *disk = bdev->bd_disk; 334 struct gendisk *disk = bdev->bd_disk;
267 335
268 switch (cmd) { 336 switch (cmd) {
337 case HDIO_GETGEO:
338 return compat_hdio_getgeo(disk, bdev, compat_ptr(arg));
269 case BLKFLSBUF: 339 case BLKFLSBUF:
270 case BLKROSET: 340 case BLKROSET:
271 /* 341 /*