- Sense handling cleanup

- How to workaround Windows READ CAPACITY(16) bug documented



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1146 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2009-09-25 18:57:10 +00:00
parent b22067d540
commit 93e8178a4f
12 changed files with 223 additions and 155 deletions

View 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'.

View 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);
/*

View 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

View 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;
}

View 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;
}

View 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;

View 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:

View 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();
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;
}
scst_set_sense(address, length, cmd->dev->d_sense,
sl = scst_set_sense(b, sizeof(b), cmd->dev->d_sense,
SCST_LOAD_SENSE(scst_sense_no_sense));
out_put:
length = scst_get_buf_first(cmd, &address);
TRACE_DBG("length %d", length);
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;
}
length = min(sl, length);
memcpy(address, b, length);
scst_set_resp_data_len(cmd, length);
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);

View 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) {
if (len < 3)
goto out;
if (sense[2] != key)
goto out;
}
/* Sense Key */
if ((valid_mask & SCST_SENSE_KEY_VALID) && (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) {
if (len < 2)
goto out;
if (sense[1] != key)
goto out;
}
/* Sense Key */
if ((valid_mask & SCST_SENSE_KEY_VALID) && (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);

View 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;

View 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);
}
}

View 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;
}