mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-18 11:11:27 +00:00
SCSI cleanups and improvements
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4334 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -2343,7 +2343,7 @@ static enum compl_status_e vdisk_exec_inquiry(struct vdisk_cmd_params *p)
|
||||
|
||||
if (virt_dev->removable)
|
||||
buf[1] = 0x80; /* removable */
|
||||
buf[2] = 5; /* Device complies to SPC-3 */
|
||||
buf[2] = 6; /* Device complies to SPC-4 */
|
||||
buf[3] = 0x02; /* Data in format specified in SPC */
|
||||
if (cmd->tgtt->fake_aca)
|
||||
buf[3] |= 0x20;
|
||||
@@ -2390,9 +2390,9 @@ static enum compl_status_e vdisk_exec_inquiry(struct vdisk_cmd_params *p)
|
||||
buf[4] += 58 - 36;
|
||||
num = 0;
|
||||
|
||||
/* SAM-3 T10/1561-D revision 14 */
|
||||
/* SAM-4 T10/1683-D revision 14 */
|
||||
buf[58 + num] = 0x0;
|
||||
buf[58 + num + 1] = 0x76;
|
||||
buf[58 + num + 1] = 0x8B;
|
||||
num += 2;
|
||||
|
||||
/* Physical transport */
|
||||
@@ -2411,9 +2411,9 @@ static enum compl_status_e vdisk_exec_inquiry(struct vdisk_cmd_params *p)
|
||||
num += 2;
|
||||
}
|
||||
|
||||
/* SPC-3 T10/1416-D revision 23 */
|
||||
buf[58 + num] = 0x3;
|
||||
buf[58 + num + 1] = 0x12;
|
||||
/* SPC-4 T10/1731-D revision 23 */
|
||||
buf[58 + num] = 0x4;
|
||||
buf[58 + num + 1] = 0x63;
|
||||
num += 2;
|
||||
|
||||
/* Device command set */
|
||||
@@ -2956,13 +2956,16 @@ static enum compl_status_e vdisk_exec_read_capacity(struct vdisk_cmd_params *p)
|
||||
/* Last block on the virt_dev is (nblocks-1) */
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
#if 0 /* we don't need this workaround anymore */
|
||||
/*
|
||||
* If we are thinly provisioned, we must ensure that the initiator
|
||||
* issues a READ_CAPACITY(16) so we can return the TPE bit. By
|
||||
* issues a READ_CAPACITY(16) so we can return the LBPME bit. By
|
||||
* returning 0xFFFFFFFF we do that.
|
||||
*/
|
||||
put_unaligned_be32(nblocks >> 32 || virt_dev->thin_provisioned ?
|
||||
0xffffffffU : nblocks - 1, &buffer[0]);
|
||||
#endif
|
||||
|
||||
put_unaligned_be32(blocksize, &buffer[4]);
|
||||
|
||||
length = scst_get_buf_full(cmd, &address);
|
||||
@@ -3037,14 +3040,14 @@ static enum compl_status_e vdisk_exec_read_capacity16(struct vdisk_cmd_params *p
|
||||
}
|
||||
|
||||
if (virt_dev->thin_provisioned) {
|
||||
buffer[14] |= 0x80; /* Add TPE */
|
||||
buffer[14] |= 0x80; /* Add LBPME */
|
||||
#if 0 /*
|
||||
* Might be a big performance and functionality win, but might be
|
||||
* dangerous as well, although generally nearly always it should be set,
|
||||
* because nearly all devices should return zero for unmapped blocks.
|
||||
* But let's be on the safe side and disable it for now.
|
||||
*/
|
||||
buffer[14] |= 0x40; /* Add TPRZ */
|
||||
buffer[14] |= 0x40; /* Add LBPRZ */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1633,6 +1633,16 @@ int scst_set_sense(uint8_t *buffer, int len, bool d_sense,
|
||||
|
||||
memset(buffer, 0, len);
|
||||
|
||||
/*
|
||||
* The RESPONSE CODE field shall be set to 70h in all unit attention
|
||||
* condition sense data in which:
|
||||
* a) the ADDITIONAL SENSE CODE field is set to 29h; or
|
||||
* b) the additional sense code is set to MODE PARAMETERS CHANGED.
|
||||
*/
|
||||
if ((key == UNIT_ATTENTION) &&
|
||||
((asc == 0x29) || ((asc == 0x2A) && (ascq == 1))))
|
||||
d_sense = false;
|
||||
|
||||
if (d_sense) {
|
||||
/* Descriptor format */
|
||||
if (len < 8) {
|
||||
@@ -1794,8 +1804,17 @@ void scst_check_convert_sense(struct scst_cmd *cmd)
|
||||
if ((cmd->sense == NULL) || (cmd->status != SAM_STAT_CHECK_CONDITION))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* The RESPONSE CODE field shall be set to 70h in all unit attention
|
||||
* condition sense data in which:
|
||||
* a) the ADDITIONAL SENSE CODE field is set to 29h; or
|
||||
* b) the additional sense code is set to MODE PARAMETERS CHANGED.
|
||||
*/
|
||||
d_sense = scst_get_cmd_dev_d_sense(cmd);
|
||||
if (d_sense && ((cmd->sense[0] == 0x70) || (cmd->sense[0] == 0x71))) {
|
||||
if (d_sense && ((cmd->sense[0] == 0x70) || (cmd->sense[0] == 0x71)) &&
|
||||
!((cmd->sense[2] == UNIT_ATTENTION) &&
|
||||
((cmd->sense[12] == 0x29) ||
|
||||
((cmd->sense[12] == 0x2A) && (cmd->sense[13] == 1))))) {
|
||||
TRACE_MGMT_DBG("Converting fixed sense to descriptor (cmd %p)",
|
||||
cmd);
|
||||
if ((cmd->sense_valid_len < 18)) {
|
||||
@@ -2280,12 +2299,16 @@ out_free:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_aen_done);
|
||||
|
||||
void scst_requeue_ua(struct scst_cmd *cmd)
|
||||
void scst_requeue_ua(struct scst_cmd *cmd, const uint8_t *buf, int size)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
|
||||
SCST_SENSE_ALL_VALID,
|
||||
if (buf == NULL) {
|
||||
buf = cmd->sense;
|
||||
size = cmd->sense_valid_len;
|
||||
}
|
||||
|
||||
if (scst_analyze_sense(buf, size, SCST_SENSE_ALL_VALID,
|
||||
SCST_LOAD_SENSE(scst_sense_reported_luns_data_changed))) {
|
||||
TRACE_MGMT_DBG("Requeuing REPORTED LUNS DATA CHANGED UA "
|
||||
"for delivery failed cmd %p", cmd);
|
||||
@@ -2295,8 +2318,7 @@ void scst_requeue_ua(struct scst_cmd *cmd)
|
||||
mutex_unlock(&scst_mutex);
|
||||
} else {
|
||||
TRACE_MGMT_DBG("Requeuing UA for delivery failed cmd %p", cmd);
|
||||
scst_check_set_UA(cmd->tgt_dev, cmd->sense,
|
||||
cmd->sense_valid_len, SCST_SET_UA_FLAG_AT_HEAD);
|
||||
scst_check_set_UA(cmd->tgt_dev, buf, size, SCST_SET_UA_FLAG_AT_HEAD);
|
||||
}
|
||||
|
||||
TRACE_EXIT();
|
||||
@@ -4628,7 +4650,7 @@ static void scst_ws_write_cmd_finished(struct scst_cmd *cmd)
|
||||
if (rc != 0) {
|
||||
/* Requeue possible UA */
|
||||
if (scst_is_ua_sense(cmd->sense, cmd->sense_buflen))
|
||||
scst_requeue_ua(cmd);
|
||||
scst_requeue_ua(cmd, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7330,7 +7352,7 @@ void scst_tgt_dev_del_free_UA(struct scst_tgt_dev *tgt_dev,
|
||||
}
|
||||
|
||||
/* No locks, no IRQ or IRQ-disabled context allowed */
|
||||
int scst_set_pending_UA(struct scst_cmd *cmd)
|
||||
int scst_set_pending_UA(struct scst_cmd *cmd, uint8_t *buf, int *size)
|
||||
{
|
||||
int res = 0, i;
|
||||
struct scst_tgt_dev_UA *UA_entry;
|
||||
@@ -7399,9 +7421,23 @@ again:
|
||||
goto again;
|
||||
}
|
||||
|
||||
if (scst_set_cmd_error_sense(cmd, UA_entry->UA_sense_buffer,
|
||||
UA_entry->UA_valid_sense_len) != 0)
|
||||
goto out_unlock;
|
||||
if (buf == NULL) {
|
||||
if (scst_set_cmd_error_sense(cmd, UA_entry->UA_sense_buffer,
|
||||
UA_entry->UA_valid_sense_len) != 0)
|
||||
goto out_unlock;
|
||||
} else {
|
||||
sBUG_ON(*size == 0);
|
||||
if (UA_entry->UA_valid_sense_len > *size) {
|
||||
TRACE(TRACE_MINOR, "%s: Being returned UA truncated "
|
||||
"to size %d (needed %d)", cmd->op_name,
|
||||
*size, UA_entry->UA_valid_sense_len);
|
||||
*size = UA_entry->UA_valid_sense_len;
|
||||
}
|
||||
TRACE_DBG_SPECIAL("Returning UA in buffer %p (size %d)",
|
||||
buf, *size); //!!!
|
||||
memcpy(buf, UA_entry->UA_sense_buffer, *size);
|
||||
*size = UA_entry->UA_valid_sense_len;
|
||||
}
|
||||
|
||||
cmd->ua_ignore = 1;
|
||||
|
||||
|
||||
@@ -574,7 +574,7 @@ void scst_dev_check_set_local_UA(struct scst_device *dev,
|
||||
|
||||
void scst_check_set_UA(struct scst_tgt_dev *tgt_dev,
|
||||
const uint8_t *sense, int sense_len, int flags);
|
||||
int scst_set_pending_UA(struct scst_cmd *cmd);
|
||||
int scst_set_pending_UA(struct scst_cmd *cmd, uint8_t *buf, int *size);
|
||||
|
||||
void scst_report_luns_changed(struct scst_acg *acg);
|
||||
|
||||
@@ -585,7 +585,7 @@ void scst_process_reset(struct scst_device *dev,
|
||||
struct scst_mgmt_cmd *mcmd, bool setUA);
|
||||
|
||||
bool scst_is_ua_global(const uint8_t *sense, int len);
|
||||
void scst_requeue_ua(struct scst_cmd *cmd);
|
||||
void scst_requeue_ua(struct scst_cmd *cmd, const uint8_t *buf, int size);
|
||||
|
||||
struct scst_aen *scst_alloc_aen(struct scst_session *sess,
|
||||
uint64_t unpacked_lun);
|
||||
|
||||
@@ -1839,21 +1839,53 @@ static int scst_request_sense_local(struct scst_cmd *cmd)
|
||||
cmd->host_status = DID_OK;
|
||||
cmd->driver_status = 0;
|
||||
|
||||
spin_lock_bh(&tgt_dev->tgt_dev_lock);
|
||||
|
||||
if (tgt_dev->tgt_dev_valid_sense_len == 0)
|
||||
goto out_unlock_not_completed;
|
||||
|
||||
TRACE(TRACE_SCSI, "%s: Returning stored sense", cmd->op_name);
|
||||
|
||||
buffer_size = scst_get_buf_full(cmd, &buffer);
|
||||
if (unlikely(buffer_size == 0))
|
||||
goto out_unlock_compl;
|
||||
goto out_compl;
|
||||
else if (unlikely(buffer_size < 0))
|
||||
goto out_unlock_hw_err;
|
||||
goto out_hw_err;
|
||||
|
||||
memset(buffer, 0, buffer_size);
|
||||
|
||||
spin_lock_bh(&tgt_dev->tgt_dev_lock);
|
||||
|
||||
if (tgt_dev->tgt_dev_valid_sense_len == 0) {
|
||||
if (test_bit(SCST_TGT_DEV_UA_PENDING, &cmd->tgt_dev->tgt_dev_flags)) {
|
||||
int rc, size = sizeof(tgt_dev->tgt_dev_sense);
|
||||
uint8_t *buf;
|
||||
|
||||
spin_unlock_bh(&tgt_dev->tgt_dev_lock);
|
||||
|
||||
buf = kzalloc(size, GFP_KERNEL);
|
||||
if (buf == NULL)
|
||||
goto out_put_busy;
|
||||
|
||||
rc = scst_set_pending_UA(cmd, buf, &size);
|
||||
|
||||
spin_lock_bh(&tgt_dev->tgt_dev_lock);
|
||||
|
||||
if (rc == 0) {
|
||||
if (tgt_dev->tgt_dev_valid_sense_len == 0) {
|
||||
tgt_dev->tgt_dev_valid_sense_len = size;
|
||||
memcpy(tgt_dev->tgt_dev_sense, buf, size);
|
||||
} else {
|
||||
/*
|
||||
* Yes, we can loose some of UA data
|
||||
* here, if UA size is bigger, than
|
||||
* size, i.e. tgt_dev_sense.
|
||||
*/
|
||||
scst_requeue_ua(cmd, buf, size);
|
||||
}
|
||||
}
|
||||
|
||||
kfree(buf);
|
||||
}
|
||||
if (tgt_dev->tgt_dev_valid_sense_len == 0)
|
||||
goto out_unlock_put_not_completed;
|
||||
}
|
||||
|
||||
TRACE(TRACE_SCSI, "%s: Returning stored/UA sense", cmd->op_name);
|
||||
|
||||
if (((tgt_dev->tgt_dev_sense[0] == 0x70) ||
|
||||
(tgt_dev->tgt_dev_sense[0] == 0x71)) && (cmd->cdb[1] & 1)) {
|
||||
PRINT_WARNING("%s: Fixed format of the saved sense, but "
|
||||
@@ -1890,12 +1922,12 @@ static int scst_request_sense_local(struct scst_cmd *cmd)
|
||||
memcpy(buffer, tgt_dev->tgt_dev_sense, sl);
|
||||
}
|
||||
|
||||
scst_put_buf_full(cmd, buffer);
|
||||
|
||||
tgt_dev->tgt_dev_valid_sense_len = 0;
|
||||
|
||||
spin_unlock_bh(&tgt_dev->tgt_dev_lock);
|
||||
|
||||
scst_put_buf_full(cmd, buffer);
|
||||
|
||||
scst_set_resp_data_len(cmd, sl);
|
||||
|
||||
out_compl:
|
||||
@@ -1908,19 +1940,20 @@ out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
|
||||
out_unlock_hw_err:
|
||||
spin_unlock_bh(&tgt_dev->tgt_dev_lock);
|
||||
out_hw_err:
|
||||
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
|
||||
goto out_compl;
|
||||
|
||||
out_unlock_not_completed:
|
||||
out_put_busy:
|
||||
scst_put_buf_full(cmd, buffer);
|
||||
scst_set_busy(cmd);
|
||||
goto out_compl;
|
||||
|
||||
out_unlock_put_not_completed:
|
||||
spin_unlock_bh(&tgt_dev->tgt_dev_lock);
|
||||
scst_put_buf_full(cmd, buffer);
|
||||
res = SCST_EXEC_NOT_COMPLETED;
|
||||
goto out;
|
||||
|
||||
out_unlock_compl:
|
||||
spin_unlock_bh(&tgt_dev->tgt_dev_lock);
|
||||
goto out_compl;
|
||||
}
|
||||
|
||||
static int scst_reserve_local(struct scst_cmd *cmd)
|
||||
@@ -2420,7 +2453,7 @@ int __scst_check_local_events(struct scst_cmd *cmd, bool preempt_tests_only)
|
||||
if (unlikely(test_bit(SCST_TGT_DEV_UA_PENDING,
|
||||
&cmd->tgt_dev->tgt_dev_flags))) {
|
||||
if (scst_is_ua_command(cmd)) {
|
||||
rc = scst_set_pending_UA(cmd);
|
||||
rc = scst_set_pending_UA(cmd, NULL, NULL);
|
||||
if (rc == 0)
|
||||
goto out_complete;
|
||||
}
|
||||
@@ -3706,7 +3739,7 @@ static int scst_finish_cmd(struct scst_cmd *cmd)
|
||||
res = SCST_CMD_STATE_RES_NEED_THREAD;
|
||||
goto out;
|
||||
}
|
||||
scst_requeue_ua(cmd);
|
||||
scst_requeue_ua(cmd, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user