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