Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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