Merge branch 'svn-trunk'

This commit is contained in:
Bart Van Assche
2019-02-11 19:41:46 -08:00

View File

@@ -5036,6 +5036,88 @@ static int scst_translate_lun(struct scst_cmd *cmd)
return res;
}
static void scst_handle_aca(struct scst_cmd *cmd)
{
struct scst_order_data *order_data = cmd->cur_order_data;
unsigned long flags;
again:
if (likely(!order_data->aca_tgt_dev)) {
if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_ACA)) {
TRACE_MGMT_DBG("Refusing ACA cmd %p, because there's no ACA, tgt_dev %p",
cmd, cmd->tgt_dev);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_message));
scst_set_cmd_abnormal_done_state(cmd);
}
return;
}
spin_lock_irqsave(&order_data->sn_lock, flags);
if (!order_data->aca_tgt_dev) {
spin_unlock_irqrestore(&order_data->sn_lock, flags);
goto again;
}
if (order_data->aca_tgt_dev == (unsigned long)cmd->tgt_dev) {
if (cmd->queue_type != SCST_CMD_QUEUE_ACA ||
order_data->aca_cmd || cmd->dev->tmf_only) {
TRACE_DBG("Refusing cmd %p, because ACA active (aca_cmd %p, tgt_dev %p)",
cmd, order_data->aca_cmd,
cmd->tgt_dev);
goto out_unlock_aca_active;
} else {
TRACE_MGMT_DBG("ACA cmd %p (tgt_dev %p)",
cmd, cmd->tgt_dev);
order_data->aca_cmd = cmd;
/* allow it */
}
} else {
/* Non-faulted I_T nexus */
EXTRACHECKS_BUG_ON(cmd->dev->tst != SCST_TST_0_SINGLE_TASK_SET);
if (cmd->queue_type == SCST_CMD_QUEUE_ACA) {
TRACE_MGMT_DBG("Refusing ACA cmd %p from wrong I_T nexus (aca_tgt_dev %ld, cmd->tgt_dev %p)",
cmd, order_data->aca_tgt_dev,
cmd->tgt_dev);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_message));
goto out_unlock_aca_active;
} else {
if (cmd->cdb[0] == PERSISTENT_RESERVE_OUT &&
(cmd->cdb[1] & 0x1f) == PR_PREEMPT_AND_ABORT) {
TRACE_MGMT_DBG("Allow PR PREEMPT AND ABORT cmd %p during ACA (tgt_dev %p)",
cmd, cmd->tgt_dev);
/* allow it */
} else {
TRACE_DBG("Refusing other IT-nexus cmd %p, because ACA active (tgt_dev %p)",
cmd, cmd->tgt_dev);
if (cmd->cmd_naca) {
goto out_unlock_aca_active;
} else {
spin_unlock_irqrestore(&order_data->sn_lock, flags);
scst_set_cmd_error_status(cmd, SAM_STAT_BUSY);
goto out_bypass_aca;
}
}
}
}
cmd->cmd_aca_allowed = 1;
spin_unlock_irqrestore(&order_data->sn_lock, flags);
return;
out_unlock_aca_active:
spin_unlock_irqrestore(&order_data->sn_lock, flags);
scst_set_cmd_error_status(cmd, SAM_STAT_ACA_ACTIVE);
out_bypass_aca:
cmd->cmd_aca_allowed = 1; /* for check in scst_pre_xmit_response2() */
scst_set_cmd_abnormal_done_state(cmd);
return;
}
/*
* No locks, but might be on IRQ.
*
@@ -5045,8 +5127,6 @@ static int scst_translate_lun(struct scst_cmd *cmd)
static int __scst_init_cmd(struct scst_cmd *cmd)
{
int res = 0;
unsigned long flags;
struct scst_order_data *order_data;
TRACE_ENTRY();
@@ -5055,8 +5135,6 @@ static int __scst_init_cmd(struct scst_cmd *cmd)
int cnt;
bool failure = false;
order_data = cmd->cur_order_data;
scst_set_cmd_state(cmd, SCST_CMD_STATE_PARSE);
cnt = atomic_inc_return(&cmd->tgt_dev->tgt_dev_cmd_count);
@@ -5102,73 +5180,9 @@ static int __scst_init_cmd(struct scst_cmd *cmd)
* queue_type to change it if needed. ToDo.
*/
scst_pre_parse(cmd);
again:
if (unlikely(order_data->aca_tgt_dev != 0)) {
spin_lock_irqsave(&order_data->sn_lock, flags);
if (order_data->aca_tgt_dev == 0) {
spin_unlock_irqrestore(&order_data->sn_lock, flags);
goto again;
}
if (order_data->aca_tgt_dev == (unsigned long)cmd->tgt_dev) {
if ((cmd->queue_type != SCST_CMD_QUEUE_ACA) ||
(order_data->aca_cmd != NULL) ||
cmd->dev->tmf_only) {
TRACE_DBG("Refusing cmd %p, because ACA "
"active (aca_cmd %p, tgt_dev %p)",
cmd, order_data->aca_cmd,
cmd->tgt_dev);
goto out_unlock_aca_active;
} else {
TRACE_MGMT_DBG("ACA cmd %p (tgt_dev %p)",
cmd, cmd->tgt_dev);
order_data->aca_cmd = cmd;
/* allow it */
}
} else {
/* Non-faulted I_T nexus */
EXTRACHECKS_BUG_ON(cmd->dev->tst != SCST_TST_0_SINGLE_TASK_SET);
if (cmd->queue_type == SCST_CMD_QUEUE_ACA) {
TRACE_MGMT_DBG("Refusing ACA cmd %p "
"from wrong I_T nexus (aca_tgt_dev %ld, "
"cmd->tgt_dev %p)", cmd,
order_data->aca_tgt_dev, cmd->tgt_dev);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_message));
goto out_unlock_aca_active;
} else {
if ((cmd->cdb[0] == PERSISTENT_RESERVE_OUT) &&
((cmd->cdb[1] & 0x1f) == PR_PREEMPT_AND_ABORT)) {
TRACE_MGMT_DBG("Allow PR PREEMPT AND "
"ABORT cmd %p during ACA "
"(tgt_dev %p)", cmd, cmd->tgt_dev);
/* allow it */
} else {
TRACE_DBG("Refusing other IT-nexus "
"cmd %p, because ACA active "
"(tgt_dev %p)", cmd, cmd->tgt_dev);
if (cmd->cmd_naca)
goto out_unlock_aca_active;
else {
spin_unlock_irqrestore(&order_data->sn_lock, flags);
scst_set_cmd_error_status(cmd, SAM_STAT_BUSY);
goto out_bypass_aca;
}
}
}
}
cmd->cmd_aca_allowed = 1;
spin_unlock_irqrestore(&order_data->sn_lock, flags);
} else if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_ACA)) {
TRACE_MGMT_DBG("Refusing ACA cmd %p, because there's no ACA, "
"tgt_dev %p", cmd, cmd->tgt_dev);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_message));
goto out_abnormal;
}
scst_handle_aca(cmd);
if (cmd->completed)
goto out;
if (!cmd->set_sn_on_restart_cmd) {
if (!cmd->tgtt->multithreaded_init_done)
@@ -5194,18 +5208,11 @@ out:
out_busy_bypass_aca:
scst_set_busy(cmd);
out_bypass_aca:
cmd->cmd_aca_allowed = 1; /* for check in scst_pre_xmit_response2() */
out_abnormal:
scst_set_cmd_abnormal_done_state(cmd);
goto out;
out_unlock_aca_active:
spin_unlock_irqrestore(&order_data->sn_lock, flags);
scst_set_cmd_error_status(cmd, SAM_STAT_ACA_ACTIVE);
goto out_bypass_aca;
}
/* Called under scst_init_lock and IRQs disabled */