[stgt] [PATCH] changes in iscsi login/text prototypes, structs
Alexander Nezhinsky
alexandern at Voltaire.COM
Tue Sep 21 14:33:31 CEST 2010
This patch breaks the dependence of iscsi login/text code on the
static structures within struct iscsi_conn. Most of the changes
are concerned with the following two issues:
1. changed function prototypes, to include pointers to the relevant
pdu or bhs structures or data buffers. These changes ultimately
start with the new prototype of cmnd_execute(), to which
two new arguments: struct iscsi_pdu *req_pdu, *rsp_pdu
are added. All other functions called from this point and on
are changed according to their needs.
2. struct login_state is defined and added to iscsi_conn.
It encapsulates login/text specific data and status.
All login/text data buffers are copied to the buffers
internal to this new structure. When necessary, data from multiple
pdus is accumulated in a single request buffer, and conversely,
a long response buffer can be sent piecewise within multiple pdus.
These changes enable using dynamically allocated pdus and their
immediate release after processing by the login/text code.
Such scheme is to be employed by the new iser code, i.e. it's
the first step towards its integration.
Verified: discovery and login (auth=None, auth=CHAP)
Signed-off-by: Alexander Nezhinsky <alexandern at voltaire.com>
---
usr/iscsi/conn.c | 21 +++
usr/iscsi/iscsi_proto.h | 2 +-
usr/iscsi/iscsid.c | 313 +++++++++++++++++++++++++++++++----------------
usr/iscsi/iscsid.h | 25 ++++-
4 files changed, 254 insertions(+), 107 deletions(-)
diff --git a/usr/iscsi/conn.c b/usr/iscsi/conn.c
index ba7a58f..afc6dd9 100644
--- a/usr/iscsi/conn.c
+++ b/usr/iscsi/conn.c
@@ -56,6 +56,14 @@ int conn_init(struct iscsi_connection *conn)
}
conn->rsp_buffer_size = INCOMING_BUFSIZE;
+ conn->login.rsp_buf = malloc(INCOMING_BUFSIZE);
+ if (!conn->login.rsp_buf) {
+ free(conn->req_buffer);
+ free(conn->rsp_buffer);
+ return -ENOMEM;
+ }
+ conn->login.rsp_buf_sz = INCOMING_BUFSIZE;
+
conn->refcount = 1;
conn->state = STATE_FREE;
param_set_defaults(conn->session_param, session_keys);
@@ -75,6 +83,10 @@ void conn_exit(struct iscsi_connection *conn)
free(conn->req_buffer);
free(conn->rsp_buffer);
free(conn->initiator);
+ if (conn->login.req_buf)
+ free(conn->login.req_buf);
+ if (conn->login.rsp_buf)
+ free(conn->login.rsp_buf);
if (session)
session_put(session);
@@ -175,6 +187,15 @@ void conn_close(struct iscsi_connection *conn)
continue;
iscsi_free_task(task);
}
+
+ if (conn->login.req_buf) {
+ free(conn->login.req_buf);
+ conn->login.req_buf = NULL;
+ }
+ if (conn->login.rsp_buf) {
+ free(conn->login.rsp_buf);
+ conn->login.rsp_buf = NULL;
+ }
done:
conn_put(conn);
}
diff --git a/usr/iscsi/iscsi_proto.h b/usr/iscsi/iscsi_proto.h
index d5e58df..17e481f 100644
--- a/usr/iscsi/iscsi_proto.h
+++ b/usr/iscsi/iscsi_proto.h
@@ -589,7 +589,7 @@ struct iscsi_reject {
#define VALUE_MAXLEN 255
#define TARGET_NAME_MAXLEN VALUE_MAXLEN
-#define DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH 8192
+#define LOGIN_MAX_RECV_DATA_SEG_LEN 8192
/************************* RFC 3720 End *****************************/
diff --git a/usr/iscsi/iscsid.c b/usr/iscsi/iscsid.c
index facc999..306e15a 100644
--- a/usr/iscsi/iscsid.c
+++ b/usr/iscsi/iscsid.c
@@ -99,12 +99,10 @@ static struct iscsi_key login_keys[] = {
char *text_key_find(struct iscsi_connection *conn, char *searchKey)
{
- char *data, *key, *value;
- int keylen, datasize;
-
- keylen = strlen(searchKey);
- data = conn->req.data;
- datasize = conn->req.datasize;
+ char *data = conn->login.req_buf;
+ int datasize = conn->login.req_buf_sz;
+ int keylen = strlen(searchKey);
+ char *key, *value;
while (1) {
for (key = data; datasize > 0 && *data != '='; data++, datasize--)
@@ -154,6 +152,22 @@ static char *next_key(char **data, int *datasize, char **value)
return key;
}
+static char *buffer_resize(char **buffer, int *size, int add_size)
+{
+ int new_size = *size + add_size;
+ char *new_ptr;
+
+ if (!*size)
+ new_ptr = malloc(new_size);
+ else
+ new_ptr = realloc(*buffer, new_size);
+ if (new_ptr) {
+ *buffer = new_ptr;
+ *size = new_size;
+ }
+ return new_ptr;
+}
+
void text_key_add(struct iscsi_connection *conn, char *key, char *value)
{
int keylen = strlen(key);
@@ -165,34 +179,26 @@ void text_key_add(struct iscsi_connection *conn, char *key, char *value)
if (conn->state == STATE_FULL)
max_len = conn->session_param[ISCSI_PARAM_MAX_XMIT_DLENGTH].val;
else
- max_len = conn->rsp_buffer_size;
-
- if (!conn->rsp.datasize)
- conn->rsp.data = conn->rsp_buffer;
-
- buffer = conn->rsp_buffer;
+ max_len = LOGIN_MAX_RECV_DATA_SEG_LEN;
- if (conn->rsp.datasize + len > max_len &&
+ if (conn->login.rsp_data_sz + len > max_len &&
(conn->req.bhs.opcode & ISCSI_OPCODE_MASK) != ISCSI_OP_TEXT)
goto drop;
- if (conn->rsp.datasize + len > conn->rsp_buffer_size) {
- buffer = realloc(buffer, conn->rsp.datasize + len);
- if (buffer) {
- conn->rsp_buffer = buffer;
- conn->rsp.data = conn->rsp_buffer;
- conn->rsp_buffer_size = conn->rsp.datasize + len;
- } else
+ if (conn->login.rsp_data_sz + len > conn->login.rsp_buf_sz) {
+ buffer = buffer_resize(&conn->login.rsp_buf,
+ &conn->login.rsp_buf_sz,
+ max_len);
+ if (!buffer)
goto drop;
}
-
- buffer += conn->rsp.datasize;
- conn->rsp.datasize += len;
-
+ buffer = conn->login.rsp_buf + conn->login.rsp_data_sz;
strcpy(buffer, key);
buffer += keylen;
*buffer++ = '=';
strcpy(buffer, value);
+ conn->login.rsp_data_sz += len;
+ dprintf("%s=%s (tx)\n", key, value);
return;
drop:
log_warning("Dropping key (%s=%s)", key, value);
@@ -204,16 +210,14 @@ static void text_key_add_reject(struct iscsi_connection *conn, char *key)
text_key_add(conn, key, "Reject");
}
-static void text_scan_security(struct iscsi_connection *conn)
+static void text_scan_security(struct iscsi_connection *conn,
+ struct iscsi_login_rsp *rsp)
{
- struct iscsi_login_rsp *rsp = (struct iscsi_login_rsp *)&conn->rsp.bhs;
- char *key, *value, *data, *nextValue;
- int datasize;
+ char *req_buf = conn->login.req_buf;
+ int req_size = conn->login.req_buf_sz;
+ char *key, *value, *nextValue;
- data = conn->req.data;
- datasize = conn->req.datasize;
-
- while ((key = next_key(&data, &datasize, &value))) {
+ while ((key = next_key(&req_buf, &req_size, &value))) {
if (!(param_index_by_name(key, login_keys) < 0))
;
else if (!strcmp(key, "AuthMethod")) {
@@ -249,10 +253,10 @@ static void text_scan_security(struct iscsi_connection *conn)
}
}
-static void login_security_done(struct iscsi_connection *conn)
+static void login_security_done(struct iscsi_connection *conn,
+ struct iscsi_login *req,
+ struct iscsi_login_rsp *rsp)
{
- struct iscsi_login *req = (struct iscsi_login *)&conn->req.bhs;
- struct iscsi_login_rsp *rsp = (struct iscsi_login_rsp *) &conn->rsp.bhs;
struct iscsi_session *session;
if (!conn->tid)
@@ -299,16 +303,16 @@ static void login_security_done(struct iscsi_connection *conn)
}
}
-static void text_scan_login(struct iscsi_connection *conn)
+static void text_scan_login(struct iscsi_connection *conn,
+ struct iscsi_login_rsp *rsp)
{
- char *key, *value, *data;
- int datasize, idx, is_rdma = 0;
- struct iscsi_login_rsp *rsp = (struct iscsi_login_rsp *)&conn->rsp.bhs;
+ char *key, *value;
+ int idx, is_rdma = 0;
+ char *req_buf = conn->login.req_buf;
+ int req_size = conn->login.req_buf_sz;
- data = conn->req.data;
- datasize = conn->req.datasize;
-
- while ((key = next_key(&data, &datasize, &value))) {
+ while ((key = next_key(&req_buf, &req_size, &value))) {
+ dprintf("%s=%s (rx)\n", key, value);
if (!(param_index_by_name(key, login_keys) < 0))
;
else if (!strcmp(key, "AuthMethod"))
@@ -424,10 +428,10 @@ static int text_check_param(struct iscsi_connection *conn)
return cnt;
}
-static void login_start(struct iscsi_connection *conn)
+static void login_start(struct iscsi_connection *conn,
+ struct iscsi_login *req,
+ struct iscsi_login_rsp *rsp)
{
- struct iscsi_login *req = (struct iscsi_login *)&conn->req.bhs;
- struct iscsi_login_rsp *rsp = (struct iscsi_login_rsp *)&conn->rsp.bhs;
char *name, *alias, *session_type, *target_name;
struct iscsi_target *target;
@@ -541,6 +545,26 @@ static void login_start(struct iscsi_connection *conn)
text_key_add(conn, "TargetPortalGroupTag", "1");
}
+static void login_cleanup(struct iscsi_connection *conn)
+{
+ int max_len = conn->session_param[ISCSI_PARAM_MAX_XMIT_DLENGTH].val;
+
+ if (conn->login.req_buf) {
+ free(conn->login.req_buf);
+ conn->login.req_buf = NULL;
+ conn->login.req_buf_sz = 0;
+ }
+ conn->login.req_data_sz = 0;
+ /* leave enough space for text responces */
+ if (conn->login.rsp_buf && conn->login.rsp_buf_sz > max_len) {
+ conn->login.rsp_buf = realloc(conn->login.rsp_buf, max_len);
+ conn->login.rsp_buf_sz = max_len;
+ }
+ conn->login.rsp_data_sz = 0;
+ conn->login.rsp_offset = 0;
+ conn->login.status = LOGIN_NONE;
+}
+
static void login_finish(struct iscsi_connection *conn)
{
struct iscsi_login_rsp *rsp = (struct iscsi_login_rsp *) &conn->rsp.bhs;
@@ -612,9 +636,12 @@ static int cmnd_exec_auth(struct iscsi_connection *conn)
return res;
}
-static void cmnd_reject(struct iscsi_connection *conn, uint8_t reason)
+static void cmnd_reject(struct iscsi_connection *conn,
+ struct iscsi_pdu *req_pdu,
+ struct iscsi_pdu *rsp_pdu,
+ uint8_t reason)
{
- struct iscsi_reject *rsp = (struct iscsi_reject *)&conn->rsp.bhs;
+ struct iscsi_reject *rsp = (struct iscsi_reject *)&rsp_pdu->bhs;
memset(rsp, 0, BHS_SIZE);
@@ -627,24 +654,59 @@ static void cmnd_reject(struct iscsi_connection *conn, uint8_t reason)
rsp->exp_cmdsn = cpu_to_be32(conn->exp_cmd_sn);
rsp->max_cmdsn = cpu_to_be32(conn->max_cmd_sn);
- conn->rsp.data = conn->rsp_buffer;
- conn->rsp.datasize = BHS_SIZE;
- memcpy(conn->rsp.data, &conn->req.bhs, BHS_SIZE);
+ memcpy(conn->login.rsp_buf, &req_pdu->bhs, BHS_SIZE);
+ rsp_pdu->datasize = BHS_SIZE;
}
-static void cmnd_exec_login(struct iscsi_connection *conn)
+static int add_req_login_text_data(struct iscsi_connection *conn,
+ char *req_data,
+ int data_size)
{
- struct iscsi_login *req = (struct iscsi_login *)&conn->req.bhs;
- struct iscsi_login_rsp *rsp = (struct iscsi_login_rsp *)&conn->rsp.bhs;
+ char *buffer;
+
+ if (!data_size)
+ return 0;
+ if (conn->login.req_data_sz + data_size > conn->login.req_buf_sz) {
+ buffer = buffer_resize(&conn->login.req_buf,
+ &conn->login.req_buf_sz,
+ INCOMING_BUFSIZE);
+ if (!buffer)
+ return -ENOMEM;
+ }
+ buffer = conn->login.req_buf + conn->login.req_data_sz;
+ memcpy(buffer, req_data, data_size);
+ conn->login.req_data_sz += data_size;
+ return 0;
+}
+
+static void cmnd_exec_login(struct iscsi_connection *conn,
+ struct iscsi_pdu *req_pdu,
+ struct iscsi_pdu *rsp_pdu)
+{
+ struct iscsi_login *req = (struct iscsi_login *)&req_pdu->bhs;
+ struct iscsi_login_rsp *rsp = (struct iscsi_login_rsp *)&rsp_pdu->bhs;
int stay = 0, nsg_disagree = 0;
memset(rsp, 0, BHS_SIZE);
if ((req->opcode & ISCSI_OPCODE_MASK) != ISCSI_OP_LOGIN ||
!(req->opcode & ISCSI_OP_IMMEDIATE)) {
- cmnd_reject(conn, ISCSI_REASON_PROTOCOL_ERROR);
+ cmnd_reject(conn, req_pdu, rsp_pdu,
+ ISCSI_REASON_PROTOCOL_ERROR);
+ return;
+ }
+
+ if (add_req_login_text_data(conn, req_pdu->data, req_pdu->datasize)) {
+ rsp->status_class = ISCSI_STATUS_CLS_TARGET_ERR;
+ rsp->status_detail = ISCSI_LOGIN_STATUS_NO_RESOURCES;
+ conn->state = STATE_EXIT;
return;
}
+ if (conn->login.status != LOGIN_IN_PROGRESS) {
+ conn->login.rsp_data_sz = 0;
+ conn->login.rsp_offset = 0;
+ }
+
rsp->opcode = ISCSI_OP_LOGIN_RSP;
rsp->max_version = ISCSI_DRAFT20_VERSION;
rsp->active_version = ISCSI_DRAFT20_VERSION;
@@ -667,12 +729,12 @@ static void cmnd_exec_login(struct iscsi_connection *conn)
switch (conn->state) {
case STATE_FREE:
conn->state = STATE_SECURITY;
- login_start(conn);
+ login_start(conn, req, rsp);
if (rsp->status_class)
return;
/* fall through */
case STATE_SECURITY:
- text_scan_security(conn);
+ text_scan_security(conn, rsp);
if (rsp->status_class)
return;
if (conn->auth_method != AUTH_NONE) {
@@ -705,18 +767,18 @@ static void cmnd_exec_login(struct iscsi_connection *conn)
case STATE_FREE:
conn->state = STATE_LOGIN;
- login_start(conn);
+ login_start(conn, req, rsp);
if (account_available(conn->tid, AUTH_DIR_INCOMING))
goto auth_err;
if (rsp->status_class)
return;
- text_scan_login(conn);
+ text_scan_login(conn, rsp);
if (rsp->status_class)
return;
stay = text_check_param(conn);
break;
case STATE_LOGIN:
- text_scan_login(conn);
+ text_scan_login(conn, rsp);
if (rsp->status_class)
return;
stay = text_check_param(conn);
@@ -741,7 +803,7 @@ static void cmnd_exec_login(struct iscsi_connection *conn)
case STATE_SECURITY:
case STATE_SECURITY_DONE:
conn->state = STATE_SECURITY_LOGIN;
- login_security_done(conn);
+ login_security_done(conn, req, rsp);
break;
default:
goto init_err;
@@ -757,7 +819,7 @@ static void cmnd_exec_login(struct iscsi_connection *conn)
break;
}
conn->state = STATE_SECURITY_FULL;
- login_security_done(conn);
+ login_security_done(conn, req, rsp);
break;
case STATE_LOGIN:
if (stay)
@@ -780,6 +842,11 @@ static void cmnd_exec_login(struct iscsi_connection *conn)
rsp->flags |= nsg | (stay ? 0 : ISCSI_FLAG_LOGIN_TRANSIT);
}
+ conn->login.req_data_sz = 0; /* done with the request */
+ if (conn->login.status == LOGIN_NONE)
+ conn->login.status = LOGIN_LAST_TX;
+ rsp_pdu->datasize = conn->login.rsp_data_sz; /* single response */
+
memcpy(rsp->isid, conn->isid, sizeof(rsp->isid));
rsp->tsih = conn->tsih;
rsp->statsn = cpu_to_be32(conn->stat_sn++);
@@ -805,10 +872,11 @@ static void text_scan_text(struct iscsi_connection *conn)
char *key, *value, *data;
int datasize;
- data = conn->req.data;
- datasize = conn->req.datasize;
+ data = conn->login.req_buf;
+ datasize = conn->login.req_buf_sz;
while ((key = next_key(&data, &datasize, &value))) {
+ dprintf("%s=%s (rx)\n", key, value);
if (!strcmp(key, "SendTargets")) {
struct sockaddr_storage ss;
socklen_t slen, blen;
@@ -855,60 +923,74 @@ static void text_scan_text(struct iscsi_connection *conn)
}
}
-static void cmnd_exec_text(struct iscsi_connection *conn)
+static void cmnd_exec_text(struct iscsi_connection *conn,
+ struct iscsi_pdu *req_pdu,
+ struct iscsi_pdu *rsp_pdu)
{
- struct iscsi_text *req = (struct iscsi_text *)&conn->req.bhs;
- struct iscsi_text_rsp *rsp = (struct iscsi_text_rsp *)&conn->rsp.bhs;
+ struct iscsi_text *req = (struct iscsi_text *)&req_pdu->bhs;
+ struct iscsi_text_rsp *rsp = (struct iscsi_text_rsp *)&rsp_pdu->bhs;
int max_len = conn->session_param[ISCSI_PARAM_MAX_XMIT_DLENGTH].val;
+ int rsp_left;
- memset(rsp, 0, BHS_SIZE);
+ dprintf("Text request: %d %d\n", conn->state, max_len);
+
+ if (add_req_login_text_data(conn, req_pdu->data, req_pdu->datasize)) {
+ cmnd_reject(conn, req_pdu, rsp_pdu,
+ ISCSI_REASON_OUT_OF_RESOURCES);
+ return;
+ }
+ if (conn->login.status != TEXT_IN_PROGRESS) {
+ conn->login.rsp_data_sz = 0;
+ conn->login.rsp_offset = 0;
+ }
+
+ memset(rsp, 0, BHS_SIZE);
rsp->opcode = ISCSI_OP_TEXT_RSP;
rsp->itt = req->itt;
conn->exp_cmd_sn = be32_to_cpu(req->cmdsn);
if (!(req->opcode & ISCSI_OP_IMMEDIATE))
conn->exp_cmd_sn++;
- if (be32_to_cpu(req->ttt) == ISCSI_RESERVED_TAG) {
- conn->text_datasize = 0;
-
+ if (be32_to_cpu(req->ttt) == ISCSI_RESERVED_TAG) { /* new request */
text_scan_text(conn);
-
- conn->text_rsp_buffer = conn->rsp_buffer;
- conn->text_datasize = conn->rsp.datasize;
-
- if (conn->text_datasize > max_len) {
+ if (conn->login.rsp_data_sz <= max_len)
+ conn->ttt = ISCSI_RESERVED_TAG;
+ else {
conn->ttt++;
if (conn->ttt == ISCSI_RESERVED_TAG)
conn->ttt++;
- } else
- conn->ttt = ISCSI_RESERVED_TAG;
- } else if (!conn->text_datasize || conn->ttt != be32_to_cpu(req->ttt)) {
- cmnd_reject(conn, ISCSI_REASON_INVALID_PDU_FIELD);
+ }
+ } else if (conn->login.status != TEXT_IN_PROGRESS ||
+ conn->ttt != be32_to_cpu(req->ttt)) {
+ cmnd_reject(conn, req_pdu, rsp_pdu,
+ ISCSI_REASON_INVALID_PDU_FIELD);
return;
}
- if (conn->text_datasize <= max_len) {
+ rsp_left = conn->login.rsp_data_sz - conn->login.rsp_offset;
+ if (rsp_left <= max_len) {
+ rsp_pdu->datasize = rsp_left;
rsp->flags = ISCSI_FLAG_CMD_FINAL;
- conn->ttt = ISCSI_RESERVED_TAG;
+ conn->login.status = TEXT_LAST_TX;
+ conn->login.req_data_sz = 0; /* done with the request */
+ } else {
+ rsp_pdu->datasize = max_len;
+ conn->login.status = TEXT_IN_PROGRESS;
}
- conn->rsp.datasize = min(max_len, conn->text_datasize);
- conn->rsp.data = conn->text_rsp_buffer;
- conn->text_rsp_buffer += conn->rsp.datasize;
- conn->text_datasize -= conn->rsp.datasize;
-
rsp->ttt = cpu_to_be32(conn->ttt);
-
rsp->statsn = cpu_to_be32(conn->stat_sn++);
rsp->exp_cmdsn = cpu_to_be32(conn->exp_cmd_sn);
rsp->max_cmdsn = cpu_to_be32(conn->max_cmd_sn);
}
-static void cmnd_exec_logout(struct iscsi_connection *conn)
+static void cmnd_exec_logout(struct iscsi_connection *conn,
+ struct iscsi_pdu *req_pdu,
+ struct iscsi_pdu *rsp_pdu)
{
- struct iscsi_logout *req = (struct iscsi_logout *)&conn->req.bhs;
- struct iscsi_logout_rsp *rsp = (struct iscsi_logout_rsp *)&conn->rsp.bhs;
+ struct iscsi_logout *req = (struct iscsi_logout *)&req_pdu->bhs;
+ struct iscsi_logout_rsp *rsp = (struct iscsi_logout_rsp *)&rsp_pdu->bhs;
memset(rsp, 0, BHS_SIZE);
rsp->opcode = ISCSI_OP_LOGOUT_RSP;
@@ -923,28 +1005,46 @@ static void cmnd_exec_logout(struct iscsi_connection *conn)
rsp->max_cmdsn = cpu_to_be32(conn->max_cmd_sn);
}
-static int cmnd_execute(struct iscsi_connection *conn)
+static void finalize_text_rsp_pdu(struct iscsi_connection *conn,
+ struct iscsi_pdu *rsp_pdu)
+{
+ struct iscsi_hdr *rsp = &rsp_pdu->bhs;
+
+ rsp->hlength = rsp_pdu->ahssize / 4;
+
+ rsp_pdu->data = conn->login.rsp_buf + conn->login.rsp_offset;
+ conn->login.rsp_offset += rsp_pdu->datasize;
+ hton24(rsp->dlength, rsp_pdu->datasize);
+}
+
+static int cmnd_execute(struct iscsi_connection *conn,
+ struct iscsi_pdu *req_pdu,
+ struct iscsi_pdu *rsp_pdu)
{
+ struct iscsi_hdr *req = &req_pdu->bhs;
+ struct iscsi_hdr *rsp = &rsp_pdu->bhs;
int res = 0;
- switch (conn->req.bhs.opcode & ISCSI_OPCODE_MASK) {
+ switch (req->opcode & ISCSI_OPCODE_MASK) {
case ISCSI_OP_LOGIN:
- cmnd_exec_login(conn);
- conn->rsp.bhs.hlength = conn->rsp.ahssize / 4;
- hton24(conn->rsp.bhs.dlength, conn->rsp.datasize);
+ cmnd_exec_login(conn, req_pdu, rsp_pdu);
+ finalize_text_rsp_pdu(conn, rsp_pdu);
+ /* clean up on error, otherwise decided internally */
+ if (conn->state == STATE_EXIT)
+ login_cleanup(conn);
break;
case ISCSI_OP_TEXT:
- cmnd_exec_text(conn);
- conn->rsp.bhs.hlength = conn->rsp.ahssize / 4;
- hton24(conn->rsp.bhs.dlength, conn->rsp.datasize);
+ cmnd_exec_text(conn, req_pdu, rsp_pdu);
+ finalize_text_rsp_pdu(conn, rsp_pdu);
break;
case ISCSI_OP_LOGOUT:
- cmnd_exec_logout(conn);
- conn->rsp.bhs.hlength = conn->rsp.ahssize / 4;
- hton24(conn->rsp.bhs.dlength, conn->rsp.datasize);
+ cmnd_exec_logout(conn, req_pdu, rsp_pdu);
+ rsp->hlength = rsp_pdu->ahssize / 4;
+ hton24(rsp->dlength, rsp_pdu->datasize);
break;
default:
- cmnd_reject(conn, ISCSI_REASON_CMD_NOT_SUPPORTED);
+ cmnd_reject(conn, req_pdu, rsp_pdu,
+ ISCSI_REASON_CMD_NOT_SUPPORTED);
res = 1;
break;
}
@@ -964,11 +1064,16 @@ static void cmnd_finish(struct iscsi_connection *conn)
case STATE_SECURITY_FULL:
/* fall through */
case STATE_LOGIN_FULL:
+ login_cleanup(conn);
if (conn->session_type == SESSION_NORMAL)
conn->state = STATE_KERNEL;
else
conn->state = STATE_FULL;
break;
+ case STATE_FULL:
+ if (conn->login.status == TEXT_LAST_TX)
+ login_cleanup(conn);
+ break;
}
}
@@ -2066,7 +2171,7 @@ again:
} else {
conn_write_pdu(conn);
conn->tp->ep_event_modify(conn, EPOLLOUT);
- ret = cmnd_execute(conn);
+ ret = cmnd_execute(conn, &conn->req, &conn->rsp);
if (ret)
conn->state = STATE_CLOSE;
}
diff --git a/usr/iscsi/iscsid.h b/usr/iscsi/iscsid.h
index 35bb068..1de8580 100644
--- a/usr/iscsi/iscsid.h
+++ b/usr/iscsi/iscsid.h
@@ -132,6 +132,27 @@ struct iscsi_task {
unsigned long extdata[0];
};
+enum login_status {
+ LOGIN_NONE = 0,
+ LOGIN_IN_PROGRESS,
+ LOGIN_LAST_TX,
+ TEXT_IN_PROGRESS,
+ TEXT_LAST_TX
+};
+
+struct login_state {
+ char *req_buf;
+ int req_buf_sz;
+ int req_data_sz;
+
+ char *rsp_buf;
+ int rsp_buf_sz;
+ int rsp_data_sz;
+ int rsp_offset;
+
+ enum login_status status;
+};
+
struct iscsi_connection {
int state;
@@ -173,8 +194,8 @@ struct iscsi_connection {
int tx_size;
uint32_t ttt;
- int text_datasize;
- void *text_rsp_buffer;
+
+ struct login_state login;
struct iscsi_task *rx_task;
struct iscsi_task *tx_task;
--
1.6.5
--
To unsubscribe from this list: send the line "unsubscribe stgt" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
More information about the stgt
mailing list