aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/scsi_ioctl.c101
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 387int sg_scsi_ioctl(struct file *file, struct request_queue *q,
355static 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
477out:
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 496EXPORT_SYMBOL_GPL(sg_scsi_ioctl);
454 497
455/* Send basic block requests */ 498/* Send basic block requests */
456static int __blk_send_generic(request_queue_t *q, struct gendisk *bd_disk, int cmd, int data) 499static int __blk_send_generic(request_queue_t *q, struct gendisk *bd_disk, int cmd, int data)