Commit f58c4c0a17e500e767473598b3deafaa1d64051d

Authored by Arnd Bergmann
Committed by Jens Axboe
1 parent d2bbf3da37

compat_ioctl: move common block ioctls to compat_blkdev_ioctl

Make compat_blkdev_ioctl and blkdev_ioctl reflect the respective
native versions. This is somewhat more efficient and makes it easier
to keep the two in sync.

Also get rid of the bogus handling for broken_blkgetsize and the
duplicate entry for BLKRASET.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>

Showing 4 changed files with 126 additions and 62 deletions Side-by-side Diff

... ... @@ -11,4 +11,5 @@
11 11 obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o
12 12  
13 13 obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o
  14 +obj-$(CONFIG_COMPAT) += compat_ioctl.o
block/compat_ioctl.c
  1 +#include <linux/blkdev.h>
  2 +#include <linux/blkpg.h>
  3 +#include <linux/blktrace_api.h>
  4 +#include <linux/cdrom.h>
  5 +#include <linux/compat.h>
  6 +#include <linux/elevator.h>
  7 +#include <linux/fd.h>
  8 +#include <linux/hdreg.h>
  9 +#include <linux/syscalls.h>
  10 +#include <linux/smp_lock.h>
  11 +#include <linux/types.h>
  12 +#include <linux/uaccess.h>
  13 +
  14 +static int compat_put_ushort(unsigned long arg, unsigned short val)
  15 +{
  16 + return put_user(val, (unsigned short __user *)compat_ptr(arg));
  17 +}
  18 +
  19 +static int compat_put_int(unsigned long arg, int val)
  20 +{
  21 + return put_user(val, (compat_int_t __user *)compat_ptr(arg));
  22 +}
  23 +
  24 +static int compat_put_long(unsigned long arg, long val)
  25 +{
  26 + return put_user(val, (compat_long_t __user *)compat_ptr(arg));
  27 +}
  28 +
  29 +static int compat_put_ulong(unsigned long arg, compat_ulong_t val)
  30 +{
  31 + return put_user(val, (compat_ulong_t __user *)compat_ptr(arg));
  32 +}
  33 +
  34 +static int compat_put_u64(unsigned long arg, u64 val)
  35 +{
  36 + return put_user(val, (compat_u64 __user *)compat_ptr(arg));
  37 +}
  38 +
  39 +#define BLKBSZGET_32 _IOR(0x12, 112, int)
  40 +#define BLKBSZSET_32 _IOW(0x12, 113, int)
  41 +#define BLKGETSIZE64_32 _IOR(0x12, 114, int)
  42 +
  43 +static int compat_blkdev_locked_ioctl(struct inode *inode, struct file *file,
  44 + struct block_device *bdev,
  45 + unsigned cmd, unsigned long arg)
  46 +{
  47 + struct backing_dev_info *bdi;
  48 +
  49 + switch (cmd) {
  50 + case BLKRAGET:
  51 + case BLKFRAGET:
  52 + if (!arg)
  53 + return -EINVAL;
  54 + bdi = blk_get_backing_dev_info(bdev);
  55 + if (bdi == NULL)
  56 + return -ENOTTY;
  57 + return compat_put_long(arg,
  58 + (bdi->ra_pages * PAGE_CACHE_SIZE) / 512);
  59 + case BLKROGET: /* compatible */
  60 + return compat_put_int(arg, bdev_read_only(bdev) != 0);
  61 + case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */
  62 + return compat_put_int(arg, block_size(bdev));
  63 + case BLKSSZGET: /* get block device hardware sector size */
  64 + return compat_put_int(arg, bdev_hardsect_size(bdev));
  65 + case BLKSECTGET:
  66 + return compat_put_ushort(arg,
  67 + bdev_get_queue(bdev)->max_sectors);
  68 + case BLKRASET: /* compatible, but no compat_ptr (!) */
  69 + case BLKFRASET:
  70 + if (!capable(CAP_SYS_ADMIN))
  71 + return -EACCES;
  72 + bdi = blk_get_backing_dev_info(bdev);
  73 + if (bdi == NULL)
  74 + return -ENOTTY;
  75 + bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
  76 + return 0;
  77 + case BLKGETSIZE:
  78 + if ((bdev->bd_inode->i_size >> 9) > ~0UL)
  79 + return -EFBIG;
  80 + return compat_put_ulong(arg, bdev->bd_inode->i_size >> 9);
  81 +
  82 + case BLKGETSIZE64_32:
  83 + return compat_put_u64(arg, bdev->bd_inode->i_size);
  84 + }
  85 + return -ENOIOCTLCMD;
  86 +}
  87 +
  88 +/* Most of the generic ioctls are handled in the normal fallback path.
  89 + This assumes the blkdev's low level compat_ioctl always returns
  90 + ENOIOCTLCMD for unknown ioctls. */
  91 +long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
  92 +{
  93 + int ret = -ENOIOCTLCMD;
  94 + struct inode *inode = file->f_mapping->host;
  95 + struct block_device *bdev = inode->i_bdev;
  96 + struct gendisk *disk = bdev->bd_disk;
  97 +
  98 + switch (cmd) {
  99 + case BLKFLSBUF:
  100 + case BLKROSET:
  101 + /*
  102 + * the ones below are implemented in blkdev_locked_ioctl,
  103 + * but we call blkdev_ioctl, which gets the lock for us
  104 + */
  105 + case BLKRRPART:
  106 + return blkdev_ioctl(inode, file, cmd,
  107 + (unsigned long)compat_ptr(arg));
  108 + case BLKBSZSET_32:
  109 + return blkdev_ioctl(inode, file, BLKBSZSET,
  110 + (unsigned long)compat_ptr(arg));
  111 + }
  112 +
  113 + lock_kernel();
  114 + ret = compat_blkdev_locked_ioctl(inode, file, bdev, cmd, arg);
  115 + /* FIXME: why do we assume -> compat_ioctl needs the BKL? */
  116 + if (ret == -ENOIOCTLCMD && disk->fops->compat_ioctl)
  117 + ret = disk->fops->compat_ioctl(file, cmd, arg);
  118 + unlock_kernel();
  119 +
  120 + return ret;
  121 +}
... ... @@ -217,6 +217,10 @@
217 217 }
218 218 EXPORT_SYMBOL_GPL(blkdev_driver_ioctl);
219 219  
  220 +/*
  221 + * always keep this in sync with compat_blkdev_ioctl() and
  222 + * compat_blkdev_locked_ioctl()
  223 + */
220 224 int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
221 225 unsigned long arg)
222 226 {
... ... @@ -284,22 +288,5 @@
284 288  
285 289 return blkdev_driver_ioctl(inode, file, disk, cmd, arg);
286 290 }
287   -
288   -/* Most of the generic ioctls are handled in the normal fallback path.
289   - This assumes the blkdev's low level compat_ioctl always returns
290   - ENOIOCTLCMD for unknown ioctls. */
291   -long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
292   -{
293   - struct block_device *bdev = file->f_path.dentry->d_inode->i_bdev;
294   - struct gendisk *disk = bdev->bd_disk;
295   - int ret = -ENOIOCTLCMD;
296   - if (disk->fops->compat_ioctl) {
297   - lock_kernel();
298   - ret = disk->fops->compat_ioctl(file, cmd, arg);
299   - unlock_kernel();
300   - }
301   - return ret;
302   -}
303   -
304 291 EXPORT_SYMBOL_GPL(blkdev_ioctl);
... ... @@ -1537,12 +1537,6 @@
1537 1537 }
1538 1538  
1539 1539 #ifdef CONFIG_BLOCK
1540   -static int broken_blkgetsize(unsigned int fd, unsigned int cmd, unsigned long arg)
1541   -{
1542   - /* The mkswap binary hard codes it to Intel value :-((( */
1543   - return w_long(fd, BLKGETSIZE, arg);
1544   -}
1545   -
1546 1540 struct blkpg_ioctl_arg32 {
1547 1541 compat_int_t op;
1548 1542 compat_int_t flags;
... ... @@ -1578,29 +1572,6 @@
1578 1572 return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg);
1579 1573 }
1580 1574  
1581   -#ifdef CONFIG_BLOCK
1582   -/* Fix sizeof(sizeof()) breakage */
1583   -#define BLKBSZGET_32 _IOR(0x12,112,int)
1584   -#define BLKBSZSET_32 _IOW(0x12,113,int)
1585   -#define BLKGETSIZE64_32 _IOR(0x12,114,int)
1586   -
1587   -static int do_blkbszget(unsigned int fd, unsigned int cmd, unsigned long arg)
1588   -{
1589   - return sys_ioctl(fd, BLKBSZGET, (unsigned long)compat_ptr(arg));
1590   -}
1591   -
1592   -static int do_blkbszset(unsigned int fd, unsigned int cmd, unsigned long arg)
1593   -{
1594   - return sys_ioctl(fd, BLKBSZSET, (unsigned long)compat_ptr(arg));
1595   -}
1596   -
1597   -static int do_blkgetsize64(unsigned int fd, unsigned int cmd,
1598   - unsigned long arg)
1599   -{
1600   - return sys_ioctl(fd, BLKGETSIZE64, (unsigned long)compat_ptr(arg));
1601   -}
1602   -#endif
1603   -
1604 1575 /* Bluetooth ioctls */
1605 1576 #define HCIUARTSETPROTO _IOW('U', 200, int)
1606 1577 #define HCIUARTGETPROTO _IOR('U', 201, int)
1607 1578  
1608 1579  
... ... @@ -2546,19 +2517,11 @@
2546 2517 COMPATIBLE_IOCTL(FDRAWCMD)
2547 2518 /* 0x12 */
2548 2519 #ifdef CONFIG_BLOCK
2549   -COMPATIBLE_IOCTL(BLKRASET)
2550   -COMPATIBLE_IOCTL(BLKROSET)
2551   -COMPATIBLE_IOCTL(BLKROGET)
2552   -COMPATIBLE_IOCTL(BLKRRPART)
2553   -COMPATIBLE_IOCTL(BLKFLSBUF)
2554 2520 COMPATIBLE_IOCTL(BLKSECTSET)
2555   -COMPATIBLE_IOCTL(BLKSSZGET)
2556 2521 COMPATIBLE_IOCTL(BLKTRACESTART)
2557 2522 COMPATIBLE_IOCTL(BLKTRACESTOP)
2558 2523 COMPATIBLE_IOCTL(BLKTRACESETUP)
2559 2524 COMPATIBLE_IOCTL(BLKTRACETEARDOWN)
2560   -ULONG_IOCTL(BLKRASET)
2561   -ULONG_IOCTL(BLKFRASET)
2562 2525 #endif
2563 2526 /* RAID */
2564 2527 COMPATIBLE_IOCTL(RAID_VERSION)
... ... @@ -3337,11 +3300,6 @@
3337 3300 #endif
3338 3301 #ifdef CONFIG_BLOCK
3339 3302 HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo)
3340   -HANDLE_IOCTL(BLKRAGET, w_long)
3341   -HANDLE_IOCTL(BLKGETSIZE, w_long)
3342   -HANDLE_IOCTL(0x1260, broken_blkgetsize)
3343   -HANDLE_IOCTL(BLKFRAGET, w_long)
3344   -HANDLE_IOCTL(BLKSECTGET, w_long)
3345 3303 HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans)
3346 3304 HANDLE_IOCTL(HDIO_GET_UNMASKINTR, hdio_ioctl_trans)
3347 3305 HANDLE_IOCTL(HDIO_GET_MULTCOUNT, hdio_ioctl_trans)
... ... @@ -3415,9 +3373,6 @@
3415 3373 HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl)
3416 3374 /* block stuff */
3417 3375 #ifdef CONFIG_BLOCK
3418   -HANDLE_IOCTL(BLKBSZGET_32, do_blkbszget)
3419   -HANDLE_IOCTL(BLKBSZSET_32, do_blkbszset)
3420   -HANDLE_IOCTL(BLKGETSIZE64_32, do_blkgetsize64)
3421 3376 /* Raw devices */
3422 3377 HANDLE_IOCTL(RAW_SETBIND, raw_ioctl)
3423 3378 HANDLE_IOCTL(RAW_GETBIND, raw_ioctl)