Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/capability.h>
0003 #include <linux/compat.h>
0004 #include <linux/blkdev.h>
0005 #include <linux/export.h>
0006 #include <linux/gfp.h>
0007 #include <linux/blkpg.h>
0008 #include <linux/hdreg.h>
0009 #include <linux/backing-dev.h>
0010 #include <linux/fs.h>
0011 #include <linux/blktrace_api.h>
0012 #include <linux/pr.h>
0013 #include <linux/uaccess.h>
0014 #include "blk.h"
0015 
0016 static int blkpg_do_ioctl(struct block_device *bdev,
0017               struct blkpg_partition __user *upart, int op)
0018 {
0019     struct gendisk *disk = bdev->bd_disk;
0020     struct blkpg_partition p;
0021     long long start, length;
0022 
0023     if (!capable(CAP_SYS_ADMIN))
0024         return -EACCES;
0025     if (copy_from_user(&p, upart, sizeof(struct blkpg_partition)))
0026         return -EFAULT;
0027     if (bdev_is_partition(bdev))
0028         return -EINVAL;
0029 
0030     if (p.pno <= 0)
0031         return -EINVAL;
0032 
0033     if (op == BLKPG_DEL_PARTITION)
0034         return bdev_del_partition(disk, p.pno);
0035 
0036     start = p.start >> SECTOR_SHIFT;
0037     length = p.length >> SECTOR_SHIFT;
0038 
0039     switch (op) {
0040     case BLKPG_ADD_PARTITION:
0041         /* check if partition is aligned to blocksize */
0042         if (p.start & (bdev_logical_block_size(bdev) - 1))
0043             return -EINVAL;
0044         return bdev_add_partition(disk, p.pno, start, length);
0045     case BLKPG_RESIZE_PARTITION:
0046         return bdev_resize_partition(disk, p.pno, start, length);
0047     default:
0048         return -EINVAL;
0049     }
0050 }
0051 
0052 static int blkpg_ioctl(struct block_device *bdev,
0053                struct blkpg_ioctl_arg __user *arg)
0054 {
0055     struct blkpg_partition __user *udata;
0056     int op;
0057 
0058     if (get_user(op, &arg->op) || get_user(udata, &arg->data))
0059         return -EFAULT;
0060 
0061     return blkpg_do_ioctl(bdev, udata, op);
0062 }
0063 
0064 #ifdef CONFIG_COMPAT
0065 struct compat_blkpg_ioctl_arg {
0066     compat_int_t op;
0067     compat_int_t flags;
0068     compat_int_t datalen;
0069     compat_caddr_t data;
0070 };
0071 
0072 static int compat_blkpg_ioctl(struct block_device *bdev,
0073                   struct compat_blkpg_ioctl_arg __user *arg)
0074 {
0075     compat_caddr_t udata;
0076     int op;
0077 
0078     if (get_user(op, &arg->op) || get_user(udata, &arg->data))
0079         return -EFAULT;
0080 
0081     return blkpg_do_ioctl(bdev, compat_ptr(udata), op);
0082 }
0083 #endif
0084 
0085 static int blk_ioctl_discard(struct block_device *bdev, fmode_t mode,
0086         unsigned long arg)
0087 {
0088     uint64_t range[2];
0089     uint64_t start, len;
0090     struct inode *inode = bdev->bd_inode;
0091     int err;
0092 
0093     if (!(mode & FMODE_WRITE))
0094         return -EBADF;
0095 
0096     if (!bdev_max_discard_sectors(bdev))
0097         return -EOPNOTSUPP;
0098 
0099     if (copy_from_user(range, (void __user *)arg, sizeof(range)))
0100         return -EFAULT;
0101 
0102     start = range[0];
0103     len = range[1];
0104 
0105     if (start & 511)
0106         return -EINVAL;
0107     if (len & 511)
0108         return -EINVAL;
0109 
0110     if (start + len > bdev_nr_bytes(bdev))
0111         return -EINVAL;
0112 
0113     filemap_invalidate_lock(inode->i_mapping);
0114     err = truncate_bdev_range(bdev, mode, start, start + len - 1);
0115     if (err)
0116         goto fail;
0117     err = blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL);
0118 fail:
0119     filemap_invalidate_unlock(inode->i_mapping);
0120     return err;
0121 }
0122 
0123 static int blk_ioctl_secure_erase(struct block_device *bdev, fmode_t mode,
0124         void __user *argp)
0125 {
0126     uint64_t start, len;
0127     uint64_t range[2];
0128     int err;
0129 
0130     if (!(mode & FMODE_WRITE))
0131         return -EBADF;
0132     if (!bdev_max_secure_erase_sectors(bdev))
0133         return -EOPNOTSUPP;
0134     if (copy_from_user(range, argp, sizeof(range)))
0135         return -EFAULT;
0136 
0137     start = range[0];
0138     len = range[1];
0139     if ((start & 511) || (len & 511))
0140         return -EINVAL;
0141     if (start + len > bdev_nr_bytes(bdev))
0142         return -EINVAL;
0143 
0144     filemap_invalidate_lock(bdev->bd_inode->i_mapping);
0145     err = truncate_bdev_range(bdev, mode, start, start + len - 1);
0146     if (!err)
0147         err = blkdev_issue_secure_erase(bdev, start >> 9, len >> 9,
0148                         GFP_KERNEL);
0149     filemap_invalidate_unlock(bdev->bd_inode->i_mapping);
0150     return err;
0151 }
0152 
0153 
0154 static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode,
0155         unsigned long arg)
0156 {
0157     uint64_t range[2];
0158     uint64_t start, end, len;
0159     struct inode *inode = bdev->bd_inode;
0160     int err;
0161 
0162     if (!(mode & FMODE_WRITE))
0163         return -EBADF;
0164 
0165     if (copy_from_user(range, (void __user *)arg, sizeof(range)))
0166         return -EFAULT;
0167 
0168     start = range[0];
0169     len = range[1];
0170     end = start + len - 1;
0171 
0172     if (start & 511)
0173         return -EINVAL;
0174     if (len & 511)
0175         return -EINVAL;
0176     if (end >= (uint64_t)bdev_nr_bytes(bdev))
0177         return -EINVAL;
0178     if (end < start)
0179         return -EINVAL;
0180 
0181     /* Invalidate the page cache, including dirty pages */
0182     filemap_invalidate_lock(inode->i_mapping);
0183     err = truncate_bdev_range(bdev, mode, start, end);
0184     if (err)
0185         goto fail;
0186 
0187     err = blkdev_issue_zeroout(bdev, start >> 9, len >> 9, GFP_KERNEL,
0188                    BLKDEV_ZERO_NOUNMAP);
0189 
0190 fail:
0191     filemap_invalidate_unlock(inode->i_mapping);
0192     return err;
0193 }
0194 
0195 static int put_ushort(unsigned short __user *argp, unsigned short val)
0196 {
0197     return put_user(val, argp);
0198 }
0199 
0200 static int put_int(int __user *argp, int val)
0201 {
0202     return put_user(val, argp);
0203 }
0204 
0205 static int put_uint(unsigned int __user *argp, unsigned int val)
0206 {
0207     return put_user(val, argp);
0208 }
0209 
0210 static int put_long(long __user *argp, long val)
0211 {
0212     return put_user(val, argp);
0213 }
0214 
0215 static int put_ulong(unsigned long __user *argp, unsigned long val)
0216 {
0217     return put_user(val, argp);
0218 }
0219 
0220 static int put_u64(u64 __user *argp, u64 val)
0221 {
0222     return put_user(val, argp);
0223 }
0224 
0225 #ifdef CONFIG_COMPAT
0226 static int compat_put_long(compat_long_t __user *argp, long val)
0227 {
0228     return put_user(val, argp);
0229 }
0230 
0231 static int compat_put_ulong(compat_ulong_t __user *argp, compat_ulong_t val)
0232 {
0233     return put_user(val, argp);
0234 }
0235 #endif
0236 
0237 #ifdef CONFIG_COMPAT
0238 /*
0239  * This is the equivalent of compat_ptr_ioctl(), to be used by block
0240  * drivers that implement only commands that are completely compatible
0241  * between 32-bit and 64-bit user space
0242  */
0243 int blkdev_compat_ptr_ioctl(struct block_device *bdev, fmode_t mode,
0244             unsigned cmd, unsigned long arg)
0245 {
0246     struct gendisk *disk = bdev->bd_disk;
0247 
0248     if (disk->fops->ioctl)
0249         return disk->fops->ioctl(bdev, mode, cmd,
0250                      (unsigned long)compat_ptr(arg));
0251 
0252     return -ENOIOCTLCMD;
0253 }
0254 EXPORT_SYMBOL(blkdev_compat_ptr_ioctl);
0255 #endif
0256 
0257 static int blkdev_pr_register(struct block_device *bdev,
0258         struct pr_registration __user *arg)
0259 {
0260     const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
0261     struct pr_registration reg;
0262 
0263     if (!capable(CAP_SYS_ADMIN))
0264         return -EPERM;
0265     if (!ops || !ops->pr_register)
0266         return -EOPNOTSUPP;
0267     if (copy_from_user(&reg, arg, sizeof(reg)))
0268         return -EFAULT;
0269 
0270     if (reg.flags & ~PR_FL_IGNORE_KEY)
0271         return -EOPNOTSUPP;
0272     return ops->pr_register(bdev, reg.old_key, reg.new_key, reg.flags);
0273 }
0274 
0275 static int blkdev_pr_reserve(struct block_device *bdev,
0276         struct pr_reservation __user *arg)
0277 {
0278     const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
0279     struct pr_reservation rsv;
0280 
0281     if (!capable(CAP_SYS_ADMIN))
0282         return -EPERM;
0283     if (!ops || !ops->pr_reserve)
0284         return -EOPNOTSUPP;
0285     if (copy_from_user(&rsv, arg, sizeof(rsv)))
0286         return -EFAULT;
0287 
0288     if (rsv.flags & ~PR_FL_IGNORE_KEY)
0289         return -EOPNOTSUPP;
0290     return ops->pr_reserve(bdev, rsv.key, rsv.type, rsv.flags);
0291 }
0292 
0293 static int blkdev_pr_release(struct block_device *bdev,
0294         struct pr_reservation __user *arg)
0295 {
0296     const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
0297     struct pr_reservation rsv;
0298 
0299     if (!capable(CAP_SYS_ADMIN))
0300         return -EPERM;
0301     if (!ops || !ops->pr_release)
0302         return -EOPNOTSUPP;
0303     if (copy_from_user(&rsv, arg, sizeof(rsv)))
0304         return -EFAULT;
0305 
0306     if (rsv.flags)
0307         return -EOPNOTSUPP;
0308     return ops->pr_release(bdev, rsv.key, rsv.type);
0309 }
0310 
0311 static int blkdev_pr_preempt(struct block_device *bdev,
0312         struct pr_preempt __user *arg, bool abort)
0313 {
0314     const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
0315     struct pr_preempt p;
0316 
0317     if (!capable(CAP_SYS_ADMIN))
0318         return -EPERM;
0319     if (!ops || !ops->pr_preempt)
0320         return -EOPNOTSUPP;
0321     if (copy_from_user(&p, arg, sizeof(p)))
0322         return -EFAULT;
0323 
0324     if (p.flags)
0325         return -EOPNOTSUPP;
0326     return ops->pr_preempt(bdev, p.old_key, p.new_key, p.type, abort);
0327 }
0328 
0329 static int blkdev_pr_clear(struct block_device *bdev,
0330         struct pr_clear __user *arg)
0331 {
0332     const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
0333     struct pr_clear c;
0334 
0335     if (!capable(CAP_SYS_ADMIN))
0336         return -EPERM;
0337     if (!ops || !ops->pr_clear)
0338         return -EOPNOTSUPP;
0339     if (copy_from_user(&c, arg, sizeof(c)))
0340         return -EFAULT;
0341 
0342     if (c.flags)
0343         return -EOPNOTSUPP;
0344     return ops->pr_clear(bdev, c.key);
0345 }
0346 
0347 static int blkdev_flushbuf(struct block_device *bdev, fmode_t mode,
0348         unsigned cmd, unsigned long arg)
0349 {
0350     if (!capable(CAP_SYS_ADMIN))
0351         return -EACCES;
0352     fsync_bdev(bdev);
0353     invalidate_bdev(bdev);
0354     return 0;
0355 }
0356 
0357 static int blkdev_roset(struct block_device *bdev, fmode_t mode,
0358         unsigned cmd, unsigned long arg)
0359 {
0360     int ret, n;
0361 
0362     if (!capable(CAP_SYS_ADMIN))
0363         return -EACCES;
0364 
0365     if (get_user(n, (int __user *)arg))
0366         return -EFAULT;
0367     if (bdev->bd_disk->fops->set_read_only) {
0368         ret = bdev->bd_disk->fops->set_read_only(bdev, n);
0369         if (ret)
0370             return ret;
0371     }
0372     bdev->bd_read_only = n;
0373     return 0;
0374 }
0375 
0376 static int blkdev_getgeo(struct block_device *bdev,
0377         struct hd_geometry __user *argp)
0378 {
0379     struct gendisk *disk = bdev->bd_disk;
0380     struct hd_geometry geo;
0381     int ret;
0382 
0383     if (!argp)
0384         return -EINVAL;
0385     if (!disk->fops->getgeo)
0386         return -ENOTTY;
0387 
0388     /*
0389      * We need to set the startsect first, the driver may
0390      * want to override it.
0391      */
0392     memset(&geo, 0, sizeof(geo));
0393     geo.start = get_start_sect(bdev);
0394     ret = disk->fops->getgeo(bdev, &geo);
0395     if (ret)
0396         return ret;
0397     if (copy_to_user(argp, &geo, sizeof(geo)))
0398         return -EFAULT;
0399     return 0;
0400 }
0401 
0402 #ifdef CONFIG_COMPAT
0403 struct compat_hd_geometry {
0404     unsigned char heads;
0405     unsigned char sectors;
0406     unsigned short cylinders;
0407     u32 start;
0408 };
0409 
0410 static int compat_hdio_getgeo(struct block_device *bdev,
0411                   struct compat_hd_geometry __user *ugeo)
0412 {
0413     struct gendisk *disk = bdev->bd_disk;
0414     struct hd_geometry geo;
0415     int ret;
0416 
0417     if (!ugeo)
0418         return -EINVAL;
0419     if (!disk->fops->getgeo)
0420         return -ENOTTY;
0421 
0422     memset(&geo, 0, sizeof(geo));
0423     /*
0424      * We need to set the startsect first, the driver may
0425      * want to override it.
0426      */
0427     geo.start = get_start_sect(bdev);
0428     ret = disk->fops->getgeo(bdev, &geo);
0429     if (ret)
0430         return ret;
0431 
0432     ret = copy_to_user(ugeo, &geo, 4);
0433     ret |= put_user(geo.start, &ugeo->start);
0434     if (ret)
0435         ret = -EFAULT;
0436 
0437     return ret;
0438 }
0439 #endif
0440 
0441 /* set the logical block size */
0442 static int blkdev_bszset(struct block_device *bdev, fmode_t mode,
0443         int __user *argp)
0444 {
0445     int ret, n;
0446 
0447     if (!capable(CAP_SYS_ADMIN))
0448         return -EACCES;
0449     if (!argp)
0450         return -EINVAL;
0451     if (get_user(n, argp))
0452         return -EFAULT;
0453 
0454     if (mode & FMODE_EXCL)
0455         return set_blocksize(bdev, n);
0456 
0457     if (IS_ERR(blkdev_get_by_dev(bdev->bd_dev, mode | FMODE_EXCL, &bdev)))
0458         return -EBUSY;
0459     ret = set_blocksize(bdev, n);
0460     blkdev_put(bdev, mode | FMODE_EXCL);
0461 
0462     return ret;
0463 }
0464 
0465 /*
0466  * Common commands that are handled the same way on native and compat
0467  * user space. Note the separate arg/argp parameters that are needed
0468  * to deal with the compat_ptr() conversion.
0469  */
0470 static int blkdev_common_ioctl(struct block_device *bdev, fmode_t mode,
0471                 unsigned cmd, unsigned long arg, void __user *argp)
0472 {
0473     unsigned int max_sectors;
0474 
0475     switch (cmd) {
0476     case BLKFLSBUF:
0477         return blkdev_flushbuf(bdev, mode, cmd, arg);
0478     case BLKROSET:
0479         return blkdev_roset(bdev, mode, cmd, arg);
0480     case BLKDISCARD:
0481         return blk_ioctl_discard(bdev, mode, arg);
0482     case BLKSECDISCARD:
0483         return blk_ioctl_secure_erase(bdev, mode, argp);
0484     case BLKZEROOUT:
0485         return blk_ioctl_zeroout(bdev, mode, arg);
0486     case BLKGETDISKSEQ:
0487         return put_u64(argp, bdev->bd_disk->diskseq);
0488     case BLKREPORTZONE:
0489         return blkdev_report_zones_ioctl(bdev, mode, cmd, arg);
0490     case BLKRESETZONE:
0491     case BLKOPENZONE:
0492     case BLKCLOSEZONE:
0493     case BLKFINISHZONE:
0494         return blkdev_zone_mgmt_ioctl(bdev, mode, cmd, arg);
0495     case BLKGETZONESZ:
0496         return put_uint(argp, bdev_zone_sectors(bdev));
0497     case BLKGETNRZONES:
0498         return put_uint(argp, bdev_nr_zones(bdev));
0499     case BLKROGET:
0500         return put_int(argp, bdev_read_only(bdev) != 0);
0501     case BLKSSZGET: /* get block device logical block size */
0502         return put_int(argp, bdev_logical_block_size(bdev));
0503     case BLKPBSZGET: /* get block device physical block size */
0504         return put_uint(argp, bdev_physical_block_size(bdev));
0505     case BLKIOMIN:
0506         return put_uint(argp, bdev_io_min(bdev));
0507     case BLKIOOPT:
0508         return put_uint(argp, bdev_io_opt(bdev));
0509     case BLKALIGNOFF:
0510         return put_int(argp, bdev_alignment_offset(bdev));
0511     case BLKDISCARDZEROES:
0512         return put_uint(argp, 0);
0513     case BLKSECTGET:
0514         max_sectors = min_t(unsigned int, USHRT_MAX,
0515                     queue_max_sectors(bdev_get_queue(bdev)));
0516         return put_ushort(argp, max_sectors);
0517     case BLKROTATIONAL:
0518         return put_ushort(argp, !bdev_nonrot(bdev));
0519     case BLKRASET:
0520     case BLKFRASET:
0521         if(!capable(CAP_SYS_ADMIN))
0522             return -EACCES;
0523         bdev->bd_disk->bdi->ra_pages = (arg * 512) / PAGE_SIZE;
0524         return 0;
0525     case BLKRRPART:
0526         if (!capable(CAP_SYS_ADMIN))
0527             return -EACCES;
0528         if (bdev_is_partition(bdev))
0529             return -EINVAL;
0530         return disk_scan_partitions(bdev->bd_disk, mode & ~FMODE_EXCL);
0531     case BLKTRACESTART:
0532     case BLKTRACESTOP:
0533     case BLKTRACETEARDOWN:
0534         return blk_trace_ioctl(bdev, cmd, argp);
0535     case IOC_PR_REGISTER:
0536         return blkdev_pr_register(bdev, argp);
0537     case IOC_PR_RESERVE:
0538         return blkdev_pr_reserve(bdev, argp);
0539     case IOC_PR_RELEASE:
0540         return blkdev_pr_release(bdev, argp);
0541     case IOC_PR_PREEMPT:
0542         return blkdev_pr_preempt(bdev, argp, false);
0543     case IOC_PR_PREEMPT_ABORT:
0544         return blkdev_pr_preempt(bdev, argp, true);
0545     case IOC_PR_CLEAR:
0546         return blkdev_pr_clear(bdev, argp);
0547     default:
0548         return -ENOIOCTLCMD;
0549     }
0550 }
0551 
0552 /*
0553  * Always keep this in sync with compat_blkdev_ioctl()
0554  * to handle all incompatible commands in both functions.
0555  *
0556  * New commands must be compatible and go into blkdev_common_ioctl
0557  */
0558 long blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
0559 {
0560     struct block_device *bdev = I_BDEV(file->f_mapping->host);
0561     void __user *argp = (void __user *)arg;
0562     fmode_t mode = file->f_mode;
0563     int ret;
0564 
0565     /*
0566      * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have
0567      * to updated it before every ioctl.
0568      */
0569     if (file->f_flags & O_NDELAY)
0570         mode |= FMODE_NDELAY;
0571     else
0572         mode &= ~FMODE_NDELAY;
0573 
0574     switch (cmd) {
0575     /* These need separate implementations for the data structure */
0576     case HDIO_GETGEO:
0577         return blkdev_getgeo(bdev, argp);
0578     case BLKPG:
0579         return blkpg_ioctl(bdev, argp);
0580 
0581     /* Compat mode returns 32-bit data instead of 'long' */
0582     case BLKRAGET:
0583     case BLKFRAGET:
0584         if (!argp)
0585             return -EINVAL;
0586         return put_long(argp,
0587             (bdev->bd_disk->bdi->ra_pages * PAGE_SIZE) / 512);
0588     case BLKGETSIZE:
0589         if (bdev_nr_sectors(bdev) > ~0UL)
0590             return -EFBIG;
0591         return put_ulong(argp, bdev_nr_sectors(bdev));
0592 
0593     /* The data is compatible, but the command number is different */
0594     case BLKBSZGET: /* get block device soft block size (cf. BLKSSZGET) */
0595         return put_int(argp, block_size(bdev));
0596     case BLKBSZSET:
0597         return blkdev_bszset(bdev, mode, argp);
0598     case BLKGETSIZE64:
0599         return put_u64(argp, bdev_nr_bytes(bdev));
0600 
0601     /* Incompatible alignment on i386 */
0602     case BLKTRACESETUP:
0603         return blk_trace_ioctl(bdev, cmd, argp);
0604     default:
0605         break;
0606     }
0607 
0608     ret = blkdev_common_ioctl(bdev, mode, cmd, arg, argp);
0609     if (ret != -ENOIOCTLCMD)
0610         return ret;
0611 
0612     if (!bdev->bd_disk->fops->ioctl)
0613         return -ENOTTY;
0614     return bdev->bd_disk->fops->ioctl(bdev, mode, cmd, arg);
0615 }
0616 
0617 #ifdef CONFIG_COMPAT
0618 
0619 #define BLKBSZGET_32        _IOR(0x12, 112, int)
0620 #define BLKBSZSET_32        _IOW(0x12, 113, int)
0621 #define BLKGETSIZE64_32     _IOR(0x12, 114, int)
0622 
0623 /* Most of the generic ioctls are handled in the normal fallback path.
0624    This assumes the blkdev's low level compat_ioctl always returns
0625    ENOIOCTLCMD for unknown ioctls. */
0626 long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
0627 {
0628     int ret;
0629     void __user *argp = compat_ptr(arg);
0630     struct block_device *bdev = I_BDEV(file->f_mapping->host);
0631     struct gendisk *disk = bdev->bd_disk;
0632     fmode_t mode = file->f_mode;
0633 
0634     /*
0635      * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have
0636      * to updated it before every ioctl.
0637      */
0638     if (file->f_flags & O_NDELAY)
0639         mode |= FMODE_NDELAY;
0640     else
0641         mode &= ~FMODE_NDELAY;
0642 
0643     switch (cmd) {
0644     /* These need separate implementations for the data structure */
0645     case HDIO_GETGEO:
0646         return compat_hdio_getgeo(bdev, argp);
0647     case BLKPG:
0648         return compat_blkpg_ioctl(bdev, argp);
0649 
0650     /* Compat mode returns 32-bit data instead of 'long' */
0651     case BLKRAGET:
0652     case BLKFRAGET:
0653         if (!argp)
0654             return -EINVAL;
0655         return compat_put_long(argp,
0656             (bdev->bd_disk->bdi->ra_pages * PAGE_SIZE) / 512);
0657     case BLKGETSIZE:
0658         if (bdev_nr_sectors(bdev) > ~(compat_ulong_t)0)
0659             return -EFBIG;
0660         return compat_put_ulong(argp, bdev_nr_sectors(bdev));
0661 
0662     /* The data is compatible, but the command number is different */
0663     case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */
0664         return put_int(argp, bdev_logical_block_size(bdev));
0665     case BLKBSZSET_32:
0666         return blkdev_bszset(bdev, mode, argp);
0667     case BLKGETSIZE64_32:
0668         return put_u64(argp, bdev_nr_bytes(bdev));
0669 
0670     /* Incompatible alignment on i386 */
0671     case BLKTRACESETUP32:
0672         return blk_trace_ioctl(bdev, cmd, argp);
0673     default:
0674         break;
0675     }
0676 
0677     ret = blkdev_common_ioctl(bdev, mode, cmd, arg, argp);
0678     if (ret == -ENOIOCTLCMD && disk->fops->compat_ioctl)
0679         ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg);
0680 
0681     return ret;
0682 }
0683 #endif