Patch from Alexey Obitotskiy <alexeyo1@open-e.com> (with changes) implementing suppor...
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Wed, 17 Mar 2010 14:03:41 +0000 (14:03 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Wed, 17 Mar 2010 14:03:41 +0000 (14:03 +0000)
git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@1547 d57e44dd-8a1f-0410-8b47-8ef2f437770f

iscsi-scst/include/iscsi_scst.h
iscsi-scst/usr/iscsid.c
iscsi-scst/usr/iscsid.h
iscsi-scst/usr/param.c
iscsi-scst/usr/session.c

index 101c1e9..ba326e1 100644 (file)
@@ -64,6 +64,7 @@ enum {
        key_queued_cmnds,
        key_rsp_timeout,
        key_nop_in_interval,
+       key_max_sessions,
        target_key_last,
 };
 
index 6bf9aa4..cf9edcb 100644 (file)
@@ -238,6 +238,13 @@ static void text_scan_security(struct connection *conn)
        return;
 }
 
+#define ISCSI_SESS_REINSTATEMENT       1
+#define ISCSI_CONN_REINSTATEMENT       2
+
+/*
+ * Returns above ISCSI_*_REINSTATEMENT for session reinstatement,
+ * <0 for error, 0 otherwise.
+ */
 static int login_check_reinstatement(struct connection *conn)
 {
        struct iscsi_login_req_hdr *req = (struct iscsi_login_req_hdr *)&conn->req.bhs;
@@ -259,6 +266,7 @@ static int login_check_reinstatement(struct connection *conn)
                        log_debug(1, "Session sid %#" PRIx64 " reinstatement "
                                "detected (tid %d, initiator %s)", req->sid.id64,
                                conn->tid, conn->initiator);
+                       res = ISCSI_SESS_REINSTATEMENT;
                } else if (req->sid.id.tsih != session->sid.id.tsih) {
                        log_error("TSIH for existing session sid %#" PRIx64
                                ") doesn't match (tid %d, initiator %s, sid requested "
@@ -280,6 +288,7 @@ static int login_check_reinstatement(struct connection *conn)
                                        req->sid.id64, conn->initiator);
                                conn->sess = session;
                                list_add_tail(&conn->clist, &session->conn_list);
+                               res = ISCSI_CONN_REINSTATEMENT;
                        } else {
                                log_error("Only a single connection supported "
                                        "(initiator %s)", conn->initiator);
@@ -504,7 +513,7 @@ static void login_start(struct connection *conn)
 
        if (conn->session_type == SESSION_NORMAL) {
                struct target *target;
-               int err;
+               int err, rc;
 
                if (!target_name) {
                        rsp->status_class = ISCSI_STATUS_INITIATOR_ERR;
@@ -542,7 +551,7 @@ static void login_start(struct connection *conn)
 
                err = init_conn_session_params(conn);
                if (err != 0) {
-                       log_error("Can't get session params for session 0x%" PRIu64 
+                       log_error("Can't get session params for session 0x%" PRIu64
                                " (err %d): %s\n", conn->sid.id64, err,
                                strerror(-err));
                        rsp->status_class = ISCSI_STATUS_TARGET_ERR;
@@ -551,8 +560,28 @@ static void login_start(struct connection *conn)
                        return;
                }
 
-               if (login_check_reinstatement(conn) != 0)
+               rc = login_check_reinstatement(conn);
+               if (rc < 0)
                        return;
+               else if (rc == ISCSI_SESS_REINSTATEMENT)
+                       target->sessions_count++;
+               else if (rc != ISCSI_CONN_REINSTATEMENT) {
+                       if ((target->target_params[key_max_sessions] == 0) ||
+                           (target->sessions_count < target->target_params[key_max_sessions]))
+                               target->sessions_count++;
+                       else {
+                               log_warning("Initiator %s not allowed to connect to "
+                                       "target %s - max sessions limit "
+                                       "reached (%d)", name, target_name,
+                                       target->target_params[key_max_sessions]);
+                               rsp->status_class = ISCSI_STATUS_TARGET_ERR;
+                               rsp->status_detail = ISCSI_STATUS_NO_RESOURCES;
+                               conn->state = STATE_CLOSE;
+                               return;
+                       }
+               }
+               log_debug(1, "target %s, sessions_count %d", target_name,
+                       target->sessions_count);
        }
 
        conn->exp_cmd_sn = be32_to_cpu(req->cmd_sn);
index 33a536d..227400a 100644 (file)
@@ -174,6 +174,7 @@ struct target {
        u32 tid;
        char name[ISCSI_NAME_LEN];
        char *alias;
+       unsigned int sessions_count;
 
        struct __qelem target_in_accounts;
        struct __qelem target_out_accounts;
@@ -269,7 +270,7 @@ extern int kernel_session_create(struct connection *conn);
 extern int kernel_session_destroy(u32 tid, u64 sid);
 extern int kernel_conn_create(u32 tid, u64 sid, u32 cid, u32 stat_sn, u32 exp_stat_sn,
        int fd);
-extern int kernel_conn_destroy(u32 tid, u64 sid, u32 cid);     
+extern int kernel_conn_destroy(u32 tid, u64 sid, u32 cid);
 
 /* event.c */
 extern void handle_iscsi_events(int fd);
index 928a418..bf1c8da 100644 (file)
@@ -349,6 +349,7 @@ struct iscsi_key target_keys[] = {
        {"QueuedCommands", SET_KEY_VALUES(NR_QUEUED_CMNDS), 1, &minimum_ops},
        {"RspTimeout", SET_KEY_VALUES(RSP_TIMEOUT), 1, &minimum_ops},
        {"NopInInterval", SET_KEY_VALUES(NOP_IN_INTERVAL), 1, &minimum_ops},
+       {"MaxSessions", 0, 0, 0, 65535, 1, &minimum_ops},
        {NULL,},
 };
 
index 744da11..83d91ed 100644 (file)
@@ -155,8 +155,15 @@ void session_free(struct session *session)
        if (!session->sid.id.tsih)
                kernel_session_destroy(session->target->tid, session->sid.id64);
 
-       if (session->target)
+       if (session->target) {
+               struct target *target = session->target;
+
+               target->sessions_count--;
+               log_debug(1, "target %s, sessions_count %d", target->name,
+                       target->sessions_count);
+
                list_del(&session->slist);
+       }
 
        free(session->initiator);
        free(session);