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'.
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;
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];
};
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)
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:
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;
}
/*
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);
/*
* 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
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;
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;
}
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),
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;
}
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;
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:
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;
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:
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);
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);
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);
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();
}
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);
}
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);
}
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);
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;
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]);
}
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);
{
struct scst_tgt_template *tgtt = tgt_dev->sess->tgt->tgtt;
uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
+ int sl;
TRACE_ENTRY();
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);
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();
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);
}
}
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)",
{
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 "
} 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();
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];
&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);
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();
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);
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();
}
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;
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);
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);
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);
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;
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 "
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();
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) ||
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);
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) {
}
}
scst_dev_check_set_UA(dev, cmd, cmd->sense,
- cmd->sense_bufflen);
+ cmd->sense_valid_len);
}
}
(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);
/* 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 "
(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)) {
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) {
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;
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);
}
}
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);
{
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;
}