mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-21 12:41:26 +00:00
Minor extended CDBs handling cleanups and fixes
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@2351 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -2027,7 +2027,8 @@ static int scsi_cmnd_start(struct iscsi_cmnd *req)
|
||||
struct iscsi_cdb_ahdr *eca =
|
||||
(struct iscsi_cdb_ahdr *)ahdr;
|
||||
scst_cmd_set_ext_cdb(scst_cmd, eca->cdb,
|
||||
be16_to_cpu(ahdr->ahslength) - 1);
|
||||
be16_to_cpu(ahdr->ahslength) - 1,
|
||||
GFP_KERNEL);
|
||||
break;
|
||||
}
|
||||
s = 3 + be16_to_cpu(ahdr->ahslength);
|
||||
|
||||
@@ -2844,7 +2844,7 @@ static inline unsigned int scst_cmd_get_cdb_len(struct scst_cmd *cmd)
|
||||
}
|
||||
|
||||
void scst_cmd_set_ext_cdb(struct scst_cmd *cmd,
|
||||
uint8_t *ext_cdb, unsigned int ext_cdb_len);
|
||||
uint8_t *ext_cdb, unsigned int ext_cdb_len, gfp_t gfp_mask);
|
||||
|
||||
/* Returns cmd's session */
|
||||
static inline struct scst_session *scst_cmd_get_session(struct scst_cmd *cmd)
|
||||
|
||||
@@ -37,6 +37,9 @@
|
||||
/* Max size of CDB */
|
||||
#define SCST_MAX_CDB_SIZE 16
|
||||
|
||||
/* Max size of long CDB */
|
||||
#define SCST_MAX_LONG_CDB_SIZE 65536
|
||||
|
||||
/* Max size of various names */
|
||||
#define SCST_MAX_NAME 50
|
||||
|
||||
|
||||
@@ -3684,14 +3684,15 @@ int scst_acg_remove_name(struct scst_acg *acg, const char *name, bool reassign)
|
||||
#endif
|
||||
|
||||
static struct scst_cmd *scst_create_prepare_internal_cmd(
|
||||
struct scst_cmd *orig_cmd, int bufsize)
|
||||
struct scst_cmd *orig_cmd, const uint8_t *cdb,
|
||||
unsigned int cdb_len, int bufsize)
|
||||
{
|
||||
struct scst_cmd *res;
|
||||
gfp_t gfp_mask = scst_cmd_atomic(orig_cmd) ? GFP_ATOMIC : GFP_KERNEL;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
res = scst_alloc_cmd(gfp_mask);
|
||||
res = scst_alloc_cmd(cdb, cdb_len, gfp_mask);
|
||||
if (res == NULL)
|
||||
goto out;
|
||||
|
||||
@@ -3738,13 +3739,12 @@ int scst_prepare_request_sense(struct scst_cmd *orig_cmd)
|
||||
}
|
||||
|
||||
rs_cmd = scst_create_prepare_internal_cmd(orig_cmd,
|
||||
request_sense, sizeof(request_sense),
|
||||
SCST_SENSE_BUFFERSIZE);
|
||||
if (rs_cmd == NULL)
|
||||
goto out_error;
|
||||
|
||||
memcpy(rs_cmd->cdb, request_sense, sizeof(request_sense));
|
||||
rs_cmd->cdb[1] |= scst_get_cmd_dev_d_sense(orig_cmd);
|
||||
rs_cmd->cdb_len = sizeof(request_sense);
|
||||
rs_cmd->data_direction = SCST_DATA_READ;
|
||||
rs_cmd->expected_data_direction = rs_cmd->data_direction;
|
||||
rs_cmd->expected_transfer_len = SCST_SENSE_BUFFERSIZE;
|
||||
@@ -4155,16 +4155,28 @@ EXPORT_SYMBOL(scst_cmd_put);
|
||||
* scst_cmd_set_ext_cdb() - sets cmd's extended CDB and its length
|
||||
*/
|
||||
void scst_cmd_set_ext_cdb(struct scst_cmd *cmd,
|
||||
uint8_t *ext_cdb, unsigned int ext_cdb_len)
|
||||
uint8_t *ext_cdb, unsigned int ext_cdb_len,
|
||||
gfp_t gfp_mask)
|
||||
{
|
||||
unsigned int len = cmd->cdb_len + ext_cdb_len;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if ((cmd->cdb_len + ext_cdb_len) <= sizeof(cmd->cdb_buf))
|
||||
if (len <= sizeof(cmd->cdb_buf))
|
||||
goto copy;
|
||||
|
||||
cmd->cdb = kmalloc(cmd->cdb_len + ext_cdb_len, GFP_ATOMIC);
|
||||
if (cmd->cdb == NULL)
|
||||
if (unlikely(len > SCST_MAX_LONG_CDB_SIZE)) {
|
||||
PRINT_ERROR("Too big CDB (%d)", len);
|
||||
scst_set_cmd_error(cmd,
|
||||
SCST_LOAD_SENSE(scst_sense_hardw_error));
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd->cdb = kmalloc(len, gfp_mask);
|
||||
if (unlikely(cmd->cdb == NULL)) {
|
||||
PRINT_ERROR("Unable to alloc extended CDB (size %d)", len);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
memcpy(cmd->cdb, cmd->cdb_buf, cmd->cdb_len);
|
||||
|
||||
@@ -4184,7 +4196,8 @@ out_err:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_cmd_set_ext_cdb);
|
||||
|
||||
struct scst_cmd *scst_alloc_cmd(gfp_t gfp_mask)
|
||||
struct scst_cmd *scst_alloc_cmd(const uint8_t *cdb,
|
||||
unsigned int cdb_len, gfp_t gfp_mask)
|
||||
{
|
||||
struct scst_cmd *cmd;
|
||||
|
||||
@@ -4221,9 +4234,36 @@ struct scst_cmd *scst_alloc_cmd(gfp_t gfp_mask)
|
||||
cmd->dbl_ua_orig_data_direction = SCST_DATA_UNKNOWN;
|
||||
cmd->dbl_ua_orig_resp_data_len = -1;
|
||||
|
||||
if (unlikely(cdb_len == 0)) {
|
||||
PRINT_ERROR("%s", "Wrong CDB len 0, finishing cmd");
|
||||
goto out_free;
|
||||
} else if (cdb_len <= SCST_MAX_CDB_SIZE) {
|
||||
/* Duplicate memcpy to save a branch on the most common path */
|
||||
memcpy(cmd->cdb, cdb, cdb_len);
|
||||
} else {
|
||||
if (unlikely(cdb_len > SCST_MAX_LONG_CDB_SIZE)) {
|
||||
PRINT_ERROR("Too big CDB (%d), finishing cmd", cdb_len);
|
||||
goto out_free;
|
||||
}
|
||||
cmd->cdb = kmalloc(cdb_len, gfp_mask);
|
||||
if (unlikely(cmd->cdb == NULL)) {
|
||||
PRINT_ERROR("Unable to alloc extended CDB (size %d)",
|
||||
cdb_len);
|
||||
goto out_free;
|
||||
}
|
||||
memcpy(cmd->cdb, cdb, cdb_len);
|
||||
}
|
||||
|
||||
cmd->cdb_len = cdb_len;
|
||||
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
return cmd;
|
||||
|
||||
out_free:
|
||||
kmem_cache_free(scst_cmd_cachep, cmd);
|
||||
cmd = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
static void scst_destroy_put_cmd(struct scst_cmd *cmd)
|
||||
|
||||
@@ -363,7 +363,8 @@ struct scst_session *scst_alloc_session(struct scst_tgt *tgt, gfp_t gfp_mask,
|
||||
void scst_free_session(struct scst_session *sess);
|
||||
void scst_free_session_callback(struct scst_session *sess);
|
||||
|
||||
struct scst_cmd *scst_alloc_cmd(gfp_t gfp_mask);
|
||||
struct scst_cmd *scst_alloc_cmd(const uint8_t *cdb,
|
||||
unsigned int cdb_len, gfp_t gfp_mask);
|
||||
void scst_free_cmd(struct scst_cmd *cmd);
|
||||
static inline void scst_destroy_cmd(struct scst_cmd *cmd)
|
||||
{
|
||||
|
||||
@@ -127,8 +127,8 @@ struct scst_cmd *scst_rx_cmd(struct scst_session *sess,
|
||||
}
|
||||
#endif
|
||||
|
||||
cmd = scst_alloc_cmd(atomic ? GFP_ATOMIC : GFP_KERNEL);
|
||||
if (cmd == NULL)
|
||||
cmd = scst_alloc_cmd(cdb, cdb_len, atomic ? GFP_ATOMIC : GFP_KERNEL);
|
||||
if (unlikely(cmd == NULL))
|
||||
goto out;
|
||||
|
||||
cmd->sess = sess;
|
||||
@@ -142,20 +142,6 @@ struct scst_cmd *scst_rx_cmd(struct scst_session *sess,
|
||||
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);
|
||||
|
||||
@@ -337,12 +323,6 @@ void scst_cmd_init_done(struct scst_cmd *cmd,
|
||||
|
||||
spin_unlock_irqrestore(&sess->sess_list_lock, flags);
|
||||
|
||||
if (unlikely(cmd->cdb_len == 0)) {
|
||||
PRINT_ERROR("%s", "Wrong CDB len 0, finishing cmd");
|
||||
scst_set_cmd_error(cmd,
|
||||
SCST_LOAD_SENSE(scst_sense_invalid_opcode));
|
||||
}
|
||||
|
||||
if (unlikely(cmd->queue_type >= SCST_CMD_QUEUE_ACA)) {
|
||||
PRINT_ERROR("Unsupported queue type %d", cmd->queue_type);
|
||||
scst_set_cmd_error(cmd,
|
||||
|
||||
Reference in New Issue
Block a user