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/slab.h> 10#include <linux/syscalls.h> 11#include <linux/types.h> 12#include <linux/uaccess.h> 13 14static int compat_put_ushort(unsigned long arg, unsigned short val) 15{ 16 return put_user(val, (unsigned short __user *)compat_ptr(arg)); 17} 18 19static int compat_put_int(unsigned long arg, int val) 20{ 21 return put_user(val, (compat_int_t __user *)compat_ptr(arg)); 22} 23 24static int compat_put_uint(unsigned long arg, unsigned int val) 25{ 26 return put_user(val, (compat_uint_t __user *)compat_ptr(arg)); 27} 28 29static int compat_put_long(unsigned long arg, long val) 30{ 31 return put_user(val, (compat_long_t __user *)compat_ptr(arg)); 32} 33 34static int compat_put_ulong(unsigned long arg, compat_ulong_t val) 35{ 36 return put_user(val, (compat_ulong_t __user *)compat_ptr(arg)); 37} 38 39static int compat_put_u64(unsigned long arg, u64 val) 40{ 41 return put_user(val, (compat_u64 __user *)compat_ptr(arg)); 42} 43 44struct compat_hd_geometry { 45 unsigned char heads; 46 unsigned char sectors; 47 unsigned short cylinders; 48 u32 start; 49}; 50 51static int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev, 52 struct compat_hd_geometry __user *ugeo) 53{ 54 struct hd_geometry geo; 55 int ret; 56 57 if (!ugeo) 58 return -EINVAL; 59 if (!disk->fops->getgeo) 60 return -ENOTTY; 61 62 memset(&geo, 0, sizeof(geo)); 63 /* 64 * We need to set the startsect first, the driver may 65 * want to override it. 66 */ 67 geo.start = get_start_sect(bdev); 68 ret = disk->fops->getgeo(bdev, &geo); 69 if (ret) 70 return ret; 71 72 ret = copy_to_user(ugeo, &geo, 4); 73 ret |= put_user(geo.start, &ugeo->start); 74 if (ret) 75 ret = -EFAULT; 76 77 return ret; 78} 79 80static int compat_hdio_ioctl(struct block_device *bdev, fmode_t mode, 81 unsigned int cmd, unsigned long arg) 82{ 83 mm_segment_t old_fs = get_fs(); 84 unsigned long kval; 85 unsigned int __user *uvp; 86 int error; 87 88 set_fs(KERNEL_DS); 89 error = __blkdev_driver_ioctl(bdev, mode, 90 cmd, (unsigned long)(&kval)); 91 set_fs(old_fs); 92 93 if (error == 0) { 94 uvp = compat_ptr(arg); 95 if (put_user(kval, uvp)) 96 error = -EFAULT; 97 } 98 return error; 99} 100 101struct compat_cdrom_read_audio { 102 union cdrom_addr addr; 103 u8 addr_format; 104 compat_int_t nframes; 105 compat_caddr_t buf; 106}; 107 108struct compat_cdrom_generic_command { 109 unsigned char cmd[CDROM_PACKET_SIZE]; 110 compat_caddr_t buffer; 111 compat_uint_t buflen; 112 compat_int_t stat; 113 compat_caddr_t sense; 114 unsigned char data_direction; 115 compat_int_t quiet; 116 compat_int_t timeout; 117 compat_caddr_t reserved[1]; 118}; 119 120static int compat_cdrom_read_audio(struct block_device *bdev, fmode_t mode, 121 unsigned int cmd, unsigned long arg) 122{ 123 struct cdrom_read_audio __user *cdread_audio; 124 struct compat_cdrom_read_audio __user *cdread_audio32; 125 __u32 data; 126 void __user *datap; 127 128 cdread_audio = compat_alloc_user_space(sizeof(*cdread_audio)); 129 cdread_audio32 = compat_ptr(arg); 130 131 if (copy_in_user(&cdread_audio->addr, 132 &cdread_audio32->addr, 133 (sizeof(*cdread_audio32) - 134 sizeof(compat_caddr_t)))) 135 return -EFAULT; 136 137 if (get_user(data, &cdread_audio32->buf)) 138 return -EFAULT; 139 datap = compat_ptr(data); 140 if (put_user(datap, &cdread_audio->buf)) 141 return -EFAULT; 142 143 return __blkdev_driver_ioctl(bdev, mode, cmd, 144 (unsigned long)cdread_audio); 145} 146 147static int compat_cdrom_generic_command(struct block_device *bdev, fmode_t mode, 148 unsigned int cmd, unsigned long arg) 149{ 150 struct cdrom_generic_command __user *cgc; 151 struct compat_cdrom_generic_command __user *cgc32; 152 u32 data; 153 unsigned char dir; 154 int itmp; 155 156 cgc = compat_alloc_user_space(sizeof(*cgc)); 157 cgc32 = compat_ptr(arg); 158 159 if (copy_in_user(&cgc->cmd, &cgc32->cmd, sizeof(cgc->cmd)) || 160 get_user(data, &cgc32->buffer) || 161 put_user(compat_ptr(data), &cgc->buffer) || 162 copy_in_user(&cgc->buflen, &cgc32->buflen, 163 (sizeof(unsigned int) + sizeof(int))) || 164 get_user(data, &cgc32->sense) || 165 put_user(compat_ptr(data), &cgc->sense) || 166 get_user(dir, &cgc32->data_direction) || 167 put_user(dir, &cgc->data_direction) || 168 get_user(itmp, &cgc32->quiet) || 169 put_user(itmp, &cgc->quiet) || 170 get_user(itmp, &cgc32->timeout) || 171 put_user(itmp, &cgc->timeout) || 172 get_user(data, &cgc32->reserved[0]) || 173 put_user(compat_ptr(data), &cgc->reserved[0])) 174 return -EFAULT; 175 176 return __blkdev_driver_ioctl(bdev, mode, cmd, (unsigned long)cgc); 177} 178 179struct compat_blkpg_ioctl_arg { 180 compat_int_t op; 181 compat_int_t flags; 182 compat_int_t datalen; 183 compat_caddr_t data; 184}; 185 186static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode, 187 unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32) 188{ 189 struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a)); 190 compat_caddr_t udata; 191 compat_int_t n; 192 int err; 193 194 err = get_user(n, &ua32->op); 195 err |= put_user(n, &a->op); 196 err |= get_user(n, &ua32->flags); 197 err |= put_user(n, &a->flags); 198 err |= get_user(n, &ua32->datalen); 199 err |= put_user(n, &a->datalen); 200 err |= get_user(udata, &ua32->data); 201 err |= put_user(compat_ptr(udata), &a->data); 202 if (err) 203 return err; 204 205 return blkdev_ioctl(bdev, mode, cmd, (unsigned long)a); 206} 207 208#define BLKBSZGET_32 _IOR(0x12, 112, int) 209#define BLKBSZSET_32 _IOW(0x12, 113, int) 210#define BLKGETSIZE64_32 _IOR(0x12, 114, int) 211 212struct compat_floppy_drive_params { 213 char cmos; 214 compat_ulong_t max_dtr; 215 compat_ulong_t hlt; 216 compat_ulong_t hut; 217 compat_ulong_t srt; 218 compat_ulong_t spinup; 219 compat_ulong_t spindown; 220 unsigned char spindown_offset; 221 unsigned char select_delay; 222 unsigned char rps; 223 unsigned char tracks; 224 compat_ulong_t timeout; 225 unsigned char interleave_sect; 226 struct floppy_max_errors max_errors; 227 char flags; 228 char read_track; 229 short autodetect[8]; 230 compat_int_t checkfreq; 231 compat_int_t native_format; 232}; 233 234struct compat_floppy_drive_struct { 235 signed char flags; 236 compat_ulong_t spinup_date; 237 compat_ulong_t select_date; 238 compat_ulong_t first_read_date; 239 short probed_format; 240 short track; 241 short maxblock; 242 short maxtrack; 243 compat_int_t generation; 244 compat_int_t keep_data; 245 compat_int_t fd_ref; 246 compat_int_t fd_device; 247 compat_int_t last_checked; 248 compat_caddr_t dmabuf; 249 compat_int_t bufblocks; 250}; 251 252struct compat_floppy_fdc_state { 253 compat_int_t spec1; 254 compat_int_t spec2; 255 compat_int_t dtr; 256 unsigned char version; 257 unsigned char dor; 258 compat_ulong_t address; 259 unsigned int rawcmd:2; 260 unsigned int reset:1; 261 unsigned int need_configure:1; 262 unsigned int perp_mode:2; 263 unsigned int has_fifo:1; 264 unsigned int driver_version; 265 unsigned char track[4]; 266}; 267 268struct compat_floppy_write_errors { 269 unsigned int write_errors; 270 compat_ulong_t first_error_sector; 271 compat_int_t first_error_generation; 272 compat_ulong_t last_error_sector; 273 compat_int_t last_error_generation; 274 compat_uint_t badness; 275}; 276 277#define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct) 278#define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct) 279#define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params) 280#define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params) 281#define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct) 282#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct compat_floppy_drive_struct) 283#define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state) 284#define FDWERRORGET32 _IOR(2, 0x17, struct compat_floppy_write_errors) 285 286static struct { 287 unsigned int cmd32; 288 unsigned int cmd; 289} fd_ioctl_trans_table[] = { 290 { FDSETPRM32, FDSETPRM }, 291 { FDDEFPRM32, FDDEFPRM }, 292 { FDGETPRM32, FDGETPRM }, 293 { FDSETDRVPRM32, FDSETDRVPRM }, 294 { FDGETDRVPRM32, FDGETDRVPRM }, 295 { FDGETDRVSTAT32, FDGETDRVSTAT }, 296 { FDPOLLDRVSTAT32, FDPOLLDRVSTAT }, 297 { FDGETFDCSTAT32, FDGETFDCSTAT }, 298 { FDWERRORGET32, FDWERRORGET } 299}; 300 301#define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table) 302 303static int compat_fd_ioctl(struct block_device *bdev, fmode_t mode, 304 unsigned int cmd, unsigned long arg) 305{ 306 mm_segment_t old_fs = get_fs(); 307 void *karg = NULL; 308 unsigned int kcmd = 0; 309 int i, err; 310 311 for (i = 0; i < NR_FD_IOCTL_TRANS; i++) 312 if (cmd == fd_ioctl_trans_table[i].cmd32) { 313 kcmd = fd_ioctl_trans_table[i].cmd; 314 break; 315 } 316 if (!kcmd) 317 return -EINVAL; 318 319 switch (cmd) { 320 case FDSETPRM32: 321 case FDDEFPRM32: 322 case FDGETPRM32: 323 { 324 compat_uptr_t name; 325 struct compat_floppy_struct __user *uf; 326 struct floppy_struct *f; 327 328 uf = compat_ptr(arg); 329 f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL); 330 if (!karg) 331 return -ENOMEM; 332 if (cmd == FDGETPRM32) 333 break; 334 err = __get_user(f->size, &uf->size); 335 err |= __get_user(f->sect, &uf->sect); 336 err |= __get_user(f->head, &uf->head); 337 err |= __get_user(f->track, &uf->track); 338 err |= __get_user(f->stretch, &uf->stretch); 339 err |= __get_user(f->gap, &uf->gap); 340 err |= __get_user(f->rate, &uf->rate); 341 err |= __get_user(f->spec1, &uf->spec1); 342 err |= __get_user(f->fmt_gap, &uf->fmt_gap); 343 err |= __get_user(name, &uf->name); 344 f->name = compat_ptr(name); 345 if (err) { 346 err = -EFAULT; 347 goto out; 348 } 349 break; 350 } 351 case FDSETDRVPRM32: 352 case FDGETDRVPRM32: 353 { 354 struct compat_floppy_drive_params __user *uf; 355 struct floppy_drive_params *f; 356 357 uf = compat_ptr(arg); 358 f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL); 359 if (!karg) 360 return -ENOMEM; 361 if (cmd == FDGETDRVPRM32) 362 break; 363 err = __get_user(f->cmos, &uf->cmos); 364 err |= __get_user(f->max_dtr, &uf->max_dtr); 365 err |= __get_user(f->hlt, &uf->hlt); 366 err |= __get_user(f->hut, &uf->hut); 367 err |= __get_user(f->srt, &uf->srt); 368 err |= __get_user(f->spinup, &uf->spinup); 369 err |= __get_user(f->spindown, &uf->spindown); 370 err |= __get_user(f->spindown_offset, &uf->spindown_offset); 371 err |= __get_user(f->select_delay, &uf->select_delay); 372 err |= __get_user(f->rps, &uf->rps); 373 err |= __get_user(f->tracks, &uf->tracks); 374 err |= __get_user(f->timeout, &uf->timeout); 375 err |= __get_user(f->interleave_sect, &uf->interleave_sect); 376 err |= __copy_from_user(&f->max_errors, &uf->max_errors, sizeof(f->max_errors)); 377 err |= __get_user(f->flags, &uf->flags); 378 err |= __get_user(f->read_track, &uf->read_track); 379 err |= __copy_from_user(f->autodetect, uf->autodetect, sizeof(f->autodetect)); 380 err |= __get_user(f->checkfreq, &uf->checkfreq); 381 err |= __get_user(f->native_format, &uf->native_format); 382 if (err) { 383 err = -EFAULT; 384 goto out; 385 } 386 break; 387 } 388 case FDGETDRVSTAT32: 389 case FDPOLLDRVSTAT32: 390 karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL); 391 if (!karg) 392 return -ENOMEM; 393 break; 394 case FDGETFDCSTAT32: 395 karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL); 396 if (!karg) 397 return -ENOMEM; 398 break; 399 case FDWERRORGET32: 400 karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL); 401 if (!karg) 402 return -ENOMEM; 403 break; 404 default: 405 return -EINVAL; 406 } 407 set_fs(KERNEL_DS); 408 err = __blkdev_driver_ioctl(bdev, mode, kcmd, (unsigned long)karg); 409 set_fs(old_fs); 410 if (err) 411 goto out; 412 switch (cmd) { 413 case FDGETPRM32: 414 { 415 struct floppy_struct *f = karg; 416 struct compat_floppy_struct __user *uf = compat_ptr(arg); 417 418 err = __put_user(f->size, &uf->size); 419 err |= __put_user(f->sect, &uf->sect); 420 err |= __put_user(f->head, &uf->head); 421 err |= __put_user(f->track, &uf->track); 422 err |= __put_user(f->stretch, &uf->stretch); 423 err |= __put_user(f->gap, &uf->gap); 424 err |= __put_user(f->rate, &uf->rate); 425 err |= __put_user(f->spec1, &uf->spec1); 426 err |= __put_user(f->fmt_gap, &uf->fmt_gap); 427 err |= __put_user((u64)f->name, (compat_caddr_t __user *)&uf->name); 428 break; 429 } 430 case FDGETDRVPRM32: 431 { 432 struct compat_floppy_drive_params __user *uf; 433 struct floppy_drive_params *f = karg; 434 435 uf = compat_ptr(arg); 436 err = __put_user(f->cmos, &uf->cmos); 437 err |= __put_user(f->max_dtr, &uf->max_dtr); 438 err |= __put_user(f->hlt, &uf->hlt); 439 err |= __put_user(f->hut, &uf->hut); 440 err |= __put_user(f->srt, &uf->srt); 441 err |= __put_user(f->spinup, &uf->spinup); 442 err |= __put_user(f->spindown, &uf->spindown); 443 err |= __put_user(f->spindown_offset, &uf->spindown_offset); 444 err |= __put_user(f->select_delay, &uf->select_delay); 445 err |= __put_user(f->rps, &uf->rps); 446 err |= __put_user(f->tracks, &uf->tracks); 447 err |= __put_user(f->timeout, &uf->timeout); 448 err |= __put_user(f->interleave_sect, &uf->interleave_sect); 449 err |= __copy_to_user(&uf->max_errors, &f->max_errors, sizeof(f->max_errors)); 450 err |= __put_user(f->flags, &uf->flags); 451 err |= __put_user(f->read_track, &uf->read_track); 452 err |= __copy_to_user(uf->autodetect, f->autodetect, sizeof(f->autodetect)); 453 err |= __put_user(f->checkfreq, &uf->checkfreq); 454 err |= __put_user(f->native_format, &uf->native_format); 455 break; 456 } 457 case FDGETDRVSTAT32: 458 case FDPOLLDRVSTAT32: 459 { 460 struct compat_floppy_drive_struct __user *uf; 461 struct floppy_drive_struct *f = karg; 462 463 uf = compat_ptr(arg); 464 err = __put_user(f->flags, &uf->flags); 465 err |= __put_user(f->spinup_date, &uf->spinup_date); 466 err |= __put_user(f->select_date, &uf->select_date); 467 err |= __put_user(f->first_read_date, &uf->first_read_date); 468 err |= __put_user(f->probed_format, &uf->probed_format); 469 err |= __put_user(f->track, &uf->track); 470 err |= __put_user(f->maxblock, &uf->maxblock); 471 err |= __put_user(f->maxtrack, &uf->maxtrack); 472 err |= __put_user(f->generation, &uf->generation); 473 err |= __put_user(f->keep_data, &uf->keep_data); 474 err |= __put_user(f->fd_ref, &uf->fd_ref); 475 err |= __put_user(f->fd_device, &uf->fd_device); 476 err |= __put_user(f->last_checked, &uf->last_checked); 477 err |= __put_user((u64)f->dmabuf, &uf->dmabuf); 478 err |= __put_user((u64)f->bufblocks, &uf->bufblocks); 479 break; 480 } 481 case FDGETFDCSTAT32: 482 { 483 struct compat_floppy_fdc_state __user *uf; 484 struct floppy_fdc_state *f = karg; 485 486 uf = compat_ptr(arg); 487 err = __put_user(f->spec1, &uf->spec1); 488 err |= __put_user(f->spec2, &uf->spec2); 489 err |= __put_user(f->dtr, &uf->dtr); 490 err |= __put_user(f->version, &uf->version); 491 err |= __put_user(f->dor, &uf->dor); 492 err |= __put_user(f->address, &uf->address); 493 err |= __copy_to_user((char __user *)&uf->address + sizeof(uf->address), 494 (char *)&f->address + sizeof(f->address), sizeof(int)); 495 err |= __put_user(f->driver_version, &uf->driver_version); 496 err |= __copy_to_user(uf->track, f->track, sizeof(f->track)); 497 break; 498 } 499 case FDWERRORGET32: 500 { 501 struct compat_floppy_write_errors __user *uf; 502 struct floppy_write_errors *f = karg; 503 504 uf = compat_ptr(arg); 505 err = __put_user(f->write_errors, &uf->write_errors); 506 err |= __put_user(f->first_error_sector, &uf->first_error_sector); 507 err |= __put_user(f->first_error_generation, &uf->first_error_generation); 508 err |= __put_user(f->last_error_sector, &uf->last_error_sector); 509 err |= __put_user(f->last_error_generation, &uf->last_error_generation); 510 err |= __put_user(f->badness, &uf->badness); 511 break; 512 } 513 default: 514 break; 515 } 516 if (err) 517 err = -EFAULT; 518 519out: 520 kfree(karg); 521 return err; 522} 523 524static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, 525 unsigned cmd, unsigned long arg) 526{ 527 switch (cmd) { 528 case HDIO_GET_UNMASKINTR: 529 case HDIO_GET_MULTCOUNT: 530 case HDIO_GET_KEEPSETTINGS: 531 case HDIO_GET_32BIT: 532 case HDIO_GET_NOWERR: 533 case HDIO_GET_DMA: 534 case HDIO_GET_NICE: 535 case HDIO_GET_WCACHE: 536 case HDIO_GET_ACOUSTIC: 537 case HDIO_GET_ADDRESS: 538 case HDIO_GET_BUSSTATE: 539 return compat_hdio_ioctl(bdev, mode, cmd, arg); 540 case FDSETPRM32: 541 case FDDEFPRM32: 542 case FDGETPRM32: 543 case FDSETDRVPRM32: 544 case FDGETDRVPRM32: 545 case FDGETDRVSTAT32: 546 case FDPOLLDRVSTAT32: 547 case FDGETFDCSTAT32: 548 case FDWERRORGET32: 549 return compat_fd_ioctl(bdev, mode, cmd, arg); 550 case CDROMREADAUDIO: 551 return compat_cdrom_read_audio(bdev, mode, cmd, arg); 552 case CDROM_SEND_PACKET: 553 return compat_cdrom_generic_command(bdev, mode, cmd, arg); 554 555 /* 556 * No handler required for the ones below, we just need to 557 * convert arg to a 64 bit pointer. 558 */ 559 case BLKSECTSET: 560 /* 561 * 0x03 -- HD/IDE ioctl's used by hdparm and friends. 562 * Some need translations, these do not. 563 */ 564 case HDIO_GET_IDENTITY: 565 case HDIO_DRIVE_TASK: 566 case HDIO_DRIVE_CMD: 567 /* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */ 568 case 0x330: 569 /* 0x02 -- Floppy ioctls */ 570 case FDMSGON: 571 case FDMSGOFF: 572 case FDSETEMSGTRESH: 573 case FDFLUSH: 574 case FDWERRORCLR: 575 case FDSETMAXERRS: 576 case FDGETMAXERRS: 577 case FDGETDRVTYP: 578 case FDEJECT: 579 case FDCLRPRM: 580 case FDFMTBEG: 581 case FDFMTEND: 582 case FDRESET: 583 case FDTWADDLE: 584 case FDFMTTRK: 585 case FDRAWCMD: 586 /* CDROM stuff */ 587 case CDROMPAUSE: 588 case CDROMRESUME: 589 case CDROMPLAYMSF: 590 case CDROMPLAYTRKIND: 591 case CDROMREADTOCHDR: 592 case CDROMREADTOCENTRY: 593 case CDROMSTOP: 594 case CDROMSTART: 595 case CDROMEJECT: 596 case CDROMVOLCTRL: 597 case CDROMSUBCHNL: 598 case CDROMMULTISESSION: 599 case CDROM_GET_MCN: 600 case CDROMRESET: 601 case CDROMVOLREAD: 602 case CDROMSEEK: 603 case CDROMPLAYBLK: 604 case CDROMCLOSETRAY: 605 case CDROM_DISC_STATUS: 606 case CDROM_CHANGER_NSLOTS: 607 case CDROM_GET_CAPABILITY: 608 /* Ignore cdrom.h about these next 5 ioctls, they absolutely do 609 * not take a struct cdrom_read, instead they take a struct cdrom_msf 610 * which is compatible. 611 */ 612 case CDROMREADMODE2: 613 case CDROMREADMODE1: 614 case CDROMREADRAW: 615 case CDROMREADCOOKED: 616 case CDROMREADALL: 617 /* DVD ioctls */ 618 case DVD_READ_STRUCT: 619 case DVD_WRITE_STRUCT: 620 case DVD_AUTH: 621 arg = (unsigned long)compat_ptr(arg); 622 /* These intepret arg as an unsigned long, not as a pointer, 623 * so we must not do compat_ptr() conversion. */ 624 case HDIO_SET_MULTCOUNT: 625 case HDIO_SET_UNMASKINTR: 626 case HDIO_SET_KEEPSETTINGS: 627 case HDIO_SET_32BIT: 628 case HDIO_SET_NOWERR: 629 case HDIO_SET_DMA: 630 case HDIO_SET_PIO_MODE: 631 case HDIO_SET_NICE: 632 case HDIO_SET_WCACHE: 633 case HDIO_SET_ACOUSTIC: 634 case HDIO_SET_BUSSTATE: 635 case HDIO_SET_ADDRESS: 636 case CDROMEJECT_SW: 637 case CDROM_SET_OPTIONS: 638 case CDROM_CLEAR_OPTIONS: 639 case CDROM_SELECT_SPEED: 640 case CDROM_SELECT_DISC: 641 case CDROM_MEDIA_CHANGED: 642 case CDROM_DRIVE_STATUS: 643 case CDROM_LOCKDOOR: 644 case CDROM_DEBUG: 645 break; 646 default: 647 /* unknown ioctl number */ 648 return -ENOIOCTLCMD; 649 } 650 651 return __blkdev_driver_ioctl(bdev, mode, cmd, arg); 652} 653 654/* Most of the generic ioctls are handled in the normal fallback path. 655 This assumes the blkdev's low level compat_ioctl always returns 656 ENOIOCTLCMD for unknown ioctls. */ 657long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) 658{ 659 int ret = -ENOIOCTLCMD; 660 struct inode *inode = file->f_mapping->host; 661 struct block_device *bdev = inode->i_bdev; 662 struct gendisk *disk = bdev->bd_disk; 663 fmode_t mode = file->f_mode; 664 struct backing_dev_info *bdi; 665 loff_t size; 666 unsigned int max_sectors; 667 668 /* 669 * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have 670 * to updated it before every ioctl. 671 */ 672 if (file->f_flags & O_NDELAY) 673 mode |= FMODE_NDELAY; 674 else 675 mode &= ~FMODE_NDELAY; 676 677 switch (cmd) { 678 case HDIO_GETGEO: 679 return compat_hdio_getgeo(disk, bdev, compat_ptr(arg)); 680 case BLKPBSZGET: 681 return compat_put_uint(arg, bdev_physical_block_size(bdev)); 682 case BLKIOMIN: 683 return compat_put_uint(arg, bdev_io_min(bdev)); 684 case BLKIOOPT: 685 return compat_put_uint(arg, bdev_io_opt(bdev)); 686 case BLKALIGNOFF: 687 return compat_put_int(arg, bdev_alignment_offset(bdev)); 688 case BLKDISCARDZEROES: 689 return compat_put_uint(arg, bdev_discard_zeroes_data(bdev)); 690 case BLKFLSBUF: 691 case BLKROSET: 692 case BLKDISCARD: 693 case BLKSECDISCARD: 694 case BLKZEROOUT: 695 /* 696 * the ones below are implemented in blkdev_locked_ioctl, 697 * but we call blkdev_ioctl, which gets the lock for us 698 */ 699 case BLKRRPART: 700 return blkdev_ioctl(bdev, mode, cmd, 701 (unsigned long)compat_ptr(arg)); 702 case BLKBSZSET_32: 703 return blkdev_ioctl(bdev, mode, BLKBSZSET, 704 (unsigned long)compat_ptr(arg)); 705 case BLKPG: 706 return compat_blkpg_ioctl(bdev, mode, cmd, compat_ptr(arg)); 707 case BLKRAGET: 708 case BLKFRAGET: 709 if (!arg) 710 return -EINVAL; 711 bdi = blk_get_backing_dev_info(bdev); 712 return compat_put_long(arg, 713 (bdi->ra_pages * PAGE_CACHE_SIZE) / 512); 714 case BLKROGET: /* compatible */ 715 return compat_put_int(arg, bdev_read_only(bdev) != 0); 716 case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */ 717 return compat_put_int(arg, block_size(bdev)); 718 case BLKSSZGET: /* get block device hardware sector size */ 719 return compat_put_int(arg, bdev_logical_block_size(bdev)); 720 case BLKSECTGET: 721 max_sectors = min_t(unsigned int, USHRT_MAX, 722 queue_max_sectors(bdev_get_queue(bdev))); 723 return compat_put_ushort(arg, max_sectors); 724 case BLKROTATIONAL: 725 return compat_put_ushort(arg, 726 !blk_queue_nonrot(bdev_get_queue(bdev))); 727 case BLKRASET: /* compatible, but no compat_ptr (!) */ 728 case BLKFRASET: 729 if (!capable(CAP_SYS_ADMIN)) 730 return -EACCES; 731 bdi = blk_get_backing_dev_info(bdev); 732 bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; 733 return 0; 734 case BLKGETSIZE: 735 size = i_size_read(bdev->bd_inode); 736 if ((size >> 9) > ~0UL) 737 return -EFBIG; 738 return compat_put_ulong(arg, size >> 9); 739 740 case BLKGETSIZE64_32: 741 return compat_put_u64(arg, i_size_read(bdev->bd_inode)); 742 743 case BLKTRACESETUP32: 744 case BLKTRACESTART: /* compatible */ 745 case BLKTRACESTOP: /* compatible */ 746 case BLKTRACETEARDOWN: /* compatible */ 747 ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg)); 748 return ret; 749 default: 750 if (disk->fops->compat_ioctl) 751 ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg); 752 if (ret == -ENOIOCTLCMD) 753 ret = compat_blkdev_driver_ioctl(bdev, mode, cmd, arg); 754 return ret; 755 } 756} 757