- 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:
Vladislav Bolkhovitin
2010-04-28 13:05:18 +00:00
parent 57b5ed9895
commit 5a87f2af9e
6 changed files with 144 additions and 26 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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">&nbsp;</td></tr></table>
</div>