- Cleanups
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Tue, 3 Mar 2009 18:02:25 +0000 (18:02 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Tue, 3 Mar 2009 18:02:25 +0000 (18:02 +0000)
 - scst_set_initial_UA() added. It sets initial Unit Attention for session, replacing default scst_sense_reset_UA
 - task_mgmt_affected_cmds_done() callback added in struct scst_tgt_template. It's informs target driver that a received task management fun
ction has been completed.
 - Now devices blocked only in reset TM commands. ABORTs, etc. now done without devices blocking
 - scst_unregister_session_ex() removed, since there are no users of it

git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@684 d57e44dd-8a1f-0410-8b47-8ef2f437770f

scst/include/scst.h
scst/include/scst_const.h
scst/src/scst_lib.c
scst/src/scst_priv.h
scst/src/scst_targ.c

index 49ffeeb..2f274ee 100644 (file)
@@ -153,22 +153,22 @@ typedef _Bool bool;
  *************************************************************/
 
 /* LUN translation (mcmd->tgt_dev assignment) */
-#define SCST_MGMT_CMD_STATE_INIT     0
+#define SCST_MCMD_STATE_INIT     0
 
 /* Mgmt cmd is ready for processing */
-#define SCST_MGMT_CMD_STATE_READY    1
+#define SCST_MCMD_STATE_READY    1
 
 /* Mgmt cmd is being executing */
-#define SCST_MGMT_CMD_STATE_EXECUTING 2
+#define SCST_MCMD_STATE_EXECUTING 2
 
-/* Reservations are going to be cleared, if necessary */
-#define SCST_MGMT_CMD_STATE_CHECK_NEXUS_LOSS 3
+/* Post check when affected commands done */
+#define SCST_MCMD_STATE_POST_AFFECTED_CMDS_DONE 3
 
 /* Target driver's task_mgmt_fn_done() is going to be called */
-#define SCST_MGMT_CMD_STATE_DONE     4
+#define SCST_MCMD_STATE_DONE     4
 
 /* The mcmd finished */
-#define SCST_MGMT_CMD_STATE_FINISHED 5
+#define SCST_MCMD_STATE_FINISHED 5
 
 /*************************************************************
  ** Constants for "atomic" parameter of SCST's functions
@@ -616,21 +616,28 @@ struct scst_tgt_template {
        int (*pre_exec) (struct scst_cmd *cmd);
 
        /*
-        * This function informs the driver that a
-        * received task management function has been completed. This
-        * function is necessary because low-level protocols have some
-        * means of informing the initiator about the completion of a
-        * Task Management function. This function being called will
-        * signify that a Task Management function is completed as far
-        * as the mid-level is concerned. Any information that must be
-        * stored about the command is the responsibility of the low-
-        * level driver. No return value expected.
+        * This function informs the driver that all affected by the
+        * corresponding task management function commands have beed completed.
+        * No return value expected.
         *
-        * This function is expected to be NON-BLOCKING
+        * This function is expected to be NON-BLOCKING.
         *
         * Called without any locks held from a thread context.
         *
-        * MUST HAVE if the target supports ABORTs
+        * OPTIONAL
+        */
+       void (*task_mgmt_affected_cmds_done) (struct scst_mgmt_cmd *mgmt_cmd);
+
+       /*
+        * This function informs the driver that the corresponding task 
+        * management function has been completed, i.e. all the corresponding
+        * commands completed and freed. No return value expected.
+        *
+        * This function is expected to be NON-BLOCKING.
+        *
+        * Called without any locks held from a thread context.
+        *
+        * MUST HAVE if the target supports task management.
         */
        void (*task_mgmt_fn_done) (struct scst_mgmt_cmd *mgmt_cmd);
 
@@ -987,7 +994,6 @@ struct scst_session {
        void (*init_result_fn) (struct scst_session *sess, void *data,
                                int result);
        void (*unreg_done_fn) (struct scst_session *sess);
-       void (*unreg_cmds_done_fn) (struct scst_session *sess);
 
 #ifdef CONFIG_SCST_MEASURE_LATENCY /* must be last */
        spinlock_t meas_lock;
@@ -1299,7 +1305,7 @@ struct scst_mgmt_cmd {
 
        struct scst_session *sess;
 
-       /* Mgmt cmd state, one of SCST_MGMT_CMD_STATE_* constants */
+       /* Mgmt cmd state, one of SCST_MCMD_STATE_* constants */
        int state;
 
        int fn;
@@ -1309,8 +1315,8 @@ struct scst_mgmt_cmd {
        unsigned int needs_unblocking:1;
        unsigned int lun_set:1;         /* set, if lun field is valid */
        unsigned int cmd_sn_set:1;      /* set, if cmd_sn field is valid */
-       /* set, if nexus loss check is done */
-       unsigned int nexus_loss_check_done:1;
+       /* set, if scst_mgmt_affected_cmds_done was called */
+       unsigned int affected_cmds_done_called:1;
 
        /*
         * Number of commands to finish before sending response,
@@ -1690,11 +1696,6 @@ struct scst_session *scst_register_session(struct scst_tgt *tgt, int atomic,
  *      the session is about to be completely freed. Can be NULL.
  *      Parameter:
  *       - sess - session
- *   unreg_cmds_done_fn - pointer to the function that will be
- *      asynchronously called when the last session's command completes, i.e.
- *      goes to XMIT stage. Can be NULL.
- *      Parameter:
- *       - sess - session
  *
  * Notes:
  *
@@ -1714,15 +1715,8 @@ struct scst_session *scst_register_session(struct scst_tgt *tgt, int atomic,
  *   but it also starts recovering stuck commands, if there are any.
  *   Otherwise, your target driver could wait for those commands forever.
  */
-void scst_unregister_session_ex(struct scst_session *sess, int wait,
-       void (*unreg_done_fn) (struct scst_session *sess),
-       void (*unreg_cmds_done_fn) (struct scst_session *sess));
-
-static inline void scst_unregister_session(struct scst_session *sess, int wait,
-       void (*unreg_done_fn) (struct scst_session *sess))
-{
-       scst_unregister_session_ex(sess, wait, unreg_done_fn, NULL);
-}
+void scst_unregister_session(struct scst_session *sess, int wait,
+       void (*unreg_done_fn) (struct scst_session *sess));
 
 /*
  * Registers dev handler driver
@@ -1921,6 +1915,11 @@ void scst_set_cmd_error(struct scst_cmd *cmd, int key, int asc, int ascq);
  */
 void scst_set_busy(struct scst_cmd *cmd);
 
+/*
+ * Sets initial Unit Attention for sess, replacing default scst_sense_reset_UA
+ */
+void scst_set_initial_UA(struct scst_session *sess, int key, int asc, int ascq);
+
 /*
  * Finds a command based on the supplied tag comparing it with one
  * that previously set by scst_cmd_set_tag().
index e2be7b8..ad71965 100644 (file)
 
 /*
  * Internal TM command issued by SCST in scst_unregister_session(). It is the
- * same as SCST_NEXUS_LOSS_SESS, except it calls unreg_cmds_done_fn().
+ * same as SCST_NEXUS_LOSS_SESS, except:
+ *  - it doesn't call task_mgmt_affected_cmds_done()
+ *  - it doesn't call task_mgmt_fn_done()
+ *  - it doesn't queue NEXUS LOSS UA.
  *
  * Target driver shall NEVER use it!!
  */
index bf8d0d2..1cc0192 100644 (file)
@@ -197,6 +197,56 @@ void scst_set_busy(struct scst_cmd *cmd)
 }
 EXPORT_SYMBOL(scst_set_busy);
 
+void scst_set_initial_UA(struct scst_session *sess, int key, int asc, int ascq)
+{
+       int i;
+
+       TRACE_ENTRY();
+
+       TRACE_MGMT_DBG("Setting for sess %p initial UA %x/%x/%x", sess, key,
+               asc, ascq);
+
+       /* Protect sess_tgt_dev_list_hash */
+       mutex_lock(&scst_mutex); 
+
+       for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
+               struct list_head *sess_tgt_dev_list_head =
+                       &sess->sess_tgt_dev_list_hash[i];
+               struct scst_tgt_dev *tgt_dev;
+
+               list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
+                               sess_tgt_dev_list_entry) {
+                       spin_lock_bh(&tgt_dev->tgt_dev_lock);
+                       if (!list_empty(&tgt_dev->UA_list)) {
+                               struct scst_tgt_dev_UA *ua;
+                               uint8_t *sense;
+
+                               ua = list_entry(tgt_dev->UA_list.next,
+                                       typeof(*ua), UA_list_entry);
+                               sense = ua->UA_sense_buffer;
+                               if ((sense[2] == UNIT_ATTENTION) &&
+                                   (sense[12] == 0x29) &&
+                                   (sense[13] == 0)) {
+                                       scst_set_sense(sense,
+                                               sizeof(ua->UA_sense_buffer),
+                                               key, asc, ascq);
+                               } else
+                                       PRINT_ERROR("%s",
+                                               "The first UA isn't RESET UA");
+                       } else
+                               PRINT_ERROR("%s", "There's no RESET UA to "
+                                       "replace");
+                       spin_unlock_bh(&tgt_dev->tgt_dev_lock);
+               }
+       }
+
+       mutex_unlock(&scst_mutex); 
+
+       TRACE_EXIT();
+       return;
+}
+EXPORT_SYMBOL(scst_set_initial_UA);
+
 int scst_get_cmd_abnormal_done_state(const struct scst_cmd *cmd)
 {
        int res;
@@ -642,7 +692,7 @@ out_free:
 static void scst_clear_reservation(struct scst_tgt_dev *tgt_dev);
 
 /* No locks supposed to be held, scst_mutex - held */
-void scst_nexus_loss(struct scst_tgt_dev *tgt_dev)
+void scst_nexus_loss(struct scst_tgt_dev *tgt_dev, bool queue_UA)
 {
        TRACE_ENTRY();
 
@@ -653,11 +703,13 @@ void scst_nexus_loss(struct scst_tgt_dev *tgt_dev)
        scst_free_all_UA(tgt_dev);
        spin_unlock_bh(&tgt_dev->tgt_dev_lock);
 
-       spin_lock_bh(&scst_temp_UA_lock);
-       scst_set_sense(scst_temp_UA, sizeof(scst_temp_UA),
-               SCST_LOAD_SENSE(scst_sense_nexus_loss_UA));
-       scst_check_set_UA(tgt_dev, scst_temp_UA, sizeof(scst_temp_UA), 0);
-       spin_unlock_bh(&scst_temp_UA_lock);
+       if (queue_UA) {
+               spin_lock_bh(&scst_temp_UA_lock);
+               scst_set_sense(scst_temp_UA, sizeof(scst_temp_UA),
+                       SCST_LOAD_SENSE(scst_sense_nexus_loss_UA));
+               scst_check_set_UA(tgt_dev, scst_temp_UA, sizeof(scst_temp_UA), 0);
+               spin_unlock_bh(&scst_temp_UA_lock);
+       }
 
        TRACE_EXIT();
        return;
index 57df677..7141c52 100644 (file)
@@ -251,7 +251,7 @@ struct scst_acg *scst_alloc_add_acg(const char *acg_name);
 int scst_destroy_acg(struct scst_acg *acg);
 
 int scst_sess_alloc_tgt_devs(struct scst_session *sess);
-void scst_nexus_loss(struct scst_tgt_dev *tgt_dev);
+void scst_nexus_loss(struct scst_tgt_dev *tgt_dev, bool queue_UA);
 
 int scst_acg_add_dev(struct scst_acg *acg, struct scst_device *dev,
                     uint64_t lun, int read_only);
index b4c4e48..1e2196f 100644 (file)
@@ -3659,9 +3659,9 @@ void scst_done_cmd_mgmt(struct scst_cmd *cmd)
                }
 
                if (mcmd->completed) {
-                       sBUG_ON(mcmd->nexus_loss_check_done);
+                       sBUG_ON(mcmd->affected_cmds_done_called);
                        mcmd->completed = 0;
-                       mcmd->state = SCST_MGMT_CMD_STATE_CHECK_NEXUS_LOSS;
+                       mcmd->state = SCST_MCMD_STATE_POST_AFFECTED_CMDS_DONE;
                        TRACE_MGMT_DBG("Adding mgmt cmd %p to active mgmt cmd "
                                "list", mcmd);
                        list_add_tail(&mcmd->mgmt_cmd_list_entry,
@@ -3692,7 +3692,7 @@ static int __scst_dec_finish_wait_count(struct scst_mgmt_cmd *mcmd, bool *wake)
        }
 
        if (mcmd->completed) {
-               mcmd->state = SCST_MGMT_CMD_STATE_DONE;
+               mcmd->state = SCST_MCMD_STATE_DONE;
                TRACE_MGMT_DBG("Adding mgmt cmd %p to active mgmt cmd "
                        "list", mcmd);
                list_add_tail(&mcmd->mgmt_cmd_list_entry,
@@ -3938,20 +3938,20 @@ static int scst_set_mcmd_next_state(struct scst_mgmt_cmd *mcmd)
        spin_lock_irq(&scst_mcmd_lock);
 
        if (mcmd->cmd_finish_wait_count == 0) {
-               if (!mcmd->nexus_loss_check_done)
-                       mcmd->state = SCST_MGMT_CMD_STATE_CHECK_NEXUS_LOSS;
+               if (!mcmd->affected_cmds_done_called)
+                       mcmd->state = SCST_MCMD_STATE_POST_AFFECTED_CMDS_DONE;
                else
-                       mcmd->state = SCST_MGMT_CMD_STATE_DONE;
+                       mcmd->state = SCST_MCMD_STATE_DONE;
                res = 0;
        } else if ((mcmd->cmd_done_wait_count == 0) &&
-                  (!mcmd->nexus_loss_check_done)) {
-               mcmd->state = SCST_MGMT_CMD_STATE_CHECK_NEXUS_LOSS;
+                  (!mcmd->affected_cmds_done_called)) {
+               mcmd->state = SCST_MCMD_STATE_POST_AFFECTED_CMDS_DONE;
                res = 0;
                goto out_unlock;
        } else {
                TRACE_MGMT_DBG("cmd_finish_wait_count(%d) not 0, preparing to "
                        "wait", mcmd->cmd_finish_wait_count);
-               mcmd->state = SCST_MGMT_CMD_STATE_EXECUTING;
+               mcmd->state = SCST_MCMD_STATE_EXECUTING;
                res = -1;
        }
 
@@ -4067,17 +4067,10 @@ static int scst_abort_task_set(struct scst_mgmt_cmd *mcmd)
 {
        int res;
        struct scst_tgt_dev *tgt_dev = mcmd->mcmd_tgt_dev;
-       struct scst_device *dev = tgt_dev->dev;
 
        TRACE(TRACE_MGMT, "Aborting task set (lun=%lld, mcmd=%p)",
              (long long unsigned int)tgt_dev->lun, mcmd);
 
-       mcmd->needs_unblocking = 1;
-
-       spin_lock_bh(&dev->dev_lock);
-       __scst_block_dev(dev);
-       spin_unlock_bh(&dev->dev_lock);
-
        __scst_abort_task_set(mcmd, tgt_dev);
 
        scst_unblock_aborted_cmds(0);
@@ -4131,12 +4124,6 @@ static int scst_clear_task_set(struct scst_mgmt_cmd *mcmd)
        TRACE(TRACE_MGMT, "Clearing task set (lun=%lld, mcmd=%p)",
                (long long unsigned int)mcmd->lun, mcmd);
 
-       mcmd->needs_unblocking = 1;
-
-       spin_lock_bh(&dev->dev_lock);
-       __scst_block_dev(dev);
-       spin_unlock_bh(&dev->dev_lock);
-
        __scst_abort_task_set(mcmd, mcmd->mcmd_tgt_dev);
 
        mutex_lock(&scst_mutex);
@@ -4201,7 +4188,7 @@ static int scst_mgmt_cmd_init(struct scst_mgmt_cmd *mcmd)
 
        TRACE_ENTRY();
 
-       mcmd->state = SCST_MGMT_CMD_STATE_READY;
+       mcmd->state = SCST_MCMD_STATE_READY;
 
        switch (mcmd->fn) {
        case SCST_ABORT_TASK:
@@ -4216,7 +4203,7 @@ static int scst_mgmt_cmd_init(struct scst_mgmt_cmd *mcmd)
                              "for tag %llu not found",
                              (long long unsigned int)mcmd->tag);
                        mcmd->status = SCST_MGMT_STATUS_TASK_NOT_EXIST;
-                       mcmd->state = SCST_MGMT_CMD_STATE_DONE;
+                       mcmd->state = SCST_MCMD_STATE_DONE;
                        spin_unlock_irq(&sess->sess_list_lock);
                        goto out;
                }
@@ -4269,7 +4256,7 @@ static int scst_mgmt_cmd_init(struct scst_mgmt_cmd *mcmd)
                                    "found",
                                    (long long unsigned int)mcmd->lun);
                        mcmd->status = SCST_MGMT_STATUS_LUN_NOT_EXIST;
-                       mcmd->state = SCST_MGMT_CMD_STATE_DONE;
+                       mcmd->state = SCST_MCMD_STATE_DONE;
                } else if (rc != 0)
                        res = rc;
                break;
@@ -4430,10 +4417,10 @@ static int scst_lun_reset(struct scst_mgmt_cmd *mcmd)
                if (rc != SUCCESS && mcmd->status == SCST_MGMT_STATUS_SUCCESS)
                        mcmd->status = SCST_MGMT_STATUS_FAILED;
 #else
-       /*
-        * scsi_reset_provider() returns very weird status, so let's
-        * always succeed
-        */
+               /*
+                * scsi_reset_provider() returns very weird status, so let's
+                * always succeed
+                */
 #endif
                dev->scsi_dev->was_reset = 0;
        }
@@ -4463,7 +4450,8 @@ static void scst_do_nexus_loss_sess(struct scst_mgmt_cmd *mcmd)
                        &sess->sess_tgt_dev_list_hash[i];
                list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
                                sess_tgt_dev_list_entry) {
-                       scst_nexus_loss(tgt_dev);
+                       scst_nexus_loss(tgt_dev,
+                               (mcmd->fn != SCST_UNREG_SESS_TM));
                }
        }
 
@@ -4490,9 +4478,6 @@ static int scst_abort_all_nexus_loss_sess(struct scst_mgmt_cmd *mcmd,
                        sess, mcmd);
        }
 
-       if (mcmd->fn != SCST_UNREG_SESS_TM)
-               mcmd->needs_unblocking = 1;
-
        mutex_lock(&scst_mutex);
 
        for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
@@ -4500,15 +4485,8 @@ static int scst_abort_all_nexus_loss_sess(struct scst_mgmt_cmd *mcmd,
                        &sess->sess_tgt_dev_list_hash[i];
                list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
                                sess_tgt_dev_list_entry) {
-                       struct scst_device *dev = tgt_dev->dev;
                        int rc;
 
-                       if (mcmd->fn != SCST_UNREG_SESS_TM) {
-                               spin_lock_bh(&dev->dev_lock);
-                               __scst_block_dev(dev);
-                               spin_unlock_bh(&dev->dev_lock);
-                       }
-
                        __scst_abort_task_set(mcmd, tgt_dev);
 
                        rc = scst_call_dev_task_mgmt_fn(mcmd, tgt_dev, 0);
@@ -4543,7 +4521,7 @@ static void scst_do_nexus_loss_tgt(struct scst_mgmt_cmd *mcmd)
                        struct scst_tgt_dev *tgt_dev;
                        list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
                                        sess_tgt_dev_list_entry) {
-                               scst_nexus_loss(tgt_dev);
+                               scst_nexus_loss(tgt_dev, true);
                        }
                }
        }
@@ -4558,9 +4536,7 @@ static int scst_abort_all_nexus_loss_tgt(struct scst_mgmt_cmd *mcmd,
        int res;
        int i;
        struct scst_tgt *tgt = mcmd->sess->tgt;
-       struct scst_acg *acg = mcmd->sess->acg;
        struct scst_session *sess;
-       struct scst_acg_dev *acg_dev;
 
        TRACE_ENTRY();
 
@@ -4572,18 +4548,8 @@ static int scst_abort_all_nexus_loss_tgt(struct scst_mgmt_cmd *mcmd,
                        tgt, mcmd);
        }
 
-       mcmd->needs_unblocking = 1;
-
        mutex_lock(&scst_mutex);
 
-       list_for_each_entry(acg_dev, &acg->acg_dev_list, acg_dev_list_entry) {
-               struct scst_device *dev = acg_dev->dev;
-
-               spin_lock_bh(&dev->dev_lock);
-               __scst_block_dev(dev);
-               spin_unlock_bh(&dev->dev_lock);
-       }
-
        list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) {
                for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
                        struct list_head *sess_tgt_dev_list_head =
@@ -4596,7 +4562,7 @@ static int scst_abort_all_nexus_loss_tgt(struct scst_mgmt_cmd *mcmd,
                                __scst_abort_task_set(mcmd, tgt_dev);
 
                                if (nexus_loss)
-                                       scst_nexus_loss(tgt_dev);
+                                       scst_nexus_loss(tgt_dev, true);
 
                                if (mcmd->sess == tgt_dev->sess) {
                                        rc = scst_call_dev_task_mgmt_fn(
@@ -4685,11 +4651,26 @@ out:
        return res;
 
 out_done:
-       mcmd->state = SCST_MGMT_CMD_STATE_DONE;
+       mcmd->state = SCST_MCMD_STATE_DONE;
        goto out;
 }
 
-static int scst_mgmt_cmd_check_nexus_loss(struct scst_mgmt_cmd *mcmd)
+static void scst_call_task_mgmt_affected_cmds_done(struct scst_mgmt_cmd *mcmd)
+{
+       struct scst_session *sess = mcmd->sess;
+
+       if ((sess->tgt->tgtt->task_mgmt_affected_cmds_done != NULL) &&
+           (mcmd->fn != SCST_UNREG_SESS_TM)) {
+               TRACE_DBG("Calling target %s task_mgmt_affected_cmds_done(%p)",
+                       sess->tgt->tgtt->name, sess);
+               sess->tgt->tgtt->task_mgmt_affected_cmds_done(mcmd);
+               TRACE_MGMT_DBG("Target's %s task_mgmt_affected_cmds_done() "
+                       "returned", sess->tgt->tgtt->name);
+       }
+       return;
+}
+
+static int scst_mgmt_affected_cmds_done(struct scst_mgmt_cmd *mcmd)
 {
        int res;
 
@@ -4710,19 +4691,9 @@ static int scst_mgmt_cmd_check_nexus_loss(struct scst_mgmt_cmd *mcmd)
 
        mutex_unlock(&scst_mutex);
 
-       if ((mcmd->fn == SCST_UNREG_SESS_TM) &&
-           (mcmd->sess->unreg_cmds_done_fn != NULL)) {
-               struct scst_session *sess = mcmd->sess;
-
-               TRACE_MGMT_DBG("Calling unreg_cmds_done_fn(%p)", sess);
-               sess->unreg_cmds_done_fn(sess);
-               TRACE_MGMT_DBG("task_mgmt_all_cmds_done(%p) returned", sess);
-
-               /* To prevent scst_mgmt_cmd_send_done() to call it again */
-               sess->unreg_cmds_done_fn = NULL;
-       }
+       scst_call_task_mgmt_affected_cmds_done(mcmd);
 
-       mcmd->nexus_loss_check_done = 1;
+       mcmd->affected_cmds_done_called = 1;
 
        res = scst_set_mcmd_next_state(mcmd);
 
@@ -4733,46 +4704,38 @@ static int scst_mgmt_cmd_check_nexus_loss(struct scst_mgmt_cmd *mcmd)
 static void scst_mgmt_cmd_send_done(struct scst_mgmt_cmd *mcmd)
 {
        struct scst_device *dev;
-       struct scst_tgt_dev *tgt_dev;
        struct scst_session *sess = mcmd->sess;
 
        TRACE_ENTRY();
 
-       mcmd->state = SCST_MGMT_CMD_STATE_FINISHED;
+       mcmd->state = SCST_MCMD_STATE_FINISHED;
        if (scst_is_strict_mgmt_fn(mcmd->fn) && (mcmd->completed_cmd_count > 0))
                mcmd->status = SCST_MGMT_STATUS_TASK_NOT_EXIST;
 
        TRACE(TRACE_MGMT_MINOR, "TM command fn %d finished, status %x",
                mcmd->fn, mcmd->status);
 
-       if (mcmd->fn == SCST_UNREG_SESS_TM) {
-               if (sess->unreg_cmds_done_fn != NULL) {
-                       TRACE_MGMT_DBG("Calling unreg_cmds_done_fn(%p)", sess);
-                       sess->unreg_cmds_done_fn(sess);
-                       TRACE_MGMT_DBG("task_mgmt_all_cmds_done(%p) returned",
-                                       sess);
-               }
-       } else {
-               if (sess->tgt->tgtt->task_mgmt_fn_done) {
-                       TRACE_DBG("Calling target %s task_mgmt_fn_done(%p)",
-                               sess->tgt->tgtt->name, sess);
-                       sess->tgt->tgtt->task_mgmt_fn_done(mcmd);
-                       TRACE_MGMT_DBG("Target's %s task_mgmt_fn_done() "
-                               "returned", sess->tgt->tgtt->name);
-               }
+       if (!mcmd->affected_cmds_done_called) {
+               /* It might happen in case of errors */
+               scst_call_task_mgmt_affected_cmds_done(mcmd);
+       }
+
+       if ((sess->tgt->tgtt->task_mgmt_fn_done != NULL) &&
+           (mcmd->fn != SCST_UNREG_SESS_TM)) {
+               TRACE_DBG("Calling target %s task_mgmt_fn_done(%p)",
+                       sess->tgt->tgtt->name, sess);
+               sess->tgt->tgtt->task_mgmt_fn_done(mcmd);
+               TRACE_MGMT_DBG("Target's %s task_mgmt_fn_done() "
+                       "returned", sess->tgt->tgtt->name);
        }
 
        if (mcmd->needs_unblocking) {
                switch (mcmd->fn) {
-               case SCST_ABORT_TASK_SET:
-               case SCST_CLEAR_TASK_SET:
                case SCST_LUN_RESET:
                        scst_unblock_dev(mcmd->mcmd_tgt_dev->dev);
                        break;
 
                case SCST_TARGET_RESET:
-               case SCST_ABORT_ALL_TASKS:
-               case SCST_NEXUS_LOSS:
                {
                        struct scst_acg *acg = mcmd->sess->acg;
                        struct scst_acg_dev *acg_dev;
@@ -4787,25 +4750,6 @@ static void scst_mgmt_cmd_send_done(struct scst_mgmt_cmd *mcmd)
                        break;
                }
 
-               case SCST_NEXUS_LOSS_SESS:
-               case SCST_ABORT_ALL_TASKS_SESS:
-               {
-                       int i;
-
-                       mutex_lock(&scst_mutex);
-                       for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
-                               struct list_head *sess_tgt_dev_list_head =
-                                       &mcmd->sess->sess_tgt_dev_list_hash[i];
-                               list_for_each_entry(tgt_dev,
-                                               sess_tgt_dev_list_head,
-                                               sess_tgt_dev_list_entry) {
-                                       scst_unblock_dev(tgt_dev->dev);
-                               }
-                       }
-                       mutex_unlock(&scst_mutex);
-
-                       break;
-               }
                default:
                        sBUG();
                        break;
@@ -4829,23 +4773,23 @@ static int scst_process_mgmt_cmd(struct scst_mgmt_cmd *mcmd)
 
        while (1) {
                switch (mcmd->state) {
-               case SCST_MGMT_CMD_STATE_INIT:
+               case SCST_MCMD_STATE_INIT:
                        res = scst_mgmt_cmd_init(mcmd);
                        if (res)
                                goto out;
                        break;
 
-               case SCST_MGMT_CMD_STATE_READY:
+               case SCST_MCMD_STATE_READY:
                        if (scst_mgmt_cmd_exec(mcmd))
                                goto out;
                        break;
 
-               case SCST_MGMT_CMD_STATE_CHECK_NEXUS_LOSS:
-                       if (scst_mgmt_cmd_check_nexus_loss(mcmd))
+               case SCST_MCMD_STATE_POST_AFFECTED_CMDS_DONE:
+                       if (scst_mgmt_affected_cmds_done(mcmd))
                                goto out;
                        break;
 
-               case SCST_MGMT_CMD_STATE_DONE:
+               case SCST_MCMD_STATE_DONE:
                        scst_mgmt_cmd_send_done(mcmd);
                        break;
 
@@ -4854,12 +4798,12 @@ static int scst_process_mgmt_cmd(struct scst_mgmt_cmd *mcmd)
                                    mcmd->state);
                        res = -1;
                        /* go through */
-               case SCST_MGMT_CMD_STATE_FINISHED:
+               case SCST_MCMD_STATE_FINISHED:
                        scst_free_mgmt_cmd(mcmd);
                        goto out;
 
 #ifdef CONFIG_SCST_EXTRACHECKS
-               case SCST_MGMT_CMD_STATE_EXECUTING:
+               case SCST_MCMD_STATE_EXECUTING:
                        sBUG();
 #endif
                }
@@ -4973,7 +4917,7 @@ static struct scst_mgmt_cmd *scst_pre_rx_mgmt_cmd(struct scst_session
 
        mcmd->sess = sess;
        mcmd->fn = fn;
-       mcmd->state = SCST_MGMT_CMD_STATE_INIT;
+       mcmd->state = SCST_MCMD_STATE_INIT;
        mcmd->tgt_priv = tgt_priv;
 
 out:
@@ -5299,9 +5243,8 @@ EXPORT_SYMBOL(scst_register_session);
  * Must not be called in parallel with scst_rx_cmd() or
  * scst_rx_mgmt_fn_*() for the same sess
  */
-void scst_unregister_session_ex(struct scst_session *sess, int wait,
-       void (*unreg_done_fn) (struct scst_session *sess),
-       void (*unreg_cmds_done_fn) (struct scst_session *sess))
+void scst_unregister_session(struct scst_session *sess, int wait,
+       void (*unreg_done_fn) (struct scst_session *sess))
 {
        unsigned long flags;
        struct completion *pc;
@@ -5321,7 +5264,6 @@ void scst_unregister_session_ex(struct scst_session *sess, int wait,
 #endif
 
        sess->unreg_done_fn = unreg_done_fn;
-       sess->unreg_cmds_done_fn = unreg_cmds_done_fn;
 
        /* Abort all outstanding commands and clear reservation, if necessary */
        lun = 0;
@@ -5359,7 +5301,7 @@ void scst_unregister_session_ex(struct scst_session *sess, int wait,
        TRACE_EXIT();
        return;
 }
-EXPORT_SYMBOL(scst_unregister_session_ex);
+EXPORT_SYMBOL(scst_unregister_session);
 
 static inline int test_mgmt_list(void)
 {