- TM fixes
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Fri, 29 Feb 2008 18:25:56 +0000 (18:25 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Fri, 29 Feb 2008 18:25:56 +0000 (18:25 +0000)
 - Optimizations and send timeout introduced in r295 temporary disabled
 - Big connection shutdown times improvements. Great thanks to Alexey Kuznetsov for suggestions!
 - RESERVE/RELEASE serialization now made with TST field 0 (i.e. single task set)
 - Other minor fixes and improvements

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

iscsi-scst/README
iscsi-scst/kernel/iscsi.c
iscsi-scst/kernel/iscsi.h
iscsi-scst/kernel/iscsi_dbg.h
iscsi-scst/kernel/nthread.c
scst/src/dev_handlers/scst_vdisk.c
scst/src/scst_lib.c
scst/src/scst_priv.h
scst/src/scst_targ.c

index cedb919..7a1cd69 100644 (file)
@@ -115,15 +115,6 @@ iscsi-scstd.conf file for the corresponding target to some lower value,
 like 8 (default is 32). See also SCST README file for more details about
 that issue.
 
-Sometimes, when there are communication problems with initiator(s),
-shutting down iSCSI-SCST can take very long time, up to about 10
-minutes. This can happen, because iSCSI-SCST can't be shutdown before
-all already sent to TCP for initiator(s) data will be actually sent
-and/or released by TCP. In case of communication failures this can take
-up to TCP transmit timeout, which is about 10 minutes. In such cases
-using netstat utility you can see that there is/are connection(s) to
-initiator(s) with non-0 "Send-Q".
-
 CAUTION:  Working of target and initiator on the same host isn't
 ========  supported. See SCST README file for details.
 
index e3a7eb9..de866e3 100644 (file)
@@ -1742,7 +1742,7 @@ static void execute_task_management(struct iscsi_cmnd *req)
        struct iscsi_session *sess = conn->session;
        struct iscsi_task_mgt_hdr *req_hdr =
                (struct iscsi_task_mgt_hdr *)&req->pdu.bhs;
-       int err = 0, function = req_hdr->function & ISCSI_FUNCTION_MASK;
+       int rc, status, function = req_hdr->function & ISCSI_FUNCTION_MASK;
        struct scst_rx_mgmt_params params;
 
        TRACE((function == ISCSI_FUNCTION_ABORT_TASK) ? TRACE_MGMT_MINOR : TRACE_MGMT,
@@ -1754,13 +1754,20 @@ static void execute_task_management(struct iscsi_cmnd *req)
        iscsi_extracheck_is_rd_thread(conn);
 
        spin_lock(&sess->sn_lock);
-       sess->tm_active = 1;
+       sess->tm_active++;
        sess->tm_sn = req_hdr->cmd_sn;
        if (sess->tm_rsp != NULL) {
                struct iscsi_cmnd *tm_rsp = sess->tm_rsp;
+
                TRACE(TRACE_MGMT_MINOR, "Dropping delayed TM rsp %p", tm_rsp);
+
                sess->tm_rsp = NULL;
+               sess->tm_active--;
+
                spin_unlock(&sess->sn_lock);
+
+               sBUG_ON(sess->tm_active < 0);
+
                rsp_cmnd_release(tm_rsp);
        } else
                spin_unlock(&sess->sn_lock);
@@ -1773,7 +1780,8 @@ static void execute_task_management(struct iscsi_cmnd *req)
            (req_hdr->rtt != ISCSI_RESERVED_TAG)) {
                PRINT_ERROR("Invalid RTT %x (TM fn %x)", req_hdr->rtt,
                        function);
-               err = -1;
+               rc = -1;
+               status = ISCSI_RESPONSE_FUNCTION_REJECTED;
                goto reject;
        }
 
@@ -1781,8 +1789,9 @@ static void execute_task_management(struct iscsi_cmnd *req)
 
        switch (function) {
        case ISCSI_FUNCTION_ABORT_TASK:
-               err = cmnd_abort(req);
-               if (err == 0) {
+               rc = -1;
+               status = cmnd_abort(req);
+               if (status == 0) {
                        params.fn = SCST_ABORT_TASK;
                        params.tag = req_hdr->rtt;
                        params.tag_set = 1;
@@ -1791,8 +1800,9 @@ static void execute_task_management(struct iscsi_cmnd *req)
                        params.lun_set = 1;
                        params.cmd_sn = req_hdr->cmd_sn;
                        params.cmd_sn_set = 1;
-                       err = scst_rx_mgmt_fn(conn->session->scst_sess,
+                       rc = scst_rx_mgmt_fn(conn->session->scst_sess,
                                &params);
+                       status = ISCSI_RESPONSE_FUNCTION_REJECTED;
                }
                break;
        case ISCSI_FUNCTION_ABORT_TASK_SET:
@@ -1803,8 +1813,9 @@ static void execute_task_management(struct iscsi_cmnd *req)
                params.lun_set = 1;
                params.cmd_sn = req_hdr->cmd_sn;
                params.cmd_sn_set = 1;
-               err = scst_rx_mgmt_fn(conn->session->scst_sess,
+               rc = scst_rx_mgmt_fn(conn->session->scst_sess,
                        &params);
+               status = ISCSI_RESPONSE_FUNCTION_REJECTED;
                break;
        case ISCSI_FUNCTION_CLEAR_TASK_SET:
                task_set_abort(req);
@@ -1814,8 +1825,9 @@ static void execute_task_management(struct iscsi_cmnd *req)
                params.lun_set = 1;
                params.cmd_sn = req_hdr->cmd_sn;
                params.cmd_sn_set = 1;
-               err = scst_rx_mgmt_fn(conn->session->scst_sess,
+               rc = scst_rx_mgmt_fn(conn->session->scst_sess,
                        &params);
+               status = ISCSI_RESPONSE_FUNCTION_REJECTED;
                break;
        case ISCSI_FUNCTION_CLEAR_ACA:
                params.fn = SCST_CLEAR_ACA;
@@ -1824,8 +1836,9 @@ static void execute_task_management(struct iscsi_cmnd *req)
                params.lun_set = 1;
                params.cmd_sn = req_hdr->cmd_sn;
                params.cmd_sn_set = 1;
-               err = scst_rx_mgmt_fn(conn->session->scst_sess,
+               rc = scst_rx_mgmt_fn(conn->session->scst_sess,
                        &params);
+               status = ISCSI_RESPONSE_FUNCTION_REJECTED;
                break;
        case ISCSI_FUNCTION_TARGET_COLD_RESET:
        case ISCSI_FUNCTION_TARGET_WARM_RESET:
@@ -1833,8 +1846,9 @@ static void execute_task_management(struct iscsi_cmnd *req)
                params.fn = SCST_TARGET_RESET;
                params.cmd_sn = req_hdr->cmd_sn;
                params.cmd_sn_set = 1;
-               err = scst_rx_mgmt_fn(conn->session->scst_sess,
+               rc = scst_rx_mgmt_fn(conn->session->scst_sess,
                        &params);
+               status = ISCSI_RESPONSE_FUNCTION_REJECTED;
                break;
        case ISCSI_FUNCTION_LOGICAL_UNIT_RESET:
                target_abort(req, 0);
@@ -1844,25 +1858,26 @@ static void execute_task_management(struct iscsi_cmnd *req)
                params.lun_set = 1;
                params.cmd_sn = req_hdr->cmd_sn;
                params.cmd_sn_set = 1;
-               err = scst_rx_mgmt_fn(conn->session->scst_sess,
+               rc = scst_rx_mgmt_fn(conn->session->scst_sess,
                        &params);
+               status = ISCSI_RESPONSE_FUNCTION_REJECTED;
                break;
        case ISCSI_FUNCTION_TASK_REASSIGN:
-               iscsi_send_task_mgmt_resp(req, 
-                       ISCSI_RESPONSE_FUNCTION_UNSUPPORTED);
+               rc = -1;
+               status = ISCSI_RESPONSE_FUNCTION_UNSUPPORTED;
                break;
        default:
                PRINT_ERROR("Unknown TM function %d", function);
-               iscsi_send_task_mgmt_resp(req,
-                       ISCSI_RESPONSE_FUNCTION_REJECTED);
+               rc = -1;
+               status = ISCSI_RESPONSE_FUNCTION_REJECTED;
                break;
        }
 
 reject:
-       if (err != 0) {
-               iscsi_send_task_mgmt_resp(req,
-                       ISCSI_RESPONSE_FUNCTION_REJECTED);
-       }
+       if (rc != 0)
+               iscsi_send_task_mgmt_resp(req, status);
+
+       return;
 }
 
 static void noop_out_exec(struct iscsi_cmnd *req)
@@ -2140,7 +2155,7 @@ static void iscsi_session_push_cmnd(struct iscsi_cmnd *cmnd)
                while (1) {
                        session->exp_cmd_sn = ++cmd_sn;
 
-                       if (unlikely(session->tm_active)) {
+                       if (unlikely(session->tm_active > 0)) {
                                if (before(cmd_sn, session->tm_sn)) {
                                        struct iscsi_conn *conn = cmnd->conn;
 
@@ -2476,7 +2491,11 @@ static int iscsi_xmit_response(struct scst_cmd *scst_cmd)
        u8 *sense = scst_cmd_get_sense_buffer(scst_cmd);
        int sense_len = scst_cmd_get_sense_buffer_len(scst_cmd);
        int old_state = req->scst_state;
+#if 0 /* temp. ToDo */
        bool single_only = !scst_get_long_xmit(scst_cmd);
+#else
+       bool single_only = 0;
+#endif
 
        scst_cmd_set_tgt_priv(scst_cmd, NULL);
 
@@ -2622,10 +2641,12 @@ static void iscsi_check_send_delayed_tm_resp(struct iscsi_session *sess)
        TRACE(TRACE_MGMT_MINOR, "Sending delayed rsp %p", tm_rsp);
 
        sess->tm_rsp = NULL;
-       sess->tm_active = 0;
+       sess->tm_active--;
 
        spin_unlock(&sess->sn_lock);
 
+       sBUG_ON(sess->tm_active < 0);
+
        iscsi_cmnd_init_write(tm_rsp,
                ISCSI_INIT_WRITE_REMOVE_HASH | ISCSI_INIT_WRITE_WAKE);
 
@@ -2676,9 +2697,11 @@ static void iscsi_send_task_mgmt_resp(struct iscsi_cmnd *req, int status)
                spin_unlock(&sess->sn_lock);
                goto out_release;
        }
-       sess->tm_active = 0;
+       sess->tm_active--;
        spin_unlock(&sess->sn_lock);
 
+       sBUG_ON(sess->tm_active < 0);
+
        iscsi_cmnd_init_write(rsp,
                ISCSI_INIT_WRITE_REMOVE_HASH | ISCSI_INIT_WRITE_WAKE);
 
index 5bb7c87..809de8a 100644 (file)
@@ -99,8 +99,7 @@ struct iscsi_session {
        u32 exp_cmd_sn; /* protected by sn_lock */
 
        /* All 3 protected by sn_lock */
-       unsigned int tm_active:1;
-       unsigned int shutting_down:1; /* Let's save some cache footprint by putting it here */
+       int tm_active;
        u32 tm_sn;
        struct iscsi_cmnd *tm_rsp;
 
@@ -118,6 +117,7 @@ struct iscsi_session {
 
        /* Both don't need any protection */
        char *initiator_name;
+       unsigned int shutting_down:1;
        u64 sid;
 };
 
index f4947ef..8f76aac 100644 (file)
@@ -35,7 +35,7 @@
 #ifdef DEBUG
 #define ISCSI_DEFAULT_LOG_FLAGS (TRACE_FUNCTION | TRACE_LINE | TRACE_PID | \
        TRACE_OUT_OF_MEM | TRACE_MGMT | TRACE_MGMT_MINOR | TRACE_MGMT_DEBUG | \
-       TRACE_MINOR | TRACE_SPECIAL | TRACE_CONN_OC | TRACE_CONN_OC_DBG)
+       TRACE_MINOR | TRACE_SPECIAL | TRACE_CONN_OC)
 #else
 #define ISCSI_DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MGMT | \
        TRACE_MINOR | TRACE_SPECIAL)
index 6f92c67..922ee8d 100644 (file)
@@ -61,16 +61,17 @@ static void iscsi_check_closewait(struct iscsi_conn *conn)
 
        TRACE_ENTRY();
 
-       if ((conn->sock->sk->sk_state != TCP_CLOSE_WAIT) &&
-           (conn->sock->sk->sk_state != TCP_CLOSE)) {
-               TRACE_CONN_CLOSE("sk_state %d, skipping",
-                       conn->sock->sk->sk_state);
+       TRACE_CONN_CLOSE("conn %p, sk_state %d", conn, conn->sock->sk->sk_state);
+
+       if (conn->sock->sk->sk_state != TCP_CLOSE) {
+               TRACE_CONN_CLOSE_DBG("conn %p, skipping", conn);
                goto out;
        }
 
        /*
-        * No data are going to be sent, so all being sent buffers can be freed
-        * now. Strange that TCP doesn't do that itself.
+        * No data are going to be sent, so all queued buffers can be freed
+        * now. In many cases TCP does that only in close(), but we can't rely
+        * on user space on calling it.
         */
 
 again:
@@ -235,7 +236,8 @@ static void close_conn(struct iscsi_conn *conn)
                        TRACE(TRACE_MGMT_MINOR, "Dropping delayed TM rsp %p",
                                tm_rsp);
                        session->tm_rsp = NULL;
-                       session->tm_active = 0;
+                       session->tm_active--;
+                       WARN_ON(session->tm_active < 0);
                        spin_unlock(&session->sn_lock);
                        mutex_unlock(&target->target_mutex);
 
@@ -329,10 +331,18 @@ static void close_conn(struct iscsi_conn *conn)
                iscsi_make_conn_wr_active(conn);
 
                if (time_after(jiffies, start_waiting + 7*HZ)) {
-                       TRACE_CONN_CLOSE("%s", "Wait time expired");
+                       TRACE_CONN_CLOSE("Wait time expired (conn %p, "
+                               "sk_state %d)", conn, conn->sock->sk->sk_state);
                        conn->sock->ops->shutdown(conn->sock, SEND_SHUTDOWN);
                }
 
+               if (time_after(jiffies, start_waiting + 15*HZ)) {
+                       TRACE_CONN_CLOSE("Wait time after shutdown expired "
+                               "(conn %p, sk_state %d)", conn,
+                               conn->sock->sk->sk_state);
+                       conn->sock->sk->sk_prot->disconnect(conn->sock->sk, 0);
+               }
+
                msleep(200);
 
                TRACE_CONN_CLOSE("conn %p, conn_ref_cnt %d left, wr_state %d, "
@@ -914,6 +924,7 @@ static int write_data(struct iscsi_conn *conn)
                spin_unlock_bh(&conn->write_list_lock);
        }
 
+#if 0 /* temp. ToDo */
        if (!timer_pending(&conn->rsp_timer)) {
                sBUG_ON(!ref_cmd->on_written_list);
                spin_lock_bh(&conn->write_list_lock);
@@ -925,6 +936,7 @@ static int write_data(struct iscsi_conn *conn)
                }
                spin_unlock_bh(&conn->write_list_lock);
        }
+#endif
 
        file = conn->file;
        saved_size = size = conn->write_size;
index e1c8cbe..7b62608 100644 (file)
@@ -2571,6 +2571,43 @@ out:
        return res;
 }
 
+static void vdisk_report_registering(const char *type,
+       const struct scst_vdisk_dev *virt_dev)
+{
+       char buf[128];
+       int i, j;
+
+       i = snprintf(buf, sizeof(buf), "Registering virtual %s device %s",
+               type, virt_dev->name);
+       j = i;
+
+       if (virt_dev->wt_flag)
+               i += snprintf(&buf[i], sizeof(buf) - i, " (WRITE_THROUGH");
+
+       if (virt_dev->nv_cache)
+               i += snprintf(&buf[i], sizeof(buf) - i, "%sNV_CACHE",
+                       (j == i) ? "(" : ", ");
+
+       if (virt_dev->rd_only_flag)
+               i += snprintf(&buf[i], sizeof(buf) - i, "%sREAD_ONLY",
+                       (j == i) ? "(" : ", ");
+
+       if (virt_dev->o_direct_flag)
+               i += snprintf(&buf[i], sizeof(buf) - i, "%sO_DIRECT",
+                       (j == i) ? "(" : ", ");
+
+       if (virt_dev->nullio)
+               i += snprintf(&buf[i], sizeof(buf) - i, "%sNULLIO",
+                       (j == i) ? "(" : ", ");
+
+       if (j == i)
+               PRINT_INFO("%s", buf);
+       else
+               PRINT_INFO("%s)", buf);
+
+       return;
+}
+
 /* 
  * Called when a file in the /proc/VDISK_NAME/VDISK_NAME is written
  */
@@ -2753,14 +2790,17 @@ static int vdisk_write_proc(char *buffer, char **start, off_t offset,
                list_add_tail(&virt_dev->vdisk_dev_list_entry,
                                  &vdisk_dev_list);
 
-               if (virt_dev->blockio)
+               if (virt_dev->blockio) {
+                       vdisk_report_registering("BLOCKIO", virt_dev);
                        virt_dev->virt_id =
                                scst_register_virtual_device(&vdisk_blk_devtype,
                                                         virt_dev->name);
-               else
+               } else {
+                       vdisk_report_registering("FILEIO", virt_dev);
                        virt_dev->virt_id =
                                scst_register_virtual_device(&vdisk_devtype,
                                                         virt_dev->name);
+               }
                if (virt_dev->virt_id < 0) {
                        res = virt_dev->virt_id;
                        goto out_free_vpath;
@@ -2880,6 +2920,8 @@ static int vcdrom_open(char *p, char *name)
        list_add_tail(&virt_dev->vdisk_dev_list_entry,
                      &vcdrom_dev_list);
 
+       PRINT_INFO("Registering virtual CDROM %s", name);
+
        virt_dev->virt_id =
            scst_register_virtual_device(&vcdrom_devtype,
                                         virt_dev->name);
index 0d9c2a0..1039c41 100644 (file)
@@ -719,13 +719,15 @@ int scst_acg_add_dev(struct scst_acg *acg, struct scst_device *dev, lun_t lun,
 out:
        if (res == 0) {
                if (dev->virt_name != NULL) {
-                       PRINT_INFO("Added device %s to group %s",
-                               dev->virt_name, acg->acg_name);
+                       PRINT_INFO("Added device %s to group %s (LUN %Ld, "
+                               "rd_only %d)", dev->virt_name, acg->acg_name,
+                               lun, read_only);
                } else {
-                       PRINT_INFO("Added device %d:%d:%d:%d to group %s",
-                               dev->scsi_dev->host->host_no,
+                       PRINT_INFO("Added device %d:%d:%d:%d to group %s (LUN "
+                               "%Ld, rd_only %d)", dev->scsi_dev->host->host_no,
                                dev->scsi_dev->channel, dev->scsi_dev->id,
-                               dev->scsi_dev->lun, acg->acg_name);
+                               dev->scsi_dev->lun, acg->acg_name, lun,
+                               read_only);
                }
        }
 
@@ -1568,9 +1570,9 @@ int scst_alloc_space(struct scst_cmd *cmd)
                flags |= SCST_POOL_ALLOC_NO_CACHED;
 
        if (unlikely(cmd->bufflen == 0)) {
-               TRACE(TRACE_MGMT_MINOR, "Data direction %d or/and zero buffer "
-                       "length. Opcode 0x%x, handler %s, target %s",
-                       cmd->data_direction, cmd->cdb[0],
+               TRACE(TRACE_MGMT_MINOR, "Warning: data direction %d or/and "
+                       "zero buffer length. Opcode 0x%x, handler %s, target "
+                       "%s", cmd->data_direction, cmd->cdb[0],
                        cmd->dev->handler->name, cmd->tgtt->name);
                /*
                 * Be on the safe side and alloc stub buffer. Neither target
index f92857e..4fd0c87 100644 (file)
@@ -240,7 +240,9 @@ static inline void scst_make_deferred_commands_active(
                spin_lock_irq(&c->cmd_lists->cmd_list_lock);
                list_add_tail(&c->cmd_list_entry,
                        &c->cmd_lists->active_cmd_list);
+#if 0 /* temp. ToDo */
                if (!curr_cmd->context_processable || curr_cmd->long_xmit)
+#endif
                        wake_up(&c->cmd_lists->cmd_list_waitQ);
                spin_unlock_irq(&c->cmd_lists->cmd_list_lock);
        }
index bc7d246..608a99c 100644 (file)
@@ -476,6 +476,7 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
                PRINT_ERROR("Dev handler supplied data buffer (size %d), "
                        "is less, than required (size %d)", cmd->bufflen,
                        orig_bufflen);
+               PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
                goto out_error;
        }
 
@@ -487,6 +488,7 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
                PRINT_ERROR("Unknown data transfer length for opcode 0x%x "
                        "(handler %s, target %s)", cmd->cdb[0],
                        dev->handler->name, cmd->tgtt->name);
+               PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
                goto out_error;
        }
 
@@ -499,6 +501,7 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
                        "or sg %p (opcode 0x%x)", dev->handler->name, 
                        cmd->data_direction, cmd->bufflen, state, cmd->sg,
                        cmd->cdb[0]);
+               PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
                goto out_error;
        }
 #endif
@@ -513,20 +516,27 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
                                "bufflen %d, expected_transfer_len %d",
                                cmd->data_direction, cmd->expected_data_direction,
                                cmd->bufflen, cmd->expected_transfer_len);
+                       PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
                }
 #      endif
                cmd->data_direction = cmd->expected_data_direction;
                cmd->bufflen = cmd->expected_transfer_len;
 #else
                if (unlikely(cmd->data_direction != cmd->expected_data_direction)) {
-                       PRINT_ERROR("Expected data direction %d for opcode "
-                               "0x%02x (handler %s, target %s) doesn't match "
-                               "decoded value %d", cmd->data_direction,
-                               cmd->cdb[0], dev->handler->name,
-                               cmd->tgtt->name, cmd->expected_data_direction);
-                       scst_set_cmd_error(cmd,
-                               SCST_LOAD_SENSE(scst_sense_invalid_message));
-                       goto out_dev_done;
+                       if (((cmd->expected_data_direction != SCST_DATA_NONE) ||
+                           (cmd->bufflen != 0)) &&
+                           /* Crazy VMware people sometimes do TUR with READ direction */
+                           !(cmd->cdb[0] == TEST_UNIT_READY)) {
+                               PRINT_ERROR("Expected data direction %d for opcode "
+                                       "0x%02x (handler %s, target %s) doesn't match "
+                                       "decoded value %d", cmd->expected_data_direction,
+                                       cmd->cdb[0], dev->handler->name,
+                                       cmd->tgtt->name, cmd->data_direction);
+                               PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
+                               scst_set_cmd_error(cmd,
+                                       SCST_LOAD_SENSE(scst_sense_invalid_message));
+                               goto out_dev_done;
+                       }
                }
                if (unlikely(cmd->bufflen != cmd->expected_transfer_len)) {
                        TRACE(TRACE_MINOR, "Warning: expected transfer length "
@@ -547,6 +557,7 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
                PRINT_ERROR("Unknown data direction. Opcode 0x%x, handler %s, "
                        "target %s", cmd->cdb[0], dev->handler->name,
                        cmd->tgtt->name);
+               PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
                goto out_error;
        }
 
@@ -1418,7 +1429,8 @@ static int scst_reserve_local(struct scst_cmd *cmd)
 
        dev = cmd->dev;
 
-       scst_block_dev_cmd(cmd, 1);
+       if (dev->tst == SCST_CONTR_MODE_ONE_TASK_SET)
+               scst_block_dev_cmd(cmd, 1);
 
        rc = scst_check_local_events(cmd);
        if (unlikely(rc != 0))
@@ -1473,7 +1485,8 @@ static int scst_release_local(struct scst_cmd *cmd)
 
        dev = cmd->dev;
 
-       scst_block_dev_cmd(cmd, 1);
+       if (dev->tst == SCST_CONTR_MODE_ONE_TASK_SET)
+               scst_block_dev_cmd(cmd, 1);
 
        rc = scst_check_local_events(cmd);
        if (unlikely(rc != 0))
@@ -3497,7 +3510,7 @@ void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd,
        TRACE_ENTRY();
 
        TRACE(((mcmd != NULL) && (mcmd->fn == SCST_ABORT_TASK)) ? TRACE_MGMT_MINOR : TRACE_MGMT,
-               "Aborting cmd %p (tag %llu)", cmd, cmd->tag);
+               "Aborting cmd %p (tag %llu, op %x)", cmd, cmd->tag, cmd->cdb[0]);
 
        if (other_ini) {
                set_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags);
@@ -3890,11 +3903,17 @@ static int scst_mgmt_cmd_init(struct scst_mgmt_cmd *mcmd)
        }
 
        case SCST_TARGET_RESET:
-       case SCST_ABORT_ALL_TASKS:
+       case SCST_NEXUS_LOSS_SESS:
+       case SCST_ABORT_ALL_TASKS_SESS:
        case SCST_NEXUS_LOSS:
+       case SCST_ABORT_ALL_TASKS:
+       case SCST_UNREG_SESS_TM:
                break;
 
-       default:
+       case SCST_ABORT_TASK_SET:
+       case SCST_CLEAR_ACA:
+       case SCST_CLEAR_TASK_SET:
+       case SCST_LUN_RESET:
                rc = scst_mgmt_translate_lun(mcmd);
                if (rc < 0) {
                        PRINT_ERROR("Corresponding device for lun %Ld not "
@@ -3904,6 +3923,9 @@ static int scst_mgmt_cmd_init(struct scst_mgmt_cmd *mcmd)
                } else if (rc != 0)
                        res = rc;
                break;
+
+       default:
+               sBUG();
        }
 
 out:
@@ -4315,9 +4337,13 @@ static int scst_mgmt_cmd_check_nexus_loss(struct scst_mgmt_cmd *mcmd)
        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;
        }
 
        mcmd->nexus_loss_check_done = 1;
@@ -4332,6 +4358,7 @@ 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();
 
@@ -4342,13 +4369,20 @@ static void scst_mgmt_cmd_send_done(struct scst_mgmt_cmd *mcmd)
        TRACE(TRACE_MGMT_MINOR, "TM command fn %d finished, status %x",
                mcmd->fn, mcmd->status);
 
-       if (mcmd->sess->tgt->tgtt->task_mgmt_fn_done &&
-           (mcmd->fn != SCST_UNREG_SESS_TM)) {
-               TRACE_DBG("Calling target %s task_mgmt_fn_done()",
-                     mcmd->sess->tgt->tgtt->name);
-               mcmd->sess->tgt->tgtt->task_mgmt_fn_done(mcmd);
-               TRACE_MGMT_DBG("Target's %s task_mgmt_fn_done() returned",
-                     mcmd->sess->tgt->tgtt->name);
+       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->needs_unblocking) {