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