mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-17 12:46:27 +00:00
Web updates
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4831 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
-621
@@ -1,621 +0,0 @@
|
||||
This patch is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, version 2
|
||||
of the License.
|
||||
|
||||
--- scst/include/scst.h
|
||||
+++ scst/include/scst.h
|
||||
@@ -410,6 +410,12 @@ enum scst_exec_context {
|
||||
/* Set if tgt_dev is RESERVED by another session */
|
||||
#define SCST_TGT_DEV_RESERVED 1
|
||||
|
||||
+/* Set if the tgt_dev is in ACA state */
|
||||
+#define SCST_TGT_DEV_ACA_ACTIVE 2
|
||||
+
|
||||
+/* Set if the tgt_dev is handling a task with an ACA attribute */
|
||||
+#define SCST_TGT_DEV_ACA_CMD_ACTIVE 3
|
||||
+
|
||||
/* Set if the corresponding context is atomic */
|
||||
#define SCST_TGT_DEV_AFTER_INIT_WR_ATOMIC 5
|
||||
#define SCST_TGT_DEV_AFTER_INIT_OTH_ATOMIC 6
|
||||
@@ -1164,6 +1170,12 @@ struct scst_cmd {
|
||||
/* Set if hq_cmd_count was incremented */
|
||||
unsigned int hq_cmd_inced:1;
|
||||
|
||||
+ /* set if this command goes to the head of the queue (HQ or ACA) */
|
||||
+ unsigned int hq_cmd:1;
|
||||
+
|
||||
+ /* set if this is a naca command */
|
||||
+ unsigned int naca_cmd:1;
|
||||
+
|
||||
/*
|
||||
* Set if scst_cmd_init_stage1_done() called and the target wants
|
||||
* that the SN for the cmd won't be assigned until scst_restart_cmd()
|
||||
@@ -1217,7 +1229,7 @@ struct scst_cmd {
|
||||
#endif
|
||||
|
||||
/* List entry for tgt_dev's SN related lists */
|
||||
- struct list_head sn_cmd_list_entry;
|
||||
+ struct list_head deferred_cmd_list_entry;
|
||||
|
||||
/* Cmd's serial number, used to execute cmd's in order of arrival */
|
||||
unsigned long sn;
|
||||
@@ -2718,7 +2730,7 @@ int scst_check_local_events(struct scst_cmd *cmd);
|
||||
* Returns the next state of the SCSI target state machine in case if command's
|
||||
* completed abnormally.
|
||||
*/
|
||||
-int scst_get_cmd_abnormal_done_state(const struct scst_cmd *cmd);
|
||||
+int scst_get_cmd_abnormal_done_state(struct scst_cmd *cmd);
|
||||
|
||||
/*
|
||||
* Sets state of the SCSI target state machine in case if command's completed
|
||||
--- scst/src/scst_lib.c
|
||||
+++ scst/src/scst_lib.c
|
||||
@@ -683,7 +683,7 @@ out_free:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_aen_done);
|
||||
|
||||
-int scst_get_cmd_abnormal_done_state(const struct scst_cmd *cmd)
|
||||
+int scst_get_cmd_abnormal_done_state(struct scst_cmd *cmd)
|
||||
{
|
||||
int res;
|
||||
|
||||
@@ -693,6 +693,14 @@ EXPORT_SYMBOL(scst_aen_done);
|
||||
case SCST_CMD_STATE_INIT_WAIT:
|
||||
case SCST_CMD_STATE_INIT:
|
||||
case SCST_CMD_STATE_PRE_PARSE:
|
||||
+ if (cmd->tgt_dev != NULL) {
|
||||
+ int rc;
|
||||
+ rc = scst_get_cdb_info(cmd);
|
||||
+ if (rc == 0) {
|
||||
+ int cbyte = cmd->cdb[cmd->cdb_len -1];
|
||||
+ cmd->naca_cmd = (cbyte & CONTROL_BYTE_NACA_BIT) != 0;
|
||||
+ }
|
||||
+ }
|
||||
case SCST_CMD_STATE_DEV_PARSE:
|
||||
case SCST_CMD_STATE_DEV_DONE:
|
||||
if (cmd->internal)
|
||||
@@ -1221,6 +1229,8 @@ void scst_nexus_loss(struct scst_tgt_dev *tgt_dev,
|
||||
|
||||
/* With activity suspended the lock isn't needed, but let's be safe */
|
||||
spin_lock_bh(&tgt_dev->tgt_dev_lock);
|
||||
+ clear_bit(SCST_TGT_DEV_ACA_ACTIVE, &tgt_dev->tgt_dev_flags);
|
||||
+ clear_bit(SCST_TGT_DEV_ACA_CMD_ACTIVE, &tgt_dev->tgt_dev_flags);
|
||||
scst_free_all_UA(tgt_dev);
|
||||
spin_unlock_bh(&tgt_dev->tgt_dev_lock);
|
||||
|
||||
@@ -3367,6 +3377,8 @@ void scst_process_reset(struct scst_device *dev,
|
||||
struct scst_session *sess = tgt_dev->sess;
|
||||
|
||||
spin_lock_bh(&tgt_dev->tgt_dev_lock);
|
||||
+ clear_bit(SCST_TGT_DEV_ACA_ACTIVE, &tgt_dev->tgt_dev_flags);
|
||||
+ clear_bit(SCST_TGT_DEV_ACA_CMD_ACTIVE, &tgt_dev->tgt_dev_flags);
|
||||
scst_free_all_UA(tgt_dev);
|
||||
spin_unlock_bh(&tgt_dev->tgt_dev_lock);
|
||||
|
||||
@@ -3689,14 +3701,13 @@ struct scst_cmd *__scst_check_deferred_commands(st
|
||||
|
||||
restart:
|
||||
list_for_each_entry_safe(cmd, t, &tgt_dev->deferred_cmd_list,
|
||||
- sn_cmd_list_entry) {
|
||||
- EXTRACHECKS_BUG_ON(cmd->queue_type ==
|
||||
- SCST_CMD_QUEUE_HEAD_OF_QUEUE);
|
||||
+ deferred_cmd_list_entry) {
|
||||
+ EXTRACHECKS_BUG_ON(cmd->hq_cmd);
|
||||
if (cmd->sn == expected_sn) {
|
||||
TRACE_SN("Deferred command %p (sn %ld, set %d) found",
|
||||
cmd, cmd->sn, cmd->sn_set);
|
||||
tgt_dev->def_cmd_count--;
|
||||
- list_del(&cmd->sn_cmd_list_entry);
|
||||
+ list_del(&cmd->deferred_cmd_list_entry);
|
||||
if (res == NULL)
|
||||
res = cmd;
|
||||
else {
|
||||
@@ -3714,9 +3725,8 @@ restart:
|
||||
goto out_unlock;
|
||||
|
||||
list_for_each_entry(cmd, &tgt_dev->skipped_sn_list,
|
||||
- sn_cmd_list_entry) {
|
||||
- EXTRACHECKS_BUG_ON(cmd->queue_type ==
|
||||
- SCST_CMD_QUEUE_HEAD_OF_QUEUE);
|
||||
+ deferred_cmd_list_entry) {
|
||||
+ EXTRACHECKS_BUG_ON(cmd->hq_cmd);
|
||||
if (cmd->sn == expected_sn) {
|
||||
atomic_t *slot = cmd->sn_slot;
|
||||
/*
|
||||
@@ -3729,7 +3739,7 @@ restart:
|
||||
(long long unsigned int)cmd->tag,
|
||||
cmd->sn);
|
||||
tgt_dev->def_cmd_count--;
|
||||
- list_del(&cmd->sn_cmd_list_entry);
|
||||
+ list_del(&cmd->deferred_cmd_list_entry);
|
||||
spin_unlock_irq(&tgt_dev->sn_lock);
|
||||
if (test_and_set_bit(SCST_CMD_CAN_BE_DESTROYED,
|
||||
&cmd->cmd_flags))
|
||||
@@ -4019,7 +4029,7 @@ static void scst_unblock_cmds(struct scst_device *
|
||||
list_del(&cmd->blocked_cmd_list_entry);
|
||||
TRACE_MGMT_DBG("Adding blocked cmd %p to active cmd list", cmd);
|
||||
spin_lock(&cmd->cmd_lists->cmd_list_lock);
|
||||
- if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
|
||||
+ if (unlikely(cmd->hq_cmd))
|
||||
list_add(&cmd->cmd_list_entry,
|
||||
&cmd->cmd_lists->active_cmd_list);
|
||||
else
|
||||
@@ -4047,7 +4057,7 @@ static void __scst_unblock_deferred(struct scst_tg
|
||||
out_of_sn_cmd->out_of_sn = 1;
|
||||
spin_lock_irq(&tgt_dev->sn_lock);
|
||||
tgt_dev->def_cmd_count++;
|
||||
- list_add_tail(&out_of_sn_cmd->sn_cmd_list_entry,
|
||||
+ list_add_tail(&out_of_sn_cmd->deferred_cmd_list_entry,
|
||||
&tgt_dev->skipped_sn_list);
|
||||
TRACE_SN("out_of_sn_cmd %p with sn %ld added to skipped_sn_list"
|
||||
" (expected_sn %ld)", out_of_sn_cmd, out_of_sn_cmd->sn,
|
||||
--- scst/src/scst_targ.c
|
||||
+++ scst/src/scst_targ.c
|
||||
@@ -40,6 +40,7 @@ static struct scst_cmd *__scst_find_cmd_by_tag(str
|
||||
uint64_t tag);
|
||||
static void scst_proccess_redirect_cmd(struct scst_cmd *cmd,
|
||||
enum scst_exec_context context, int check_retries);
|
||||
+static int scst_set_mcmd_next_state(struct scst_mgmt_cmd *mcmd);
|
||||
|
||||
static inline void scst_schedule_tasklet(struct scst_cmd *cmd)
|
||||
{
|
||||
@@ -280,7 +281,7 @@ void scst_cmd_init_done(struct scst_cmd *cmd,
|
||||
goto active;
|
||||
}
|
||||
|
||||
- if (unlikely(cmd->queue_type >= SCST_CMD_QUEUE_ACA)) {
|
||||
+ if (unlikely(cmd->queue_type > SCST_CMD_QUEUE_ACA)) {
|
||||
PRINT_ERROR("Unsupported queue type %d", cmd->queue_type);
|
||||
scst_set_cmd_error(cmd,
|
||||
SCST_LOAD_SENSE(scst_sense_invalid_message));
|
||||
@@ -300,6 +301,10 @@ void scst_cmd_init_done(struct scst_cmd *cmd,
|
||||
else if (unlikely(cmd->status == SAM_STAT_CHECK_CONDITION)) {
|
||||
if (rc == 0) {
|
||||
/* Target driver preliminary completed cmd */
|
||||
+ if (cmd->tgt_dev != NULL) {
|
||||
+ atomic_inc(&cmd->tgt_dev->tgt_dev_cmd_count);
|
||||
+ atomic_inc(&cmd->dev->dev_cmd_count);
|
||||
+ }
|
||||
scst_set_cmd_abnormal_done_state(cmd);
|
||||
}
|
||||
}
|
||||
@@ -328,7 +333,7 @@ active:
|
||||
case SCST_CONTEXT_THREAD:
|
||||
spin_lock_irqsave(&cmd->cmd_lists->cmd_list_lock, flags);
|
||||
TRACE_DBG("Adding cmd %p to active cmd list", cmd);
|
||||
- if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
|
||||
+ if (unlikely(cmd->hq_cmd))
|
||||
list_add(&cmd->cmd_list_entry,
|
||||
&cmd->cmd_lists->active_cmd_list);
|
||||
else
|
||||
@@ -434,13 +439,8 @@ static int scst_pre_parse(struct scst_cmd *cmd)
|
||||
}
|
||||
}
|
||||
|
||||
- if (unlikely(cmd->cdb[cmd->cdb_len - 1] & CONTROL_BYTE_NACA_BIT)) {
|
||||
- PRINT_ERROR("NACA bit in control byte CDB is not supported "
|
||||
- "(opcode 0x%02x)", cmd->cdb[0]);
|
||||
- scst_set_cmd_error(cmd,
|
||||
- SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
|
||||
- goto out_xmit;
|
||||
- }
|
||||
+ cmd->naca_cmd = (cmd->cdb[cmd->cdb_len - 1] & CONTROL_BYTE_NACA_BIT) !=0;
|
||||
+ TRACE(TRACE_SCSI,"cmd %p NACA bit %d", cmd, cmd->naca_cmd);
|
||||
|
||||
if (unlikely(cmd->cdb[cmd->cdb_len - 1] & CONTROL_BYTE_LINK_BIT)) {
|
||||
PRINT_ERROR("Linked commands are not supported "
|
||||
@@ -537,6 +537,9 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
|
||||
} else
|
||||
state = SCST_CMD_STATE_PREPARE_SPACE;
|
||||
|
||||
+ if (cmd->naca_cmd)
|
||||
+ cmd->inc_expected_sn_on_done = 1;
|
||||
+
|
||||
if (cmd->data_len == -1)
|
||||
cmd->data_len = cmd->bufflen;
|
||||
|
||||
@@ -1069,7 +1072,7 @@ static void scst_proccess_redirect_cmd(struct scst
|
||||
scst_check_retries(cmd->tgt);
|
||||
spin_lock_irqsave(&cmd->cmd_lists->cmd_list_lock, flags);
|
||||
TRACE_DBG("Adding cmd %p to active cmd list", cmd);
|
||||
- if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
|
||||
+ if (unlikely(cmd->hq_cmd))
|
||||
list_add(&cmd->cmd_list_entry,
|
||||
&cmd->cmd_lists->active_cmd_list);
|
||||
else
|
||||
@@ -2252,11 +2255,36 @@ static int scst_send_for_exec(struct scst_cmd **ac
|
||||
if (unlikely(cmd->internal))
|
||||
goto exec;
|
||||
|
||||
- if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
|
||||
+ /* this will cause HQ & ACA commands to goto exec */
|
||||
+ if (unlikely(cmd->hq_cmd))
|
||||
goto exec;
|
||||
|
||||
sBUG_ON(!cmd->sn_set);
|
||||
|
||||
+ /* Handla ACA */
|
||||
+ if (unlikely(test_bit(SCST_TGT_DEV_ACA_ACTIVE, &tgt_dev->tgt_dev_flags))) {
|
||||
+ spin_lock_irq(&tgt_dev->sn_lock);
|
||||
+ TRACE_DBG("ACA_ACTIVE: handling exec cmd %p queue type %d", cmd, cmd->queue_type);
|
||||
+ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) {
|
||||
+ TRACE_MGMT_DBG("Aborting out of sn cmd %p "
|
||||
+ "(tag %llu, sn %lu)", cmd,
|
||||
+ (long long unsigned)cmd->tag, cmd->sn);
|
||||
+ spin_unlock_irq(&tgt_dev->sn_lock);
|
||||
+ scst_set_cmd_abnormal_done_state(cmd);
|
||||
+ res = SCST_CMD_STATE_RES_CONT_SAME;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* defer the command */
|
||||
+ TRACE(TRACE_SCSI, "ACA active for tgt_dev %p: deferring cmd %p",
|
||||
+ tgt_dev, cmd);
|
||||
+ list_add_tail(&cmd->deferred_cmd_list_entry,
|
||||
+ &tgt_dev->deferred_cmd_list);
|
||||
+ spin_unlock_irq(&tgt_dev->sn_lock);
|
||||
+ res = SCST_CMD_STATE_RES_CONT_NEXT;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
expected_sn = tgt_dev->expected_sn;
|
||||
/* Optimized for lockless fast path */
|
||||
if ((cmd->sn != expected_sn) || (tgt_dev->hq_cmd_count > 0)) {
|
||||
@@ -2291,7 +2319,7 @@ static int scst_send_for_exec(struct scst_cmd **ac
|
||||
TRACE_SN("Deferring cmd %p (sn=%ld, set %d, "
|
||||
"expected_sn=%ld)", cmd, cmd->sn,
|
||||
cmd->sn_set, expected_sn);
|
||||
- list_add_tail(&cmd->sn_cmd_list_entry,
|
||||
+ list_add_tail(&cmd->deferred_cmd_list_entry,
|
||||
&tgt_dev->deferred_cmd_list);
|
||||
res = SCST_CMD_STATE_RES_CONT_NEXT;
|
||||
}
|
||||
@@ -2435,6 +2463,72 @@ static int scst_check_auto_sense(struct scst_cmd *
|
||||
return res;
|
||||
}
|
||||
|
||||
+/* called under no locks*/
|
||||
+static int scst_clear_aca(struct scst_mgmt_cmd* mcmd, struct scst_tgt_dev *tgt_dev)
|
||||
+{
|
||||
+ unsigned long flags;
|
||||
+ struct scst_cmd *cmd, *tcmd;
|
||||
+ struct scst_session *sess;
|
||||
+ int res = 0;
|
||||
+
|
||||
+ TRACE_ENTRY();
|
||||
+
|
||||
+ TRACE_MGMT_DBG("Clearing ACA for tgt_dev %p (lun %lld)",
|
||||
+ tgt_dev, tgt_dev->lun);
|
||||
+ if (!test_bit(SCST_TGT_DEV_ACA_ACTIVE, &tgt_dev->tgt_dev_flags)) {
|
||||
+ /* reject CLEAR_ACA when not in ACA state */
|
||||
+ TRACE_MGMT_DBG("Rejecting CLEAR_ACA for tgt_dev %p (lun %lld)",
|
||||
+ tgt_dev, tgt_dev->lun);
|
||||
+ res = 1;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ clear_bit(SCST_TGT_DEV_ACA_ACTIVE, &tgt_dev->tgt_dev_flags);
|
||||
+ if (test_bit(SCST_TGT_DEV_ACA_CMD_ACTIVE, &tgt_dev->tgt_dev_flags) && (mcmd)) {
|
||||
+ sess = tgt_dev->sess;
|
||||
+ spin_lock_irqsave(&sess->sess_list_lock, flags);
|
||||
+ TRACE_DBG("Searching in search cmd list (sess=%p) "
|
||||
+ "for an ACA command", sess);
|
||||
+ list_for_each_entry(cmd, &sess->search_cmd_list,
|
||||
+ search_cmd_list_entry) {
|
||||
+ if ((cmd->tgt_dev == tgt_dev) &&
|
||||
+ (cmd->queue_type == SCST_CMD_QUEUE_ACA)) {
|
||||
+ /* Found the ACA command - abort it */
|
||||
+ scst_abort_cmd(cmd, mcmd, 0, 0);
|
||||
+ res = -1;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ spin_unlock_irqrestore(&sess->sess_list_lock, flags);
|
||||
+ }
|
||||
+
|
||||
+ spin_lock_irq(&tgt_dev->sn_lock);
|
||||
+ list_for_each_entry_safe(cmd, tcmd,
|
||||
+ &tgt_dev->deferred_cmd_list,
|
||||
+ deferred_cmd_list_entry) {
|
||||
+
|
||||
+ TRACE_MGMT_DBG("Move cmd %p (sn %lu) "
|
||||
+ "from deferred list to active_list",
|
||||
+ cmd, cmd->sn);
|
||||
+
|
||||
+ list_del(&cmd->deferred_cmd_list_entry);
|
||||
+ spin_lock(&cmd->cmd_lists->cmd_list_lock);
|
||||
+ list_add_tail(&cmd->cmd_list_entry,
|
||||
+ &cmd->cmd_lists->active_cmd_list);
|
||||
+ wake_up(&cmd->cmd_lists->cmd_list_waitQ);
|
||||
+ spin_unlock(&cmd->cmd_lists->cmd_list_lock);
|
||||
+ tgt_dev->def_cmd_count--;
|
||||
+ }
|
||||
+ spin_unlock_irq(&tgt_dev->sn_lock);
|
||||
+
|
||||
+ if (mcmd != NULL)
|
||||
+ res = scst_set_mcmd_next_state(mcmd);
|
||||
+
|
||||
+out:
|
||||
+ TRACE_EXIT_RES(res);
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
static int scst_pre_dev_done(struct scst_cmd *cmd)
|
||||
{
|
||||
int res = SCST_CMD_STATE_RES_CONT_SAME, rc;
|
||||
@@ -2506,14 +2600,14 @@ static int scst_pre_dev_done(struct scst_cmd *cmd)
|
||||
if (buflen > SCST_INQ_BYTE3) {
|
||||
#ifdef CONFIG_SCST_EXTRACHECKS
|
||||
if (buffer[SCST_INQ_BYTE3] & SCST_INQ_NORMACA_BIT) {
|
||||
- PRINT_INFO("NormACA set for device: "
|
||||
- "lun=%lld, type 0x%02x. Clear it, "
|
||||
- "since it's unsupported.",
|
||||
+ TRACE_DBG("NormACA set for device: "
|
||||
+ "lun=%lld, type 0x%02x "
|
||||
+ "NACA is only supported for "
|
||||
+ "TST=1 & QErr=0.",
|
||||
(long long unsigned int)cmd->lun,
|
||||
buffer[0]);
|
||||
}
|
||||
#endif
|
||||
- buffer[SCST_INQ_BYTE3] &= ~SCST_INQ_NORMACA_BIT;
|
||||
} else if (buflen != 0) {
|
||||
PRINT_ERROR("%s", "Unable to get INQUIRY "
|
||||
"buffer");
|
||||
@@ -2761,9 +2855,6 @@ static int scst_dev_done(struct scst_cmd *cmd)
|
||||
if (likely(cmd->dec_on_dev_needed))
|
||||
scst_dec_on_dev_cmd(cmd);
|
||||
|
||||
- if (cmd->inc_expected_sn_on_done && cmd->sent_for_exec)
|
||||
- scst_inc_check_expected_sn(cmd);
|
||||
-
|
||||
if (unlikely(cmd->internal))
|
||||
cmd->state = SCST_CMD_STATE_FINISHED_INTERNAL;
|
||||
|
||||
@@ -2794,15 +2885,48 @@ static int scst_pre_xmit_response(struct scst_cmd
|
||||
schedule_timeout_uninterruptible(HZ);
|
||||
}
|
||||
#endif
|
||||
+ if (cmd->queue_type == SCST_CMD_QUEUE_ACA)
|
||||
+ TRACE_DBG("ACA command %p, tgt_dev %p, status %d, naca %d",cmd, cmd->tgt_dev, cmd->status, cmd->naca_cmd);
|
||||
|
||||
if (likely(cmd->tgt_dev != NULL)) {
|
||||
+ if (cmd->inc_expected_sn_on_done && cmd->sent_for_exec)
|
||||
+ scst_inc_check_expected_sn(cmd);
|
||||
+
|
||||
+ /* Enter\Exit ACA state */
|
||||
+ if (cmd->status == SAM_STAT_CHECK_CONDITION) {
|
||||
+ /* If the command attribute is ACA, exit from ACA state */
|
||||
+ if ((cmd->queue_type == SCST_CMD_QUEUE_ACA) &&
|
||||
+ (test_bit(SCST_TGT_DEV_ACA_ACTIVE, &cmd->tgt_dev->tgt_dev_flags))) {
|
||||
+ TRACE(TRACE_SCSI, "ACA: tgt_dev %p exits from ACA state "
|
||||
+ "because of cmd %p", cmd->tgt_dev, cmd);
|
||||
+ scst_clear_aca(NULL, cmd->tgt_dev);
|
||||
+ }
|
||||
+
|
||||
+ /* If this is a NACA command enter ACA state */
|
||||
+ if (cmd->naca_cmd) {
|
||||
+ int cmd_count = atomic_read(&cmd->tgt_dev->tgt_dev_cmd_count);
|
||||
+ set_bit(SCST_TGT_DEV_ACA_ACTIVE, &cmd->tgt_dev->tgt_dev_flags);
|
||||
+ TRACE(TRACE_SCSI, "ACA: tgt_dev %p enters ACA state because "
|
||||
+ "of cmd %p (tgt_dev_cmd_count = %d)",
|
||||
+ cmd->tgt_dev,
|
||||
+ cmd,
|
||||
+ cmd_count);
|
||||
+
|
||||
+ PRINT_BUFF_FLAG(TRACE_SCSI, "cdb that caused the ACA state",
|
||||
+ cmd->cdb, cmd->cdb_len);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (unlikely(test_bit(SCST_TGT_DEV_ACA_ACTIVE, &cmd->tgt_dev->tgt_dev_flags)))
|
||||
+ clear_bit(SCST_TGT_DEV_ACA_CMD_ACTIVE, &cmd->tgt_dev->tgt_dev_flags);
|
||||
+
|
||||
atomic_dec(&cmd->tgt_dev->tgt_dev_cmd_count);
|
||||
atomic_dec(&cmd->dev->dev_cmd_count);
|
||||
/* If expected values not set, expected direction is UNKNOWN */
|
||||
if (cmd->expected_data_direction == SCST_DATA_WRITE)
|
||||
atomic_dec(&cmd->dev->write_cmd_count);
|
||||
|
||||
- if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
|
||||
+ if (unlikely(cmd->hq_cmd))
|
||||
scst_on_hq_cmd_response(cmd);
|
||||
|
||||
if (unlikely(!cmd->sent_for_exec)) {
|
||||
@@ -3128,11 +3252,13 @@ ordered:
|
||||
break;
|
||||
|
||||
case SCST_CMD_QUEUE_HEAD_OF_QUEUE:
|
||||
- TRACE_SN("HQ cmd %p (op %x)", cmd, cmd->cdb[0]);
|
||||
+ case SCST_CMD_QUEUE_ACA:
|
||||
+ TRACE_SN("HQ or ACA (%d) cmd %p (op %x)", cmd->queue_type, cmd, cmd->cdb[0]);
|
||||
spin_lock_irqsave(&tgt_dev->sn_lock, flags);
|
||||
tgt_dev->hq_cmd_count++;
|
||||
spin_unlock_irqrestore(&tgt_dev->sn_lock, flags);
|
||||
cmd->hq_cmd_inced = 1;
|
||||
+ cmd->hq_cmd = 1;
|
||||
goto out;
|
||||
|
||||
default:
|
||||
@@ -3223,7 +3349,9 @@ static int scst_translate_lun(struct scst_cmd *cmd
|
||||
*/
|
||||
static int __scst_init_cmd(struct scst_cmd *cmd)
|
||||
{
|
||||
+ struct scst_tgt_dev *tgt_dev;
|
||||
int res = 0;
|
||||
+ bool done = false;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -3234,28 +3362,74 @@ static int __scst_init_cmd(struct scst_cmd *cmd)
|
||||
|
||||
cmd->state = SCST_CMD_STATE_PRE_PARSE;
|
||||
|
||||
- cnt = atomic_inc_return(&cmd->tgt_dev->tgt_dev_cmd_count);
|
||||
- if (unlikely(cnt > SCST_MAX_TGT_DEV_COMMANDS)) {
|
||||
- TRACE(TRACE_MGMT_MINOR,
|
||||
- "Too many pending commands (%d) in "
|
||||
- "session, returning BUSY to initiator \"%s\"",
|
||||
- cnt, (cmd->sess->initiator_name[0] == '\0') ?
|
||||
- "Anonymous" : cmd->sess->initiator_name);
|
||||
- failure = true;
|
||||
- }
|
||||
+ /* Handle ACA for TST=1 QErr=0*/
|
||||
+ tgt_dev = cmd->tgt_dev;
|
||||
+ if (unlikely(test_bit(SCST_TGT_DEV_ACA_ACTIVE,
|
||||
+ &tgt_dev->tgt_dev_flags))) {
|
||||
+ /* Terminate commands without ACA attribute,
|
||||
+ * Only one ACA command should be handled at a time */
|
||||
+ if ((cmd->queue_type != SCST_CMD_QUEUE_ACA) ||
|
||||
+ test_bit(SCST_TGT_DEV_ACA_CMD_ACTIVE,
|
||||
+ &tgt_dev->tgt_dev_flags)) {
|
||||
+ TRACE(TRACE_SCSI|TRACE_DEBUG,
|
||||
+ "cmd %p terminated with ACA_ACTIVE "
|
||||
+ "(queue_type=%d, tgt_dev %p)",
|
||||
+ cmd, cmd->queue_type,tgt_dev);
|
||||
+ atomic_inc(&cmd->tgt_dev->tgt_dev_cmd_count);
|
||||
+ atomic_inc(&cmd->dev->dev_cmd_count);
|
||||
+ scst_set_cmd_error_status(cmd,
|
||||
+ SAM_STAT_ACA_ACTIVE);
|
||||
+ scst_set_cmd_abnormal_done_state(cmd);
|
||||
+ failure = true;
|
||||
+ done = true;
|
||||
+ res = -1;
|
||||
+ } else {
|
||||
+ TRACE(TRACE_SCSI|TRACE_DEBUG,
|
||||
+ "tgt_dev %p received ACA CMD %p ",
|
||||
+ tgt_dev, cmd);
|
||||
+ set_bit(SCST_TGT_DEV_ACA_CMD_ACTIVE, &tgt_dev->tgt_dev_flags);
|
||||
+ atomic_inc(&cmd->tgt_dev->tgt_dev_cmd_count);
|
||||
+ atomic_inc(&cmd->dev->dev_cmd_count);
|
||||
+ }
|
||||
+ } else {
|
||||
+ /* Terminate commands with ACA attribute when not
|
||||
+ * in ACA state*/
|
||||
+ if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_ACA)) {
|
||||
+ TRACE(TRACE_SCSI|TRACE_DEBUG,
|
||||
+ "ACA cmd %p terminated because ITL "
|
||||
+ "nexus is not in ACA state "
|
||||
+ "(tgt dev %p)", cmd, tgt_dev);
|
||||
+ scst_set_cmd_error(cmd,
|
||||
+ SCST_LOAD_SENSE(scst_sense_invalid_message));
|
||||
+ scst_set_cmd_abnormal_done_state(cmd);
|
||||
+ failure = true;
|
||||
+ done = true;
|
||||
+ res = -1;
|
||||
+ }
|
||||
|
||||
- cnt = atomic_inc_return(&cmd->dev->dev_cmd_count);
|
||||
- if (unlikely(cnt > SCST_MAX_DEV_COMMANDS)) {
|
||||
- if (!failure) {
|
||||
+ cnt = atomic_inc_return(&cmd->tgt_dev->tgt_dev_cmd_count);
|
||||
+ if (unlikely(cnt > SCST_MAX_TGT_DEV_COMMANDS)) {
|
||||
TRACE(TRACE_MGMT_MINOR,
|
||||
- "Too many pending device "
|
||||
- "commands (%d), returning BUSY to "
|
||||
- "initiator \"%s\"", cnt,
|
||||
- (cmd->sess->initiator_name[0] == '\0') ?
|
||||
- "Anonymous" :
|
||||
- cmd->sess->initiator_name);
|
||||
+ "Too many pending commands (%d) in "
|
||||
+ "session, returning BUSY to initiator \"%s\"",
|
||||
+ cnt, (cmd->sess->initiator_name[0] == '\0') ?
|
||||
+ "Anonymous" : cmd->sess->initiator_name);
|
||||
failure = true;
|
||||
}
|
||||
+
|
||||
+ cnt = atomic_inc_return(&cmd->dev->dev_cmd_count);
|
||||
+ if (unlikely(cnt > SCST_MAX_DEV_COMMANDS)) {
|
||||
+ if (!failure) {
|
||||
+ TRACE(TRACE_MGMT_MINOR,
|
||||
+ "Too many pending device "
|
||||
+ "commands (%d), returning BUSY to "
|
||||
+ "initiator \"%s\"", cnt,
|
||||
+ (cmd->sess->initiator_name[0] == '\0') ?
|
||||
+ "Anonymous" :
|
||||
+ cmd->sess->initiator_name);
|
||||
+ failure = true;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
/* If expected values not set, expected direction is UNKNOWN */
|
||||
@@ -3263,7 +3437,7 @@ static int __scst_init_cmd(struct scst_cmd *cmd)
|
||||
atomic_inc(&cmd->dev->write_cmd_count);
|
||||
|
||||
if (unlikely(failure))
|
||||
- goto out_busy;
|
||||
+ goto out_failure;
|
||||
|
||||
if (!cmd->set_sn_on_restart_cmd)
|
||||
scst_cmd_set_sn(cmd);
|
||||
@@ -3279,9 +3453,11 @@ out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
|
||||
-out_busy:
|
||||
- scst_set_busy(cmd);
|
||||
- scst_set_cmd_abnormal_done_state(cmd);
|
||||
+out_failure:
|
||||
+ if (!done) {
|
||||
+ scst_set_busy(cmd);
|
||||
+ scst_set_cmd_abnormal_done_state(cmd);
|
||||
+ }
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -3343,7 +3519,7 @@ restart:
|
||||
|
||||
spin_lock(&cmd->cmd_lists->cmd_list_lock);
|
||||
TRACE_MGMT_DBG("Adding cmd %p to active cmd list", cmd);
|
||||
- if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
|
||||
+ if (unlikely(cmd->hq_cmd))
|
||||
list_add(&cmd->cmd_list_entry,
|
||||
&cmd->cmd_lists->active_cmd_list);
|
||||
else
|
||||
@@ -4138,9 +4314,9 @@ static void scst_unblock_aborted_cmds(int scst_mut
|
||||
spin_lock(&tgt_dev->sn_lock);
|
||||
list_for_each_entry_safe(cmd, tcmd,
|
||||
&tgt_dev->deferred_cmd_list,
|
||||
- sn_cmd_list_entry) {
|
||||
+ deferred_cmd_list_entry) {
|
||||
if (__scst_check_unblock_aborted_cmd(cmd,
|
||||
- &cmd->sn_cmd_list_entry)) {
|
||||
+ &cmd->deferred_cmd_list_entry)) {
|
||||
TRACE_MGMT_DBG("Unblocked aborted SN "
|
||||
"cmd %p (sn %lu)",
|
||||
cmd, cmd->sn);
|
||||
@@ -4773,12 +4949,13 @@ static int scst_mgmt_cmd_exec(struct scst_mgmt_cmd
|
||||
break;
|
||||
|
||||
case SCST_CLEAR_ACA:
|
||||
- if (scst_call_dev_task_mgmt_fn(mcmd, mcmd->mcmd_tgt_dev, 1) ==
|
||||
- SCST_DEV_TM_NOT_COMPLETED) {
|
||||
- mcmd->status = SCST_MGMT_STATUS_FN_NOT_SUPPORTED;
|
||||
- /* Nothing to do (yet) */
|
||||
+ res = scst_clear_aca(mcmd, mcmd->mcmd_tgt_dev);
|
||||
+ if (res > 0) {
|
||||
+ res = 0;
|
||||
+ mcmd->status = SCST_MGMT_STATUS_REJECTED;
|
||||
+ goto out_done;
|
||||
}
|
||||
- goto out_done;
|
||||
+ break;
|
||||
|
||||
default:
|
||||
PRINT_ERROR("Unknown task management function %d", mcmd->fn);
|
||||
--- scst/src/dev_handlers/scst_user.c
|
||||
+++ scst/src/dev_handlers/scst_user.c
|
||||
@@ -1061,8 +1061,9 @@ static void dev_user_add_to_ready(struct scst_user
|
||||
do_wake = 1;
|
||||
} else {
|
||||
if ((ucmd->cmd != NULL) &&
|
||||
- unlikely((ucmd->cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))) {
|
||||
- TRACE_DBG("Adding HQ ucmd %p to head of ready cmd list",
|
||||
+ unlikely((ucmd->cmd->hq_cmd))) {
|
||||
+ TRACE_DBG("Adding HQ or ACA (%d) ucmd %p to head of ready cmd list",
|
||||
+ ucmd->cmd->queue_type,
|
||||
ucmd);
|
||||
list_add(&ucmd->ready_cmd_list_entry,
|
||||
&dev->ready_cmd_list);
|
||||
+61
-68
@@ -52,7 +52,7 @@
|
||||
mailing list and it will be corrected.
|
||||
</p>
|
||||
|
||||
<p><small>As on June 2011.</small></p>
|
||||
<p><small>As on June 2011, briefly reviewed April 2013.</small></p>
|
||||
|
||||
<table bgcolor="#F0F0F0" border="1" cellspacing="1" cellpadding="7" style="text-align:center" width="620">
|
||||
|
||||
@@ -68,32 +68,30 @@
|
||||
<td colspan="5"> <b>General</b>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="left"><b>Upstream kernel</b></td> <td> - </td> <td>Interface with
|
||||
in-kernel target
|
||||
drivers (obsolete)</td> <td> - </td> <td> <a href="scstvslio.html">Since 2.6.38</a></td>
|
||||
<td align="left"><b>Upstream kernel</b></td> <td> - </td> <td> - </td> <td> - </td> <td> <a href="scstvslio.html">Since 2.6.38</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Generic Target Engine</b></td> <td> + </td> <td> + </td> <td> iSCSI only </td> <td> + </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Architecture</b></td> <td> Kernel only</td> <td> User space only
|
||||
<sup><A HREF="#1">1</A>
|
||||
</sup> </td> <td> - </td> <td> Kernel only </td>
|
||||
<td align="left"><b>Architecture</b></td> <td> Kernel only</td> <td> User space only </td> <td> Split <sup>
|
||||
<A HREF="#1">1</A>
|
||||
</sup> </td> <td> Kernel only </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Stability</b></td> <td> + </td> <td> + </td> <td> + </td> <td> Probably (no released packages) </td>
|
||||
<td align="left"><b>Stability</b></td> <td> + </td> <td> + </td> <td> + </td> <td> Probably </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Performance <sup><A HREF="#3">3</A></sup></b></td> <td> ***** <sup>
|
||||
<A HREF="#4">4</A>
|
||||
<td align="left"><b>Performance <sup><A HREF="#2">2</A></sup></b></td> <td> ***** <sup>
|
||||
<A HREF="#3">3</A>
|
||||
</sup></td> <td> ***</td> <td> **** </td> <td> ****- </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th align="left"> Zero-copy passing data between target and
|
||||
backend drivers</th> <td> + <sup>
|
||||
<A HREF="#5">5</A>
|
||||
<A HREF="#4">4</A>
|
||||
</sup></td> <td> + <sup>
|
||||
<A HREF="#6">6</A>
|
||||
<A HREF="#5">5</A>
|
||||
</sup> </td> <td> + </td> <td> + </td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -122,12 +120,11 @@ transfer values (Wide (parallel) SCSI, SAS)</b></td> <td> + </td> <td> - </td
|
||||
<td align="left"><b>Backstorage handlers in kernel space</b></td> <td> + </td> <td> - </td> <td> - </td> <td> + </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Backstorage handlers in user space</b></td> <td>+</td> <td> + </td> <td> - </td> <td> Via STGT
|
||||
(under development) </td>
|
||||
<td align="left"><b>Backstorage handlers in user space</b></td> <td>+</td> <td> + </td> <td> - </td> <td> - </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Advanced devices access control
|
||||
<sup><A HREF="#8">8</A></sup></b></td> <td> + </td> <td> - </td> <td> - </td> <td> + </td>
|
||||
<sup><A HREF="#7">7</A></sup></b></td> <td> + </td> <td> - </td> <td> - </td> <td> + </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Automatic sessions reassignment (changes in the
|
||||
@@ -157,12 +154,12 @@ any target reconfiguration in a PnP-like manner)</b></td> <td> + </td> <td> -
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Safe RESERVE/RELEASE implementation according to
|
||||
SCSI requirements <sup><A HREF="#10">10</A></sup></b></td> <td> Safe </td> <td> Safe </td> <td> Safe from
|
||||
SCSI requirements <sup><A HREF="#9">9</A></sup></b></td> <td> Safe </td> <td> Safe </td> <td> Safe from
|
||||
v1.4.18</td> <td> Not safe </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Safe implementation of Task Management commands
|
||||
<sup><A HREF="#11">11</A></sup></b></td> <td> Safe </td> <td> Not safe </td> <td> Not safe </td> <td> LUN RESET - safe.
|
||||
<sup><A HREF="#10">10</A></sup></b></td> <td> Safe </td> <td> Not safe </td> <td> Not safe </td> <td> LUN RESET - safe.
|
||||
Other TM commands not
|
||||
implemented. </td>
|
||||
</tr>
|
||||
@@ -170,15 +167,15 @@ SCSI requirements <sup><A HREF="#10">10</A></sup></b></td> <td> Safe </td> <td
|
||||
<td align="left"><b>Support for SCSI task attributes, including
|
||||
ORDERED commands</b></td> <td> + </td> <td> + </td> <td> -, <br> data
|
||||
corruption possible
|
||||
<sup><A HREF="#12">
|
||||
12</A></sup></td> <td> -, <br>data
|
||||
<sup><A HREF="#11">
|
||||
11</A></sup></td> <td> -, <br>data
|
||||
corruption possible
|
||||
<sup><A HREF="#12">
|
||||
12</A></sup> </td>
|
||||
<sup><A HREF="#11">
|
||||
11</A></sup> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Persistent (SCSI-3) Reservations
|
||||
(Windows 2008 clustering / RHEL5 I/O fencing)</b></td> <td> + </td> <td> + <br> (limited
|
||||
(Windows 2008 clustering / RHEL5 I/O fencing)</b></td> <td> + </td> <td> + <br> (not all
|
||||
functionality
|
||||
implemented)</td> <td> - </td> <td> + </td>
|
||||
<tr>
|
||||
@@ -188,9 +185,9 @@ Through Power Loss Persistent Reservation data</b></td> <td> Durable </td> <td
|
||||
<tr>
|
||||
<td align="left"><b>ALUA</b></td> <td> +/- (Implicit
|
||||
only)<sup>
|
||||
<A HREF="#20">20</A>
|
||||
</sup> </td> <td> - </td> <td> - </td> <td> +/-<sup><A HREF="#20">
|
||||
20</A></sup></td>
|
||||
<A HREF="#19">19</A>
|
||||
</sup> </td> <td> - </td> <td> - </td> <td> +/-<sup><A HREF="#19">
|
||||
19</A></sup></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Failover Clustering</b></td> <td> + </td> <td> + </td> <td> + </td> <td> + </td>
|
||||
@@ -233,7 +230,7 @@ apply changes in the config file on fly without any restarts</b></td> <td> scsta
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>SCSI MIBs</b></td> <td> - </td> <td> - </td> <td> - </td> <td> +-
|
||||
<sup><A HREF="#13">13</A></sup></td>
|
||||
<sup><A HREF="#12">12</A></sup></td>
|
||||
</tr>
|
||||
|
||||
|
||||
@@ -244,7 +241,7 @@ apply changes in the config file on fly without any restarts</b></td> <td> scsta
|
||||
<td align="left"><b>iSCSI</b></td> <td> + </td> <td> + </td> <td> + </td> <td> + </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>QLogic (Fibre Channel)</b></td> <td> + </td> <td> - </td> <td> - </td> <td> Preliminary</td>
|
||||
<td align="left"><b>QLogic (Fibre Channel and FCoE)</b></td> <td> + </td> <td> - </td> <td> - </td> <td> Preliminary</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Emulex (Fibre Channel and FCoE)</b></td> <td> + </td> <td> - </td> <td> - </td> <td> - </td>
|
||||
@@ -253,7 +250,7 @@ apply changes in the config file on fly without any restarts</b></td> <td> scsta
|
||||
<td align="left"><b>SRP</b></td> <td> + </td> <td> - </td> <td> - </td> <td> Preliminary </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>iSER</b></td> <td> - </td> <td> + </td> <td> - </td> <td> - </td>
|
||||
<td align="left"><b>iSER</b></td> <td> - </td> <td> + </td> <td> - </td> <td> Preliminary </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Marvell (SAS)</b></td> <td> Beta </td> <td> - </td> <td> - </td> <td> - </td>
|
||||
@@ -275,7 +272,7 @@ apply changes in the config file on fly without any restarts</b></td> <td> scsta
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Local access to emulated backstorage devices
|
||||
<sup><A HREF="#7">7</A></sup></b></td> <td> scst_local </td> <td> - </td> <td> - </td> <td> tcm_loop </td>
|
||||
<sup><A HREF="#6">6</A></sup></b></td> <td> scst_local </td> <td> - </td> <td> - </td> <td> tcm_loop </td>
|
||||
</tr>
|
||||
<tr bgcolor="#E0E0E0">
|
||||
<td colspan="5"> <b>Supported backstorage</b>
|
||||
@@ -300,32 +297,32 @@ apply changes in the config file on fly without any restarts</b></td> <td> scsta
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>SCSI pass-through
|
||||
<sup><A HREF="#14">14</A></sup></b></td> <td> + </td> <td> Single
|
||||
<sup><A HREF="#13">13</A></sup></b></td> <td> + </td> <td> Single
|
||||
initiator only, not
|
||||
enforced<sup>
|
||||
<A HREF="#15">15</A>
|
||||
<A HREF="#14">14</A>
|
||||
</sup> </td> <td> - </td> <td> Single initiator only, not enforced,
|
||||
limited functionality for tapes
|
||||
<sup><A HREF="#15">15</A></sup></td>
|
||||
<sup><A HREF="#14">14</A></sup></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Zero-copy data read/write to/from backstorage
|
||||
</b></td> <td>BLOCKIO, user space
|
||||
FILEIO in O_DIRECT mode,
|
||||
pass-through <sup>
|
||||
<A HREF="#16">16</A>
|
||||
<A HREF="#15">15</A>
|
||||
</sup></td> <td> - <sup>
|
||||
<A HREF="#6">6</A>
|
||||
<A HREF="#5">5</A>
|
||||
</sup> </td> <td> BLOCKIO </td> <td> BLOCKIO, pass-
|
||||
through </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Cache safe<sup><A HREF="#9">9</A></sup>
|
||||
<td align="left"><b>Cache safe<sup><A HREF="#8">8</A></sup>
|
||||
FILEIO</b></td> <td> Safe </td> <td>Safe only RDWR
|
||||
backend</td> <td> Safe </td> <td> Safe </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Cache safe<sup><A HREF="#9">9</A></sup>
|
||||
<td align="left"><b>Cache safe<sup><A HREF="#8">8</A></sup>
|
||||
BLOCKIO</b></td> <td> Safe </td> <td> - </td> <td> Not safe </td> <td> Safe </td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -348,7 +345,7 @@ CD devices</b></td> <td> - </td> <td> + </td> <td> - </td> <td> - </td>
|
||||
devices (VTL)</b></td> <td> - </td> <td>Experimental</td> <td> - </td> <td> - </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Thin provisioning support</b></td> <td>+<br></td> <td> - </td> <td> - </td> <td> + </td>
|
||||
<td align="left"><b>Thin provisioning support</b></td> <td>+<br></td> <td> ? </td> <td> - </td> <td> + </td>
|
||||
</tr>
|
||||
|
||||
<tr bgcolor="#E0E0E0">
|
||||
@@ -356,10 +353,10 @@ devices (VTL)</b></td> <td> - </td> <td>Experimental</td> <td> - </td> <
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="left"><b>Architecture</b></td> <td> Split <sup>
|
||||
<A HREF="#2">2</A>
|
||||
<A HREF="#1">1</A>
|
||||
</sup> </td> <td> User space
|
||||
only </td> <td> Split <sup>
|
||||
<A HREF="#2">2</A>
|
||||
<A HREF="#1">1</A>
|
||||
</sup></td> <td> Kernel only </td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -370,10 +367,10 @@ devices (VTL)</b></td> <td> - </td> <td>Experimental</td> <td> - </td> <
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Zero-copy data send/receive</b></td> <td> Send only<sup>
|
||||
<A HREF="#17">17</A>
|
||||
<A HREF="#16">16</A>
|
||||
</sup> </td> <td> In some cases,
|
||||
send only <sup>
|
||||
<A HREF="#6">6</A>
|
||||
<A HREF="#5">5</A>
|
||||
</sup> </td> <td> Send only</td> <td> Send only </td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -414,14 +411,14 @@ target reconfiguration in a PnP-like manner)</b></td> <td> + </td> <td> - </t
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Safe implementation of Task Management commands
|
||||
<sup><A HREF="#11">11</A></sup></b></td> <td> Safe </td> <td> Not safe </td> <td> Not safe </td> <td> ABORT TASK - not safe,
|
||||
<sup><A HREF="#10">10</A></sup></b></td> <td> Safe </td> <td> Not safe </td> <td> Not safe </td> <td> ABORT TASK - not safe,
|
||||
LUN RESET - safe,
|
||||
other TM commands not
|
||||
implemented. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Safe implementation of connections and sessions
|
||||
reinstatement <sup><A HREF="#18">18</A></sup></b></td> <td> Safe </td> <td> Not safe </td> <td> Not safe </td> <td> Not safe </td>
|
||||
reinstatement <sup><A HREF="#17">17</A></sup></b></td> <td> Safe </td> <td> Not safe </td> <td> Not safe </td> <td> Not safe </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Usage of hardware instructions for digest
|
||||
@@ -432,14 +429,14 @@ calculations, if available</b></td> <td> + </td> <td> - </td> <td> - </td>
|
||||
</b></td> <td> + </td> <td> - </td> <td> - </td> <td> - </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Safe restart <sup><A HREF="#19">19</A></sup>
|
||||
<td align="left"><b>Safe restart <sup><A HREF="#18">18</A></sup>
|
||||
</b></td> <td> Safe </td> <td> ? </td> <td> Not safe before
|
||||
v1.4.18. After -
|
||||
probably safe.</td> <td> ?</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>iSCSI MIBs</b></td> <td> - </td> <td> - </td> <td> - </td> <td> +-
|
||||
<sup><A HREF="#13">13</A></sup></td>
|
||||
<sup><A HREF="#12">12</A></sup></td>
|
||||
</tr>
|
||||
<tr bgcolor="#E0E0E0">
|
||||
<td colspan="5"> <b>Local access target</b>
|
||||
@@ -456,49 +453,45 @@ target reconfiguration in a PnP-like manner)</b></td> <td> + </td> <td> - </t
|
||||
<br>
|
||||
<p><strong><big><u>REMARKS:</u></big></strong></p>
|
||||
|
||||
<p><A NAME="1"></A> 1. STGT has all SCSI target processing and memory management in the user space. In the kernel it has only a small library
|
||||
to help in-kernel target drivers to interact with it. As a direct consequence, neither iSCSI, nor iSER as well as
|
||||
any other user space STGT target need any STGT kernel modules loaded to run.</p>
|
||||
<p><A NAME="1"></A> 1. All iSCSI management implemented in user space and actual data transfers in kernel space without user space involved.</p>
|
||||
|
||||
<p><A NAME="2"></A> 2. All iSCSI management implemented in user space and actual data transfers in kernel space without user space involved.</p>
|
||||
|
||||
<p><A NAME="3"></A> 3. The result "in average" is listed. One target can be better somewhere, another one somewhere else. Although manual tuning of target and
|
||||
<p><A NAME="2"></A> 2. The result "in average" is listed. One target can be better somewhere, another one somewhere else. Although manual tuning of target and
|
||||
system parameters tends the restore the difference listed in the comparison. You can find example measurements <a href="vl_res.txt">here</a>,
|
||||
<a href="bart_res.txt">here</a> and <a href="tomasz_res.txt">here</a>.</p>
|
||||
|
||||
<p><A NAME="4"></A> 4. All SCST and its drivers' kernel patches supposed to be applied and SCST with the drivers built in the release or performance build.
|
||||
<p><A NAME="3"></A> 3. All SCST and its drivers' kernel patches supposed to be applied and SCST with the drivers built in the release or performance build.
|
||||
Without the kernel patches SCST performance will be at "****+" level, except for the case, when user space backstorage handler used
|
||||
with iSCSI-SCST iSCSI target driver, where performance will be at "***+" level.</p>
|
||||
|
||||
<p><A NAME="5"></A> 5. In SCST data are always passed in zero-copy manner between target and backend drivers without need for any
|
||||
<p><A NAME="4"></A> 4 In SCST data are always passed in zero-copy manner between target and backend drivers without need for any
|
||||
additional kernel patches, except in case, when local access (scst_local) used with user space backend. </p>
|
||||
|
||||
<p><A NAME="6"></A> 6. Some zero-copy functionality isn't available from user space, sometimes fundamentally.
|
||||
<p><A NAME="5"></A> 5. Some zero-copy functionality isn't available from user space, sometimes fundamentally.
|
||||
For instance, zero-copy FILEIO with page cache or zero-copy send to a socket. Also STGT can't use splice() for in-kernel
|
||||
target drivers, because it has memory management in user space. To use splice() with socket-based user space target drivers
|
||||
STGT would need a deep redesign of internal interactions between target drivers, core and backend handlers. But in
|
||||
some cases STGT can use zero-copy sendfile().</p>
|
||||
|
||||
<p><A NAME="7"></A> 7. "Local access to emulated backstorage devices" means that you can access emulated by a SCSI target devices
|
||||
<p><A NAME="6"></A> 6. "Local access to emulated backstorage devices" means that you can access emulated by a SCSI target devices
|
||||
locally on the target host. For instance, you can mount your ISO image from emulated by the target
|
||||
CDROM device locally on the target host.</p>
|
||||
|
||||
<p><A NAME="8"></A> 8. "Advanced devices access control" means that different initiators can see different sets
|
||||
<p><A NAME="7"></A> 7. "Advanced devices access control" means that different initiators can see different sets
|
||||
of devices from the same target. This feature is required for hardware targets, which don't have ability
|
||||
to create virtual targets.</p>
|
||||
|
||||
<p><A NAME="9"></A> 9. "Cache safe" means that cache synchronization commands (SYNCHRONIZE_CACHE and FUA attribute) from initiators perform
|
||||
<p><A NAME="8"></A> 8. "Cache safe" means that cache synchronization commands (SYNCHRONIZE_CACHE and FUA attribute) from initiators perform
|
||||
what they expected to perform, i.e. push all the requested blocks from all caches, including devices' caches,
|
||||
to non-volatile media.</p>
|
||||
|
||||
<p><A NAME="10"></A> 10. SCSI requires that if an initiator clears reservation held by another initiator, the reservation holder must be notified
|
||||
<p><A NAME="9"></A> 9. SCSI requires that if an initiator clears reservation held by another initiator, the reservation holder must be notified
|
||||
about the reservation clearance. Otherwise, several initiators can at the same time change supposed to be protected by the
|
||||
reservation data, which can corrupt them. This is what was called
|
||||
<a href="http://communities.vmware.com/thread/53797?tstart=0&start=15">"Russian roulette with your data"</a> on the VMware
|
||||
community forum by someone working for VMware. But, sure, it can affect not only VMware, but also any other cluster
|
||||
implementation, relying on this functionality.</p>
|
||||
|
||||
<p><A NAME="11"></A> 11. After a task management command completed and before the corresponding response was sent to the initiator, who sent that task management
|
||||
<p><A NAME="10"></A> 10. After a task management command completed and before the corresponding response was sent to the initiator, who sent that task management
|
||||
command, all the affected SCSI commands must get into a state, where they can't affect following after
|
||||
the tasks management response commands from this initiator. This is the safe implementation.
|
||||
The unsafe implementation only marks all the affected
|
||||
@@ -508,17 +501,17 @@ target reconfiguration in a PnP-like manner)</b></td> <td> + </td> <td> - </t
|
||||
SCSI command, which initiator will send after it received the task management response thinking
|
||||
that all the aborted commands actually fully aborted. This could lead to a data corruption.</p>
|
||||
|
||||
<p><A NAME="12"></A> 12. Both IET and LIO report in INQUIRY command response support for full task management model. But they process ORDERED
|
||||
<p><A NAME="11"></A> 11. Both IET and LIO report in INQUIRY command response support for full task management model. But they process ORDERED
|
||||
commands the same way as SIMPLE commands, i.e. allow free reorder of them before they get executed. That violates SCSI standard
|
||||
and can lead to a data corruption to any application relying on commands order provided by ORDERED attribute.</p>
|
||||
|
||||
<p><A NAME="13"></A> 13. LIO exports the information needed for an RFC 4455 implementation, but requires additional RFC 4455 implementing module.
|
||||
<p><A NAME="12"></A> 12. LIO exports the information needed for an RFC 4455 implementation, but requires additional RFC 4455 implementing module.
|
||||
At the moment, there is no open source implementation of such module.</p>
|
||||
|
||||
<p><A NAME="14"></A> 14. SCSI pass-through mode allows to export your local SCSI-capable device. For instance with it you can share your parallel
|
||||
<p><A NAME="13"></A> 13. SCSI pass-through mode allows to export your local SCSI-capable device. For instance with it you can share your parallel
|
||||
SCSI tape or SATA DVD-RW device to your iSCSI network.</p>
|
||||
|
||||
<p><A NAME="15"></A> 15. STGT and LIO don't emulate all the necessary SCSI host functionality to allow to share SCSI devices
|
||||
<p><A NAME="14"></A> 14. STGT and LIO don't emulate all the necessary SCSI host functionality to allow to share SCSI devices
|
||||
in pass-through mode to several initiators, although LIO has some necessary processing, but not all.
|
||||
They can only pass SCSI commands from initiators to
|
||||
SCSI devices and responses back. This is safe only with a single initiator. This limitation
|
||||
@@ -528,22 +521,22 @@ target reconfiguration in a PnP-like manner)</b></td> <td> + </td> <td> - </t
|
||||
Also LIO in pass-through mode doesn't do necessary sense processing for tape devices to
|
||||
correctly return residual information, so tapes can used with it with limited functionality.</p>
|
||||
|
||||
<p><A NAME="16"></A> 16. You can find a proposal how to implement zero-copy FILEIO in SCST on the <a href="contributing.html#ZC_READ">
|
||||
<p><A NAME="15"></A> 15. You can find a proposal how to implement zero-copy FILEIO in SCST on the <a href="contributing.html#ZC_READ">
|
||||
Contributing</a> page.</p>
|
||||
|
||||
<p><A NAME="17"></A> 17. Doesn't need any kernel patch, except in the case, when used with user space backend.</p>
|
||||
<p><A NAME="16"></A> 16. Doesn't need any kernel patch, except in the case, when used with user space backend.</p>
|
||||
|
||||
<p><A NAME="18"></A> 18. Connections and sessions reinstatement is, basically, a kind of Task Management command, because it implies commands aborting.
|
||||
<p><A NAME="17"></A> 17. Connections and sessions reinstatement is, basically, a kind of Task Management command, because it implies commands aborting.
|
||||
So, similarly to the safe task management above, a safe implementation of connections and sessions reinstatement
|
||||
must not accept SCSI commands from new connection/session until all the SCSI commands in
|
||||
being reinstated connection/session get into a state, where they can't affect new commands.</p>
|
||||
|
||||
<p><A NAME="19"></A> 19. "Safe restart" means that after the iSCSI target restart, all the connected initiators will seamlessly restore all existing before
|
||||
<p><A NAME="18"></A> 18. "Safe restart" means that after the iSCSI target restart, all the connected initiators will seamlessly restore all existing before
|
||||
the restart connections. "Not safe" means that, most likely, the connected initiators will fail to restore
|
||||
existing connections with some errors. However, your iSCSI initiator also should be able to handle the safe restart. For instance,
|
||||
old (pre-CentOS/RHEL 5) open-iscsi has problems in this area. But the latest versions do it pretty well.</p>
|
||||
|
||||
<p><A NAME="20"></A> 20. Generic implementation, i.e. not coupled to any particular cluster implementation, which means it is needed additional effort
|
||||
<p><A NAME="19"></A> 19. Generic implementation, i.e. not coupled to any particular cluster implementation, which means it is needed additional effort
|
||||
to used with each particular cluster setup.</p>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -198,32 +198,6 @@
|
||||
with some programs depending on the result of GET CONFIGURATION command execution.</p>
|
||||
|
||||
<p>It would be good to add support for it in the SCST core.</p>
|
||||
|
||||
<A NAME="Per_Device_Suspend"></A><h3>Per-device suspending</h3>
|
||||
|
||||
<p>Currently before doing any management operations SCST core performs so called "activities suspending", i.e.
|
||||
it suspends new coming SCSI commands and wait until currently being executed ones finished. It allows to
|
||||
simplify internal locking and reference counting a lot, but has a drawback that it is global, i.e. affects
|
||||
all devices and SCSI commands, even ones which don't participate in the management operation. In the majority
|
||||
of regular cases it works pretty well, but sometimes it can be a problem.
|
||||
For instance, if a SCSI command needs a big amount of execution time (hours for some tapes operations),
|
||||
the management command and all other SCSI commands will wait until it's finished. Even worse, if a user space
|
||||
dev handler hangs and stops processing commands, any SCST management command will not be able to complete and fail
|
||||
with timeout until the user space dev handler gets killed.</p>
|
||||
|
||||
<p>The global suspending should be changed to more fine-grained per-device suspending
|
||||
and only for cases where it's really needed, like device unregistration. This is a very tricky task, because
|
||||
all the internal SCST locking should be reimplemented.</p>
|
||||
|
||||
<A NAME="ACA"></A><h3>Auto Contingent Allegiance (ACA)</h3>
|
||||
|
||||
<p>Auto Contingent Allegiance (ACA) - is a powerful SCSI state, where in case of some special conditions,
|
||||
like a command finished with an error, all subsequent SCSI commands are delayed or aborted by SCSI device.
|
||||
It is necessary to protect order of queued commands after errors. See SAM for more details.</p>
|
||||
|
||||
<p>There is a patch <a href="aca.diff">aca.diff</a> implementing ACA for SCST 1.0. Update of it for SCST 3.0
|
||||
is welcome!</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user