mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-14 09:11:27 +00:00
- Unify unknown commands handling between kernel and user mode dev handlers. Particularly, new hook alloc_data_buf was added to struct scst_dev_type
- Minor web updates git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1661 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -971,6 +971,7 @@ struct scst_dev_type {
|
||||
* the atomic (non-sleeping) context
|
||||
*/
|
||||
unsigned parse_atomic:1;
|
||||
unsigned alloc_data_buf_atomic:1;
|
||||
unsigned exec_atomic:1;
|
||||
unsigned dev_done_atomic:1;
|
||||
|
||||
@@ -988,6 +989,7 @@ struct scst_dev_type {
|
||||
/*
|
||||
* Called to parse CDB from the cmd and initialize
|
||||
* cmd->bufflen and cmd->data_direction (both - REQUIRED).
|
||||
*
|
||||
* Returns the command's next state or SCST_CMD_STATE_DEFAULT,
|
||||
* if the next default state should be used, or
|
||||
* SCST_CMD_STATE_NEED_THREAD_CTX if the function called in atomic
|
||||
@@ -1004,6 +1006,26 @@ struct scst_dev_type {
|
||||
*/
|
||||
int (*parse) (struct scst_cmd *cmd);
|
||||
|
||||
/*
|
||||
* This function allows dev handler to handle data buffer
|
||||
* allocations on its own.
|
||||
*
|
||||
* Returns the command's next state or SCST_CMD_STATE_DEFAULT,
|
||||
* if the next default state should be used, or
|
||||
* SCST_CMD_STATE_NEED_THREAD_CTX if the function called in atomic
|
||||
* context, but requires sleeping, or SCST_CMD_STATE_STOP if the
|
||||
* command should not be further processed for now. In the
|
||||
* SCST_CMD_STATE_NEED_THREAD_CTX case the function
|
||||
* will be recalled in the thread context, where sleeping is allowed.
|
||||
*
|
||||
* Pay attention to "atomic" attribute of the cmd, which can be get
|
||||
* by scst_cmd_atomic(): it is true if the function called in the
|
||||
* atomic (non-sleeping) context.
|
||||
*
|
||||
* OPTIONAL
|
||||
*/
|
||||
int (*alloc_data_buf) (struct scst_cmd *cmd);
|
||||
|
||||
/*
|
||||
* Called to execute CDB. Useful, for instance, to implement
|
||||
* data caching. The result of CDB execution is reported via
|
||||
@@ -3153,7 +3175,9 @@ int scst_suspend_activity(bool interruptible);
|
||||
void scst_resume_activity(void);
|
||||
|
||||
void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic);
|
||||
void scst_post_parse_process_active_cmd(struct scst_cmd *cmd, bool atomic);
|
||||
|
||||
void scst_post_parse(struct scst_cmd *cmd);
|
||||
void scst_post_alloc_data_buf(struct scst_cmd *cmd);
|
||||
|
||||
int scst_check_local_events(struct scst_cmd *cmd);
|
||||
|
||||
|
||||
@@ -145,6 +145,7 @@ static struct scst_user_cmd *dev_user_alloc_ucmd(struct scst_user_dev *dev,
|
||||
static void dev_user_free_ucmd(struct scst_user_cmd *ucmd);
|
||||
|
||||
static int dev_user_parse(struct scst_cmd *cmd);
|
||||
static int dev_user_alloc_data_buf(struct scst_cmd *cmd);
|
||||
static int dev_user_exec(struct scst_cmd *cmd);
|
||||
static void dev_user_on_free_cmd(struct scst_cmd *cmd);
|
||||
static int dev_user_task_mgmt_fn(struct scst_mgmt_cmd *mcmd,
|
||||
@@ -777,14 +778,18 @@ static int dev_user_parse(struct scst_cmd *cmd)
|
||||
|
||||
TRACE_DBG("ucmd %p, cmd %p, state %x", ucmd, cmd, ucmd->state);
|
||||
|
||||
if (ucmd->state != UCMD_STATE_NEW)
|
||||
goto alloc;
|
||||
if (ucmd->state == UCMD_STATE_PARSING) {
|
||||
/* We've already done */
|
||||
goto done;
|
||||
}
|
||||
|
||||
EXTRACHECKS_BUG_ON(ucmd->state != UCMD_STATE_NEW);
|
||||
|
||||
switch (dev->parse_type) {
|
||||
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_VALID))
|
||||
if (rc != 0)
|
||||
goto out_invalid;
|
||||
break;
|
||||
|
||||
@@ -837,7 +842,7 @@ static int dev_user_parse(struct scst_cmd *cmd)
|
||||
goto out;
|
||||
}
|
||||
|
||||
alloc:
|
||||
done:
|
||||
if (cmd->bufflen == 0) {
|
||||
/*
|
||||
* According to SPC bufflen 0 for data transfer commands isn't
|
||||
@@ -846,9 +851,6 @@ alloc:
|
||||
cmd->data_direction = SCST_DATA_NONE;
|
||||
}
|
||||
|
||||
if (cmd->data_direction != SCST_DATA_NONE)
|
||||
res = dev_user_alloc_space(ucmd);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
@@ -862,6 +864,23 @@ out_error:
|
||||
goto out;
|
||||
}
|
||||
|
||||
static int dev_user_alloc_data_buf(struct scst_cmd *cmd)
|
||||
{
|
||||
int res = SCST_CMD_STATE_DEFAULT;
|
||||
struct scst_user_cmd *ucmd = (struct scst_user_cmd *)cmd->dh_priv;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
EXTRACHECKS_BUG_ON((ucmd->state != UCMD_STATE_NEW) &&
|
||||
(ucmd->state != UCMD_STATE_PARSING) &&
|
||||
(ucmd->state != UCMD_STATE_BUF_ALLOCING));
|
||||
|
||||
res = dev_user_alloc_space(ucmd);
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void dev_user_flush_dcache(struct scst_user_cmd *ucmd)
|
||||
{
|
||||
struct scst_user_cmd *buf_ucmd = ucmd->buf_ucmd;
|
||||
@@ -1234,7 +1253,8 @@ static int dev_user_process_reply_alloc(struct scst_user_cmd *ucmd,
|
||||
}
|
||||
|
||||
out_process:
|
||||
scst_post_parse_process_active_cmd(cmd, false);
|
||||
scst_post_alloc_data_buf(cmd);
|
||||
scst_process_active_cmd(cmd, false);
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
@@ -1294,7 +1314,8 @@ static int dev_user_process_reply_parse(struct scst_user_cmd *ucmd,
|
||||
cmd->op_flags = preply->op_flags;
|
||||
|
||||
out_process:
|
||||
scst_post_parse_process_active_cmd(cmd, false);
|
||||
scst_post_parse(cmd);
|
||||
scst_process_active_cmd(cmd, false);
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
@@ -2192,6 +2213,11 @@ static void dev_user_unjam_cmd(struct scst_user_cmd *ucmd, int busy,
|
||||
}
|
||||
scst_set_cmd_abnormal_done_state(ucmd->cmd);
|
||||
|
||||
if (state == UCMD_STATE_PARSING)
|
||||
scst_post_parse(ucmd->cmd);
|
||||
else
|
||||
scst_post_alloc_data_buf(ucmd->cmd);
|
||||
|
||||
TRACE_MGMT_DBG("Adding ucmd %p to active list", ucmd);
|
||||
list_add(&ucmd->cmd->cmd_list_entry,
|
||||
&ucmd->cmd->cmd_threads->active_cmd_list);
|
||||
@@ -2682,6 +2708,7 @@ static void dev_user_setup_functions(struct scst_user_dev *dev)
|
||||
TRACE_ENTRY();
|
||||
|
||||
dev->devtype.parse = dev_user_parse;
|
||||
dev->devtype.alloc_data_buf = dev_user_alloc_data_buf;
|
||||
dev->devtype.dev_done = NULL;
|
||||
|
||||
if (dev->parse_type != SCST_USER_PARSE_CALL) {
|
||||
@@ -2862,6 +2889,7 @@ static int dev_user_register_dev(struct file *file,
|
||||
dev->devtype.type = dev_desc->type;
|
||||
dev->devtype.threads_num = -1;
|
||||
dev->devtype.parse_atomic = 1;
|
||||
dev->devtype.alloc_data_buf_atomic = 1;
|
||||
dev->devtype.exec_atomic = 0; /* no point to make it 1 */
|
||||
dev->devtype.dev_done_atomic = 1;
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
|
||||
@@ -2841,6 +2841,7 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
|
||||
atomic_set(&tgt_dev->sn_slots[i], 0);
|
||||
|
||||
if (dev->handler->parse_atomic &&
|
||||
dev->handler->alloc_data_buf_atomic &&
|
||||
(sess->tgt->tgtt->preprocessing_done == NULL)) {
|
||||
if (sess->tgt->tgtt->rdy_to_xfer_atomic)
|
||||
__set_bit(SCST_TGT_DEV_AFTER_INIT_WR_ATOMIC,
|
||||
|
||||
@@ -963,6 +963,9 @@ static int scst_dev_handler_check(struct scst_dev_type *dev_handler)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (dev_handler->alloc_data_buf == NULL)
|
||||
dev_handler->alloc_data_buf_atomic = 1;
|
||||
|
||||
if (dev_handler->dev_done == NULL)
|
||||
dev_handler->dev_done_atomic = 1;
|
||||
|
||||
|
||||
@@ -51,6 +51,31 @@ static struct scst_cmd *__scst_find_cmd_by_tag(struct scst_session *sess,
|
||||
static void scst_process_redirect_cmd(struct scst_cmd *cmd,
|
||||
enum scst_exec_context context, int check_retries);
|
||||
|
||||
/**
|
||||
* scst_post_parse() - do post parse actions
|
||||
*
|
||||
* This function must be called by dev handler after its parse() callback
|
||||
* returned SCST_CMD_STATE_STOP before calling scst_process_active_cmd().
|
||||
*/
|
||||
void scst_post_parse(struct scst_cmd *cmd)
|
||||
{
|
||||
scst_set_parse_time(cmd);
|
||||
}
|
||||
EXPORT_SYMBOL(scst_post_parse);
|
||||
|
||||
/**
|
||||
* scst_post_alloc_data_buf() - do post alloc_data_buf actions
|
||||
*
|
||||
* This function must be called by dev handler after its alloc_data_buf()
|
||||
* callback returned SCST_CMD_STATE_STOP before calling
|
||||
* scst_process_active_cmd().
|
||||
*/
|
||||
void scst_post_alloc_data_buf(struct scst_cmd *cmd)
|
||||
{
|
||||
scst_set_alloc_buf_time(cmd);
|
||||
}
|
||||
EXPORT_SYMBOL(scst_post_alloc_data_buf);
|
||||
|
||||
static inline void scst_schedule_tasklet(struct scst_cmd *cmd)
|
||||
{
|
||||
struct scst_tasklet *t = &scst_tasklets[smp_processor_id()];
|
||||
@@ -762,12 +787,62 @@ out_done:
|
||||
static int scst_prepare_space(struct scst_cmd *cmd)
|
||||
{
|
||||
int r = 0, res = SCST_CMD_STATE_RES_CONT_SAME;
|
||||
struct scst_device *dev = cmd->dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (cmd->data_direction == SCST_DATA_NONE)
|
||||
goto done;
|
||||
|
||||
if (likely(!scst_is_cmd_fully_local(cmd)) &&
|
||||
(dev->handler->alloc_data_buf != NULL)) {
|
||||
int state;
|
||||
|
||||
if (unlikely(!dev->handler->alloc_data_buf_atomic &&
|
||||
scst_cmd_atomic(cmd))) {
|
||||
/*
|
||||
* It shouldn't be because of the SCST_TGT_DEV_AFTER_*
|
||||
* optimization.
|
||||
*/
|
||||
TRACE_DBG("Dev handler %s alloc_data_buf() needs "
|
||||
"thread context, rescheduling",
|
||||
dev->handler->name);
|
||||
res = SCST_CMD_STATE_RES_NEED_THREAD;
|
||||
goto out;
|
||||
}
|
||||
|
||||
TRACE_DBG("Calling dev handler %s alloc_data_buf(%p)",
|
||||
dev->handler->name, cmd);
|
||||
scst_set_cur_start(cmd);
|
||||
state = dev->handler->alloc_data_buf(cmd);
|
||||
/* Caution: cmd can be already dead here */
|
||||
TRACE_DBG("Dev handler %s alloc_data_buf() returned %d",
|
||||
dev->handler->name, state);
|
||||
|
||||
switch (state) {
|
||||
case SCST_CMD_STATE_NEED_THREAD_CTX:
|
||||
scst_set_alloc_buf_time(cmd);
|
||||
TRACE_DBG("Dev handler %s alloc_data_buf() requested "
|
||||
"thread context, rescheduling",
|
||||
dev->handler->name);
|
||||
res = SCST_CMD_STATE_RES_NEED_THREAD;
|
||||
goto out;
|
||||
|
||||
case SCST_CMD_STATE_STOP:
|
||||
TRACE_DBG("Dev handler %s alloc_data_buf() requested "
|
||||
"stop processing", dev->handler->name);
|
||||
res = SCST_CMD_STATE_RES_CONT_NEXT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
scst_set_alloc_buf_time(cmd);
|
||||
|
||||
if (unlikely(state != SCST_CMD_STATE_DEFAULT)) {
|
||||
cmd->state = state;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd->tgt_need_alloc_data_buf) {
|
||||
int orig_bufflen = cmd->bufflen;
|
||||
|
||||
@@ -3800,20 +3875,6 @@ void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic)
|
||||
}
|
||||
EXPORT_SYMBOL(scst_process_active_cmd);
|
||||
|
||||
/**
|
||||
* scst_post_parse_process_active_cmd() - process command after parse
|
||||
*
|
||||
* SCST commands processing routine, which should be called by dev handler
|
||||
* after its parse() callback returned SCST_CMD_STATE_STOP. Arguments are
|
||||
* the same as for scst_process_active_cmd().
|
||||
*/
|
||||
void scst_post_parse_process_active_cmd(struct scst_cmd *cmd, bool atomic)
|
||||
{
|
||||
scst_set_parse_time(cmd);
|
||||
scst_process_active_cmd(cmd, atomic);
|
||||
}
|
||||
EXPORT_SYMBOL(scst_post_parse_process_active_cmd);
|
||||
|
||||
/* Called under cmd_list_lock and IRQs disabled */
|
||||
static void scst_do_job_active(struct list_head *cmd_list,
|
||||
spinlock_t *cmd_list_lock, bool atomic)
|
||||
|
||||
@@ -135,8 +135,9 @@
|
||||
made using SCST SRP target by <strong>Hewlett Packard</strong> and <strong>Oracle</strong>.</p>
|
||||
|
||||
<p>If your company is using SCST in its products, solutions or internal storage infrastructure,
|
||||
please contact vst at vlnb net and we will list you on this page. This is the least appreciation
|
||||
your company can do for SCST.</p>
|
||||
please contact vst at vlnb net and we will be proud to add you on this page. Also, if your company has certified its
|
||||
SCST-powered product or solution, we will be proud to write on our pages that SCST engine has successfully
|
||||
passed the certification tests. This is the least appreciation your company can do for SCST.</p>
|
||||
|
||||
<table border=0><tr><td height="15px"> </td></tr></table>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user