- Update to the latest IET r145
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Fri, 21 Dec 2007 19:10:40 +0000 (19:10 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Fri, 21 Dec 2007 19:10:40 +0000 (19:10 +0000)
 - TM fixes and improvements, particularly, TARGET RESET now resets only visible to the initiator devices
 - Logs improvements

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

doc/scst_user_spec.txt
iscsi-scst/include/iscsi_u.h
iscsi-scst/kernel/iscsi.c
iscsi-scst/kernel/iscsi.h
iscsi-scst/kernel/nthread.c
iscsi-scst/usr/iscsid.c
scst/include/scst_user.h
scst/src/dev_handlers/scst_user.c
scst/src/scst_lib.c
scst/src/scst_priv.h
scst/src/scst_targ.c

index 2b89390..842d9eb 100644 (file)
@@ -2,7 +2,7 @@
 
          USER SPACE INTERFACE DESCRIPTION.
 
-                  Version 0.9.6/2
+                  Version 0.9.6/3
 
 
                I. Description.
@@ -335,6 +335,8 @@ struct scst_user_scsi_cmd_parse
        uint8_t expected_values_set;
        uint8_t expected_data_direction;
        int32_t expected_transfer_len;
+
+       uint32_t sn;
 },
 
 where:
@@ -362,6 +364,8 @@ where:
 
  - expected_transfer_len - remote initiator supplied transfer length
 
+ - sn - command's SN, which might be used for task management
+
 In the PARSE state of SCSI commands processing the user space device
 handler shall check and provide SCST values for command data buffer
 length, data flow direction and timeout, which it shall reply using the
@@ -401,6 +405,8 @@ struct scst_user_scsi_cmd_alloc_mem
 
        uint8_t queue_type;
        uint8_t data_direction;
+
+       uint32_t sn;
 },
 
 where:
@@ -418,6 +424,8 @@ where:
  - data_direction - command's data flow direction, one of SCST_DATA_*
    constants
 
+ - sn - command's SN, which might be used for task management
+
 Memory allocation, preparation and freeing are ones of the most
 complicated and expensive operations during SCSI commands processing.
 Module scst_user provides a way to almost completely eliminate those
@@ -507,6 +515,8 @@ struct scst_user_scsi_cmd_exec
        uint8_t partial;
        uint32_t timeout;
 
+       uint32_t sn;
+
        uint32_t parent_cmd_h;
        int32_t parent_cmd_data_len;
        uint32_t partial_offset;
@@ -546,6 +556,8 @@ where:
 
  - timeout - CDB execution timeout
 
+ - sn - command's SN, which might be used for task management
+
  - parent_cmd_h - has the same unique value for all partial data
    transfers subcommands of one original (parent) command
 
@@ -641,6 +653,8 @@ struct scst_user_tm
        uint64_t sess_h;
        uint32_t fn;
        uint32_t cmd_h_to_abort;
+       uint32_t cmd_sn;
+       uint8_t cmd_sn_set;
 },
 
 where:
@@ -651,6 +665,12 @@ where:
 
  - cmd_h_to_abort - handle of command to abort. Valid only if fn is
    SCST_ABORT_TASK
+
+ - cmd_sn - if cmd_sn_set is set, contains maximum commands SN, which
+   this task management function affects. See iSCSI RFC 3720 10.5.1 for
+   more details.
+
+ - cmd_sn_set - specifies if cmd_sn is valid
    
 After TM function is completed, the user space device handler shall
 reply using "result" field of the corresponding reply command. It isn't
index 807f518..512d004 100644 (file)
@@ -20,7 +20,7 @@
 #include <sys/uio.h>
 #endif
 
-#define ISCSI_VERSION_STRING   "0.9.6/0.4.15r137"
+#define ISCSI_VERSION_STRING   "0.9.6/0.4.15r145"
 
 /* The maximum length of 223 bytes in the RFC. */
 #define ISCSI_NAME_LEN 256
index 771d878..aeb1877 100644 (file)
@@ -62,7 +62,7 @@ static LIST_HEAD(iscsi_threads_list);
 static void cmnd_remove_hash(struct iscsi_cmnd *cmnd);
 static void iscsi_send_task_mgmt_resp(struct iscsi_cmnd *req, int status);
 static void cmnd_prepare_skip_pdu(struct iscsi_cmnd *cmnd);
-static void iscsi_cond_send_tm_resp(struct iscsi_cmnd *rsp, int force);
+static void iscsi_check_send_delayed_tm_resp(struct iscsi_session *sess);
 
 static inline u32 cmnd_write_size(struct iscsi_cmnd *cmnd)
 {
@@ -780,8 +780,10 @@ static int cmnd_insert_hash(struct iscsi_cmnd *cmnd)
        if (!tmp) {
                list_add_tail(&cmnd->hash_list_entry, head);
                cmnd->hashed = 1;
-       } else
+       } else {
+               PRINT_ERROR("Task %x in progress, cmnd %p", itt, cmnd);
                err = -ISCSI_REASON_TASK_IN_PROGRESS;
+       }
 
        spin_unlock(&session->cmnd_hash_lock);
 
@@ -965,6 +967,13 @@ static void send_r2t(struct iscsi_cmnd *req)
        u32 length, offset, burst;
        LIST_HEAD(send);
 
+       if (unlikely(req->tmfabort)) {
+               TRACE_MGMT_DBG("req %p (scst_cmd %p) aborted on R2T", req,
+                       req->scst_cmd);
+               req_cmnd_release_force(req, ISCSI_FORCE_RELEASE_WRITE);
+               goto out;
+       }
+
        /*
         * There is no race with data_out_start() and __cmnd_abort(), since
         * all functions called from single read thread
@@ -1009,6 +1018,9 @@ static void send_r2t(struct iscsi_cmnd *req)
        iscsi_cmnds_init_write(&send, ISCSI_INIT_WRITE_WAKE);
 
        req->data_waiting = 1;
+
+out:
+       return;
 }
 
 static int iscsi_pre_exec(struct scst_cmd *scst_cmd)
@@ -1333,7 +1345,8 @@ static int data_out_start(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd)
        cmnd->cmd_req = req = cmnd_find_hash(conn->session, req_hdr->itt,
                                        req_hdr->ttt);
        if (!req) {
-               PRINT_ERROR("Unable to find scsi task %x %x",
+               /* It might happen if req was aborted and then freed */
+               TRACE(TRACE_MGMT_MINOR, "Unable to find scsi task %x %x",
                        cmnd_itt(cmnd), cmnd_ttt(cmnd));
                goto skip_pdu;
        }
@@ -1447,12 +1460,12 @@ static inline int __cmnd_abort(struct iscsi_cmnd *cmnd)
                goto out;
 
        TRACE_MGMT_DBG("Aborting cmd %p, scst_cmd %p (scst state %x, "
-               "ref_cnt %d, itt %x, op %x, r2t_len %x, CDB op %x, "
+               "ref_cnt %d, itt %x, sn %d, op %x, r2t_len %x, CDB op %x, "
                "size to write %u, is_unsolicited_data %u, "
                "outstanding_r2t %u)", cmnd, cmnd->scst_cmd,
                cmnd->scst_state, atomic_read(&cmnd->ref_cnt),
-               cmnd_itt(cmnd), cmnd_opcode(cmnd), cmnd->r2t_length,
-               cmnd_scsicode(cmnd), cmnd_write_size(cmnd),
+               cmnd_itt(cmnd), cmnd->pdu.bhs.sn, cmnd_opcode(cmnd),
+               cmnd->r2t_length, cmnd_scsicode(cmnd), cmnd_write_size(cmnd),
                cmnd->is_unsolicited_data, cmnd->outstanding_r2t);
 
 #ifdef NET_PAGE_CALLBACKS_DEFINED
@@ -1615,26 +1628,32 @@ again:
 static void execute_task_management(struct iscsi_cmnd *req)
 {
        struct iscsi_conn *conn = req->conn;
+       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;
        struct scst_rx_mgmt_params params;
 
        TRACE((function == ISCSI_FUNCTION_ABORT_TASK) ? TRACE_MGMT_MINOR : TRACE_MGMT,
-               "TM cmd: req %p, itt %x, fn %d, rtt %x", req, cmnd_itt(req),
-               function, req_hdr->rtt);
+               "TM cmd: req %p, itt %x, fn %d, rtt %x, sn %d", req, cmnd_itt(req),
+               function, req_hdr->rtt, req_hdr->cmd_sn);
+
+       spin_lock(&sess->sn_lock);
+       sess->tm_active = 1;
+       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;
+               spin_unlock(&sess->sn_lock);
+               rsp_cmnd_release(tm_rsp);
+       } else
+               spin_unlock(&sess->sn_lock);
 
        memset(&params, 0, sizeof(params));
        params.atomic = SCST_NON_ATOMIC;
        params.tgt_priv = req;
 
-       if (conn->session->tm_rsp != NULL) {
-               struct iscsi_task_rsp_hdr *rsp_hdr = 
-                       (struct iscsi_task_rsp_hdr *)&conn->session->tm_rsp->pdu.bhs;
-               rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_REJECTED;
-               iscsi_cond_send_tm_resp(conn->session->tm_rsp, 1);
-       }
-
        if ((function != ISCSI_FUNCTION_ABORT_TASK) &&
            (req_hdr->rtt != ISCSI_RESERVED_TAG)) {
                PRINT_ERROR("Invalid RTT %x (TM fn %x)", req_hdr->rtt,
@@ -1697,6 +1716,8 @@ static void execute_task_management(struct iscsi_cmnd *req)
        case ISCSI_FUNCTION_TARGET_WARM_RESET:
                target_abort(req, 1);
                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,
                        &params);
                break;
@@ -1706,6 +1727,8 @@ static void execute_task_management(struct iscsi_cmnd *req)
                params.lun = (uint8_t *)&req_hdr->lun;
                params.lun_len = sizeof(req_hdr->lun);
                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,
                        &params);
                break;
@@ -1985,16 +2008,23 @@ static void iscsi_session_push_cmnd(struct iscsi_cmnd *cmnd)
                while (1) {
                        session->exp_cmd_sn = ++cmd_sn;
 
-                       spin_unlock(&session->sn_lock);
+                       if (unlikely(session->tm_active)) {
+                               if (before(cmd_sn, session->tm_sn)) {
+                                       struct iscsi_conn *conn = cmnd->conn;
+
+                                       spin_unlock(&session->sn_lock);
+
+                                       spin_lock_bh(&conn->cmd_list_lock);
+                                       __cmnd_abort(cmnd);
+                                       spin_unlock_bh(&conn->cmd_list_lock);
 
-                       if (unlikely(session->tm_rsp != NULL)) {
-                               struct iscsi_conn *conn = cmnd->conn;
-                               spin_lock_bh(&conn->cmd_list_lock);
-                               __cmnd_abort(cmnd);
-                               spin_unlock_bh(&conn->cmd_list_lock);
-                               iscsi_cond_send_tm_resp(session->tm_rsp, 0);
+                                       spin_lock(&session->sn_lock);
+                               }
+                               iscsi_check_send_delayed_tm_resp(session);
                        }
 
+                       spin_unlock(&session->sn_lock);
+
                        iscsi_cmnd_exec(cmnd);
 
                        if (list_empty(&session->pending_list))
@@ -2010,13 +2040,13 @@ static void iscsi_session_push_cmnd(struct iscsi_cmnd *cmnd)
                }
        } else {
                cmnd->pending = 1;
-               if (before(cmd_sn, session->exp_cmd_sn)) { /* close the conn */
+               if (before(cmd_sn, session->exp_cmd_sn)) {
                        PRINT_ERROR("unexpected cmd_sn (%u,%u)", cmd_sn,
                                session->exp_cmd_sn);
                }
 
                if (after(cmd_sn, session->exp_cmd_sn + iscsi_get_allowed_cmds(session))) {
-                       PRINT_ERROR("too large cmd_sn %u (exp_cmd_sn %u, "
+                       PRINT_INFO("Suspicious: too large cmd_sn %u (exp_cmd_sn %u, "
                                "max_sn %u)", cmd_sn, session->exp_cmd_sn,
                                iscsi_get_allowed_cmds(session));
                }
@@ -2360,45 +2390,53 @@ out:
        return SCST_TGT_RES_SUCCESS;
 }
 
-static void iscsi_cond_send_tm_resp(struct iscsi_cmnd *rsp, int force)
+/* Called under sn_lock */
+static bool iscsi_is_delay_tm_resp(struct iscsi_cmnd *rsp)
 {
+       bool res = 0;
        struct iscsi_task_mgt_hdr *req_hdr =
-                       (struct iscsi_task_mgt_hdr *)&rsp->parent_req->pdu.bhs;
+               (struct iscsi_task_mgt_hdr *)&rsp->parent_req->pdu.bhs;
        int function = req_hdr->function & ISCSI_FUNCTION_MASK;
        struct iscsi_session *sess = rsp->conn->session;
 
        TRACE_ENTRY();
 
-       if (!force) {
-               spin_lock(&sess->sn_lock);
-               switch(function) {
-               case ISCSI_FUNCTION_ABORT_TASK_SET:
-               case ISCSI_FUNCTION_CLEAR_TASK_SET:
-               case ISCSI_FUNCTION_CLEAR_ACA:
-                       if (before(sess->exp_cmd_sn, req_hdr->cmd_sn)) {
-                               TRACE_MGMT_DBG("Delaying TM fn %x response, "
-                                       "because not all affected commands "
-                                       "received (rsp %p, cmd sn %x, exp sn "
-                                       "%x)", function, rsp, req_hdr->cmd_sn,
-                                       sess->exp_cmd_sn);
-                               sess->tm_rsp = rsp;
-                               spin_unlock(&sess->sn_lock);
-                               goto out;
-                       }
-                       break;
-               default:
-                       break;
-               }
-               spin_unlock(&sess->sn_lock);
+       switch(function) {
+       default:
+               if (before(sess->exp_cmd_sn, req_hdr->cmd_sn))
+                       res = 1;
+               break;
        }
 
-       if (rsp == sess->tm_rsp) {
-               TRACE_MGMT_DBG("Sending delayed rsp %p (fn %x)", rsp, function);
-               sess->tm_rsp = NULL;
-       }
-       iscsi_cmnd_init_write(rsp,
+       TRACE_EXIT_RES(res);
+       return res;
+}
+
+/* Called under sn_lock, but might drop it inside, then reaquire */
+static void iscsi_check_send_delayed_tm_resp(struct iscsi_session *sess)
+{
+       struct iscsi_cmnd *tm_rsp = sess->tm_rsp;
+
+       TRACE_ENTRY();
+
+       if (tm_rsp == NULL)
+               goto out;
+
+       if (iscsi_is_delay_tm_resp(tm_rsp))
+               goto out;
+
+       TRACE(TRACE_MGMT_MINOR, "Sending delayed rsp %p", tm_rsp);
+
+       sess->tm_rsp = NULL;
+       sess->tm_active = 0;
+
+       spin_unlock(&sess->sn_lock);
+
+       iscsi_cmnd_init_write(tm_rsp,
                ISCSI_INIT_WRITE_REMOVE_HASH | ISCSI_INIT_WRITE_WAKE);
 
+       spin_lock(&sess->sn_lock);
+
 out:
        TRACE_EXIT();
        return;
@@ -2410,6 +2448,7 @@ static void iscsi_send_task_mgmt_resp(struct iscsi_cmnd *req, int status)
        struct iscsi_task_mgt_hdr *req_hdr =
                                (struct iscsi_task_mgt_hdr *)&req->pdu.bhs;
        struct iscsi_task_rsp_hdr *rsp_hdr;
+       struct iscsi_session *sess = req->conn->session;
 
        TRACE_ENTRY();
 
@@ -2429,8 +2468,26 @@ static void iscsi_send_task_mgmt_resp(struct iscsi_cmnd *req, int status)
                        ISCSI_FUNCTION_TARGET_COLD_RESET)
                rsp->should_close_conn = 1;
 
-       iscsi_cond_send_tm_resp(rsp, 0);
+       sBUG_ON(sess->tm_rsp != NULL);
+
+       spin_lock(&sess->sn_lock);
+       if (iscsi_is_delay_tm_resp(rsp)) {
+               TRACE(TRACE_MGMT_MINOR, "Delaying TM fn %x response %p "
+                       "(req %p), because not all affected commands received "
+                       "(cmd sn %d, exp sn %d)",
+                       req_hdr->function & ISCSI_FUNCTION_MASK, rsp, req,
+                       req_hdr->cmd_sn, sess->exp_cmd_sn);
+               sess->tm_rsp = rsp;
+               spin_unlock(&sess->sn_lock);
+               goto out_release;
+       }
+       sess->tm_active = 0;
+       spin_unlock(&sess->sn_lock);
+
+       iscsi_cmnd_init_write(rsp,
+               ISCSI_INIT_WRITE_REMOVE_HASH | ISCSI_INIT_WRITE_WAKE);
 
+out_release:
        req_cmnd_release(req);
 
        TRACE_EXIT();
index 670f3a2..60d438d 100644 (file)
@@ -88,7 +88,7 @@ struct iscsi_session {
        struct iscsi_target *target;
        struct scst_session *scst_sess;
 
-       /* All 2 unprotected, since accessed only from a single read thread */
+       /* Both unprotected, since accessed only from a single read thread */
        struct list_head pending_list;
        u32 next_ttt;
 
@@ -98,6 +98,9 @@ struct iscsi_session {
        spinlock_t sn_lock;
        u32 exp_cmd_sn; /* protected by sn_lock */
 
+       /* All 3 protected by sn_lock */
+       unsigned int tm_active:1;
+       u32 tm_sn;
        struct iscsi_cmnd *tm_rsp;
 
        /* read only, if there are connection(s) */
index b5bf50f..1418df0 100644 (file)
@@ -136,6 +136,22 @@ static void close_conn(struct iscsi_conn *conn)
 
        conn_abort(conn);
 
+       mutex_lock(&target->target_mutex);
+       spin_lock(&session->sn_lock);
+       if ((session->tm_rsp != NULL) && (session->tm_rsp->conn == conn)) {
+               struct iscsi_cmnd *tm_rsp = session->tm_rsp;
+               TRACE(TRACE_MGMT_MINOR, "Dropping delayed TM rsp %p", tm_rsp);
+               session->tm_rsp = NULL;
+               session->tm_active = 0;
+               spin_unlock(&session->sn_lock);
+               mutex_unlock(&target->target_mutex);
+
+               rsp_cmnd_release(tm_rsp);
+       } else {
+               spin_unlock(&session->sn_lock);
+               mutex_unlock(&target->target_mutex);
+       }
+
        if (conn->read_state != RX_INIT_BHS) {
                req_cmnd_release_force(conn->read_cmnd, 0);
                conn->read_cmnd = NULL;
@@ -181,10 +197,12 @@ static void close_conn(struct iscsi_conn *conn)
 
                        spin_lock_bh(&conn->cmd_list_lock);
                        list_for_each_entry(cmnd, &conn->cmd_list, cmd_list_entry) {
-                               TRACE_CONN_CLOSE_DBG("cmd %p, scst_state %x, data_waiting "
-                                       "%d, ref_cnt %d, parent_req %p", cmnd,
-                                       cmnd->scst_state, cmnd->data_waiting,
-                                       atomic_read(&cmnd->ref_cnt), cmnd->parent_req);
+                               TRACE_CONN_CLOSE_DBG("cmd %p, scst_state %x, scst_cmd "
+                                       "state %d, data_waiting %d, ref_cnt %d, "
+                                       "parent_req %p", cmnd, cmnd->scst_state,
+                                       (cmnd->scst_cmd != NULL) ? cmnd->scst_cmd->state : -1,
+                                       cmnd->data_waiting, atomic_read(&cmnd->ref_cnt),
+                                       cmnd->parent_req);
 #ifdef NET_PAGE_CALLBACKS_DEFINED
                                TRACE_CONN_CLOSE_DBG("net_ref_cnt %d, sg %p",
                                        atomic_read(&cmnd->net_ref_cnt), cmnd->sg);
@@ -568,6 +586,8 @@ int istrd(void *arg)
 {
        TRACE_ENTRY();
 
+       PRINT_INFO("Read thread started, PID %d", current->pid);
+
        current->flags |= PF_NOFREEZE;
 
        spin_lock_bh(&iscsi_rd_lock);
@@ -598,6 +618,8 @@ int istrd(void *arg)
         */
        sBUG_ON(!list_empty(&iscsi_rd_list));
 
+       PRINT_INFO("Read thread PID %d finished", current->pid);
+
        TRACE_EXIT();
        return 0;
 }
@@ -1072,6 +1094,8 @@ int istwr(void *arg)
 {
        TRACE_ENTRY();
 
+       PRINT_INFO("Write thread started, PID %d", current->pid);
+
        current->flags |= PF_NOFREEZE;
 
        spin_lock_bh(&iscsi_wr_lock);
@@ -1102,6 +1126,8 @@ int istwr(void *arg)
         */
        sBUG_ON(!list_empty(&iscsi_wr_list));
 
+       PRINT_INFO("Write thread PID %d finished", current->pid);
+
        TRACE_EXIT();
        return 0;
 }
index 76d7057..35ae1a6 100644 (file)
@@ -108,7 +108,7 @@ void text_key_add(struct connection *conn, char *key, char *value)
                }
                conn->rsp.data = conn->rsp_buffer;
        }
-       if (conn->rwsize + len > INCOMING_BUFSIZE) {
+       if (conn->rsp.datasize + len > INCOMING_BUFSIZE) {
                log_warning("Dropping key (%s=%s)", key, value);
                return;
        }
index 53db9f9..98792fd 100644 (file)
@@ -23,9 +23,9 @@
 
 #include <scst_const.h>
 
-#define DEV_USER_NAME                "scst_user"
+#define DEV_USER_NAME                  "scst_user"
 #define DEV_USER_PATH                  "/dev/"
-#define DEV_USER_VERSION               962
+#define DEV_USER_VERSION               963
 
 /* 
  * Chosen so sizeof(scst_user_sess) <= sizeof(scst_user_scsi_cmd_exec) 
@@ -137,6 +137,8 @@ struct scst_user_scsi_cmd_parse
        uint8_t expected_values_set;
        uint8_t expected_data_direction;
        int32_t expected_transfer_len;
+
+       uint32_t sn;
 };
 
 struct scst_user_scsi_cmd_alloc_mem
@@ -150,6 +152,8 @@ struct scst_user_scsi_cmd_alloc_mem
 
        uint8_t queue_type;
        uint8_t data_direction;
+
+       uint32_t sn;
 };
 
 struct scst_user_scsi_cmd_exec
@@ -168,6 +172,8 @@ struct scst_user_scsi_cmd_exec
        uint8_t partial;
        uint32_t timeout;
 
+       uint32_t sn;
+
        uint32_t parent_cmd_h;
        int32_t parent_cmd_data_len;
        uint32_t partial_offset;
@@ -193,6 +199,8 @@ struct scst_user_tm
        aligned_u64 sess_h;
        uint32_t fn;
        uint32_t cmd_h_to_abort;
+       uint32_t cmd_sn;
+       uint8_t cmd_sn_set;
 };
 
 struct scst_user_get_cmd
index b04ec37..ed85d97 100644 (file)
@@ -596,6 +596,7 @@ static int dev_user_alloc_space(struct scst_user_cmd *ucmd)
                (cmd->sg_cnt << PAGE_SHIFT) : cmd->bufflen;
        ucmd->user_cmd.alloc_cmd.queue_type = cmd->queue_type;
        ucmd->user_cmd.alloc_cmd.data_direction = cmd->data_direction;
+       ucmd->user_cmd.alloc_cmd.sn = cmd->tgt_sn;
 
        dev_user_add_to_ready(ucmd);
 
@@ -722,6 +723,7 @@ static int dev_user_parse(struct scst_cmd *cmd)
                                        cmd->expected_data_direction;
                ucmd->user_cmd.parse_cmd.expected_transfer_len =
                                        cmd->expected_transfer_len;
+               ucmd->user_cmd.parse_cmd.sn = cmd->tgt_sn;
                ucmd->state = UCMD_STATE_PARSING;
                dev_user_add_to_ready(ucmd);
                res = SCST_CMD_STATE_STOP;
@@ -809,6 +811,7 @@ static int dev_user_exec(struct scst_cmd *cmd)
        ucmd->user_cmd.exec_cmd.data_direction = cmd->data_direction;
        ucmd->user_cmd.exec_cmd.partial = 0;
        ucmd->user_cmd.exec_cmd.timeout = cmd->timeout;
+       ucmd->user_cmd.exec_cmd.sn = cmd->tgt_sn;
 
        ucmd->state = UCMD_STATE_EXECING;
 
@@ -2126,6 +2129,8 @@ static int dev_user_task_mgmt_fn(struct scst_mgmt_cmd *mcmd,
        ucmd->user_cmd.subcode = SCST_USER_TASK_MGMT;
        ucmd->user_cmd.tm_cmd.sess_h = (unsigned long)tgt_dev;
        ucmd->user_cmd.tm_cmd.fn = mcmd->fn;
+       ucmd->user_cmd.tm_cmd.cmd_sn = mcmd->cmd_sn;
+       ucmd->user_cmd.tm_cmd.cmd_sn_set = mcmd->cmd_sn_set;
 
        if (mcmd->cmd_to_abort != NULL) {
                ucmd_to_abort = (struct scst_user_cmd*)mcmd->cmd_to_abort->dh_priv;
@@ -2990,6 +2995,8 @@ static int dev_user_cleanup_thread(void *arg)
 
        TRACE_ENTRY();
 
+       PRINT_INFO("Cleanup thread started, PID %d", current->pid);
+
        current->flags |= PF_NOFREEZE;
 
        spin_lock(&cleanup_lock);
@@ -3027,6 +3034,8 @@ restart:
         */
        sBUG_ON(!list_empty(&cleanup_list));
 
+       PRINT_INFO("Cleanup thread PID %d finished", current->pid);
+
        TRACE_EXIT();
        return 0;
 }
index 7a96da6..0aa2f4c 100644 (file)
@@ -3322,13 +3322,17 @@ void tm_dbg_release_cmd(struct scst_cmd *cmd)
 }
 
 /* No locks */
-void tm_dbg_task_mgmt(const char *fn, int force)
+void tm_dbg_task_mgmt(struct scst_tgt_dev *tgt_dev, const char *fn, int force)
 {
        unsigned long flags;
 
        if (!tm_dbg_flags.tm_dbg_active)
                goto out;
 
+       if ((tgt_dev != NULL) && !test_bit(SCST_TGT_DEV_UNDER_TM_DBG,
+                                               &tgt_dev->tgt_dev_flags))
+               goto out;
+
        spin_lock_irqsave(&scst_tm_dbg_lock, flags);
        if ((tm_dbg_state != TM_DBG_STATE_OFFLINE) || force) {
                TRACE_MGMT_DBG("%s: freeing %d delayed cmds", fn,
index 1af0296..257498e 100644 (file)
@@ -512,7 +512,8 @@ extern void tm_dbg_deinit_tgt_dev(struct scst_tgt_dev *tgt_dev);
 extern void tm_dbg_check_released_cmds(void);
 extern int tm_dbg_check_cmd(struct scst_cmd *cmd);
 extern void tm_dbg_release_cmd(struct scst_cmd *cmd);
-extern void tm_dbg_task_mgmt(const char *fn, int force);
+extern void tm_dbg_task_mgmt(struct scst_tgt_dev *tgt_dev, const char *fn,
+       int force);
 extern int tm_dbg_is_release(void);
 #else
 static inline void tm_dbg_init_tgt_dev(struct scst_tgt_dev *tgt_dev,
@@ -524,7 +525,8 @@ static inline int tm_dbg_check_cmd(struct scst_cmd *cmd)
        return 0;
 }
 static inline void tm_dbg_release_cmd(struct scst_cmd *cmd) {}
-static inline void tm_dbg_task_mgmt(const char *fn, int force) {}
+static inline void tm_dbg_task_mgmt(struct scst_tgt_dev *tgt_dev, const char *fn,
+       int force) {}
 static inline int tm_dbg_is_release(void)
 {
        return 0;
index ed3538c..df95061 100644 (file)
@@ -448,6 +448,14 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
        if (unlikely(state == SCST_CMD_STATE_PRE_XMIT_RESP))
                goto set_res;
 
+       if (unlikely((cmd->bufflen == 0) &&
+                    (cmd->op_flags & SCST_UNKNOWN_LENGTH))) {
+               PRINT_ERROR("Unknown data transfer length for opcode 0x%x "
+                       "(handler %s, target %s)", cmd->cdb[0],
+                       dev->handler->name, cmd->tgtt->name);
+               goto out_error;
+       }
+
 #ifdef EXTRACHECKS
        if ((cmd->bufflen != 0) &&
            ((cmd->data_direction == SCST_DATA_NONE) ||
@@ -2854,6 +2862,8 @@ int scst_init_cmd_thread(void *arg)
 {
        TRACE_ENTRY();
 
+       PRINT_INFO("Init thread started, PID %d", current->pid);
+
        current->flags |= PF_NOFREEZE;
 
        set_user_nice(current, -20);
@@ -2887,6 +2897,8 @@ int scst_init_cmd_thread(void *arg)
         */
        sBUG_ON(!list_empty(&scst_init_cmd_list));
 
+       PRINT_INFO("Init thread PID %d finished", current->pid);
+
        TRACE_EXIT();
        return 0;
 }
@@ -3053,6 +3065,8 @@ int scst_cmd_thread(void *arg)
 
        TRACE_ENTRY();
 
+       PRINT_INFO("Processing thread started, PID %d", current->pid);
+
 #if 0
        set_user_nice(current, 10);
 #endif
@@ -3101,6 +3115,8 @@ int scst_cmd_thread(void *arg)
        }
 #endif
 
+       PRINT_INFO("Processing thread PID %d finished", current->pid);
+
        TRACE_EXIT();
        return 0;
 }
@@ -3659,8 +3675,9 @@ out:
 static int scst_target_reset(struct scst_mgmt_cmd *mcmd)
 {
        int res, rc;
-       struct scst_device *dev, *d;
-       struct scst_tgt_dev *tgt_dev;
+       struct scst_device *dev;
+       struct scst_acg *acg = mcmd->sess->acg;
+       struct scst_acg_dev *acg_dev;
        int cont, c;
        LIST_HEAD(host_devs);
 
@@ -3673,20 +3690,12 @@ static int scst_target_reset(struct scst_mgmt_cmd *mcmd)
 
        mutex_lock(&scst_mutex);
 
-       list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
+       list_for_each_entry(acg_dev, &acg->acg_dev_list, acg_dev_list_entry) {
+               struct scst_device *d;
+               struct scst_tgt_dev *tgt_dev;
                int found = 0;
 
-               /* Skip local SCSI devices */
-               if (dev->handler == &scst_null_devtype) {
-                        /*
-                         * Generally we shouldn't reset not exported devices,
-                         * but what if a backstorage SCSI disk hung? Let's
-                         * reset it too.
-                         */
-                       if ((dev->scsi_dev != NULL) &&
-                           (dev->scsi_dev->type != TYPE_DISK))
-                               continue;
-               }
+               dev = acg_dev->dev;
 
                spin_lock_bh(&dev->dev_lock);
                __scst_block_dev(dev);
@@ -3744,14 +3753,15 @@ static int scst_target_reset(struct scst_mgmt_cmd *mcmd)
 #endif
        }
 
-       list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
+       list_for_each_entry(acg_dev, &acg->acg_dev_list, acg_dev_list_entry) {
+               dev = acg_dev->dev;
                if (dev->scsi_dev != NULL)
                        dev->scsi_dev->was_reset = 0;
        }
 
        mutex_unlock(&scst_mutex);
 
-       tm_dbg_task_mgmt("TARGET RESET", 0);
+       tm_dbg_task_mgmt(mcmd->mcmd_tgt_dev, "TARGET RESET", 0);
        res = scst_set_mcmd_next_state(mcmd);
 
        TRACE_EXIT_RES(res);
@@ -3792,7 +3802,7 @@ static int scst_lun_reset(struct scst_mgmt_cmd *mcmd)
        }
 
 out_tm_dbg:
-       tm_dbg_task_mgmt("LUN RESET", 0);
+       tm_dbg_task_mgmt(mcmd->mcmd_tgt_dev, "LUN RESET", 0);
        res = scst_set_mcmd_next_state(mcmd);
 
        TRACE_EXIT_RES(res);
@@ -3857,9 +3867,9 @@ 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_device *dev;
-       struct scst_tgt_dev *tgt_dev;
+       struct scst_acg_dev *acg_dev;
 
        TRACE_ENTRY();
 
@@ -3875,7 +3885,9 @@ static int scst_abort_all_nexus_loss_tgt(struct scst_mgmt_cmd *mcmd,
 
        mutex_lock(&scst_mutex);
 
-       list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
+       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);
@@ -3885,6 +3897,7 @@ static int scst_abort_all_nexus_loss_tgt(struct scst_mgmt_cmd *mcmd,
                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) {
                                int rc;
@@ -4020,12 +4033,19 @@ static void scst_mgmt_cmd_send_done(struct scst_mgmt_cmd *mcmd)
                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;
+
                        mutex_lock(&scst_mutex);
-                       list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
+                       list_for_each_entry(acg_dev, &acg->acg_dev_list,
+                                       acg_dev_list_entry) {
+                               dev = acg_dev->dev;
                                scst_unblock_dev(dev);
                        }
                        mutex_unlock(&scst_mutex);
                        break;
+               }
 
                case SCST_NEXUS_LOSS_SESS:
                case SCST_ABORT_ALL_TASKS_SESS:
@@ -4115,6 +4135,8 @@ int scst_mgmt_cmd_thread(void *arg)
 {
        TRACE_ENTRY();
 
+       PRINT_INFO("Task management thread started, PID %d", current->pid);
+
        current->flags |= PF_NOFREEZE;
 
        set_user_nice(current, -20);
@@ -4174,6 +4196,8 @@ int scst_mgmt_cmd_thread(void *arg)
         */
        sBUG_ON(!list_empty(&scst_active_mgmt_cmd_list));
 
+       PRINT_INFO("Task management thread PID %d finished", current->pid);
+
        TRACE_EXIT();
        return 0;
 }
@@ -4311,7 +4335,7 @@ int scst_rx_mgmt_fn(struct scst_session *sess,
 
        TRACE((params->fn == SCST_ABORT_TASK) ? TRACE_MGMT_MINOR : TRACE_MGMT,
                "sess=%p, fn %x, tag_set %d, tag %Ld, lun_set %d, "
-               "lun=%Ld, cmd_sn_set %d, cmd_sn %x", sess, params->fn,
+               "lun=%Ld, cmd_sn_set %d, cmd_sn %d", sess, params->fn,
                params->tag_set, params->tag, params->lun_set,
                (uint64_t)mcmd->lun, params->cmd_sn_set, params->cmd_sn);
 
@@ -4551,7 +4575,7 @@ void scst_unregister_session(struct scst_session *sess, int wait,
 
        spin_unlock_irqrestore(&scst_mgmt_lock, flags);
 
-       tm_dbg_task_mgmt("UNREGISTER SESSION", 1);
+       tm_dbg_task_mgmt(NULL, "UNREGISTER SESSION", 1);
 
        scst_sess_put(sess);
 
@@ -4619,6 +4643,8 @@ int scst_mgmt_thread(void *arg)
 
        TRACE_ENTRY();
 
+       PRINT_INFO("Management thread started, PID %d", current->pid);
+
        current->flags |= PF_NOFREEZE;
 
        set_user_nice(current, -20);
@@ -4700,6 +4726,8 @@ int scst_mgmt_thread(void *arg)
        sBUG_ON(!list_empty(&scst_sess_init_list));
        sBUG_ON(!list_empty(&scst_sess_shut_list));
 
+       PRINT_INFO("Management thread PID %d finished", current->pid);
+
        TRACE_EXIT();
        return 0;
 }