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:
Vladislav Bolkhovitin
2010-10-05 20:06:54 +00:00
parent 6d0fc28d20
commit d7e087e3b2
6 changed files with 59 additions and 34 deletions

View File

@@ -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);

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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)
{

View File

@@ -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,