mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-22 05:01:27 +00:00
- Fixes wrongly set context in scst_tgt_cmd_done()
- Fixes retries for stateful devices git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@22 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -227,10 +227,9 @@
|
||||
#define SCST_DEV_TM_NOT_COMPLETED 1
|
||||
|
||||
/*************************************************************
|
||||
** Default timeout and retries count for cmd's CDB execution
|
||||
** by SCSI mid-level (cmd's "timeout" and "retries" fields).
|
||||
** Default timeout for cmd's CDB execution
|
||||
** by SCSI mid-level (cmd's "timeout" field).
|
||||
*************************************************************/
|
||||
#define SCST_DEFAULT_RETRIES 5
|
||||
#define SCST_DEFAULT_TIMEOUT (30*HZ)
|
||||
|
||||
/*************************************************************
|
||||
|
||||
@@ -141,6 +141,8 @@ int changer_parse(struct scst_cmd *cmd, const struct scst_info_cdb *info_cdb)
|
||||
* based on info_cdb, therefore change them only if necessary
|
||||
*/
|
||||
|
||||
cmd->retries = 1;
|
||||
|
||||
if (info_cdb->flags & SCST_LONG_TIMEOUT) {
|
||||
cmd->timeout = CHANGER_LONG_TIMEOUT;
|
||||
} else {
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
exec: disk_exec, \
|
||||
}
|
||||
|
||||
#define DISK_RETRIES 2
|
||||
#define DISK_RETRIES 5
|
||||
#define DISK_SMALL_TIMEOUT (3 * HZ)
|
||||
#define DISK_REG_TIMEOUT (60 * HZ)
|
||||
#define DISK_LONG_TIMEOUT (3600 * HZ)
|
||||
@@ -294,6 +294,8 @@ int disk_parse(struct scst_cmd *cmd, const struct scst_info_cdb *info_cdb)
|
||||
* based on info_cdb, therefore change them only if necessary
|
||||
*/
|
||||
|
||||
cmd->retries = DISK_RETRIES;
|
||||
|
||||
if (info_cdb->flags & SCST_SMALL_TIMEOUT) {
|
||||
cmd->timeout = DISK_SMALL_TIMEOUT;
|
||||
} else if (info_cdb->flags & SCST_LONG_TIMEOUT) {
|
||||
|
||||
@@ -1725,7 +1725,7 @@ static void fileio_exec_read_capacity16(struct scst_cmd *cmd)
|
||||
nblocks = virt_dev->nblocks;
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
data64 = (uint64_t *)buffer;
|
||||
data64 = (uint64_t*)buffer;
|
||||
data64[0] = cpu_to_be64(nblocks - 1);
|
||||
buffer[8] = (blocksize >> (BYTE * 3)) & 0xFF;
|
||||
buffer[9] = (blocksize >> (BYTE * 2)) & 0xFF;
|
||||
|
||||
@@ -141,6 +141,8 @@ int processor_parse(struct scst_cmd *cmd, const struct scst_info_cdb *info_cdb)
|
||||
* based on info_cdb, therefore change them only if necessary
|
||||
*/
|
||||
|
||||
cmd->retries = 1;
|
||||
|
||||
if (info_cdb->flags & SCST_LONG_TIMEOUT) {
|
||||
cmd->timeout = PROCESSOR_LONG_TIMEOUT;
|
||||
} else {
|
||||
|
||||
@@ -141,6 +141,8 @@ int raid_parse(struct scst_cmd *cmd, const struct scst_info_cdb *info_cdb)
|
||||
* based on info_cdb, therefore change them only if necessary
|
||||
*/
|
||||
|
||||
cmd->retries = 1;
|
||||
|
||||
if (info_cdb->flags & SCST_LONG_TIMEOUT) {
|
||||
cmd->timeout = RAID_LONG_TIMEOUT;
|
||||
} else {
|
||||
|
||||
@@ -305,6 +305,8 @@ int tape_parse(struct scst_cmd *cmd, const struct scst_info_cdb *info_cdb)
|
||||
* based on info_cdb, therefore change them only if necessary
|
||||
*/
|
||||
|
||||
cmd->retries = 1;
|
||||
|
||||
if (info_cdb->flags & SCST_SMALL_TIMEOUT) {
|
||||
cmd->timeout = TAPE_SMALL_TIMEOUT;
|
||||
} else if (info_cdb->flags & SCST_LONG_TIMEOUT) {
|
||||
|
||||
@@ -949,7 +949,7 @@ struct scst_cmd *scst_alloc_cmd(int gfp_mask)
|
||||
|
||||
cmd->queue_type = SCST_CMD_QUEUE_UNTAGGED;
|
||||
cmd->timeout = SCST_DEFAULT_TIMEOUT;
|
||||
cmd->retries = SCST_DEFAULT_RETRIES;
|
||||
cmd->retries = 1;
|
||||
cmd->data_len = -1;
|
||||
cmd->tgt_resp_flags = SCST_TSC_FLAG_STATUS;
|
||||
cmd->resp_data_len = -1;
|
||||
|
||||
@@ -102,9 +102,15 @@
|
||||
#define SCST_CMD_MEM_TIMEOUT (120*HZ)
|
||||
|
||||
static inline int scst_get_context(void) {
|
||||
/* Be overinsured */
|
||||
return (in_atomic() || in_interrupt()) ? SCST_CONTEXT_DIRECT_ATOMIC :
|
||||
SCST_CONTEXT_DIRECT;
|
||||
if (in_irq())
|
||||
return SCST_CONTEXT_TASKLET;
|
||||
if (in_softirq())
|
||||
return SCST_CONTEXT_DIRECT_ATOMIC;
|
||||
if (in_interrupt()) /* Is it possible? */
|
||||
return SCST_CONTEXT_THREAD;
|
||||
if (in_atomic())
|
||||
return SCST_CONTEXT_DIRECT_ATOMIC;
|
||||
return SCST_CONTEXT_DIRECT;
|
||||
}
|
||||
|
||||
#define SCST_MGMT_CMD_CACHE_STRING "scst_mgmt_cmd"
|
||||
@@ -250,6 +256,8 @@ static inline void scst_destroy_cmd(struct scst_cmd *cmd)
|
||||
return;
|
||||
}
|
||||
|
||||
void scst_proccess_redirect_cmd(struct scst_cmd *cmd, int context,
|
||||
int check_retries);
|
||||
void scst_check_retries(struct scst_tgt *tgt, int processible_env);
|
||||
void scst_tgt_retry_timer_fn(unsigned long arg);
|
||||
|
||||
|
||||
@@ -744,12 +744,65 @@ out_dev_done:
|
||||
goto out;
|
||||
}
|
||||
|
||||
void scst_rx_data(struct scst_cmd *cmd, int status, int pref_context)
|
||||
void scst_proccess_redirect_cmd(struct scst_cmd *cmd, int context,
|
||||
int check_retries)
|
||||
{
|
||||
unsigned long flags;
|
||||
int rc;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
TRACE_DBG("Context: %d", context);
|
||||
|
||||
switch(context) {
|
||||
case SCST_CONTEXT_DIRECT:
|
||||
case SCST_CONTEXT_DIRECT_ATOMIC:
|
||||
if (check_retries)
|
||||
scst_check_retries(cmd->tgt, 0);
|
||||
cmd->non_atomic_only = 0;
|
||||
rc = __scst_process_active_cmd(cmd, context, 0);
|
||||
if (rc == SCST_CMD_STATE_RES_NEED_THREAD)
|
||||
goto out_thread;
|
||||
break;
|
||||
|
||||
default:
|
||||
PRINT_ERROR_PR("Context %x is unknown, using the thread one",
|
||||
context);
|
||||
/* go through */
|
||||
case SCST_CONTEXT_THREAD:
|
||||
if (check_retries)
|
||||
scst_check_retries(cmd->tgt, 1);
|
||||
goto out_thread;
|
||||
|
||||
case SCST_CONTEXT_TASKLET:
|
||||
if (check_retries)
|
||||
scst_check_retries(cmd->tgt, 1);
|
||||
cmd->non_atomic_only = 0;
|
||||
spin_lock_irqsave(&scst_list_lock, flags);
|
||||
TRACE_DBG("Moving cmd %p to active cmd list", cmd);
|
||||
list_move_tail(&cmd->cmd_list_entry, &scst_active_cmd_list);
|
||||
spin_unlock_irqrestore(&scst_list_lock, flags);
|
||||
scst_schedule_tasklet();
|
||||
break;
|
||||
}
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
|
||||
out_thread:
|
||||
cmd->non_atomic_only = 1;
|
||||
spin_lock_irqsave(&scst_list_lock, flags);
|
||||
TRACE_DBG("Moving cmd %p to active cmd list", cmd);
|
||||
list_move_tail(&cmd->cmd_list_entry, &scst_active_cmd_list);
|
||||
spin_unlock_irqrestore(&scst_list_lock, flags);
|
||||
wake_up(&scst_list_waitQ);
|
||||
goto out;
|
||||
}
|
||||
|
||||
void scst_rx_data(struct scst_cmd *cmd, int status, int pref_context)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
TRACE_DBG("Preferred context: %d", pref_context);
|
||||
TRACE(TRACE_SCSI, "tag=%d status=%#x", scst_cmd_get_tag(cmd), status);
|
||||
cmd->non_atomic_only = 0;
|
||||
@@ -783,40 +836,12 @@ void scst_rx_data(struct scst_cmd *cmd, int status, int pref_context)
|
||||
|
||||
default:
|
||||
PRINT_ERROR_PR("scst_rx_data() received unknown status %x",
|
||||
status);
|
||||
status);
|
||||
cmd->state = SCST_CMD_STATE_DEV_DONE;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (pref_context) {
|
||||
case SCST_CONTEXT_DIRECT:
|
||||
case SCST_CONTEXT_DIRECT_ATOMIC:
|
||||
scst_check_retries(cmd->tgt, 0);
|
||||
__scst_process_active_cmd(cmd, pref_context, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
PRINT_ERROR_PR("Context %x is undefined, using thread one",
|
||||
pref_context);
|
||||
/* go through */
|
||||
case SCST_CONTEXT_THREAD:
|
||||
spin_lock_irqsave(&scst_list_lock, flags);
|
||||
TRACE_DBG("Moving cmd %p to active cmd list", cmd);
|
||||
list_move_tail(&cmd->cmd_list_entry, &scst_active_cmd_list);
|
||||
cmd->non_atomic_only = 1;
|
||||
spin_unlock_irqrestore(&scst_list_lock, flags);
|
||||
scst_check_retries(cmd->tgt, 1);
|
||||
wake_up(&scst_list_waitQ);
|
||||
break;
|
||||
|
||||
case SCST_CONTEXT_TASKLET:
|
||||
spin_lock_irqsave(&scst_list_lock, flags);
|
||||
TRACE_DBG("Moving cmd %p to active cmd list", cmd);
|
||||
list_move_tail(&cmd->cmd_list_entry, &scst_active_cmd_list);
|
||||
spin_unlock_irqrestore(&scst_list_lock, flags);
|
||||
scst_schedule_tasklet();
|
||||
scst_check_retries(cmd->tgt, 0);
|
||||
break;
|
||||
}
|
||||
scst_proccess_redirect_cmd(cmd, pref_context, 1);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
@@ -1088,7 +1113,7 @@ static void scst_cmd_done(struct scsi_cmnd *scsi_cmd)
|
||||
cmd->state = next_state;
|
||||
cmd->non_atomic_only = 0;
|
||||
|
||||
__scst_process_active_cmd(cmd, scst_get_context(), 0);
|
||||
scst_proccess_redirect_cmd(cmd, scst_get_context(), 0);
|
||||
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
@@ -1124,7 +1149,7 @@ static void scst_cmd_done(void *data, char *sense, int result, int resid)
|
||||
cmd->state = next_state;
|
||||
cmd->non_atomic_only = 0;
|
||||
|
||||
__scst_process_active_cmd(cmd, scst_get_context(), 0);
|
||||
scst_proccess_redirect_cmd(cmd, scst_get_context(), 0);
|
||||
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
@@ -1153,7 +1178,7 @@ static void scst_cmd_done_local(struct scst_cmd *cmd, int next_state)
|
||||
cmd->sg_cnt, sg, (void*)sg[0].page);
|
||||
for(i = 0; i < cmd->sg_cnt; ++i) {
|
||||
TRACE_BUFF_FLAG(TRACE_RECV_TOP,
|
||||
"Exec'd sg:", page_address(sg[i].page),
|
||||
"Exec'd sg", page_address(sg[i].page),
|
||||
sg[i].length);
|
||||
}
|
||||
}
|
||||
@@ -1184,7 +1209,7 @@ static void scst_cmd_done_local(struct scst_cmd *cmd, int next_state)
|
||||
cmd->state = next_state;
|
||||
cmd->non_atomic_only = 0;
|
||||
|
||||
__scst_process_active_cmd(cmd, scst_get_context(), 0);
|
||||
scst_proccess_redirect_cmd(cmd, scst_get_context(), 0);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
@@ -2175,7 +2200,7 @@ static int scst_xmit_response(struct scst_cmd *cmd)
|
||||
cmd->sg_cnt, sg, (void*)sg[0].page);
|
||||
for(i = 0; i < cmd->sg_cnt; ++i) {
|
||||
TRACE_BUFF_FLAG(TRACE_SEND_BOT,
|
||||
"Xmitting sg:", page_address(sg[i].page),
|
||||
"Xmitting sg", page_address(sg[i].page),
|
||||
sg[i].length);
|
||||
}
|
||||
}
|
||||
@@ -2277,47 +2302,12 @@ static int scst_finish_cmd(struct scst_cmd *cmd)
|
||||
|
||||
void scst_tgt_cmd_done(struct scst_cmd *cmd)
|
||||
{
|
||||
int res = 0;
|
||||
unsigned long flags;
|
||||
int context;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
BUG_ON(cmd->state != SCST_CMD_STATE_XMIT_WAIT);
|
||||
|
||||
if (in_irq())
|
||||
context = SCST_CONTEXT_TASKLET;
|
||||
else
|
||||
context = scst_get_context();
|
||||
|
||||
TRACE_DBG("Context: %d", context);
|
||||
cmd->non_atomic_only = 0;
|
||||
cmd->state = SCST_CMD_STATE_FINISHED;
|
||||
|
||||
switch (context) {
|
||||
case SCST_CONTEXT_DIRECT:
|
||||
case SCST_CONTEXT_DIRECT_ATOMIC:
|
||||
flags = 0;
|
||||
scst_check_retries(cmd->tgt, 0);
|
||||
res = __scst_process_active_cmd(cmd, context, 0);
|
||||
BUG_ON(res == SCST_CMD_STATE_RES_NEED_THREAD);
|
||||
break;
|
||||
|
||||
case SCST_CONTEXT_TASKLET:
|
||||
{
|
||||
spin_lock_irqsave(&scst_list_lock, flags);
|
||||
TRACE_DBG("Moving cmd %p to active cmd list", cmd);
|
||||
list_move_tail(&cmd->cmd_list_entry, &scst_active_cmd_list);
|
||||
spin_unlock_irqrestore(&scst_list_lock, flags);
|
||||
scst_schedule_tasklet();
|
||||
scst_check_retries(cmd->tgt, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
BUG();
|
||||
break;
|
||||
}
|
||||
scst_proccess_redirect_cmd(cmd, scst_get_context(), 1);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
@@ -2577,6 +2567,14 @@ static void scst_do_job_active(struct list_head *active_cmd_list, int context)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
#ifdef EXTRACHECKS
|
||||
{
|
||||
int c = (context & ~SCST_PROCESSIBLE_ENV);
|
||||
WARN_ON((c != SCST_CONTEXT_DIRECT_ATOMIC) &&
|
||||
(c != SCST_CONTEXT_DIRECT));
|
||||
}
|
||||
#endif
|
||||
|
||||
tm_dbg_check_released_cmds();
|
||||
|
||||
restart:
|
||||
@@ -2649,7 +2647,7 @@ int scst_cmd_thread(void *arg)
|
||||
|
||||
scst_do_job_init(&scst_init_cmd_list);
|
||||
scst_do_job_active(&scst_active_cmd_list,
|
||||
SCST_CONTEXT_THREAD|SCST_PROCESSIBLE_ENV);
|
||||
SCST_CONTEXT_DIRECT|SCST_PROCESSIBLE_ENV);
|
||||
|
||||
if (unlikely(test_bit(SCST_FLAG_SHUTDOWN, &scst_flags)) &&
|
||||
list_empty(&scst_cmd_list) &&
|
||||
|
||||
Reference in New Issue
Block a user