Back to home page

LXR

 
 

    


0001 #include <linux/blkdev.h>
0002 #include <linux/blkpg.h>
0003 #include <linux/blktrace_api.h>
0004 #include <linux/cdrom.h>
0005 #include <linux/compat.h>
0006 #include <linux/elevator.h>
0007 #include <linux/fd.h>
0008 #include <linux/hdreg.h>
0009 #include <linux/slab.h>
0010 #include <linux/syscalls.h>
0011 #include <linux/types.h>
0012 #include <linux/uaccess.h>
0013 
0014 static int compat_put_ushort(unsigned long arg, unsigned short val)
0015 {
0016     return put_user(val, (unsigned short __user *)compat_ptr(arg));
0017 }
0018 
0019 static int compat_put_int(unsigned long arg, int val)
0020 {
0021     return put_user(val, (compat_int_t __user *)compat_ptr(arg));
0022 }
0023 
0024 static int compat_put_uint(unsigned long arg, unsigned int val)
0025 {
0026     return put_user(val, (compat_uint_t __user *)compat_ptr(arg));
0027 }
0028 
0029 static int compat_put_long(unsigned long arg, long val)
0030 {
0031     return put_user(val, (compat_long_t __user *)compat_ptr(arg));
0032 }
0033 
0034 static int compat_put_ulong(unsigned long arg, compat_ulong_t val)
0035 {
0036     return put_user(val, (compat_ulong_t __user *)compat_ptr(arg));
0037 }
0038 
0039 static int compat_put_u64(unsigned long arg, u64 val)
0040 {
0041     return put_user(val, (compat_u64 __user *)compat_ptr(arg));
0042 }
0043 
0044 struct compat_hd_geometry {
0045     unsigned char heads;
0046     unsigned char sectors;
0047     unsigned short cylinders;
0048     u32 start;
0049 };
0050 
0051 static int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev,
0052             struct compat_hd_geometry __user *ugeo)
0053 {
0054     struct hd_geometry geo;
0055     int ret;
0056 
0057     if (!ugeo)
0058         return -EINVAL;
0059     if (!disk->fops->getgeo)
0060         return -ENOTTY;
0061 
0062     memset(&geo, 0, sizeof(geo));
0063     /*
0064      * We need to set the startsect first, the driver may
0065      * want to override it.
0066      */
0067     geo.start = get_start_sect(bdev);
0068     ret = disk->fops->getgeo(bdev, &geo);
0069     if (ret)
0070         return ret;
0071 
0072     ret = copy_to_user(ugeo, &geo, 4);
0073     ret |= put_user(geo.start, &ugeo->start);
0074     if (ret)
0075         ret = -EFAULT;
0076 
0077     return ret;
0078 }
0079 
0080 static int compat_hdio_ioctl(struct block_device *bdev, fmode_t mode,
0081         unsigned int cmd, unsigned long arg)
0082 {
0083     mm_segment_t old_fs = get_fs();
0084     unsigned long kval;
0085     unsigned int __user *uvp;
0086     int error;
0087 
0088     set_fs(KERNEL_DS);
0089     error = __blkdev_driver_ioctl(bdev, mode,
0090                 cmd, (unsigned long)(&kval));
0091     set_fs(old_fs);
0092 
0093     if (error == 0) {
0094         uvp = compat_ptr(arg);
0095         if (put_user(kval, uvp))
0096             error = -EFAULT;
0097     }
0098     return error;
0099 }
0100 
0101 struct compat_cdrom_read_audio {
0102     union cdrom_addr    addr;
0103     u8          addr_format;
0104     compat_int_t        nframes;
0105     compat_caddr_t      buf;
0106 };
0107 
0108 struct compat_cdrom_generic_command {
0109     unsigned char   cmd[CDROM_PACKET_SIZE];
0110     compat_caddr_t  buffer;
0111     compat_uint_t   buflen;
0112     compat_int_t    stat;
0113     compat_caddr_t  sense;
0114     unsigned char   data_direction;
0115     compat_int_t    quiet;
0116     compat_int_t    timeout;
0117     compat_caddr_t  reserved[1];
0118 };
0119 
0120 static int compat_cdrom_read_audio(struct block_device *bdev, fmode_t mode,
0121         unsigned int cmd, unsigned long arg)
0122 {
0123     struct cdrom_read_audio __user *cdread_audio;
0124     struct compat_cdrom_read_audio __user *cdread_audio32;
0125     __u32 data;
0126     void __user *datap;
0127 
0128     cdread_audio = compat_alloc_user_space(sizeof(*cdread_audio));
0129     cdread_audio32 = compat_ptr(arg);
0130 
0131     if (copy_in_user(&cdread_audio->addr,
0132              &cdread_audio32->addr,
0133              (sizeof(*cdread_audio32) -
0134               sizeof(compat_caddr_t))))
0135         return -EFAULT;
0136 
0137     if (get_user(data, &cdread_audio32->buf))
0138         return -EFAULT;
0139     datap = compat_ptr(data);
0140     if (put_user(datap, &cdread_audio->buf))
0141         return -EFAULT;
0142 
0143     return __blkdev_driver_ioctl(bdev, mode, cmd,
0144             (unsigned long)cdread_audio);
0145 }
0146 
0147 static int compat_cdrom_generic_command(struct block_device *bdev, fmode_t mode,
0148         unsigned int cmd, unsigned long arg)
0149 {
0150     struct cdrom_generic_command __user *cgc;
0151     struct compat_cdrom_generic_command __user *cgc32;
0152     u32 data;
0153     unsigned char dir;
0154     int itmp;
0155 
0156     cgc = compat_alloc_user_space(sizeof(*cgc));
0157     cgc32 = compat_ptr(arg);
0158 
0159     if (copy_in_user(&cgc->cmd, &cgc32->cmd, sizeof(cgc->cmd)) ||
0160         get_user(data, &cgc32->buffer) ||
0161         put_user(compat_ptr(data), &cgc->buffer) ||
0162         copy_in_user(&cgc->buflen, &cgc32->buflen,
0163              (sizeof(unsigned int) + sizeof(int))) ||
0164         get_user(data, &cgc32->sense) ||
0165         put_user(compat_ptr(data), &cgc->sense) ||
0166         get_user(dir, &cgc32->data_direction) ||
0167         put_user(dir, &cgc->data_direction) ||
0168         get_user(itmp, &cgc32->quiet) ||
0169         put_user(itmp, &cgc->quiet) ||
0170         get_user(itmp, &cgc32->timeout) ||
0171         put_user(itmp, &cgc->timeout) ||
0172         get_user(data, &cgc32->reserved[0]) ||
0173         put_user(compat_ptr(data), &cgc->reserved[0]))
0174         return -EFAULT;
0175 
0176     return __blkdev_driver_ioctl(bdev, mode, cmd, (unsigned long)cgc);
0177 }
0178 
0179 struct compat_blkpg_ioctl_arg {
0180     compat_int_t op;
0181     compat_int_t flags;
0182     compat_int_t datalen;
0183     compat_caddr_t data;
0184 };
0185 
0186 static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode,
0187         unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32)
0188 {
0189     struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a));
0190     compat_caddr_t udata;
0191     compat_int_t n;
0192     int err;
0193 
0194     err = get_user(n, &ua32->op);
0195     err |= put_user(n, &a->op);
0196     err |= get_user(n, &ua32->flags);
0197     err |= put_user(n, &a->flags);
0198     err |= get_user(n, &ua32->datalen);
0199     err |= put_user(n, &a->datalen);
0200     err |= get_user(udata, &ua32->data);
0201     err |= put_user(compat_ptr(udata), &a->data);
0202     if (err)
0203         return err;
0204 
0205     return blkdev_ioctl(bdev, mode, cmd, (unsigned long)a);
0206 }
0207 
0208 #define BLKBSZGET_32        _IOR(0x12, 112, int)
0209 #define BLKBSZSET_32        _IOW(0x12, 113, int)
0210 #define BLKGETSIZE64_32     _IOR(0x12, 114, int)
0211 
0212 struct compat_floppy_drive_params {
0213     char        cmos;
0214     compat_ulong_t  max_dtr;
0215     compat_ulong_t  hlt;
0216     compat_ulong_t  hut;
0217     compat_ulong_t  srt;
0218     compat_ulong_t  spinup;
0219     compat_ulong_t  spindown;
0220     unsigned char   spindown_offset;
0221     unsigned char   select_delay;
0222     unsigned char   rps;
0223     unsigned char   tracks;
0224     compat_ulong_t  timeout;
0225     unsigned char   interleave_sect;
0226     struct floppy_max_errors max_errors;
0227     char        flags;
0228     char        read_track;
0229     short       autodetect[8];
0230     compat_int_t    checkfreq;
0231     compat_int_t    native_format;
0232 };
0233 
0234 struct compat_floppy_drive_struct {
0235     signed char flags;
0236     compat_ulong_t  spinup_date;
0237     compat_ulong_t  select_date;
0238     compat_ulong_t  first_read_date;
0239     short       probed_format;
0240     short       track;
0241     short       maxblock;
0242     short       maxtrack;
0243     compat_int_t    generation;
0244     compat_int_t    keep_data;
0245     compat_int_t    fd_ref;
0246     compat_int_t    fd_device;
0247     compat_int_t    last_checked;
0248     compat_caddr_t dmabuf;
0249     compat_int_t    bufblocks;
0250 };
0251 
0252 struct compat_floppy_fdc_state {
0253     compat_int_t    spec1;
0254     compat_int_t    spec2;
0255     compat_int_t    dtr;
0256     unsigned char   version;
0257     unsigned char   dor;
0258     compat_ulong_t  address;
0259     unsigned int    rawcmd:2;
0260     unsigned int    reset:1;
0261     unsigned int    need_configure:1;
0262     unsigned int    perp_mode:2;
0263     unsigned int    has_fifo:1;
0264     unsigned int    driver_version;
0265     unsigned char   track[4];
0266 };
0267 
0268 struct compat_floppy_write_errors {
0269     unsigned int    write_errors;
0270     compat_ulong_t  first_error_sector;
0271     compat_int_t    first_error_generation;
0272     compat_ulong_t  last_error_sector;
0273     compat_int_t    last_error_generation;
0274     compat_uint_t   badness;
0275 };
0276 
0277 #define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct)
0278 #define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct)
0279 #define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params)
0280 #define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params)
0281 #define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct)
0282 #define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct compat_floppy_drive_struct)
0283 #define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state)
0284 #define FDWERRORGET32  _IOR(2, 0x17, struct compat_floppy_write_errors)
0285 
0286 static struct {
0287     unsigned int    cmd32;
0288     unsigned int    cmd;
0289 } fd_ioctl_trans_table[] = {
0290     { FDSETPRM32, FDSETPRM },
0291     { FDDEFPRM32, FDDEFPRM },
0292     { FDGETPRM32, FDGETPRM },
0293     { FDSETDRVPRM32, FDSETDRVPRM },
0294     { FDGETDRVPRM32, FDGETDRVPRM },
0295     { FDGETDRVSTAT32, FDGETDRVSTAT },
0296     { FDPOLLDRVSTAT32, FDPOLLDRVSTAT },
0297     { FDGETFDCSTAT32, FDGETFDCSTAT },
0298     { FDWERRORGET32, FDWERRORGET }
0299 };
0300 
0301 #define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table)
0302 
0303 static int compat_fd_ioctl(struct block_device *bdev, fmode_t mode,
0304         unsigned int cmd, unsigned long arg)
0305 {
0306     mm_segment_t old_fs = get_fs();
0307     void *karg = NULL;
0308     unsigned int kcmd = 0;
0309     int i, err;
0310 
0311     for (i = 0; i < NR_FD_IOCTL_TRANS; i++)
0312         if (cmd == fd_ioctl_trans_table[i].cmd32) {
0313             kcmd = fd_ioctl_trans_table[i].cmd;
0314             break;
0315         }
0316     if (!kcmd)
0317         return -EINVAL;
0318 
0319     switch (cmd) {
0320     case FDSETPRM32:
0321     case FDDEFPRM32:
0322     case FDGETPRM32:
0323     {
0324         compat_uptr_t name;
0325         struct compat_floppy_struct __user *uf;
0326         struct floppy_struct *f;
0327 
0328         uf = compat_ptr(arg);
0329         f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL);
0330         if (!karg)
0331             return -ENOMEM;
0332         if (cmd == FDGETPRM32)
0333             break;
0334         err = __get_user(f->size, &uf->size);
0335         err |= __get_user(f->sect, &uf->sect);
0336         err |= __get_user(f->head, &uf->head);
0337         err |= __get_user(f->track, &uf->track);
0338         err |= __get_user(f->stretch, &uf->stretch);
0339         err |= __get_user(f->gap, &uf->gap);
0340         err |= __get_user(f->rate, &uf->rate);
0341         err |= __get_user(f->spec1, &uf->spec1);
0342         err |= __get_user(f->fmt_gap, &uf->fmt_gap);
0343         err |= __get_user(name, &uf->name);
0344         f->name = compat_ptr(name);
0345         if (err) {
0346             err = -EFAULT;
0347             goto out;
0348         }
0349         break;
0350     }
0351     case FDSETDRVPRM32:
0352     case FDGETDRVPRM32:
0353     {
0354         struct compat_floppy_drive_params __user *uf;
0355         struct floppy_drive_params *f;
0356 
0357         uf = compat_ptr(arg);
0358         f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL);
0359         if (!karg)
0360             return -ENOMEM;
0361         if (cmd == FDGETDRVPRM32)
0362             break;
0363         err = __get_user(f->cmos, &uf->cmos);
0364         err |= __get_user(f->max_dtr, &uf->max_dtr);
0365         err |= __get_user(f->hlt, &uf->hlt);
0366         err |= __get_user(f->hut, &uf->hut);
0367         err |= __get_user(f->srt, &uf->srt);
0368         err |= __get_user(f->spinup, &uf->spinup);
0369         err |= __get_user(f->spindown, &uf->spindown);
0370         err |= __get_user(f->spindown_offset, &uf->spindown_offset);
0371         err |= __get_user(f->select_delay, &uf->select_delay);
0372         err |= __get_user(f->rps, &uf->rps);
0373         err |= __get_user(f->tracks, &uf->tracks);
0374         err |= __get_user(f->timeout, &uf->timeout);
0375         err |= __get_user(f->interleave_sect, &uf->interleave_sect);
0376         err |= __copy_from_user(&f->max_errors, &uf->max_errors, sizeof(f->max_errors));
0377         err |= __get_user(f->flags, &uf->flags);
0378         err |= __get_user(f->read_track, &uf->read_track);
0379         err |= __copy_from_user(f->autodetect, uf->autodetect, sizeof(f->autodetect));
0380         err |= __get_user(f->checkfreq, &uf->checkfreq);
0381         err |= __get_user(f->native_format, &uf->native_format);
0382         if (err) {
0383             err = -EFAULT;
0384             goto out;
0385         }
0386         break;
0387     }
0388     case FDGETDRVSTAT32:
0389     case FDPOLLDRVSTAT32:
0390         karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL);
0391         if (!karg)
0392             return -ENOMEM;
0393         break;
0394     case FDGETFDCSTAT32:
0395         karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL);
0396         if (!karg)
0397             return -ENOMEM;
0398         break;
0399     case FDWERRORGET32:
0400         karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL);
0401         if (!karg)
0402             return -ENOMEM;
0403         break;
0404     default:
0405         return -EINVAL;
0406     }
0407     set_fs(KERNEL_DS);
0408     err = __blkdev_driver_ioctl(bdev, mode, kcmd, (unsigned long)karg);
0409     set_fs(old_fs);
0410     if (err)
0411         goto out;
0412     switch (cmd) {
0413     case FDGETPRM32:
0414     {
0415         struct floppy_struct *f = karg;
0416         struct compat_floppy_struct __user *uf = compat_ptr(arg);
0417 
0418         err = __put_user(f->size, &uf->size);
0419         err |= __put_user(f->sect, &uf->sect);
0420         err |= __put_user(f->head, &uf->head);
0421         err |= __put_user(f->track, &uf->track);
0422         err |= __put_user(f->stretch, &uf->stretch);
0423         err |= __put_user(f->gap, &uf->gap);
0424         err |= __put_user(f->rate, &uf->rate);
0425         err |= __put_user(f->spec1, &uf->spec1);
0426         err |= __put_user(f->fmt_gap, &uf->fmt_gap);
0427         err |= __put_user((u64)f->name, (compat_caddr_t __user *)&uf->name);
0428         break;
0429     }
0430     case FDGETDRVPRM32:
0431     {
0432         struct compat_floppy_drive_params __user *uf;
0433         struct floppy_drive_params *f = karg;
0434 
0435         uf = compat_ptr(arg);
0436         err = __put_user(f->cmos, &uf->cmos);
0437         err |= __put_user(f->max_dtr, &uf->max_dtr);
0438         err |= __put_user(f->hlt, &uf->hlt);
0439         err |= __put_user(f->hut, &uf->hut);
0440         err |= __put_user(f->srt, &uf->srt);
0441         err |= __put_user(f->spinup, &uf->spinup);
0442         err |= __put_user(f->spindown, &uf->spindown);
0443         err |= __put_user(f->spindown_offset, &uf->spindown_offset);
0444         err |= __put_user(f->select_delay, &uf->select_delay);
0445         err |= __put_user(f->rps, &uf->rps);
0446         err |= __put_user(f->tracks, &uf->tracks);
0447         err |= __put_user(f->timeout, &uf->timeout);
0448         err |= __put_user(f->interleave_sect, &uf->interleave_sect);
0449         err |= __copy_to_user(&uf->max_errors, &f->max_errors, sizeof(f->max_errors));
0450         err |= __put_user(f->flags, &uf->flags);
0451         err |= __put_user(f->read_track, &uf->read_track);
0452         err |= __copy_to_user(uf->autodetect, f->autodetect, sizeof(f->autodetect));
0453         err |= __put_user(f->checkfreq, &uf->checkfreq);
0454         err |= __put_user(f->native_format, &uf->native_format);
0455         break;
0456     }
0457     case FDGETDRVSTAT32:
0458     case FDPOLLDRVSTAT32:
0459     {
0460         struct compat_floppy_drive_struct __user *uf;
0461         struct floppy_drive_struct *f = karg;
0462 
0463         uf = compat_ptr(arg);
0464         err = __put_user(f->flags, &uf->flags);
0465         err |= __put_user(f->spinup_date, &uf->spinup_date);
0466         err |= __put_user(f->select_date, &uf->select_date);
0467         err |= __put_user(f->first_read_date, &uf->first_read_date);
0468         err |= __put_user(f->probed_format, &uf->probed_format);
0469         err |= __put_user(f->track, &uf->track);
0470         err |= __put_user(f->maxblock, &uf->maxblock);
0471         err |= __put_user(f->maxtrack, &uf->maxtrack);
0472         err |= __put_user(f->generation, &uf->generation);
0473         err |= __put_user(f->keep_data, &uf->keep_data);
0474         err |= __put_user(f->fd_ref, &uf->fd_ref);
0475         err |= __put_user(f->fd_device, &uf->fd_device);
0476         err |= __put_user(f->last_checked, &uf->last_checked);
0477         err |= __put_user((u64)f->dmabuf, &uf->dmabuf);
0478         err |= __put_user((u64)f->bufblocks, &uf->bufblocks);
0479         break;
0480     }
0481     case FDGETFDCSTAT32:
0482     {
0483         struct compat_floppy_fdc_state __user *uf;
0484         struct floppy_fdc_state *f = karg;
0485 
0486         uf = compat_ptr(arg);
0487         err = __put_user(f->spec1, &uf->spec1);
0488         err |= __put_user(f->spec2, &uf->spec2);
0489         err |= __put_user(f->dtr, &uf->dtr);
0490         err |= __put_user(f->version, &uf->version);
0491         err |= __put_user(f->dor, &uf->dor);
0492         err |= __put_user(f->address, &uf->address);
0493         err |= __copy_to_user((char __user *)&uf->address + sizeof(uf->address),
0494                    (char *)&f->address + sizeof(f->address), sizeof(int));
0495         err |= __put_user(f->driver_version, &uf->driver_version);
0496         err |= __copy_to_user(uf->track, f->track, sizeof(f->track));
0497         break;
0498     }
0499     case FDWERRORGET32:
0500     {
0501         struct compat_floppy_write_errors __user *uf;
0502         struct floppy_write_errors *f = karg;
0503 
0504         uf = compat_ptr(arg);
0505         err = __put_user(f->write_errors, &uf->write_errors);
0506         err |= __put_user(f->first_error_sector, &uf->first_error_sector);
0507         err |= __put_user(f->first_error_generation, &uf->first_error_generation);
0508         err |= __put_user(f->last_error_sector, &uf->last_error_sector);
0509         err |= __put_user(f->last_error_generation, &uf->last_error_generation);
0510         err |= __put_user(f->badness, &uf->badness);
0511         break;
0512     }
0513     default:
0514         break;
0515     }
0516     if (err)
0517         err = -EFAULT;
0518 
0519 out:
0520     kfree(karg);
0521     return err;
0522 }
0523 
0524 static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
0525             unsigned cmd, unsigned long arg)
0526 {
0527     switch (cmd) {
0528     case HDIO_GET_UNMASKINTR:
0529     case HDIO_GET_MULTCOUNT:
0530     case HDIO_GET_KEEPSETTINGS:
0531     case HDIO_GET_32BIT:
0532     case HDIO_GET_NOWERR:
0533     case HDIO_GET_DMA:
0534     case HDIO_GET_NICE:
0535     case HDIO_GET_WCACHE:
0536     case HDIO_GET_ACOUSTIC:
0537     case HDIO_GET_ADDRESS:
0538     case HDIO_GET_BUSSTATE:
0539         return compat_hdio_ioctl(bdev, mode, cmd, arg);
0540     case FDSETPRM32:
0541     case FDDEFPRM32:
0542     case FDGETPRM32:
0543     case FDSETDRVPRM32:
0544     case FDGETDRVPRM32:
0545     case FDGETDRVSTAT32:
0546     case FDPOLLDRVSTAT32:
0547     case FDGETFDCSTAT32:
0548     case FDWERRORGET32:
0549         return compat_fd_ioctl(bdev, mode, cmd, arg);
0550     case CDROMREADAUDIO:
0551         return compat_cdrom_read_audio(bdev, mode, cmd, arg);
0552     case CDROM_SEND_PACKET:
0553         return compat_cdrom_generic_command(bdev, mode, cmd, arg);
0554 
0555     /*
0556      * No handler required for the ones below, we just need to
0557      * convert arg to a 64 bit pointer.
0558      */
0559     case BLKSECTSET:
0560     /*
0561      * 0x03 -- HD/IDE ioctl's used by hdparm and friends.
0562      *         Some need translations, these do not.
0563      */
0564     case HDIO_GET_IDENTITY:
0565     case HDIO_DRIVE_TASK:
0566     case HDIO_DRIVE_CMD:
0567     /* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */
0568     case 0x330:
0569     /* 0x02 -- Floppy ioctls */
0570     case FDMSGON:
0571     case FDMSGOFF:
0572     case FDSETEMSGTRESH:
0573     case FDFLUSH:
0574     case FDWERRORCLR:
0575     case FDSETMAXERRS:
0576     case FDGETMAXERRS:
0577     case FDGETDRVTYP:
0578     case FDEJECT:
0579     case FDCLRPRM:
0580     case FDFMTBEG:
0581     case FDFMTEND:
0582     case FDRESET:
0583     case FDTWADDLE:
0584     case FDFMTTRK:
0585     case FDRAWCMD:
0586     /* CDROM stuff */
0587     case CDROMPAUSE:
0588     case CDROMRESUME:
0589     case CDROMPLAYMSF:
0590     case CDROMPLAYTRKIND:
0591     case CDROMREADTOCHDR:
0592     case CDROMREADTOCENTRY:
0593     case CDROMSTOP:
0594     case CDROMSTART:
0595     case CDROMEJECT:
0596     case CDROMVOLCTRL:
0597     case CDROMSUBCHNL:
0598     case CDROMMULTISESSION:
0599     case CDROM_GET_MCN:
0600     case CDROMRESET:
0601     case CDROMVOLREAD:
0602     case CDROMSEEK:
0603     case CDROMPLAYBLK:
0604     case CDROMCLOSETRAY:
0605     case CDROM_DISC_STATUS:
0606     case CDROM_CHANGER_NSLOTS:
0607     case CDROM_GET_CAPABILITY:
0608     /* Ignore cdrom.h about these next 5 ioctls, they absolutely do
0609      * not take a struct cdrom_read, instead they take a struct cdrom_msf
0610      * which is compatible.
0611      */
0612     case CDROMREADMODE2:
0613     case CDROMREADMODE1:
0614     case CDROMREADRAW:
0615     case CDROMREADCOOKED:
0616     case CDROMREADALL:
0617     /* DVD ioctls */
0618     case DVD_READ_STRUCT:
0619     case DVD_WRITE_STRUCT:
0620     case DVD_AUTH:
0621         arg = (unsigned long)compat_ptr(arg);
0622     /* These intepret arg as an unsigned long, not as a pointer,
0623      * so we must not do compat_ptr() conversion. */
0624     case HDIO_SET_MULTCOUNT:
0625     case HDIO_SET_UNMASKINTR:
0626     case HDIO_SET_KEEPSETTINGS:
0627     case HDIO_SET_32BIT:
0628     case HDIO_SET_NOWERR:
0629     case HDIO_SET_DMA:
0630     case HDIO_SET_PIO_MODE:
0631     case HDIO_SET_NICE:
0632     case HDIO_SET_WCACHE:
0633     case HDIO_SET_ACOUSTIC:
0634     case HDIO_SET_BUSSTATE:
0635     case HDIO_SET_ADDRESS:
0636     case CDROMEJECT_SW:
0637     case CDROM_SET_OPTIONS:
0638     case CDROM_CLEAR_OPTIONS:
0639     case CDROM_SELECT_SPEED:
0640     case CDROM_SELECT_DISC:
0641     case CDROM_MEDIA_CHANGED:
0642     case CDROM_DRIVE_STATUS:
0643     case CDROM_LOCKDOOR:
0644     case CDROM_DEBUG:
0645         break;
0646     default:
0647         /* unknown ioctl number */
0648         return -ENOIOCTLCMD;
0649     }
0650 
0651     return __blkdev_driver_ioctl(bdev, mode, cmd, arg);
0652 }
0653 
0654 /* Most of the generic ioctls are handled in the normal fallback path.
0655    This assumes the blkdev's low level compat_ioctl always returns
0656    ENOIOCTLCMD for unknown ioctls. */
0657 long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
0658 {
0659     int ret = -ENOIOCTLCMD;
0660     struct inode *inode = file->f_mapping->host;
0661     struct block_device *bdev = inode->i_bdev;
0662     struct gendisk *disk = bdev->bd_disk;
0663     fmode_t mode = file->f_mode;
0664     struct backing_dev_info *bdi;
0665     loff_t size;
0666     unsigned int max_sectors;
0667 
0668     /*
0669      * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have
0670      * to updated it before every ioctl.
0671      */
0672     if (file->f_flags & O_NDELAY)
0673         mode |= FMODE_NDELAY;
0674     else
0675         mode &= ~FMODE_NDELAY;
0676 
0677     switch (cmd) {
0678     case HDIO_GETGEO:
0679         return compat_hdio_getgeo(disk, bdev, compat_ptr(arg));
0680     case BLKPBSZGET:
0681         return compat_put_uint(arg, bdev_physical_block_size(bdev));
0682     case BLKIOMIN:
0683         return compat_put_uint(arg, bdev_io_min(bdev));
0684     case BLKIOOPT:
0685         return compat_put_uint(arg, bdev_io_opt(bdev));
0686     case BLKALIGNOFF:
0687         return compat_put_int(arg, bdev_alignment_offset(bdev));
0688     case BLKDISCARDZEROES:
0689         return compat_put_uint(arg, bdev_discard_zeroes_data(bdev));
0690     case BLKFLSBUF:
0691     case BLKROSET:
0692     case BLKDISCARD:
0693     case BLKSECDISCARD:
0694     case BLKZEROOUT:
0695     /*
0696      * the ones below are implemented in blkdev_locked_ioctl,
0697      * but we call blkdev_ioctl, which gets the lock for us
0698      */
0699     case BLKRRPART:
0700         return blkdev_ioctl(bdev, mode, cmd,
0701                 (unsigned long)compat_ptr(arg));
0702     case BLKBSZSET_32:
0703         return blkdev_ioctl(bdev, mode, BLKBSZSET,
0704                 (unsigned long)compat_ptr(arg));
0705     case BLKPG:
0706         return compat_blkpg_ioctl(bdev, mode, cmd, compat_ptr(arg));
0707     case BLKRAGET:
0708     case BLKFRAGET:
0709         if (!arg)
0710             return -EINVAL;
0711         bdi = blk_get_backing_dev_info(bdev);
0712         return compat_put_long(arg,
0713                        (bdi->ra_pages * PAGE_SIZE) / 512);
0714     case BLKROGET: /* compatible */
0715         return compat_put_int(arg, bdev_read_only(bdev) != 0);
0716     case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */
0717         return compat_put_int(arg, block_size(bdev));
0718     case BLKSSZGET: /* get block device hardware sector size */
0719         return compat_put_int(arg, bdev_logical_block_size(bdev));
0720     case BLKSECTGET:
0721         max_sectors = min_t(unsigned int, USHRT_MAX,
0722                     queue_max_sectors(bdev_get_queue(bdev)));
0723         return compat_put_ushort(arg, max_sectors);
0724     case BLKROTATIONAL:
0725         return compat_put_ushort(arg,
0726                      !blk_queue_nonrot(bdev_get_queue(bdev)));
0727     case BLKRASET: /* compatible, but no compat_ptr (!) */
0728     case BLKFRASET:
0729         if (!capable(CAP_SYS_ADMIN))
0730             return -EACCES;
0731         bdi = blk_get_backing_dev_info(bdev);
0732         bdi->ra_pages = (arg * 512) / PAGE_SIZE;
0733         return 0;
0734     case BLKGETSIZE:
0735         size = i_size_read(bdev->bd_inode);
0736         if ((size >> 9) > ~0UL)
0737             return -EFBIG;
0738         return compat_put_ulong(arg, size >> 9);
0739 
0740     case BLKGETSIZE64_32:
0741         return compat_put_u64(arg, i_size_read(bdev->bd_inode));
0742 
0743     case BLKTRACESETUP32:
0744     case BLKTRACESTART: /* compatible */
0745     case BLKTRACESTOP:  /* compatible */
0746     case BLKTRACETEARDOWN: /* compatible */
0747         ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg));
0748         return ret;
0749     default:
0750         if (disk->fops->compat_ioctl)
0751             ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg);
0752         if (ret == -ENOIOCTLCMD)
0753             ret = compat_blkdev_driver_ioctl(bdev, mode, cmd, arg);
0754         return ret;
0755     }
0756 }