linux/block/ioctl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <linux/capability.h>
   3#include <linux/compat.h>
   4#include <linux/blkdev.h>
   5#include <linux/export.h>
   6#include <linux/gfp.h>
   7#include <linux/blkpg.h>
   8#include <linux/hdreg.h>
   9#include <linux/backing-dev.h>
  10#include <linux/fs.h>
  11#include <linux/blktrace_api.h>
  12#include <linux/pr.h>
  13#include <linux/uaccess.h>
  14#include "blk.h"
  15
  16static int blkpg_do_ioctl(struct block_device *bdev,
  17                          struct blkpg_partition __user *upart, int op)
  18{
  19        struct blkpg_partition p;
  20        long long start, length;
  21
  22        if (!capable(CAP_SYS_ADMIN))
  23                return -EACCES;
  24        if (copy_from_user(&p, upart, sizeof(struct blkpg_partition)))
  25                return -EFAULT;
  26        if (bdev_is_partition(bdev))
  27                return -EINVAL;
  28
  29        if (p.pno <= 0)
  30                return -EINVAL;
  31
  32        if (op == BLKPG_DEL_PARTITION)
  33                return bdev_del_partition(bdev, p.pno);
  34
  35        start = p.start >> SECTOR_SHIFT;
  36        length = p.length >> SECTOR_SHIFT;
  37
  38        /* check for fit in a hd_struct */
  39        if (sizeof(sector_t) < sizeof(long long)) {
  40                long pstart = start, plength = length;
  41
  42                if (pstart != start || plength != length || pstart < 0 ||
  43                    plength < 0 || p.pno > 65535)
  44                        return -EINVAL;
  45        }
  46
  47        switch (op) {
  48        case BLKPG_ADD_PARTITION:
  49                /* check if partition is aligned to blocksize */
  50                if (p.start & (bdev_logical_block_size(bdev) - 1))
  51                        return -EINVAL;
  52                return bdev_add_partition(bdev, p.pno, start, length);
  53        case BLKPG_RESIZE_PARTITION:
  54                return bdev_resize_partition(bdev, p.pno, start, length);
  55        default:
  56                return -EINVAL;
  57        }
  58}
  59
  60static int blkpg_ioctl(struct block_device *bdev,
  61                       struct blkpg_ioctl_arg __user *arg)
  62{
  63        struct blkpg_partition __user *udata;
  64        int op;
  65
  66        if (get_user(op, &arg->op) || get_user(udata, &arg->data))
  67                return -EFAULT;
  68
  69        return blkpg_do_ioctl(bdev, udata, op);
  70}
  71
  72#ifdef CONFIG_COMPAT
  73struct compat_blkpg_ioctl_arg {
  74        compat_int_t op;
  75        compat_int_t flags;
  76        compat_int_t datalen;
  77        compat_caddr_t data;
  78};
  79
  80static int compat_blkpg_ioctl(struct block_device *bdev,
  81                              struct compat_blkpg_ioctl_arg __user *arg)
  82{
  83        compat_caddr_t udata;
  84        int op;
  85
  86        if (get_user(op, &arg->op) || get_user(udata, &arg->data))
  87                return -EFAULT;
  88
  89        return blkpg_do_ioctl(bdev, compat_ptr(udata), op);
  90}
  91#endif
  92
  93static int blkdev_reread_part(struct block_device *bdev)
  94{
  95        int ret;
  96
  97        if (!disk_part_scan_enabled(bdev->bd_disk) || bdev_is_partition(bdev))
  98                return -EINVAL;
  99        if (!capable(CAP_SYS_ADMIN))
 100                return -EACCES;
 101
 102        mutex_lock(&bdev->bd_mutex);
 103        ret = bdev_disk_changed(bdev, false);
 104        mutex_unlock(&bdev->bd_mutex);
 105
 106        return ret;
 107}
 108
 109static int blk_ioctl_discard(struct block_device *bdev, fmode_t mode,
 110                unsigned long arg, unsigned long flags)
 111{
 112        uint64_t range[2];
 113        uint64_t start, len;
 114        struct request_queue *q = bdev_get_queue(bdev);
 115        int err;
 116
 117        if (!(mode & FMODE_WRITE))
 118                return -EBADF;
 119
 120        if (!blk_queue_discard(q))
 121                return -EOPNOTSUPP;
 122
 123        if (copy_from_user(range, (void __user *)arg, sizeof(range)))
 124                return -EFAULT;
 125
 126        start = range[0];
 127        len = range[1];
 128
 129        if (start & 511)
 130                return -EINVAL;
 131        if (len & 511)
 132                return -EINVAL;
 133
 134        if (start + len > i_size_read(bdev->bd_inode))
 135                return -EINVAL;
 136
 137        err = truncate_bdev_range(bdev, mode, start, start + len - 1);
 138        if (err)
 139                return err;
 140
 141        return blkdev_issue_discard(bdev, start >> 9, len >> 9,
 142                                    GFP_KERNEL, flags);
 143}
 144
 145static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode,
 146                unsigned long arg)
 147{
 148        uint64_t range[2];
 149        uint64_t start, end, len;
 150        int err;
 151
 152        if (!(mode & FMODE_WRITE))
 153                return -EBADF;
 154
 155        if (copy_from_user(range, (void __user *)arg, sizeof(range)))
 156                return -EFAULT;
 157
 158        start = range[0];
 159        len = range[1];
 160        end = start + len - 1;
 161
 162        if (start & 511)
 163                return -EINVAL;
 164        if (len & 511)
 165                return -EINVAL;
 166        if (end >= (uint64_t)i_size_read(bdev->bd_inode))
 167                return -EINVAL;
 168        if (end < start)
 169                return -EINVAL;
 170
 171        /* Invalidate the page cache, including dirty pages */
 172        err = truncate_bdev_range(bdev, mode, start, end);
 173        if (err)
 174                return err;
 175
 176        return blkdev_issue_zeroout(bdev, start >> 9, len >> 9, GFP_KERNEL,
 177                        BLKDEV_ZERO_NOUNMAP);
 178}
 179
 180static int put_ushort(unsigned short __user *argp, unsigned short val)
 181{
 182        return put_user(val, argp);
 183}
 184
 185static int put_int(int __user *argp, int val)
 186{
 187        return put_user(val, argp);
 188}
 189
 190static int put_uint(unsigned int __user *argp, unsigned int val)
 191{
 192        return put_user(val, argp);
 193}
 194
 195static int put_long(long __user *argp, long val)
 196{
 197        return put_user(val, argp);
 198}
 199
 200static int put_ulong(unsigned long __user *argp, unsigned long val)
 201{
 202        return put_user(val, argp);
 203}
 204
 205static int put_u64(u64 __user *argp, u64 val)
 206{
 207        return put_user(val, argp);
 208}
 209
 210#ifdef CONFIG_COMPAT
 211static int compat_put_long(compat_long_t __user *argp, long val)
 212{
 213        return put_user(val, argp);
 214}
 215
 216static int compat_put_ulong(compat_ulong_t __user *argp, compat_ulong_t val)
 217{
 218        return put_user(val, argp);
 219}
 220#endif
 221
 222int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
 223                        unsigned cmd, unsigned long arg)
 224{
 225        struct gendisk *disk = bdev->bd_disk;
 226
 227        if (disk->fops->ioctl)
 228                return disk->fops->ioctl(bdev, mode, cmd, arg);
 229
 230        return -ENOTTY;
 231}
 232/*
 233 * For the record: _GPL here is only because somebody decided to slap it
 234 * on the previous export.  Sheer idiocy, since it wasn't copyrightable
 235 * at all and could be open-coded without any exports by anybody who cares.
 236 */
 237EXPORT_SYMBOL_GPL(__blkdev_driver_ioctl);
 238
 239#ifdef CONFIG_COMPAT
 240/*
 241 * This is the equivalent of compat_ptr_ioctl(), to be used by block
 242 * drivers that implement only commands that are completely compatible
 243 * between 32-bit and 64-bit user space
 244 */
 245int blkdev_compat_ptr_ioctl(struct block_device *bdev, fmode_t mode,
 246                        unsigned cmd, unsigned long arg)
 247{
 248        struct gendisk *disk = bdev->bd_disk;
 249
 250        if (disk->fops->ioctl)
 251                return disk->fops->ioctl(bdev, mode, cmd,
 252                                         (unsigned long)compat_ptr(arg));
 253
 254        return -ENOIOCTLCMD;
 255}
 256EXPORT_SYMBOL(blkdev_compat_ptr_ioctl);
 257#endif
 258
 259static int blkdev_pr_register(struct block_device *bdev,
 260                struct pr_registration __user *arg)
 261{
 262        const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
 263        struct pr_registration reg;
 264
 265        if (!capable(CAP_SYS_ADMIN))
 266                return -EPERM;
 267        if (!ops || !ops->pr_register)
 268                return -EOPNOTSUPP;
 269        if (copy_from_user(&reg, arg, sizeof(reg)))
 270                return -EFAULT;
 271
 272        if (reg.flags & ~PR_FL_IGNORE_KEY)
 273                return -EOPNOTSUPP;
 274        return ops->pr_register(bdev, reg.old_key, reg.new_key, reg.flags);
 275}
 276
 277static int blkdev_pr_reserve(struct block_device *bdev,
 278                struct pr_reservation __user *arg)
 279{
 280        const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
 281        struct pr_reservation rsv;
 282
 283        if (!capable(CAP_SYS_ADMIN))
 284                return -EPERM;
 285        if (!ops || !ops->pr_reserve)
 286                return -EOPNOTSUPP;
 287        if (copy_from_user(&rsv, arg, sizeof(rsv)))
 288                return -EFAULT;
 289
 290        if (rsv.flags & ~PR_FL_IGNORE_KEY)
 291                return -EOPNOTSUPP;
 292        return ops->pr_reserve(bdev, rsv.key, rsv.type, rsv.flags);
 293}
 294
 295static int blkdev_pr_release(struct block_device *bdev,
 296                struct pr_reservation __user *arg)
 297{
 298        const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
 299        struct pr_reservation rsv;
 300
 301        if (!capable(CAP_SYS_ADMIN))
 302                return -EPERM;
 303        if (!ops || !ops->pr_release)
 304                return -EOPNOTSUPP;
 305        if (copy_from_user(&rsv, arg, sizeof(rsv)))
 306                return -EFAULT;
 307
 308        if (rsv.flags)
 309                return -EOPNOTSUPP;
 310        return ops->pr_release(bdev, rsv.key, rsv.type);
 311}
 312
 313static int blkdev_pr_preempt(struct block_device *bdev,
 314                struct pr_preempt __user *arg, bool abort)
 315{
 316        const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
 317        struct pr_preempt p;
 318
 319        if (!capable(CAP_SYS_ADMIN))
 320                return -EPERM;
 321        if (!ops || !ops->pr_preempt)
 322                return -EOPNOTSUPP;
 323        if (copy_from_user(&p, arg, sizeof(p)))
 324                return -EFAULT;
 325
 326        if (p.flags)
 327                return -EOPNOTSUPP;
 328        return ops->pr_preempt(bdev, p.old_key, p.new_key, p.type, abort);
 329}
 330
 331static int blkdev_pr_clear(struct block_device *bdev,
 332                struct pr_clear __user *arg)
 333{
 334        const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
 335        struct pr_clear c;
 336
 337        if (!capable(CAP_SYS_ADMIN))
 338                return -EPERM;
 339        if (!ops || !ops->pr_clear)
 340                return -EOPNOTSUPP;
 341        if (copy_from_user(&c, arg, sizeof(c)))
 342                return -EFAULT;
 343
 344        if (c.flags)
 345                return -EOPNOTSUPP;
 346        return ops->pr_clear(bdev, c.key);
 347}
 348
 349/*
 350 * Is it an unrecognized ioctl? The correct returns are either
 351 * ENOTTY (final) or ENOIOCTLCMD ("I don't know this one, try a
 352 * fallback"). ENOIOCTLCMD gets turned into ENOTTY by the ioctl
 353 * code before returning.
 354 *
 355 * Confused drivers sometimes return EINVAL, which is wrong. It
 356 * means "I understood the ioctl command, but the parameters to
 357 * it were wrong".
 358 *
 359 * We should aim to just fix the broken drivers, the EINVAL case
 360 * should go away.
 361 */
 362static inline int is_unrecognized_ioctl(int ret)
 363{
 364        return  ret == -EINVAL ||
 365                ret == -ENOTTY ||
 366                ret == -ENOIOCTLCMD;
 367}
 368
 369static int blkdev_flushbuf(struct block_device *bdev, fmode_t mode,
 370                unsigned cmd, unsigned long arg)
 371{
 372        int ret;
 373
 374        if (!capable(CAP_SYS_ADMIN))
 375                return -EACCES;
 376
 377        ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg);
 378        if (!is_unrecognized_ioctl(ret))
 379                return ret;
 380
 381        fsync_bdev(bdev);
 382        invalidate_bdev(bdev);
 383        return 0;
 384}
 385
 386static int blkdev_roset(struct block_device *bdev, fmode_t mode,
 387                unsigned cmd, unsigned long arg)
 388{
 389        int ret, n;
 390
 391        if (!capable(CAP_SYS_ADMIN))
 392                return -EACCES;
 393
 394        ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg);
 395        if (!is_unrecognized_ioctl(ret))
 396                return ret;
 397        if (get_user(n, (int __user *)arg))
 398                return -EFAULT;
 399        set_device_ro(bdev, n);
 400        return 0;
 401}
 402
 403static int blkdev_getgeo(struct block_device *bdev,
 404                struct hd_geometry __user *argp)
 405{
 406        struct gendisk *disk = bdev->bd_disk;
 407        struct hd_geometry geo;
 408        int ret;
 409
 410        if (!argp)
 411                return -EINVAL;
 412        if (!disk->fops->getgeo)
 413                return -ENOTTY;
 414
 415        /*
 416         * We need to set the startsect first, the driver may
 417         * want to override it.
 418         */
 419        memset(&geo, 0, sizeof(geo));
 420        geo.start = get_start_sect(bdev);
 421        ret = disk->fops->getgeo(bdev, &geo);
 422        if (ret)
 423                return ret;
 424        if (copy_to_user(argp, &geo, sizeof(geo)))
 425                return -EFAULT;
 426        return 0;
 427}
 428
 429#ifdef CONFIG_COMPAT
 430struct compat_hd_geometry {
 431        unsigned char heads;
 432        unsigned char sectors;
 433        unsigned short cylinders;
 434        u32 start;
 435};
 436
 437static int compat_hdio_getgeo(struct block_device *bdev,
 438                              struct compat_hd_geometry __user *ugeo)
 439{
 440        struct gendisk *disk = bdev->bd_disk;
 441        struct hd_geometry geo;
 442        int ret;
 443
 444        if (!ugeo)
 445                return -EINVAL;
 446        if (!disk->fops->getgeo)
 447                return -ENOTTY;
 448
 449        memset(&geo, 0, sizeof(geo));
 450        /*
 451         * We need to set the startsect first, the driver may
 452         * want to override it.
 453         */
 454        geo.start = get_start_sect(bdev);
 455        ret = disk->fops->getgeo(bdev, &geo);
 456        if (ret)
 457                return ret;
 458
 459        ret = copy_to_user(ugeo, &geo, 4);
 460        ret |= put_user(geo.start, &ugeo->start);
 461        if (ret)
 462                ret = -EFAULT;
 463
 464        return ret;
 465}
 466#endif
 467
 468/* set the logical block size */
 469static int blkdev_bszset(struct block_device *bdev, fmode_t mode,
 470                int __user *argp)
 471{
 472        int ret, n;
 473
 474        if (!capable(CAP_SYS_ADMIN))
 475                return -EACCES;
 476        if (!argp)
 477                return -EINVAL;
 478        if (get_user(n, argp))
 479                return -EFAULT;
 480
 481        if (mode & FMODE_EXCL)
 482                return set_blocksize(bdev, n);
 483
 484        if (IS_ERR(blkdev_get_by_dev(bdev->bd_dev, mode | FMODE_EXCL, &bdev)))
 485                return -EBUSY;
 486        ret = set_blocksize(bdev, n);
 487        blkdev_put(bdev, mode | FMODE_EXCL);
 488
 489        return ret;
 490}
 491
 492/*
 493 * Common commands that are handled the same way on native and compat
 494 * user space. Note the separate arg/argp parameters that are needed
 495 * to deal with the compat_ptr() conversion.
 496 */
 497static int blkdev_common_ioctl(struct block_device *bdev, fmode_t mode,
 498                                unsigned cmd, unsigned long arg, void __user *argp)
 499{
 500        unsigned int max_sectors;
 501
 502        switch (cmd) {
 503        case BLKFLSBUF:
 504                return blkdev_flushbuf(bdev, mode, cmd, arg);
 505        case BLKROSET:
 506                return blkdev_roset(bdev, mode, cmd, arg);
 507        case BLKDISCARD:
 508                return blk_ioctl_discard(bdev, mode, arg, 0);
 509        case BLKSECDISCARD:
 510                return blk_ioctl_discard(bdev, mode, arg,
 511                                BLKDEV_DISCARD_SECURE);
 512        case BLKZEROOUT:
 513                return blk_ioctl_zeroout(bdev, mode, arg);
 514        case BLKREPORTZONE:
 515                return blkdev_report_zones_ioctl(bdev, mode, cmd, arg);
 516        case BLKRESETZONE:
 517        case BLKOPENZONE:
 518        case BLKCLOSEZONE:
 519        case BLKFINISHZONE:
 520                return blkdev_zone_mgmt_ioctl(bdev, mode, cmd, arg);
 521        case BLKGETZONESZ:
 522                return put_uint(argp, bdev_zone_sectors(bdev));
 523        case BLKGETNRZONES:
 524                return put_uint(argp, blkdev_nr_zones(bdev->bd_disk));
 525        case BLKROGET:
 526                return put_int(argp, bdev_read_only(bdev) != 0);
 527        case BLKSSZGET: /* get block device logical block size */
 528                return put_int(argp, bdev_logical_block_size(bdev));
 529        case BLKPBSZGET: /* get block device physical block size */
 530                return put_uint(argp, bdev_physical_block_size(bdev));
 531        case BLKIOMIN:
 532                return put_uint(argp, bdev_io_min(bdev));
 533        case BLKIOOPT:
 534                return put_uint(argp, bdev_io_opt(bdev));
 535        case BLKALIGNOFF:
 536                return put_int(argp, bdev_alignment_offset(bdev));
 537        case BLKDISCARDZEROES:
 538                return put_uint(argp, 0);
 539        case BLKSECTGET:
 540                max_sectors = min_t(unsigned int, USHRT_MAX,
 541                                    queue_max_sectors(bdev_get_queue(bdev)));
 542                return put_ushort(argp, max_sectors);
 543        case BLKROTATIONAL:
 544                return put_ushort(argp, !blk_queue_nonrot(bdev_get_queue(bdev)));
 545        case BLKRASET:
 546        case BLKFRASET:
 547                if(!capable(CAP_SYS_ADMIN))
 548                        return -EACCES;
 549                bdev->bd_bdi->ra_pages = (arg * 512) / PAGE_SIZE;
 550                return 0;
 551        case BLKRRPART:
 552                return blkdev_reread_part(bdev);
 553        case BLKTRACESTART:
 554        case BLKTRACESTOP:
 555        case BLKTRACETEARDOWN:
 556                return blk_trace_ioctl(bdev, cmd, argp);
 557        case IOC_PR_REGISTER:
 558                return blkdev_pr_register(bdev, argp);
 559        case IOC_PR_RESERVE:
 560                return blkdev_pr_reserve(bdev, argp);
 561        case IOC_PR_RELEASE:
 562                return blkdev_pr_release(bdev, argp);
 563        case IOC_PR_PREEMPT:
 564                return blkdev_pr_preempt(bdev, argp, false);
 565        case IOC_PR_PREEMPT_ABORT:
 566                return blkdev_pr_preempt(bdev, argp, true);
 567        case IOC_PR_CLEAR:
 568                return blkdev_pr_clear(bdev, argp);
 569        default:
 570                return -ENOIOCTLCMD;
 571        }
 572}
 573
 574/*
 575 * Always keep this in sync with compat_blkdev_ioctl()
 576 * to handle all incompatible commands in both functions.
 577 *
 578 * New commands must be compatible and go into blkdev_common_ioctl
 579 */
 580int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
 581                        unsigned long arg)
 582{
 583        int ret;
 584        loff_t size;
 585        void __user *argp = (void __user *)arg;
 586
 587        switch (cmd) {
 588        /* These need separate implementations for the data structure */
 589        case HDIO_GETGEO:
 590                return blkdev_getgeo(bdev, argp);
 591        case BLKPG:
 592                return blkpg_ioctl(bdev, argp);
 593
 594        /* Compat mode returns 32-bit data instead of 'long' */
 595        case BLKRAGET:
 596        case BLKFRAGET:
 597                if (!argp)
 598                        return -EINVAL;
 599                return put_long(argp, (bdev->bd_bdi->ra_pages*PAGE_SIZE) / 512);
 600        case BLKGETSIZE:
 601                size = i_size_read(bdev->bd_inode);
 602                if ((size >> 9) > ~0UL)
 603                        return -EFBIG;
 604                return put_ulong(argp, size >> 9);
 605
 606        /* The data is compatible, but the command number is different */
 607        case BLKBSZGET: /* get block device soft block size (cf. BLKSSZGET) */
 608                return put_int(argp, block_size(bdev));
 609        case BLKBSZSET:
 610                return blkdev_bszset(bdev, mode, argp);
 611        case BLKGETSIZE64:
 612                return put_u64(argp, i_size_read(bdev->bd_inode));
 613
 614        /* Incompatible alignment on i386 */
 615        case BLKTRACESETUP:
 616                return blk_trace_ioctl(bdev, cmd, argp);
 617        default:
 618                break;
 619        }
 620
 621        ret = blkdev_common_ioctl(bdev, mode, cmd, arg, argp);
 622        if (ret == -ENOIOCTLCMD)
 623                return __blkdev_driver_ioctl(bdev, mode, cmd, arg);
 624
 625        return ret;
 626}
 627EXPORT_SYMBOL_GPL(blkdev_ioctl); /* for /dev/raw */
 628
 629#ifdef CONFIG_COMPAT
 630
 631#define BLKBSZGET_32            _IOR(0x12, 112, int)
 632#define BLKBSZSET_32            _IOW(0x12, 113, int)
 633#define BLKGETSIZE64_32         _IOR(0x12, 114, int)
 634
 635/* Most of the generic ioctls are handled in the normal fallback path.
 636   This assumes the blkdev's low level compat_ioctl always returns
 637   ENOIOCTLCMD for unknown ioctls. */
 638long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
 639{
 640        int ret;
 641        void __user *argp = compat_ptr(arg);
 642        struct inode *inode = file->f_mapping->host;
 643        struct block_device *bdev = inode->i_bdev;
 644        struct gendisk *disk = bdev->bd_disk;
 645        fmode_t mode = file->f_mode;
 646        loff_t size;
 647
 648        /*
 649         * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have
 650         * to updated it before every ioctl.
 651         */
 652        if (file->f_flags & O_NDELAY)
 653                mode |= FMODE_NDELAY;
 654        else
 655                mode &= ~FMODE_NDELAY;
 656
 657        switch (cmd) {
 658        /* These need separate implementations for the data structure */
 659        case HDIO_GETGEO:
 660                return compat_hdio_getgeo(bdev, argp);
 661        case BLKPG:
 662                return compat_blkpg_ioctl(bdev, argp);
 663
 664        /* Compat mode returns 32-bit data instead of 'long' */
 665        case BLKRAGET:
 666        case BLKFRAGET:
 667                if (!argp)
 668                        return -EINVAL;
 669                return compat_put_long(argp,
 670                               (bdev->bd_bdi->ra_pages * PAGE_SIZE) / 512);
 671        case BLKGETSIZE:
 672                size = i_size_read(bdev->bd_inode);
 673                if ((size >> 9) > ~0UL)
 674                        return -EFBIG;
 675                return compat_put_ulong(argp, size >> 9);
 676
 677        /* The data is compatible, but the command number is different */
 678        case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */
 679                return put_int(argp, bdev_logical_block_size(bdev));
 680        case BLKBSZSET_32:
 681                return blkdev_bszset(bdev, mode, argp);
 682        case BLKGETSIZE64_32:
 683                return put_u64(argp, i_size_read(bdev->bd_inode));
 684
 685        /* Incompatible alignment on i386 */
 686        case BLKTRACESETUP32:
 687                return blk_trace_ioctl(bdev, cmd, argp);
 688        default:
 689                break;
 690        }
 691
 692        ret = blkdev_common_ioctl(bdev, mode, cmd, arg, argp);
 693        if (ret == -ENOIOCTLCMD && disk->fops->compat_ioctl)
 694                ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg);
 695
 696        return ret;
 697}
 698#endif
 699