From 9e3f25547319c29d2766b25f8b703ca2ac984bec Mon Sep 17 00:00:00 2001
From: Vladislav Bolkhovitin
Date: Fri, 5 Apr 2013 03:04:59 +0000
Subject: [PATCH] Web updates
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4831 d57e44dd-8a1f-0410-8b47-8ef2f437770f
---
www/aca.diff | 621 ------------------------------------------
www/comparison.html | 129 +++++----
www/contributing.html | 26 --
3 files changed, 61 insertions(+), 715 deletions(-)
delete mode 100644 www/aca.diff
diff --git a/www/aca.diff b/www/aca.diff
deleted file mode 100644
index bd1ef8e5f..000000000
--- a/www/aca.diff
+++ /dev/null
@@ -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);
diff --git a/www/comparison.html b/www/comparison.html
index 2ac939151..d6d2063b1 100644
--- a/www/comparison.html
+++ b/www/comparison.html
@@ -52,7 +52,7 @@
mailing list and it will be corrected.
- As on June 2011.
+ As on June 2011, briefly reviewed April 2013.
@@ -68,32 +68,30 @@
| General
|
-| Upstream kernel | - | Interface with
- in-kernel target
- drivers (obsolete) | - | Since 2.6.38 |
+Upstream kernel | - | - | - | Since 2.6.38 |
| Generic Target Engine | + | + | iSCSI only | + |
-| Architecture | Kernel only | User space only
- 1
- | - | Kernel only |
+Architecture | Kernel only | User space only | Split
+ 1
+ | Kernel only |
-| Stability | + | + | + | Probably (no released packages) |
+Stability | + | + | + | Probably |
-| Performance 3 | *****
- 4
+| Performance 2 | *****
+ 3
| *** | **** | ****- |
|
| Zero-copy passing data between target and
backend drivers | +
- 5
+ 4
| +
- 6
+ 5
| + | + |
@@ -122,12 +120,11 @@ transfer values (Wide (parallel) SCSI, SAS) | + | - | Backstorage handlers in kernel space + | - | - | + |
-| Backstorage handlers in user space | + | + | - | Via STGT
- (under development) |
+Backstorage handlers in user space | + | + | - | - |
| Advanced devices access control
-8 | + | - | - | + |
+7 + | - | - | + |
| Automatic sessions reassignment (changes in the
@@ -157,12 +154,12 @@ any target reconfiguration in a PnP-like manner) | + | -
|
| Safe RESERVE/RELEASE implementation according to
-SCSI requirements 10 | Safe | Safe | Safe from
+SCSI requirements 9 | Safe | Safe | Safe from
v1.4.18 | Not safe |
| Safe implementation of Task Management commands
-11 | Safe | Not safe | Not safe | LUN RESET - safe.
+10 | Safe | Not safe | Not safe | LUN RESET - safe.
Other TM commands not
implemented. |
@@ -170,15 +167,15 @@ SCSI requirements 10 Safe | Support for SCSI task attributes, including
ORDERED commands | + | + | -, data
corruption possible
-
- 12 | -, data
+
+ 11 | -, data
corruption possible
-
- 12 |
+
+ 11
| Persistent (SCSI-3) Reservations
-(Windows 2008 clustering / RHEL5 I/O fencing) | + | + (limited
+(Windows 2008 clustering / RHEL5 I/O fencing) | + | + (not all
functionality
implemented) | - | + |
@@ -188,9 +185,9 @@ Through Power Loss Persistent Reservation data | Durable |
| ALUA | +/- (Implicit
only)
- 20
- | - | - | +/-
- 20 |
+ 19
+ - | - | +/-
+ 19 |
| Failover Clustering | + | + | + | + |
@@ -233,7 +230,7 @@ apply changes in the config file on fly without any restarts scsta
|
| SCSI MIBs | - | - | - | +-
- 13 |
+ 12
@@ -244,7 +241,7 @@ apply changes in the config file on fly without any restarts scsta
| iSCSI | + | + | + | + |
-| QLogic (Fibre Channel) | + | - | - | Preliminary |
+QLogic (Fibre Channel and FCoE) | + | - | - | Preliminary |
| Emulex (Fibre Channel and FCoE) | + | - | - | - |
@@ -253,7 +250,7 @@ apply changes in the config file on fly without any restarts scsta
| SRP | + | - | - | Preliminary |
-| iSER | - | + | - | - |
+iSER | - | + | - | Preliminary |
| Marvell (SAS) | Beta | - | - | - |
@@ -275,7 +272,7 @@ apply changes in the config file on fly without any restarts scsta
|
| Local access to emulated backstorage devices
-7 | scst_local | - | - | tcm_loop |
+6 scst_local | - | - | tcm_loop |
| Supported backstorage
@@ -300,32 +297,32 @@ apply changes in the config file on fly without any restarts | scsta
|
| SCSI pass-through
- 14 | + | Single
+ 13 | + | Single
initiator only, not
enforced
- 15
+ 14
| - | Single initiator only, not enforced,
limited functionality for tapes
- 15 |
+ 14
| Zero-copy data read/write to/from backstorage
| BLOCKIO, user space
FILEIO in O_DIRECT mode,
pass-through
- 16
+ 15
| -
- 6
+ 5
| BLOCKIO | BLOCKIO, pass-
through |
-| Cache safe9
+ | Cache safe8
FILEIO | Safe | Safe only RDWR
backend | Safe | Safe |
-| Cache safe9
+ | Cache safe8
BLOCKIO | Safe | - | Not safe | Safe |
@@ -348,7 +345,7 @@ CD devices | - | + | - | - |
devices (VTL) - | Experimental | - | - |
-| Thin provisioning support | +
| - | - | + |
+Thin provisioning support | +
| ? | - | + |
@@ -356,10 +353,10 @@ devices (VTL) | - | Experimental | - | <
| Architecture | Split
- 2
+ 1
| User space
only | Split
- 2
+ 1
| Kernel only |
@@ -370,10 +367,10 @@ devices (VTL) | - | Experimental | - | <
| Zero-copy data send/receive | Send only
- 17
+ 16
| In some cases,
send only
- 6
+ 5
| Send only | Send only |
@@ -414,14 +411,14 @@ target reconfiguration in a PnP-like manner) | + | -
|
| Safe implementation of Task Management commands
-11 | Safe | Not safe | Not safe | ABORT TASK - not safe,
+10 | Safe | Not safe | Not safe | ABORT TASK - not safe,
LUN RESET - safe,
other TM commands not
implemented. |
| Safe implementation of connections and sessions
-reinstatement 18 | Safe | Not safe | Not safe | Not safe |
+reinstatement 17 Safe | Not safe | Not safe | Not safe |
| Usage of hardware instructions for digest
@@ -432,14 +429,14 @@ calculations, if available | + | - | - |
+ | - | - | - |
-| Safe restart 19
+ | Safe restart 18
| Safe | ? | Not safe before
v1.4.18. After -
probably safe. | ? |
| iSCSI MIBs | - | - | - | +-
- 13 |
+ 12
| Local access target
@@ -456,49 +453,45 @@ target reconfiguration in a PnP-like manner) | + | -
REMARKS:
- 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.
+ 1. All iSCSI management implemented in user space and actual data transfers in kernel space without user space involved.
- 2. All iSCSI management implemented in user space and actual data transfers in kernel space without user space involved.
-
- 3. The result "in average" is listed. One target can be better somewhere, another one somewhere else. Although manual tuning of target and
+ 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 here,
here and here.
- 4. All SCST and its drivers' kernel patches supposed to be applied and SCST with the drivers built in the release or performance build.
+ 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.
- 5. In SCST data are always passed in zero-copy manner between target and backend drivers without need for any
+ 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.
- 6. Some zero-copy functionality isn't available from user space, sometimes fundamentally.
+ 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().
- 7. "Local access to emulated backstorage devices" means that you can access emulated by a SCSI target devices
+ 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.
- 8. "Advanced devices access control" means that different initiators can see different sets
+ 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.
- 9. "Cache safe" means that cache synchronization commands (SYNCHRONIZE_CACHE and FUA attribute) from initiators perform
+ 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.
- 10. SCSI requires that if an initiator clears reservation held by another initiator, the reservation holder must be notified
+ 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
"Russian roulette with your data" 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.
- 11. After a task management command completed and before the corresponding response was sent to the initiator, who sent that task management
+ 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) | + | -
- 12. Both IET and LIO report in INQUIRY command response support for full task management model. But they process ORDERED
+ 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.
- 13. LIO exports the information needed for an RFC 4455 implementation, but requires additional RFC 4455 implementing module.
+ 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.
- 14. SCSI pass-through mode allows to export your local SCSI-capable device. For instance with it you can share your parallel
+ 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.
- 15. STGT and LIO don't emulate all the necessary SCSI host functionality to allow to share SCSI devices
+ 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) | + | -
- 16. You can find a proposal how to implement zero-copy FILEIO in SCST on the
+ 15. You can find a proposal how to implement zero-copy FILEIO in SCST on the
Contributing page.
- 17. Doesn't need any kernel patch, except in the case, when used with user space backend.
+ 16. Doesn't need any kernel patch, except in the case, when used with user space backend.
- 18. Connections and sessions reinstatement is, basically, a kind of Task Management command, because it implies commands aborting.
+ 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.
- 19. "Safe restart" means that after the iSCSI target restart, all the connected initiators will seamlessly restore all existing before
+ 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.
- 20. Generic implementation, i.e. not coupled to any particular cluster implementation, which means it is needed additional effort
+ 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.
diff --git a/www/contributing.html b/www/contributing.html
index 02849fa66..0a1a92597 100644
--- a/www/contributing.html
+++ b/www/contributing.html
@@ -198,32 +198,6 @@
with some programs depending on the result of GET CONFIGURATION command execution.
It would be good to add support for it in the SCST core.
-
- Per-device suspending
-
- 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.
-
- 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.
-
- Auto Contingent Allegiance (ACA)
-
- 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.
-
- There is a patch aca.diff implementing ACA for SCST 1.0. Update of it for SCST 3.0
- is welcome!
-
|