mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-17 02:31:27 +00:00
- 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:
@@ -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'.
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
/*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user