- Sense handling cleanup
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Fri, 25 Sep 2009 18:57:10 +0000 (18:57 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Fri, 25 Sep 2009 18:57:10 +0000 (18:57 +0000)
 - How to workaround Windows READ CAPACITY(16) bug documented

git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@1146 d57e44dd-8a1f-0410-8b47-8ef2f437770f

12 files changed:
scst/README
scst/include/scst.h
scst/include/scst_const.h
scst/src/dev_handlers/scst_cdrom.c
scst/src/dev_handlers/scst_disk.c
scst/src/dev_handlers/scst_modisk.c
scst/src/dev_handlers/scst_user.c
scst/src/dev_handlers/scst_vdisk.c
scst/src/scst_lib.c
scst/src/scst_priv.h
scst/src/scst_targ.c
usr/fileio/common.c

index 7e29272..6e6adb6 100644 (file)
@@ -162,6 +162,14 @@ IMPORTANT: In the current version simultaneous access to local SCSI devices
           devices READ/WRITE commands using direct disk handler look to
           be safe.
 
+IMPORTANT: Some versions of Windows have a bug, which makes them consider
+=========  response of READ CAPACITY(16) longer than 12 bytes as a faulty one.
+          As the result, such Windows'es refuse to see SCST exported
+           devices >2TB in size. This is fixed by MS in latter Windows
+          versions, probably, by some hotfix. But if you're using such
+          buggy Windows and experience this problem, change this '1' to
+          '0'.
+
 To uninstall, type 'make scst_uninstall'.
 
 
index 9831113..c26c409 100644 (file)
@@ -1392,7 +1392,8 @@ struct scst_cmd {
        uint8_t driver_status;  /* set by mid-level */
 
        uint8_t *sense;         /* pointer to sense buffer */
-       unsigned short sense_bufflen; /* length of the sense buffer, if any */
+       unsigned short sense_valid_len; /* length of valid sense data */
+       unsigned short sense_buflen; /* length of the sense buffer, if any */
 
        /* Start time when cmd was sent to rdy_to_xfer() or xmit_response() */
        unsigned long hw_pending_start;
@@ -1764,9 +1765,11 @@ struct scst_tgt_dev_UA {
        struct list_head UA_list_entry;
 
        /* Set if UA is global for session */
-       unsigned int global_UA:1;
+       unsigned short global_UA:1;
 
-       /* Unit Attention sense */
+       /* Unit Attention valid sense len */
+       unsigned short UA_valid_sense_len;
+       /* Unit Attention sense buf */
        uint8_t UA_sense_buffer[SCST_SENSE_BUFFERSIZE];
 };
 
@@ -2146,7 +2149,7 @@ enum dma_data_direction scst_to_dma_dir(int scst_dir);
 enum dma_data_direction scst_to_tgt_dma_dir(int scst_dir);
 
 /*
- * Returns 1, if cmd's CDB is locally handled by SCST and 0 otherwise.
+ * Returns true, if cmd's CDB is locally handled by SCST and 0 otherwise.
  * Dev handlers parse() and dev_done() not called for such commands.
  */
 static inline bool scst_is_cmd_local(struct scst_cmd *cmd)
@@ -2154,6 +2157,12 @@ static inline bool scst_is_cmd_local(struct scst_cmd *cmd)
        return (cmd->op_flags & SCST_LOCAL_CMD) != 0;
 }
 
+/* Returns true, if cmd can deliver UA */
+static inline bool scst_is_ua_command(struct scst_cmd *cmd)
+{
+       return (cmd->op_flags & SCST_SKIP_UA) == 0;
+}
+
 /*
  * Registers a virtual device.
  * Parameters:
@@ -2455,10 +2464,10 @@ static inline uint8_t *scst_cmd_get_sense_buffer(struct scst_cmd *cmd)
        return cmd->sense;
 }
 
-/* Returns cmd's sense buffer length */
+/* Returns cmd's valid sense length */
 static inline int scst_cmd_get_sense_buffer_len(struct scst_cmd *cmd)
 {
-       return cmd->sense_bufflen;
+       return cmd->sense_valid_len;
 }
 
 /*
@@ -3020,7 +3029,11 @@ int scst_alloc_sense(struct scst_cmd *cmd, int atomic);
 int scst_alloc_set_sense(struct scst_cmd *cmd, int atomic,
        const uint8_t *sense, unsigned int len);
 
-void scst_set_sense(uint8_t *buffer, int len, bool d_sense,
+/*
+ * Sets the corresponding field in the sense buffer taking sense type
+ * into account. Returns resulting sense length.
+ */
+int scst_set_sense(uint8_t *buffer, int len, bool d_sense,
        int key, int asc, int ascq);
 
 /*
index a5ad17f..ab738f2 100644 (file)
@@ -39,7 +39,7 @@
  * Size of sense sufficient to carry standard sense data.
  * Warning! It's allocated on stack!
  */
-#define SCST_STANDARD_SENSE_LEN      17
+#define SCST_STANDARD_SENSE_LEN      18
 
 /* Max size of sense */
 #define SCST_SENSE_BUFFERSIZE        96
index a73deaf..cef3f9f 100644 (file)
@@ -117,7 +117,8 @@ static int cdrom_attach(struct scst_device *dev)
 
                TRACE_DBG("READ_CAPACITY done: %x", res);
 
-               if ((res == 0) || !scst_analyze_sense(sense_buffer,
+               if ((res == 0) ||
+                   !scst_analyze_sense(sense_buffer,
                                sizeof(sense_buffer), SCST_SENSE_KEY_VALID,
                                UNIT_ATTENTION, 0, 0))
                        break;
@@ -141,7 +142,8 @@ static int cdrom_attach(struct scst_device *dev)
                TRACE_DBG("Sector size is %i scsi_level %d(SCSI_2 %d)",
                        sector_size, dev->scsi_dev->scsi_level, SCSI_2);
        } else {
-               TRACE_BUFFER("Sense set", sense_buffer, sizeof(sense_buffer));
+               TRACE_BUFFER("Returned sense", sense_buffer,
+                       sizeof(sense_buffer));
                params->block_shift = CDROM_DEF_BLOCK_SHIFT;
        }
 
index cba330a..ce5ea2c 100644 (file)
@@ -193,7 +193,8 @@ static int disk_attach(struct scst_device *dev)
 
                TRACE_DBG("READ_CAPACITY done: %x", res);
 
-               if ((res == 0) || !scst_analyze_sense(sense_buffer,
+               if ((res == 0) ||
+                   !scst_analyze_sense(sense_buffer,
                                sizeof(sense_buffer), SCST_SENSE_ALL_VALID,
                                SCST_LOAD_SENSE(scst_sense_medium_changed_UA)) ||
                    !scst_analyze_sense(sense_buffer, sizeof(sense_buffer),
@@ -216,7 +217,8 @@ static int disk_attach(struct scst_device *dev)
                        params->block_shift =
                                scst_calc_block_shift(sector_size);
        } else {
-               TRACE_BUFFER("Sense set", sense_buffer, sizeof(sense_buffer));
+               TRACE_BUFFER("Returned sense", sense_buffer,
+                       sizeof(sense_buffer));
                res = -ENODEV;
                goto out_free_buf;
        }
index 99f5eb3..222dba6 100644 (file)
@@ -230,7 +230,8 @@ static int modisk_attach(struct scst_device *dev)
                TRACE_DBG("Sector size is %i scsi_level %d(SCSI_2 %d)",
                      sector_size, dev->scsi_dev->scsi_level, SCSI_2);
        } else {
-               TRACE_BUFFER("Sense set", sense_buffer, sizeof(sense_buffer));
+               TRACE_BUFFER("Returned sense", sense_buffer,
+                       sizeof(sense_buffer));
 
                if (sense_buffer[2] != NOT_READY) {
                        res = -ENODEV;
index 71bf61e..4eb7a65 100644 (file)
@@ -1360,16 +1360,22 @@ static int dev_user_process_reply_exec(struct scst_user_cmd *ucmd,
 
        cmd->status = ereply->status;
        if (ereply->sense_len != 0) {
+               int sense_len;
+
                res = scst_alloc_sense(cmd, 0);
                if (res != 0)
                        goto out_compl;
+
+               sense_len = min((int)cmd->sense_buflen, (int)ereply->sense_len);
+
                res = copy_from_user(cmd->sense,
                        (void __user *)(unsigned long)ereply->psense_buffer,
-                       min((int)cmd->sense_bufflen, (int)ereply->sense_len));
+                       sense_len);
                if (res < 0) {
                        PRINT_ERROR("%s", "Unable to get sense data");
                        goto out_hwerr_res_set;
                }
+               cmd->sense_valid_len = sense_len;
        }
 
 out_compl:
index fb2a257..c80811a 100644 (file)
@@ -1116,8 +1116,7 @@ static int vcdrom_exec(struct scst_cmd *cmd)
                goto out_done;
        }
 
-       if (virt_dev->media_changed && (cmd->cdb[0] != INQUIRY) &&
-           (cmd->cdb[0] != REQUEST_SENSE) && (cmd->cdb[0] != REPORT_LUNS)) {
+       if (virt_dev->media_changed && scst_is_ua_command(cmd)) {
                spin_lock(&virt_dev->flags_lock);
                if (virt_dev->media_changed) {
                        virt_dev->media_changed = 0;
@@ -1335,31 +1334,28 @@ out:
 
 static void vdisk_exec_request_sense(struct scst_cmd *cmd)
 {
-       int32_t length;
+       int32_t length, sl;
        uint8_t *address;
+       uint8_t b[SCST_STANDARD_SENSE_LEN];
 
        TRACE_ENTRY();
 
+       sl = scst_set_sense(b, sizeof(b), cmd->dev->d_sense,
+               SCST_LOAD_SENSE(scst_sense_no_sense));
+
        length = scst_get_buf_first(cmd, &address);
        TRACE_DBG("length %d", length);
-       if (unlikely(length < SCST_STANDARD_SENSE_LEN)) {
-               if (length != 0) {
-                       PRINT_ERROR("scst_get_buf_first() failed or too small "
-                               "requested buffer (returned %d)", length);
-                       scst_set_cmd_error(cmd,
-                               SCST_LOAD_SENSE(
-                                       scst_sense_invalid_field_in_parm_list));
-               }
-               if (length > 0)
-                       goto out_put;
-               else
-                       goto out;
+       if (length < 0) {
+               PRINT_ERROR("scst_get_buf_first() failed: %d)", length);
+               scst_set_cmd_error(cmd,
+                       SCST_LOAD_SENSE(scst_sense_hardw_error));
+               goto out;
        }
 
-       scst_set_sense(address, length, cmd->dev->d_sense,
-               SCST_LOAD_SENSE(scst_sense_no_sense));
+       length = min(sl, length);
+       memcpy(address, b, length);
+       scst_set_resp_data_len(cmd, length);
 
-out_put:
        scst_put_buf(cmd, address);
 
 out:
@@ -1935,8 +1931,23 @@ static void vdisk_exec_read_capacity16(struct scst_cmd *cmd)
                goto out;
        }
 
+       /*
+        * Some versions of Windows have a bug, which makes them consider
+        * response of READ CAPACITY(16) longer than 12 bytes as a faulty one.
+        * As the result, such Windows'es refuse to see SCST exported
+        * devices >2TB in size. This is fixed by MS in latter Windows
+        * versions, probably, by some hotfix.
+        *
+        * But if you're using such buggy Windows and experience this problem,
+        * change this '1' to '0'.
+        */
+#if 1  
        if (length > READ_CAP16_LEN)
                length = READ_CAP16_LEN;
+#else
+       if (length > 12)
+               length = 12;
+#endif
        memcpy(address, buffer, length);
 
        scst_put_buf(cmd, address);
index 1b7b02d..e494c5d 100644 (file)
@@ -91,9 +91,11 @@ int scst_alloc_sense(struct scst_cmd *cmd, int atomic)
                goto out;
        }
 
+       cmd->sense_buflen = SCST_SENSE_BUFFERSIZE;
+
 memzero:
-       cmd->sense_bufflen = SCST_SENSE_BUFFERSIZE;
-       memset(cmd->sense, 0, SCST_SENSE_BUFFERSIZE);
+       cmd->sense_valid_len = 0;
+       memset(cmd->sense, 0, cmd->sense_buflen);
 
 out:
        TRACE_EXIT_RES(res);
@@ -114,8 +116,15 @@ int scst_alloc_set_sense(struct scst_cmd *cmd, int atomic,
                goto out;
        }
 
-       memcpy(cmd->sense, sense, min((int)len, (int)cmd->sense_bufflen));
-       TRACE_BUFFER("Sense set", cmd->sense, cmd->sense_bufflen);
+       cmd->sense_valid_len = len;
+       if (cmd->sense_buflen < len) {
+               PRINT_WARNING("Sense truncated (needed %d), shall you increase "
+                       "SCST_SENSE_BUFFERSIZE? Op: %x", len, cmd->cdb[0]);
+               cmd->sense_valid_len = cmd->sense_buflen;
+       }
+
+       memcpy(cmd->sense, sense, cmd->sense_valid_len);
+       TRACE_BUFFER("Sense set", cmd->sense, cmd->sense_valid_len);
 
 out:
        TRACE_EXIT_RES(res);
@@ -159,9 +168,9 @@ void scst_set_cmd_error(struct scst_cmd *cmd, int key, int asc, int ascq)
                goto out;
        }
 
-       scst_set_sense(cmd->sense, cmd->sense_bufflen,
+       cmd->sense_valid_len = scst_set_sense(cmd->sense, cmd->sense_buflen,
                scst_get_cmd_dev_d_sense(cmd), key, asc, ascq);
-       TRACE_BUFFER("Sense set", cmd->sense, cmd->sense_bufflen);
+       TRACE_BUFFER("Sense set", cmd->sense, cmd->sense_valid_len);
 
 out:
        TRACE_EXIT();
@@ -169,16 +178,18 @@ out:
 }
 EXPORT_SYMBOL(scst_set_cmd_error);
 
-void scst_set_sense(uint8_t *buffer, int len, bool d_sense,
+int scst_set_sense(uint8_t *buffer, int len, bool d_sense,
        int key, int asc, int ascq)
 {
+       int res;
+
        sBUG_ON(len == 0);
 
        memset(buffer, 0, len);
 
        if (d_sense) {
                /* Descriptor format */
-               if (len < 4) {
+               if (len < 8) {
                        PRINT_ERROR("Length %d of sense buffer too small to "
                                "fit sense %x:%x:%x", len, key, asc, ascq);
                }
@@ -190,9 +201,10 @@ void scst_set_sense(uint8_t *buffer, int len, bool d_sense,
                        buffer[2] = asc;        /* ASC                  */
                if (len > 3)
                        buffer[3] = ascq;       /* ASCQ                 */
+               res = 8;
        } else {
                /* Fixed format */
-               if (len < 14) {
+               if (len < 18) {
                        PRINT_ERROR("Length %d of sense buffer too small to "
                                "fit sense %x:%x:%x", len, key, asc, ascq);
                }
@@ -206,10 +218,11 @@ void scst_set_sense(uint8_t *buffer, int len, bool d_sense,
                        buffer[12] = asc;       /* ASC                  */
                if (len > 13)
                        buffer[13] = ascq;      /* ASCQ                 */
+               res = 18;
        }
 
-       TRACE_BUFFER("Sense set", buffer, len);
-       return;
+       TRACE_BUFFER("Sense set", buffer, res);
+       return res;
 }
 EXPORT_SYMBOL(scst_set_sense);
 
@@ -222,43 +235,55 @@ bool scst_analyze_sense(const uint8_t *sense, int len, unsigned int valid_mask,
        if ((sense[0] == 0x70) || (sense[0] == 0x71)) {
                /* Fixed format */
 
-               if (len < 14) {
-                       PRINT_ERROR("Sense too small to analyze (%d, "
-                               "type fixed)", len);
-                       goto out;
-               }
-
                /* Sense Key */
-               if ((valid_mask & SCST_SENSE_KEY_VALID) && (sense[2] != key))
-                       goto out;
+               if (valid_mask & SCST_SENSE_KEY_VALID) {
+                       if (len < 3)
+                               goto out;
+                       if (sense[2] != key)
+                               goto out;
+               }
 
                /* ASC */
-               if ((valid_mask & SCST_SENSE_ASC_VALID) && (sense[12] != asc))
-                       goto out;
+               if (valid_mask & SCST_SENSE_ASC_VALID) {
+                       if (len < 13)
+                               goto out;
+                       if (sense[12] != asc)
+                               goto out;
+               }
 
                /* ASCQ */
-               if ((valid_mask & SCST_SENSE_ASCQ_VALID) && (sense[13] != ascq))
-                       goto out;
+               if (valid_mask & SCST_SENSE_ASCQ_VALID) {
+                       if (len < 14)
+                               goto out;
+                       if (sense[13] != ascq)
+                               goto out;
+               }
        } else if ((sense[0] == 0x72) || (sense[0] == 0x73)) {
                /* Descriptor format */
 
-               if (len < 4) {
-                       PRINT_ERROR("Sense too small to analyze (%d, "
-                               "type descriptor)", len);
-                       goto out;
-               }
-
                /* Sense Key */
-               if ((valid_mask & SCST_SENSE_KEY_VALID) && (sense[1] != key))
-                       goto out;
+               if (valid_mask & SCST_SENSE_KEY_VALID) {
+                       if (len < 2)
+                               goto out;
+                       if (sense[1] != key)
+                               goto out;
+               }
 
                /* ASC */
-               if ((valid_mask & SCST_SENSE_ASC_VALID) && (sense[2] != asc))
-                       goto out;
+               if (valid_mask & SCST_SENSE_ASC_VALID) {
+                       if (len < 3)
+                               goto out;
+                       if (sense[2] != asc)
+                               goto out;
+               }
 
                /* ASCQ */
-               if ((valid_mask & SCST_SENSE_ASCQ_VALID) && (sense[3] != ascq))
-                       goto out;
+               if (valid_mask & SCST_SENSE_ASCQ_VALID) {
+                       if (len < 4)
+                               goto out;
+                       if (sense[3] != ascq)
+                               goto out;
+               }
        } else
                goto out;
 
@@ -308,23 +333,25 @@ void scst_check_convert_sense(struct scst_cmd *cmd)
        if (d_sense && ((cmd->sense[0] == 0x70) || (cmd->sense[0] == 0x71))) {
                TRACE_MGMT_DBG("Converting fixed sense to descriptor (cmd %p)",
                        cmd);
-               if (cmd->sense_bufflen < 14) {
+               if ((cmd->sense_valid_len < 18) ) {
                        PRINT_ERROR("Sense too small to convert (%d, "
-                               "type fixed)", cmd->sense_bufflen);
+                               "type: fixed)", cmd->sense_buflen);
                        goto out;
                }
-               scst_set_sense(cmd->sense, cmd->sense_bufflen, d_sense,
-                       cmd->sense[2], cmd->sense[12], cmd->sense[13]);
+               cmd->sense_valid_len = scst_set_sense(cmd->sense, cmd->sense_buflen,
+                       d_sense, cmd->sense[2], cmd->sense[12], cmd->sense[13]);
        } else if (!d_sense && ((cmd->sense[0] == 0x72) ||
                                (cmd->sense[0] == 0x73))) {
                TRACE_MGMT_DBG("Converting descriptor sense to fixed (cmd %p)",
                        cmd);
-               if (cmd->sense_bufflen < 4) {
+               if ((cmd->sense_buflen < 18) || (cmd->sense_valid_len < 8)) {
                        PRINT_ERROR("Sense too small to convert (%d, "
-                               "type descryptor)", cmd->sense_bufflen);
+                               "type: descryptor, valid %d)",
+                               cmd->sense_buflen, cmd->sense_valid_len);
                        goto out;
                }
-               scst_set_sense(cmd->sense, cmd->sense_bufflen, d_sense,
+               cmd->sense_valid_len = scst_set_sense(cmd->sense,
+                       cmd->sense_buflen, d_sense,
                        cmd->sense[1], cmd->sense[2], cmd->sense[3]);
        }
 
@@ -397,10 +424,11 @@ void scst_set_initial_UA(struct scst_session *sess, int key, int asc, int ascq)
                                ua = list_entry(tgt_dev->UA_list.next,
                                        typeof(*ua), UA_list_entry);
                                if (scst_analyze_sense(ua->UA_sense_buffer,
-                                               sizeof(ua->UA_sense_buffer),
+                                               ua->UA_valid_sense_len,
                                                SCST_SENSE_ALL_VALID,
                                                SCST_LOAD_SENSE(scst_sense_reset_UA))) {
-                                       scst_set_sense(ua->UA_sense_buffer,
+                                       ua->UA_valid_sense_len = scst_set_sense(
+                                               ua->UA_sense_buffer,
                                                sizeof(ua->UA_sense_buffer),
                                                tgt_dev->dev->d_sense,
                                                key, asc, ascq);
@@ -464,6 +492,7 @@ void scst_gen_aen_or_ua(struct scst_tgt_dev *tgt_dev,
 {
        struct scst_tgt_template *tgtt = tgt_dev->sess->tgt->tgtt;
        uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
+       int sl;
 
        TRACE_ENTRY();
 
@@ -476,9 +505,9 @@ void scst_gen_aen_or_ua(struct scst_tgt_dev *tgt_dev,
                        goto queue_ua;
 
                aen->event_fn = SCST_AEN_SCSI;
-               aen->aen_sense_len = SCST_STANDARD_SENSE_LEN;
-               scst_set_sense(aen->aen_sense, aen->aen_sense_len,
-                       tgt_dev->dev->d_sense, key, asc, ascq);
+               aen->aen_sense_len = scst_set_sense(aen->aen_sense,
+                       SCST_SENSE_BUFFERSIZE, tgt_dev->dev->d_sense,
+                       key, asc, ascq);
 
                TRACE_DBG("Calling target's %s report_aen(%p)",
                        tgtt->name, aen);
@@ -494,9 +523,9 @@ void scst_gen_aen_or_ua(struct scst_tgt_dev *tgt_dev,
 queue_ua:
        TRACE_MGMT_DBG("AEN not supported, queuing plain UA (tgt_dev %p)",
                tgt_dev);
-       scst_set_sense(sense_buffer, sizeof(sense_buffer),
+       sl = scst_set_sense(sense_buffer, sizeof(sense_buffer),
                tgt_dev->dev->d_sense, key, asc, ascq);
-       scst_check_set_UA(tgt_dev, sense_buffer, sizeof(sense_buffer), 0);
+       scst_check_set_UA(tgt_dev, sense_buffer, sl, 0);
 
 out:
        TRACE_EXIT();
@@ -585,17 +614,18 @@ static void scst_queue_report_luns_changed_UA(struct scst_session *sess,
 
                list_for_each_entry(tgt_dev, shead,
                                sess_tgt_dev_list_entry) {
+                       int sl;
+
                        if (!scst_is_report_luns_changed_type(
                                        tgt_dev->dev->type))
                                continue;
 
-                       scst_set_sense(sense_buffer, sizeof(sense_buffer),
+                       sl = scst_set_sense(sense_buffer, sizeof(sense_buffer),
                                tgt_dev->dev->d_sense,
                                SCST_LOAD_SENSE(scst_sense_reported_luns_data_changed));
 
                        __scst_check_set_UA(tgt_dev, sense_buffer,
-                               sizeof(sense_buffer),
-                               flags | SCST_SET_UA_FLAG_GLOBAL);
+                               sl, flags | SCST_SET_UA_FLAG_GLOBAL);
                }
        }
 
@@ -653,8 +683,8 @@ found:
                        goto queue_ua;
 
                aen->event_fn = SCST_AEN_SCSI;
-               aen->aen_sense_len = SCST_STANDARD_SENSE_LEN;
-               scst_set_sense(aen->aen_sense, aen->aen_sense_len, d_sense,
+               aen->aen_sense_len = scst_set_sense(aen->aen_sense,
+                       SCST_SENSE_BUFFERSIZE, d_sense,
                        SCST_LOAD_SENSE(scst_sense_reported_luns_data_changed));
 
                TRACE_DBG("Calling target's %s report_aen(%p)",
@@ -754,7 +784,7 @@ void scst_requeue_ua(struct scst_cmd *cmd)
 {
        TRACE_ENTRY();
 
-       if (scst_analyze_sense(cmd->sense, cmd->sense_bufflen,
+       if (scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
                        SCST_SENSE_ALL_VALID,
                        SCST_LOAD_SENSE(scst_sense_reported_luns_data_changed))) {
                TRACE_MGMT_DBG("Requeuing REPORTED LUNS DATA CHANGED UA "
@@ -766,7 +796,7 @@ void scst_requeue_ua(struct scst_cmd *cmd)
        } else {
                TRACE_MGMT_DBG("Requeuing UA for delivery failed cmd %p", cmd);
                scst_check_set_UA(cmd->tgt_dev, cmd->sense,
-                       cmd->sense_bufflen, SCST_SET_UA_FLAG_AT_HEAD);
+                       cmd->sense_valid_len, SCST_SET_UA_FLAG_AT_HEAD);
        }
 
        TRACE_EXIT();
@@ -1428,7 +1458,7 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
        struct scst_device *dev = acg_dev->dev;
        struct list_head *sess_tgt_dev_list_head;
        struct scst_tgt_template *vtt = sess->tgt->tgtt;
-       int rc, i;
+       int rc, i, sl;
        bool share_io_ctx = false;
        uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
 
@@ -1523,9 +1553,9 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
                        &tgt_dev->tgt_dev_flags);
        }
 
-       scst_set_sense(sense_buffer, sizeof(sense_buffer),
+       sl = scst_set_sense(sense_buffer, sizeof(sense_buffer),
                dev->d_sense, SCST_LOAD_SENSE(scst_sense_reset_UA));
-       scst_alloc_set_UA(tgt_dev, sense_buffer, sizeof(sense_buffer), 0);
+       scst_alloc_set_UA(tgt_dev, sense_buffer, sl, 0);
 
        tm_dbg_init_tgt_dev(tgt_dev, acg_dev);
 
@@ -1635,11 +1665,10 @@ void scst_nexus_loss(struct scst_tgt_dev *tgt_dev, bool queue_UA)
 
        if (queue_UA) {
                uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
-               scst_set_sense(sense_buffer, sizeof(sense_buffer),
-                       tgt_dev->dev->d_sense,
-                       SCST_LOAD_SENSE(scst_sense_nexus_loss_UA));
-               scst_check_set_UA(tgt_dev, sense_buffer,
-                       sizeof(sense_buffer), 0);
+               int sl = scst_set_sense(sense_buffer, sizeof(sense_buffer),
+                               tgt_dev->dev->d_sense,
+                               SCST_LOAD_SENSE(scst_sense_nexus_loss_UA));
+               scst_check_set_UA(tgt_dev, sense_buffer, sl, 0);
        }
 
        TRACE_EXIT();
@@ -4272,11 +4301,12 @@ static void scst_check_internal_sense(struct scst_device *dev, int result,
        TRACE_ENTRY();
 
        if (host_byte(result) == DID_RESET) {
+               int sl;
                TRACE(TRACE_MGMT_MINOR, "%s", "DID_RESET received, triggering "
                        "reset UA");
-               scst_set_sense(sense, sense_len, dev->d_sense,
+               sl = scst_set_sense(sense, sense_len, dev->d_sense,
                        SCST_LOAD_SENSE(scst_sense_reset_UA));
-               scst_dev_check_set_UA(dev, NULL, sense, sense_len);
+               scst_dev_check_set_UA(dev, NULL, sense, sl);
        } else if ((status_byte(result) == CHECK_CONDITION) &&
                   scst_is_ua_sense(sense, sense_len))
                scst_dev_check_set_UA(dev, NULL, sense, sense_len);
@@ -4526,10 +4556,9 @@ void scst_process_reset(struct scst_device *dev,
 
        if (setUA) {
                uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
-               scst_set_sense(sense_buffer, sizeof(sense_buffer),
+               int sl = scst_set_sense(sense_buffer, sizeof(sense_buffer),
                        dev->d_sense, SCST_LOAD_SENSE(scst_sense_reset_UA));
-               scst_dev_check_set_local_UA(dev, exclude_cmd, sense_buffer,
-                       sizeof(sense_buffer));
+               scst_dev_check_set_local_UA(dev, exclude_cmd, sense_buffer, sl);
        }
 
        TRACE_EXIT();
@@ -4595,7 +4624,7 @@ again:
        }
 
        scst_set_cmd_error_sense(cmd, UA_entry->UA_sense_buffer,
-               sizeof(UA_entry->UA_sense_buffer));
+               UA_entry->UA_valid_sense_len);
 
        cmd->ua_ignore = 1;
 
@@ -4614,8 +4643,8 @@ again:
                                                        UA_list_entry) {
                                        if (ua->global_UA &&
                                            memcmp(ua->UA_sense_buffer,
-                                               UA_entry->UA_sense_buffer,
-                                            sizeof(ua->UA_sense_buffer)) == 0) {
+                                             UA_entry->UA_sense_buffer,
+                                             sizeof(ua->UA_sense_buffer)) == 0) {
                                                TRACE_MGMT_DBG("Freeing not "
                                                        "needed global UA %p",
                                                        ua);
@@ -4679,9 +4708,13 @@ static void scst_alloc_set_UA(struct scst_tgt_dev *tgt_dev,
        if (UA_entry->global_UA)
                TRACE_MGMT_DBG("Queuing global UA %p", UA_entry);
 
-       if (sense_len > (int)sizeof(UA_entry->UA_sense_buffer))
+       if (sense_len > (int)sizeof(UA_entry->UA_sense_buffer)) {
+               PRINT_WARNING("Sense truncated (needed %d), shall you increase "
+                       "SCST_SENSE_BUFFERSIZE?", sense_len);
                sense_len = sizeof(UA_entry->UA_sense_buffer);
+       }
        memcpy(UA_entry->UA_sense_buffer, sense, sense_len);
+       UA_entry->UA_valid_sense_len = sense_len;
 
        set_bit(SCST_TGT_DEV_UA_PENDING, &tgt_dev->tgt_dev_flags);
 
@@ -5239,13 +5272,13 @@ void scst_store_sense(struct scst_cmd *cmd)
 
                spin_lock_bh(&tgt_dev->tgt_dev_lock);
 
-               if (cmd->sense_bufflen <= sizeof(tgt_dev->tgt_dev_sense))
-                       tgt_dev->tgt_dev_valid_sense_len = cmd->sense_bufflen;
+               if (cmd->sense_valid_len <= sizeof(tgt_dev->tgt_dev_sense))
+                       tgt_dev->tgt_dev_valid_sense_len = cmd->sense_valid_len;
                else {
                        tgt_dev->tgt_dev_valid_sense_len = sizeof(tgt_dev->tgt_dev_sense);
                        PRINT_ERROR("Stored sense truncated to size %d "
                                "(needed %d)", tgt_dev->tgt_dev_valid_sense_len,
-                               cmd->sense_bufflen);
+                               cmd->sense_valid_len);
                }
                memcpy(tgt_dev->tgt_dev_sense, cmd->sense,
                        tgt_dev->tgt_dev_valid_sense_len);
index 468ecce..154466a 100644 (file)
@@ -436,11 +436,6 @@ void scst_requeue_ua(struct scst_cmd *cmd);
 void scst_gen_aen_or_ua(struct scst_tgt_dev *tgt_dev,
        int key, int asc, int ascq);
 
-static inline bool scst_is_ua_command(struct scst_cmd *cmd)
-{
-       return (cmd->op_flags & SCST_SKIP_UA) == 0;
-}
-
 static inline bool scst_is_implicit_hq(struct scst_cmd *cmd)
 {
        return (cmd->op_flags & SCST_IMPLICIT_HQ) != 0;
index 6262717..4f28898 100644 (file)
@@ -1509,7 +1509,7 @@ out_compl:
                        list_for_each_entry(ua, &tgt_dev->UA_list,
                                                UA_list_entry) {
                                if (scst_analyze_sense(ua->UA_sense_buffer,
-                                               sizeof(ua->UA_sense_buffer),
+                                               ua->UA_valid_sense_len,
                                                SCST_SENSE_ALL_VALID,
                                                SCST_LOAD_SENSE(scst_sense_reported_luns_data_changed))) {
                                        TRACE_MGMT_DBG("Freeing not needed "
@@ -1553,7 +1553,7 @@ static int scst_request_sense_local(struct scst_cmd *cmd)
        int res = SCST_EXEC_COMPLETED, rc;
        struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
        uint8_t *buffer;
-       int buffer_size = 0;
+       int buffer_size = 0, sl;
 
        TRACE_ENTRY();
 
@@ -1590,7 +1590,7 @@ static int scst_request_sense_local(struct scst_cmd *cmd)
                        tgt_dev->tgt_dev_valid_sense_len);
 
                buffer_size = min(SCST_STANDARD_SENSE_LEN, buffer_size);
-               scst_set_sense(buffer, buffer_size, true,
+               sl = scst_set_sense(buffer, buffer_size, true,
                        tgt_dev->tgt_dev_sense[2], tgt_dev->tgt_dev_sense[12],
                        tgt_dev->tgt_dev_sense[13]);
        } else if (((tgt_dev->tgt_dev_sense[0] == 0x72) ||
@@ -1602,25 +1602,26 @@ static int scst_request_sense_local(struct scst_cmd *cmd)
                        tgt_dev->tgt_dev_valid_sense_len);
 
                buffer_size = min(SCST_STANDARD_SENSE_LEN, buffer_size);
-               scst_set_sense(buffer, buffer_size, false,
+               sl = scst_set_sense(buffer, buffer_size, false,
                        tgt_dev->tgt_dev_sense[1], tgt_dev->tgt_dev_sense[2],
                        tgt_dev->tgt_dev_sense[3]);
        } else {
                if (buffer_size >= tgt_dev->tgt_dev_valid_sense_len)
-                       buffer_size = tgt_dev->tgt_dev_valid_sense_len;
+                       sl = tgt_dev->tgt_dev_valid_sense_len;
                else {
+                       sl = buffer_size;
                        PRINT_WARNING("%s: Being returned sense truncated to "
                                "size %d (needed %d)", cmd->op_name,
                                buffer_size, tgt_dev->tgt_dev_valid_sense_len);
                }
-               memcpy(buffer, tgt_dev->tgt_dev_sense, buffer_size);
+               memcpy(buffer, tgt_dev->tgt_dev_sense, sl);
        }
 
        scst_put_buf(cmd, buffer);
 
 out_compl:
        tgt_dev->tgt_dev_valid_sense_len = 0;
-       scst_set_resp_data_len(cmd, buffer_size);
+       scst_set_resp_data_len(cmd, sl);
 
        spin_unlock_bh(&tgt_dev->tgt_dev_lock);
 
@@ -2420,11 +2421,11 @@ static int scst_check_sense(struct scst_cmd *cmd)
        if (unlikely(cmd->status == SAM_STAT_CHECK_CONDITION) &&
            SCST_SENSE_VALID(cmd->sense)) {
                PRINT_BUFF_FLAG(TRACE_SCSI, "Sense", cmd->sense,
-                       cmd->sense_bufflen);
+                       cmd->sense_valid_len);
 
                /* Check Unit Attention Sense Key */
-               if (scst_is_ua_sense(cmd->sense, cmd->sense_bufflen)) {
-                       if (scst_analyze_sense(cmd->sense, cmd->sense_bufflen,
+               if (scst_is_ua_sense(cmd->sense, cmd->sense_valid_len)) {
+                       if (scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
                                        SCST_SENSE_ASC_VALID,
                                        0, SCST_SENSE_ASC_UA_RESET, 0)) {
                                if (cmd->double_ua_possible) {
@@ -2458,7 +2459,7 @@ static int scst_check_sense(struct scst_cmd *cmd)
                                }
                        }
                        scst_dev_check_set_UA(dev, cmd, cmd->sense,
-                               cmd->sense_bufflen);
+                               cmd->sense_valid_len);
                }
        }
 
@@ -2633,7 +2634,7 @@ static int scst_pre_dev_done(struct scst_cmd *cmd)
                                        (long long unsigned int)cmd->lun,
                                        cmd->status);
                                PRINT_BUFF_FLAG(TRACE_SCSI, "Sense", cmd->sense,
-                                       cmd->sense_bufflen);
+                                       cmd->sense_valid_len);
 
                                /* Clearing the reservation */
                                spin_lock_bh(&dev->dev_lock);
@@ -2651,8 +2652,8 @@ static int scst_pre_dev_done(struct scst_cmd *cmd)
                /* Check for MODE PARAMETERS CHANGED UA */
                if ((cmd->dev->scsi_dev != NULL) &&
                    (cmd->status == SAM_STAT_CHECK_CONDITION) &&
-                   scst_is_ua_sense(cmd->sense, cmd->sense_bufflen) &&
-                   scst_analyze_sense(cmd->sense, cmd->sense_bufflen,
+                   scst_is_ua_sense(cmd->sense, cmd->sense_valid_len) &&
+                   scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
                                        SCST_SENSE_ASCx_VALID,
                                        0, 0x2a, 0x01)) {
                        TRACE(TRACE_SCSI, "MODE PARAMETERS CHANGED UA (lun "
@@ -2681,6 +2682,7 @@ static int scst_mode_select_checks(struct scst_cmd *cmd)
                    (cmd->cdb[0] == MODE_SELECT_10) ||
                    (cmd->cdb[0] == LOG_SELECT))) {
                        struct scst_device *dev = cmd->dev;
+                       int sl;
                        uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
 
                        if (atomic && (dev->scsi_dev != NULL)) {
@@ -2696,37 +2698,36 @@ static int scst_mode_select_checks(struct scst_cmd *cmd)
 
                        spin_lock_bh(&dev->dev_lock);
                        if (cmd->cdb[0] == LOG_SELECT) {
-                               scst_set_sense(sense_buffer,
+                               sl = scst_set_sense(sense_buffer,
                                        sizeof(sense_buffer),
                                        dev->d_sense,
                                        UNIT_ATTENTION, 0x2a, 0x02);
                        } else {
-                               scst_set_sense(sense_buffer,
+                               sl = scst_set_sense(sense_buffer,
                                        sizeof(sense_buffer),
                                        dev->d_sense,
                                        UNIT_ATTENTION, 0x2a, 0x01);
                        }
-                       scst_dev_check_set_local_UA(dev, cmd, sense_buffer,
-                               sizeof(sense_buffer));
+                       scst_dev_check_set_local_UA(dev, cmd, sense_buffer, sl);
                        spin_unlock_bh(&dev->dev_lock);
 
                        if (dev->scsi_dev != NULL)
                                scst_obtain_device_parameters(dev);
                }
        } else if ((cmd->status == SAM_STAT_CHECK_CONDITION) &&
-                   scst_is_ua_sense(cmd->sense, cmd->sense_bufflen) &&
+                   scst_is_ua_sense(cmd->sense, cmd->sense_valid_len) &&
                     /* mode parameters changed */
-                   (scst_analyze_sense(cmd->sense, cmd->sense_bufflen,
+                   (scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
                                        SCST_SENSE_ASCx_VALID,
                                        0, 0x2a, 0x01) ||
-                    scst_analyze_sense(cmd->sense, cmd->sense_bufflen,
+                    scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
                                        SCST_SENSE_ASC_VALID,
                                        0, 0x29, 0) /* reset */ ||
-                    scst_analyze_sense(cmd->sense, cmd->sense_bufflen,
+                    scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
                                        SCST_SENSE_ASC_VALID,
                                        0, 0x28, 0) /* medium changed */ ||
                     /* cleared by another ini (just in case) */
-                    scst_analyze_sense(cmd->sense, cmd->sense_bufflen,
+                    scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
                                        SCST_SENSE_ASC_VALID,
                                        0, 0x2F, 0))) {
                if (atomic) {
@@ -3110,10 +3111,10 @@ static int scst_finish_cmd(struct scst_cmd *cmd)
 
        if (unlikely(cmd->delivery_status != SCST_CMD_DELIVERY_SUCCESS)) {
                if ((cmd->tgt_dev != NULL) &&
-                   scst_is_ua_sense(cmd->sense, cmd->sense_bufflen)) {
+                   scst_is_ua_sense(cmd->sense, cmd->sense_valid_len)) {
                        /* This UA delivery failed, so we need to requeue it */
                        if (scst_cmd_atomic(cmd) &&
-                           scst_is_ua_global(cmd->sense, cmd->sense_bufflen)) {
+                           scst_is_ua_global(cmd->sense, cmd->sense_valid_len)) {
                                TRACE_MGMT_DBG("Requeuing of global UA for "
                                        "failed cmd %p needs a thread", cmd);
                                res = SCST_CMD_STATE_RES_NEED_THREAD;
@@ -4407,14 +4408,15 @@ static int scst_clear_task_set(struct scst_mgmt_cmd *mcmd)
 
        if (!dev->tas) {
                uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
+               int sl;
 
-               scst_set_sense(sense_buffer, sizeof(sense_buffer), dev->d_sense,
+               sl = scst_set_sense(sense_buffer, sizeof(sense_buffer),
+                       dev->d_sense,
                        SCST_LOAD_SENSE(scst_sense_cleared_by_another_ini_UA));
 
                list_for_each_entry(tgt_dev, &UA_tgt_devs,
                                extra_tgt_dev_list_entry) {
-                       scst_check_set_UA(tgt_dev, sense_buffer,
-                               sizeof(sense_buffer), 0);
+                       scst_check_set_UA(tgt_dev, sense_buffer, sl, 0);
                }
        }
 
index ca730b6..6ef62dc 100644 (file)
@@ -125,7 +125,7 @@ static inline void set_cmd_error_status(struct scst_user_scsi_cmd_reply_exec *re
 
 static int set_sense(uint8_t *buffer, int len, int key, int asc, int ascq)
 {
-       int res = SCST_STANDARD_SENSE_LEN;
+       int res = 18;
 
        EXTRACHECKS_BUG_ON(len < res);
 
@@ -1064,23 +1064,18 @@ static void exec_request_sense(struct vdisk_cmd *vcmd)
 {
        struct scst_user_scsi_cmd_exec *cmd = &vcmd->cmd->exec_cmd;
        struct scst_user_scsi_cmd_reply_exec *reply = &vcmd->reply->exec_reply;
-       int length = cmd->bufflen;
+       int length = cmd->bufflen, l;
        uint8_t *address = (uint8_t*)(unsigned long)cmd->pbuf;
+       uint8_t b[SCST_STANDARD_SENSE_LEN];
 
        TRACE_ENTRY();
 
-       if (length < SCST_STANDARD_SENSE_LEN) {
-               PRINT_ERROR("too small requested buffer for REQUEST SENSE "
-                       "(len %d)", length);
-               set_cmd_error(vcmd,
-                   SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
-               goto out;
-       }
+       l = set_sense(b, sizeof(b), SCST_LOAD_SENSE(scst_sense_no_sense));
 
-       set_sense(address, length, SCST_LOAD_SENSE(scst_sense_no_sense));
+       length = min(l, length);
+       memcpy(address, b, length);
        reply->resp_data_len = length;
 
-out:
        TRACE_EXIT();
        return;
 }