[SCSI] Prevent scsi_execute_async from guessing cdb length
authorbrking@us.ibm.com <brking@us.ibm.com>
Mon, 23 Jan 2006 21:03:22 +0000 (15:03 -0600)
committerJames Bottomley <jejb@mulgrave.(none)>
Thu, 26 Jan 2006 20:13:50 +0000 (15:13 -0500)
When the scsi_execute_async interface was added it ended up reducing
the flexibility of userspace to send arbitrary scsi commands through
sg using SG_IO. The SG_IO interface allows userspace to specify the
CDB length. This is now ignored in scsi_execute_async and it is
guessed using the COMMAND_SIZE macro, which is not always correct,
particularly for vendor specific commands. This patch adds a cmd_len
parameter to the scsi_execute_async interface to allow the caller
to specify the length of the CDB.

Signed-off-by: Brian King <brking@us.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/sg.c
drivers/scsi/st.c
include/scsi/scsi_device.h

index a2333d2..5cc97b7 100644 (file)
@@ -1350,7 +1350,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev)
        cmnd[4] = SCSI_REMOVAL_PREVENT;
        cmnd[5] = 0;
 
-       scsi_execute_async(sdev, cmnd, DMA_NONE, NULL, 0, 0, 10 * HZ,
+       scsi_execute_async(sdev, cmnd, 6, DMA_NONE, NULL, 0, 0, 10 * HZ,
                           5, NULL, NULL, GFP_KERNEL);
 }
 
index 3574ba9..4a60285 100644 (file)
@@ -436,6 +436,7 @@ free_bios:
  * scsi_execute_async - insert request
  * @sdev:      scsi device
  * @cmd:       scsi command
+ * @cmd_len:   length of scsi cdb
  * @data_direction: data direction
  * @buffer:    data buffer (this can be a kernel buffer or scatterlist)
  * @bufflen:   len of buffer
@@ -445,7 +446,7 @@ free_bios:
  * @flags:     or into request flags
  **/
 int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd,
-                      int data_direction, void *buffer, unsigned bufflen,
+                      int cmd_len, int data_direction, void *buffer, unsigned bufflen,
                       int use_sg, int timeout, int retries, void *privdata,
                       void (*done)(void *, char *, int, int), gfp_t gfp)
 {
@@ -472,7 +473,7 @@ int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd,
        if (err)
                goto free_req;
 
-       req->cmd_len = COMMAND_SIZE(cmd[0]);
+       req->cmd_len = cmd_len;
        memcpy(req->cmd, cmd, req->cmd_len);
        req->sense = sioc->sense;
        req->sense_len = 0;
index 78aad95..7d07000 100644 (file)
@@ -741,7 +741,7 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
        hp->duration = jiffies_to_msecs(jiffies);
 /* Now send everything of to mid-level. The next time we hear about this
    packet is when sg_cmd_done() is called (i.e. a callback). */
-       if (scsi_execute_async(sdp->device, cmnd, data_dir, srp->data.buffer,
+       if (scsi_execute_async(sdp->device, cmnd, hp->cmd_len, data_dir, srp->data.buffer,
                                hp->dxfer_len, srp->data.k_use_sg, timeout,
                                SG_DEFAULT_RETRIES, srp, sg_cmd_done,
                                GFP_ATOMIC)) {
index 13b1d3a..7f96f33 100644 (file)
@@ -508,7 +508,7 @@ st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd
        STp->buffer->cmdstat.have_sense = 0;
        STp->buffer->syscall_result = 0;
 
-       if (scsi_execute_async(STp->device, cmd, direction,
+       if (scsi_execute_async(STp->device, cmd, COMMAND_SIZE(cmd[0]), direction,
                        &((STp->buffer)->sg[0]), bytes, (STp->buffer)->sg_segs,
                               timeout, retries, SRpnt, st_sleep_done, GFP_KERNEL)) {
                /* could not allocate the buffer or request was too large */
index e94ca4d..290e3b4 100644 (file)
@@ -275,7 +275,7 @@ extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
                            int data_direction, void *buffer, unsigned bufflen,
                            struct scsi_sense_hdr *, int timeout, int retries);
 extern int scsi_execute_async(struct scsi_device *sdev,
-                             const unsigned char *cmd, int data_direction,
+                             const unsigned char *cmd, int cmd_len, int data_direction,
                              void *buffer, unsigned bufflen, int use_sg,
                              int timeout, int retries, void *privdata,
                              void (*done)(void *, char *, int, int),