diff options
Diffstat (limited to 'block')
-rw-r--r-- | block/scsi_ioctl.c | 101 |
1 files changed, 72 insertions, 29 deletions
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index 24f7af9d0abc..b33eda26e205 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c | |||
@@ -350,16 +350,51 @@ out: | |||
350 | return ret; | 350 | return ret; |
351 | } | 351 | } |
352 | 352 | ||
353 | /** | ||
354 | * sg_scsi_ioctl -- handle deprecated SCSI_IOCTL_SEND_COMMAND ioctl | ||
355 | * @file: file this ioctl operates on (optional) | ||
356 | * @q: request queue to send scsi commands down | ||
357 | * @disk: gendisk to operate on (option) | ||
358 | * @sic: userspace structure describing the command to perform | ||
359 | * | ||
360 | * Send down the scsi command described by @sic to the device below | ||
361 | * the request queue @q. If @file is non-NULL it's used to perform | ||
362 | * fine-grained permission checks that allow users to send down | ||
363 | * non-destructive SCSI commands. If the caller has a struct gendisk | ||
364 | * available it should be passed in as @disk to allow the low level | ||
365 | * driver to use the information contained in it. A non-NULL @disk | ||
366 | * is only allowed if the caller knows that the low level driver doesn't | ||
367 | * need it (e.g. in the scsi subsystem). | ||
368 | * | ||
369 | * Notes: | ||
370 | * - This interface is deprecated - users should use the SG_IO | ||
371 | * interface instead, as this is a more flexible approach to | ||
372 | * performing SCSI commands on a device. | ||
373 | * - The SCSI command length is determined by examining the 1st byte | ||
374 | * of the given command. There is no way to override this. | ||
375 | * - Data transfers are limited to PAGE_SIZE | ||
376 | * - The length (x + y) must be at least OMAX_SB_LEN bytes long to | ||
377 | * accommodate the sense buffer when an error occurs. | ||
378 | * The sense buffer is truncated to OMAX_SB_LEN (16) bytes so that | ||
379 | * old code will not be surprised. | ||
380 | * - If a Unix error occurs (e.g. ENOMEM) then the user will receive | ||
381 | * a negative return and the Unix error code in 'errno'. | ||
382 | * If the SCSI command succeeds then 0 is returned. | ||
383 | * Positive numbers returned are the compacted SCSI error codes (4 | ||
384 | * bytes in one int) where the lowest byte is the SCSI status. | ||
385 | */ | ||
353 | #define OMAX_SB_LEN 16 /* For backward compatibility */ | 386 | #define OMAX_SB_LEN 16 /* For backward compatibility */ |
354 | 387 | int sg_scsi_ioctl(struct file *file, struct request_queue *q, | |
355 | static int sg_scsi_ioctl(struct file *file, request_queue_t *q, | 388 | struct gendisk *disk, struct scsi_ioctl_command __user *sic) |
356 | struct gendisk *bd_disk, Scsi_Ioctl_Command __user *sic) | ||
357 | { | 389 | { |
358 | struct request *rq; | 390 | struct request *rq; |
359 | int err; | 391 | int err; |
360 | unsigned int in_len, out_len, bytes, opcode, cmdlen; | 392 | unsigned int in_len, out_len, bytes, opcode, cmdlen; |
361 | char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE]; | 393 | char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE]; |
362 | 394 | ||
395 | if (!sic) | ||
396 | return -EINVAL; | ||
397 | |||
363 | /* | 398 | /* |
364 | * get in an out lengths, verify they don't exceed a page worth of data | 399 | * get in an out lengths, verify they don't exceed a page worth of data |
365 | */ | 400 | */ |
@@ -393,45 +428,53 @@ static int sg_scsi_ioctl(struct file *file, request_queue_t *q, | |||
393 | if (copy_from_user(rq->cmd, sic->data, cmdlen)) | 428 | if (copy_from_user(rq->cmd, sic->data, cmdlen)) |
394 | goto error; | 429 | goto error; |
395 | 430 | ||
396 | if (copy_from_user(buffer, sic->data + cmdlen, in_len)) | 431 | if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len)) |
397 | goto error; | 432 | goto error; |
398 | 433 | ||
399 | err = verify_command(file, rq->cmd); | 434 | err = verify_command(file, rq->cmd); |
400 | if (err) | 435 | if (err) |
401 | goto error; | 436 | goto error; |
402 | 437 | ||
438 | /* default. possible overriden later */ | ||
439 | rq->retries = 5; | ||
440 | |||
403 | switch (opcode) { | 441 | switch (opcode) { |
404 | case SEND_DIAGNOSTIC: | 442 | case SEND_DIAGNOSTIC: |
405 | case FORMAT_UNIT: | 443 | case FORMAT_UNIT: |
406 | rq->timeout = FORMAT_UNIT_TIMEOUT; | 444 | rq->timeout = FORMAT_UNIT_TIMEOUT; |
407 | break; | 445 | rq->retries = 1; |
408 | case START_STOP: | 446 | break; |
409 | rq->timeout = START_STOP_TIMEOUT; | 447 | case START_STOP: |
410 | break; | 448 | rq->timeout = START_STOP_TIMEOUT; |
411 | case MOVE_MEDIUM: | 449 | break; |
412 | rq->timeout = MOVE_MEDIUM_TIMEOUT; | 450 | case MOVE_MEDIUM: |
413 | break; | 451 | rq->timeout = MOVE_MEDIUM_TIMEOUT; |
414 | case READ_ELEMENT_STATUS: | 452 | break; |
415 | rq->timeout = READ_ELEMENT_STATUS_TIMEOUT; | 453 | case READ_ELEMENT_STATUS: |
416 | break; | 454 | rq->timeout = READ_ELEMENT_STATUS_TIMEOUT; |
417 | case READ_DEFECT_DATA: | 455 | break; |
418 | rq->timeout = READ_DEFECT_DATA_TIMEOUT; | 456 | case READ_DEFECT_DATA: |
419 | break; | 457 | rq->timeout = READ_DEFECT_DATA_TIMEOUT; |
420 | default: | 458 | rq->retries = 1; |
421 | rq->timeout = BLK_DEFAULT_TIMEOUT; | 459 | break; |
422 | break; | 460 | default: |
461 | rq->timeout = BLK_DEFAULT_TIMEOUT; | ||
462 | break; | ||
463 | } | ||
464 | |||
465 | if (bytes && blk_rq_map_kern(q, rq, buffer, bytes, __GFP_WAIT)) { | ||
466 | err = DRIVER_ERROR << 24; | ||
467 | goto out; | ||
423 | } | 468 | } |
424 | 469 | ||
425 | memset(sense, 0, sizeof(sense)); | 470 | memset(sense, 0, sizeof(sense)); |
426 | rq->sense = sense; | 471 | rq->sense = sense; |
427 | rq->sense_len = 0; | 472 | rq->sense_len = 0; |
428 | |||
429 | rq->data = buffer; | ||
430 | rq->data_len = bytes; | ||
431 | rq->flags |= REQ_BLOCK_PC; | 473 | rq->flags |= REQ_BLOCK_PC; |
432 | rq->retries = 0; | ||
433 | 474 | ||
434 | blk_execute_rq(q, bd_disk, rq, 0); | 475 | blk_execute_rq(q, disk, rq, 0); |
476 | |||
477 | out: | ||
435 | err = rq->errors & 0xff; /* only 8 bit SCSI status */ | 478 | err = rq->errors & 0xff; /* only 8 bit SCSI status */ |
436 | if (err) { | 479 | if (err) { |
437 | if (rq->sense_len && rq->sense) { | 480 | if (rq->sense_len && rq->sense) { |
@@ -450,7 +493,7 @@ error: | |||
450 | blk_put_request(rq); | 493 | blk_put_request(rq); |
451 | return err; | 494 | return err; |
452 | } | 495 | } |
453 | 496 | EXPORT_SYMBOL_GPL(sg_scsi_ioctl); | |
454 | 497 | ||
455 | /* Send basic block requests */ | 498 | /* Send basic block requests */ |
456 | static int __blk_send_generic(request_queue_t *q, struct gendisk *bd_disk, int cmd, int data) | 499 | static int __blk_send_generic(request_queue_t *q, struct gendisk *bd_disk, int cmd, int data) |