Custom commands parsing cleanups

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1455 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2010-01-12 19:05:27 +00:00
parent e5a195516c
commit 89345ab95c
8 changed files with 237 additions and 174 deletions

View File

@@ -2,7 +2,7 @@
USER SPACE INTERFACE DESCRIPTION.
Version 1.0.2
Version 2.0.0
I. Description.
@@ -280,7 +280,7 @@ where:
- subcode - subcommand code, see 4.1 below
- preply - pointer to the reply data or, if 0, there is no reply. See
- preply - pointer to the reply data or, if 0, there is no reply. See
SCST_USER_REPLY_CMD for description of struct scst_user_reply_cmd
fields
@@ -375,6 +375,8 @@ struct scst_user_scsi_cmd_parse
int32_t bufflen;
int32_t in_bufflen;
uint32_t op_flags;
uint8_t queue_type;
uint8_t data_direction;
@@ -403,6 +405,8 @@ where:
- in_bufflen - for bidirectional commands command's IN, i.e. from
initiator to target, buffer length
- op_flags - CDB flags, one or more scst_cdb_flags bits, see below.
- queue_type - SCSI task attribute (queue type)
- data_direction - command's data flow direction, one of SCST_DATA_*
@@ -418,6 +422,30 @@ where:
- sn - command's SN, which might be used for task management
Bits of scst_cdb_flags can be:
- SCST_TRANSFER_LEN_TYPE_FIXED - this command uses fixed blocks addressing
- SCST_SMALL_TIMEOUT - this command needs small timeout
- SCST_LONG_TIMEOUT - this command needs a long timeout
- SCST_UNKNOWN_LENGTH - data buffer lenght for this command is unknown
- SCST_INFO_VALID - bits of op_flags are valid
- SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED - mismatch of data_direction with
the value supplied by target driver is allowed
- SCST_IMPLICIT_HQ - this command is an implicit HEAD OF QUEUE command
- SCST_SKIP_UA - Unit Attentions shouldn't be delivered for this command
- SCST_WRITE_MEDIUM - this command writes data on the medium, so should be
forbidden for read-only devices
- SCST_LOCAL_CMD - this command can be processed by SCST core.
In the PARSE state of SCSI commands processing the user space device
handler shall check and provide SCST values for command data buffer
length, data flow direction and timeout, which it shall reply using the
@@ -811,7 +839,8 @@ struct scst_user_scsi_cmd_reply_parse
{
uint8_t queue_type;
uint8_t data_direction;
uint8_t write_medium;
int16_t cdb_len;
uint32_t op_flags;
int32_t data_len;
int32_t bufflen;
},
@@ -822,8 +851,9 @@ where:
- data_direction - command's data flow direction, one of SCST_DATA_* constants
- write_medium - true, if command writes data to medium, so should be
forbidden for read-only devices, false otherwise
- cdb_len - length of CDB
- op_flags - commands flags, one or more scst_cdb_flags bits, see above.
- data_len - command's data length

View File

@@ -527,21 +527,6 @@ struct scst_aen;
typedef enum dma_data_direction scst_data_direction;
enum scst_cdb_flags {
/* SCST_TRANSFER_LEN_TYPE_FIXED must be equiv 1 (FIXED_BIT in cdb) */
SCST_TRANSFER_LEN_TYPE_FIXED = 0x001,
SCST_SMALL_TIMEOUT = 0x002,
SCST_LONG_TIMEOUT = 0x004,
SCST_UNKNOWN_LENGTH = 0x008,
SCST_INFO_NOT_FOUND = 0x010, /* must be single bit */
SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED = 0x020,
SCST_IMPLICIT_HQ = 0x040,
SCST_SKIP_UA = 0x080,
SCST_WRITE_MEDIUM = 0x100,
SCST_LOCAL_CMD = 0x200,
SCST_FULLY_LOCAL_CMD = 0x400,
};
/*
* Scsi_Target_Template: defines what functions a target driver will
* have to provide in order to work with the target mid-level.

View File

@@ -124,6 +124,23 @@ enum scst_cmd_queue_type {
SCST_CMD_QUEUE_ACA
};
/*************************************************************
** CDB flags
*************************************************************/
enum scst_cdb_flags {
SCST_TRANSFER_LEN_TYPE_FIXED = 0x001,
SCST_SMALL_TIMEOUT = 0x002,
SCST_LONG_TIMEOUT = 0x004,
SCST_UNKNOWN_LENGTH = 0x008,
SCST_INFO_VALID = 0x010, /* must be single bit */
SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED = 0x020,
SCST_IMPLICIT_HQ = 0x040,
SCST_SKIP_UA = 0x080,
SCST_WRITE_MEDIUM = 0x100,
SCST_LOCAL_CMD = 0x200,
SCST_FULLY_LOCAL_CMD = 0x400,
};
/*************************************************************
** Data direction aliases. Changing it don't forget to change
** scst_to_tgt_dma_dir as well!!

View File

@@ -120,6 +120,8 @@ struct scst_user_scsi_cmd_parse {
int32_t bufflen;
int32_t in_bufflen;
uint32_t op_flags;
uint8_t queue_type;
uint8_t data_direction;
@@ -211,7 +213,8 @@ struct scst_user_get_cmd {
struct scst_user_scsi_cmd_reply_parse {
uint8_t queue_type;
uint8_t data_direction;
uint8_t write_medium;
int16_t cdb_len;
uint32_t op_flags;
int32_t data_len;
int32_t bufflen;
};

View File

@@ -780,14 +780,14 @@ static int dev_user_parse(struct scst_cmd *cmd)
case SCST_USER_PARSE_STANDARD:
TRACE_DBG("PARSE STANDARD: ucmd %p", ucmd);
rc = dev->generic_parse(cmd, dev_user_get_block);
if ((rc != 0) || (cmd->op_flags & SCST_INFO_NOT_FOUND))
if ((rc != 0) || !(cmd->op_flags & SCST_INFO_VALID))
goto out_invalid;
break;
case SCST_USER_PARSE_EXCEPTION:
TRACE_DBG("PARSE EXCEPTION: ucmd %p", ucmd);
rc = dev->generic_parse(cmd, dev_user_get_block);
if ((rc == 0) && (!(cmd->op_flags & SCST_INFO_NOT_FOUND)))
if ((rc == 0) && (cmd->op_flags & SCST_INFO_VALID))
break;
else if (rc == SCST_CMD_STATE_NEED_THREAD_CTX) {
TRACE_MEM("Restarting PARSE to thread context "
@@ -821,6 +821,8 @@ static int dev_user_parse(struct scst_cmd *cmd)
ucmd->user_cmd.parse_cmd.expected_transfer_len =
cmd->expected_transfer_len;
ucmd->user_cmd.parse_cmd.sn = cmd->tgt_sn;
ucmd->user_cmd.parse_cmd.cdb_len = cmd->cdb_len;
ucmd->user_cmd.parse_cmd.op_flags = cmd->op_flags;
ucmd->state = UCMD_STATE_PARSING;
dev_user_add_to_ready(ucmd);
res = SCST_CMD_STATE_STOP;
@@ -1266,17 +1268,23 @@ static int dev_user_process_reply_parse(struct scst_user_cmd *ucmd,
if (unlikely((preply->bufflen < 0) || (preply->data_len < 0)))
goto out_inval;
if (unlikely(preply->cdb_len > SCST_MAX_CDB_SIZE))
goto out_inval;
TRACE_DBG("ucmd %p, queue_type %x, data_direction, %x, bufflen %d, "
"data_len %d, pbuf %llx", ucmd, preply->queue_type,
preply->data_direction, preply->bufflen, preply->data_len,
reply->alloc_reply.pbuf);
"data_len %d, pbuf %llx, cdb_len %d, op_flags %x", ucmd,
preply->queue_type, preply->data_direction, preply->bufflen,
preply->data_len, reply->alloc_reply.pbuf, preply->cdb_len,
preply->op_flags);
cmd->queue_type = preply->queue_type;
cmd->data_direction = preply->data_direction;
cmd->bufflen = preply->bufflen;
cmd->data_len = preply->data_len;
if (preply->write_medium)
cmd->op_flags |= SCST_WRITE_MEDIUM;
if (preply->cdb_len > 0)
cmd->cdb_len = preply->cdb_len;
if (preply->op_flags & SCST_INFO_VALID)
cmd->op_flags = preply->op_flags;
out_process:
scst_post_parse_process_active_cmd(cmd, false);

View File

@@ -4030,18 +4030,17 @@ int scst_get_cdb_info(struct scst_cmd *cmd)
}
if (unlikely(ptr == NULL)) {
/* opcode not found or now not used !!! */
TRACE(TRACE_SCSI, "Unknown opcode 0x%x for type %d", op,
/* opcode not found or now not used */
TRACE(TRACE_MINOR, "Unknown opcode 0x%x for type %d", op,
dev_type);
res = -1;
cmd->op_flags = SCST_INFO_NOT_FOUND;
goto out;
}
cmd->cdb_len = SCST_GET_CDB_LEN(op);
cmd->op_name = ptr->op_name;
cmd->data_direction = ptr->direction;
cmd->op_flags = ptr->flags;
cmd->op_flags = ptr->flags | SCST_INFO_VALID;
res = (*ptr->get_trans_len)(cmd, ptr->off);
out:

View File

@@ -93,18 +93,27 @@ struct scst_cmd *scst_rx_cmd(struct scst_session *sess,
cmd->tgt = sess->tgt;
cmd->tgtt = sess->tgt->tgtt;
/*
* For both wrong lun and CDB defer the error reporting for
* scst_cmd_init_done()
*/
cmd->lun = scst_unpack_lun(lun, lun_len);
if (cdb_len <= SCST_MAX_CDB_SIZE) {
memcpy(cmd->cdb, cdb, cdb_len);
cmd->cdb_len = cdb_len;
if (unlikely(cmd->lun == NO_SUCH_LUN)) {
PRINT_ERROR("Wrong LUN %d, finishing cmd", -1);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_lun_not_supported));
}
/*
* For cdb_len 0 defer the error reporting until scst_cmd_init_done(),
* scst_set_cmd_error() supports nested calls.
*/
if (unlikely(cdb_len > SCST_MAX_CDB_SIZE)) {
PRINT_ERROR("Too big CDB len %d, finishing cmd", cdb_len);
cdb_len = SCST_MAX_CDB_SIZE;
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_message));
}
memcpy(cmd->cdb, cdb, cdb_len);
cmd->cdb_len = cdb_len;
TRACE_DBG("cmd %p, sess %p", cmd, sess);
scst_sess_get(sess);
@@ -261,16 +270,8 @@ void scst_cmd_init_done(struct scst_cmd *cmd,
spin_unlock_irqrestore(&sess->sess_list_lock, flags);
if (unlikely(cmd->lun == NO_SUCH_LUN)) {
PRINT_ERROR("Wrong LUN %d, finishing cmd", -1);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_lun_not_supported));
scst_set_cmd_abnormal_done_state(cmd);
goto active;
}
if (unlikely(cmd->cdb_len == 0)) {
PRINT_ERROR("%s", "Wrong CDB len, finishing cmd");
PRINT_ERROR("%s", "Wrong CDB len 0, finishing cmd");
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_opcode));
scst_set_cmd_abnormal_done_state(cmd);
@@ -281,7 +282,6 @@ void scst_cmd_init_done(struct scst_cmd *cmd,
PRINT_ERROR("Unsupported queue type %d", cmd->queue_type);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_message));
scst_set_cmd_abnormal_done_state(cmd);
goto active;
}
@@ -358,95 +358,38 @@ static int scst_pre_parse(struct scst_cmd *cmd)
if (unlikely(rc != 0)) {
if (rc > 0) {
PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
goto out_xmit;
goto out_err;
}
EXTRACHECKS_BUG_ON(cmd->op_flags & SCST_INFO_VALID);
cmd->cdb_len = scst_get_cdb_len(cmd->cdb);
TRACE(TRACE_MINOR, "Unknown opcode 0x%02x for %s. "
"Should you update scst_scsi_op_table?",
cmd->cdb[0], dev->handler->name);
PRINT_BUFF_FLAG(TRACE_MINOR, "Failed CDB", cmd->cdb,
cmd->cdb_len);
#ifdef CONFIG_SCST_USE_EXPECTED_VALUES
if (scst_cmd_is_expected_set(cmd)) {
TRACE(TRACE_SCSI, "Using initiator supplied values: "
"direction %d, transfer_len %d",
cmd->expected_data_direction,
cmd->expected_transfer_len);
cmd->data_direction = cmd->expected_data_direction;
cmd->bufflen = cmd->expected_transfer_len;
/* Restore (possibly) lost CDB length */
cmd->cdb_len = scst_get_cdb_len(cmd->cdb);
if (cmd->cdb_len == -1) {
PRINT_ERROR("Unable to get CDB length for "
"opcode 0x%02x. Returning INVALID "
"OPCODE", cmd->cdb[0]);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_opcode));
goto out_xmit;
}
} else {
PRINT_ERROR("Unknown opcode 0x%02x for %s and "
"target %s not supplied expected values",
cmd->cdb[0], dev->handler->name, cmd->tgtt->name);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_opcode));
goto out_xmit;
}
#else
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_opcode));
goto out_xmit;
#endif
} else {
TRACE(TRACE_SCSI, "op_name <%s> (cmd %p), direction=%d "
"(expected %d, set %s), transfer_len=%d (expected "
"len %d), flags=%d", cmd->op_name, cmd,
cmd->data_direction, cmd->expected_data_direction,
scst_cmd_is_expected_set(cmd) ? "yes" : "no",
cmd->bufflen, cmd->expected_transfer_len,
cmd->op_flags);
if (unlikely((cmd->op_flags & SCST_UNKNOWN_LENGTH) != 0)) {
if (scst_cmd_is_expected_set(cmd)) {
/*
* Command data length can't be easily
* determined from the CDB. ToDo, all such
* commands processing should be fixed. Until
* it's done, get the length from the supplied
* expected value, but limit it to some
* reasonable value (15MB).
*/
cmd->bufflen = min(cmd->expected_transfer_len,
15*1024*1024);
cmd->op_flags &= ~SCST_UNKNOWN_LENGTH;
} else
cmd->bufflen = 0;
}
}
if (unlikely(cmd->cdb[cmd->cdb_len - 1] & CONTROL_BYTE_NACA_BIT)) {
PRINT_ERROR("NACA bit in control byte CDB is not supported "
"(opcode 0x%02x)", cmd->cdb[0]);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
goto out_xmit;
}
if (unlikely(cmd->cdb[cmd->cdb_len - 1] & CONTROL_BYTE_LINK_BIT)) {
PRINT_ERROR("Linked commands are not supported "
"(opcode 0x%02x)", cmd->cdb[0]);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
goto out_xmit;
EXTRACHECKS_BUG_ON(!(cmd->op_flags & SCST_INFO_VALID));
}
cmd->state = SCST_CMD_STATE_DEV_PARSE;
TRACE_DBG("op_name <%s> (cmd %p), direction=%d "
"(expected %d, set %s), transfer_len=%d (expected "
"len %d), flags=%d", cmd->op_name, cmd,
cmd->data_direction, cmd->expected_data_direction,
scst_cmd_is_expected_set(cmd) ? "yes" : "no",
cmd->bufflen, cmd->expected_transfer_len,
cmd->op_flags);
out:
TRACE_EXIT_RES(res);
return res;
out_xmit:
out_err:
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_cmd_abnormal_done_state(cmd);
res = SCST_CMD_STATE_RES_CONT_SAME;
goto out;
@@ -457,22 +400,21 @@ static bool scst_is_allowed_to_mismatch_cmd(struct scst_cmd *cmd)
{
bool res = false;
/* VERIFY commands with BYTCHK unset shouldn't fail here */
if ((cmd->op_flags & SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED) &&
(cmd->cdb[1] & BYTCHK) == 0) {
res = true;
goto out;
}
switch (cmd->cdb[0]) {
case TEST_UNIT_READY:
/* Crazy VMware people sometimes do TUR with READ direction */
res = true;
break;
case VERIFY:
case VERIFY_6:
case VERIFY_12:
case VERIFY_16:
/* VERIFY commands with BYTCHK unset shouldn't fail here */
if ((cmd->op_flags & SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED) &&
(cmd->cdb[1] & BYTCHK) == 0)
res = true;
break;
}
out:
return res;
}
#endif
@@ -490,7 +432,7 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
if (unlikely(!dev->handler->parse_atomic &&
scst_cmd_atomic(cmd))) {
/*
* It shouldn't be because of SCST_TGT_DEV_AFTER_*
* It shouldn't be because of the SCST_TGT_DEV_AFTER_*
* optimization.
*/
TRACE_DBG("Dev handler %s parse() needs thread "
@@ -531,15 +473,90 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
} else
state = SCST_CMD_STATE_PREPARE_SPACE;
if (cmd->data_len == -1)
cmd->data_len = cmd->bufflen;
if (unlikely(state == SCST_CMD_STATE_PRE_XMIT_RESP))
goto set_res;
if (cmd->bufflen == 0) {
/*
* According to SPC bufflen 0 for data transfer commands isn't
* an error, so we need to fix the transfer direction.
*/
cmd->data_direction = SCST_DATA_NONE;
if (unlikely(!(cmd->op_flags & SCST_INFO_VALID))) {
#ifdef CONFIG_SCST_USE_EXPECTED_VALUES
if (scst_cmd_is_expected_set(cmd)) {
TRACE(TRACE_MINOR, "Using initiator supplied values: "
"direction %d, transfer_len %d",
cmd->expected_data_direction,
cmd->expected_transfer_len);
cmd->data_direction = cmd->expected_data_direction;
cmd->bufflen = cmd->expected_transfer_len;
} else {
PRINT_ERROR("Unknown opcode 0x%02x for %s and "
"target %s not supplied expected values",
cmd->cdb[0], dev->handler->name, cmd->tgtt->name);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_opcode));
goto out_done;
}
#else
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_opcode));
goto out_done;
#endif
}
if (unlikely(cmd->cdb_len == -1)) {
PRINT_ERROR("Unable to get CDB length for "
"opcode 0x%02x. Returning INVALID "
"OPCODE", cmd->cdb[0]);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_opcode));
goto out_done;
}
EXTRACHECKS_BUG_ON(cmd->cdb_len == 0);
TRACE(TRACE_SCSI, "op_name <%s> (cmd %p), direction=%d "
"(expected %d, set %s), transfer_len=%d (expected "
"len %d), flags=%d", cmd->op_name, cmd,
cmd->data_direction, cmd->expected_data_direction,
scst_cmd_is_expected_set(cmd) ? "yes" : "no",
cmd->bufflen, cmd->expected_transfer_len,
cmd->op_flags);
if (unlikely((cmd->op_flags & SCST_UNKNOWN_LENGTH) != 0)) {
if (scst_cmd_is_expected_set(cmd)) {
/*
* Command data length can't be easily
* determined from the CDB. ToDo, all such
* commands processing should be fixed. Until
* it's done, get the length from the supplied
* expected value, but limit it to some
* reasonable value (15MB).
*/
cmd->bufflen = min(cmd->expected_transfer_len,
15*1024*1024);
cmd->op_flags &= ~SCST_UNKNOWN_LENGTH;
} else {
PRINT_ERROR("Unknown data transfer length for opcode "
"0x%x (handler %s, target %s)", cmd->cdb[0],
dev->handler->name, cmd->tgtt->name);
PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_message));
goto out_done;
}
}
if (unlikely(cmd->cdb[cmd->cdb_len - 1] & CONTROL_BYTE_NACA_BIT)) {
PRINT_ERROR("NACA bit in control byte CDB is not supported "
"(opcode 0x%02x)", cmd->cdb[0]);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
goto out_done;
}
if (unlikely(cmd->cdb[cmd->cdb_len - 1] & CONTROL_BYTE_LINK_BIT)) {
PRINT_ERROR("Linked commands are not supported "
"(opcode 0x%02x)", cmd->cdb[0]);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
goto out_done;
}
if (cmd->dh_data_buf_alloced &&
@@ -548,19 +565,7 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
"is less, than required (size %d)", cmd->bufflen,
orig_bufflen);
PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
goto out_error;
}
if (unlikely(state == SCST_CMD_STATE_PRE_XMIT_RESP))
goto set_res;
if (unlikely((cmd->bufflen == 0) &&
(cmd->op_flags & SCST_UNKNOWN_LENGTH))) {
PRINT_ERROR("Unknown data transfer length for opcode 0x%x "
"(handler %s, target %s)", cmd->cdb[0],
dev->handler->name, cmd->tgtt->name);
PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
goto out_error;
goto out_hw_error;
}
#ifdef CONFIG_SCST_EXTRACHECKS
@@ -573,7 +578,7 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
cmd->data_direction, cmd->bufflen, state, cmd->sg,
cmd->cdb[0]);
PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
goto out_error;
goto out_hw_error;
}
#endif
@@ -582,14 +587,15 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
# ifdef CONFIG_SCST_EXTRACHECKS
if ((cmd->data_direction != cmd->expected_data_direction) ||
(cmd->bufflen != cmd->expected_transfer_len)) {
PRINT_WARNING("Expected values don't match decoded "
"ones: data_direction %d, "
TRACE(TRACE_MINOR, "Expected values don't match "
"decoded ones: data_direction %d, "
"expected_data_direction %d, "
"bufflen %d, expected_transfer_len %d",
cmd->data_direction,
cmd->expected_data_direction,
cmd->bufflen, cmd->expected_transfer_len);
PRINT_BUFFER("Suspicious CDB", cmd->cdb, cmd->cdb_len);
PRINT_BUFF_FLAG(TRACE_MINOR, "Suspicious CDB",
cmd->cdb, cmd->cdb_len);
}
# endif
cmd->data_direction = cmd->expected_data_direction;
@@ -606,11 +612,11 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
cmd->expected_data_direction,
cmd->cdb[0], dev->handler->name,
cmd->tgtt->name, cmd->data_direction);
PRINT_BUFFER("Failed CDB",
cmd->cdb, cmd->cdb_len);
PRINT_BUFFER("Failed CDB", cmd->cdb,
cmd->cdb_len);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_message));
goto out_dev_done;
goto out_done;
}
}
if (unlikely(cmd->bufflen != cmd->expected_transfer_len)) {
@@ -634,10 +640,21 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
"target %s", cmd->cdb[0], dev->handler->name,
cmd->tgtt->name);
PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
goto out_error;
goto out_hw_error;
}
set_res:
if (cmd->data_len == -1)
cmd->data_len = cmd->bufflen;
if (cmd->bufflen == 0) {
/*
* According to SPC bufflen 0 for data transfer commands isn't
* an error, so we need to fix the transfer direction.
*/
cmd->data_direction = SCST_DATA_NONE;
}
#ifdef CONFIG_SCST_EXTRACHECKS
switch (state) {
case SCST_CMD_STATE_PREPARE_SPACE:
@@ -670,7 +687,7 @@ set_res:
"error %d (opcode %d)", dev->handler->name,
state, cmd->cdb[0]);
}
goto out_error;
goto out_hw_error;
}
#endif
@@ -681,18 +698,20 @@ set_res:
cmd->resp_data_len = 0;
}
/* We already completed (with an error) */
if (unlikely(cmd->completed))
goto out_done;
out:
TRACE_EXIT_HRES(res);
return res;
out_error:
out_hw_error:
/* dev_done() will be called as part of the regular cmd's finish */
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
#ifndef CONFIG_SCST_USE_EXPECTED_VALUES
out_dev_done:
#endif
cmd->state = SCST_CMD_STATE_PRE_DEV_DONE;
out_done:
scst_set_cmd_abnormal_done_state(cmd);
res = SCST_CMD_STATE_RES_CONT_SAME;
goto out;
}
@@ -915,7 +934,7 @@ static int scst_rdy_to_xfer(struct scst_cmd *cmd)
if (unlikely(!tgtt->rdy_to_xfer_atomic && scst_cmd_atomic(cmd))) {
/*
* It shouldn't be because of SCST_TGT_DEV_AFTER_*
* It shouldn't be because of the SCST_TGT_DEV_AFTER_*
* optimization.
*/
TRACE_DBG("Target driver %s rdy_to_xfer() needs thread "
@@ -1976,7 +1995,7 @@ static int scst_do_real_exec(struct scst_cmd *cmd)
if (handler->exec) {
if (unlikely(!dev->handler->exec_atomic && atomic)) {
/*
* It shouldn't be because of SCST_TGT_DEV_AFTER_*
* It shouldn't be because of the SCST_TGT_DEV_AFTER_*
* optimization.
*/
TRACE_DBG("Dev handler %s exec() needs thread "
@@ -2762,7 +2781,7 @@ static int scst_dev_done(struct scst_cmd *cmd)
if (unlikely(!dev->handler->dev_done_atomic &&
scst_cmd_atomic(cmd))) {
/*
* It shouldn't be because of SCST_TGT_DEV_AFTER_*
* It shouldn't be because of the SCST_TGT_DEV_AFTER_*
* optimization.
*/
TRACE_DBG("Dev handler %s dev_done() needs thread "
@@ -2931,7 +2950,7 @@ static int scst_xmit_response(struct scst_cmd *cmd)
if (unlikely(!tgtt->xmit_response_atomic &&
scst_cmd_atomic(cmd))) {
/*
* It shouldn't be because of SCST_TGT_DEV_AFTER_*
* It shouldn't be because of the SCST_TGT_DEV_AFTER_*
* optimization.
*/
TRACE_DBG("Target driver %s xmit_response() needs thread "

View File

@@ -191,6 +191,8 @@ static int do_parse(struct vdisk_cmd *vcmd)
reply->data_direction = cmd->expected_data_direction;
reply->data_len = cmd->expected_transfer_len;
reply->bufflen = cmd->expected_transfer_len;
reply->cdb_len = cmd->cdb_len;
reply->op_flags = reply->op_flags;
out:
TRACE_EXIT_RES(res);