Fri Jun 19 16:13:09 2009 UTC ()
WARNS=4 (all sign-comparison changes)


(agc)
diff -r1.18 -r1.19 src/dist/iscsi/src/initiator.c

cvs diff -r1.18 -r1.19 src/dist/iscsi/src/Attic/initiator.c (switch to unified diff)

--- src/dist/iscsi/src/Attic/initiator.c 2007/12/11 19:57:58 1.18
+++ src/dist/iscsi/src/Attic/initiator.c 2009/06/19 16:13:09 1.19
@@ -1,3246 +1,3246 @@ @@ -1,3246 +1,3246 @@
1/* 1/*
2 * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or 2 * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
3 * using the software you agree to this license. If you do not agree to this license, do not download, install, 3 * using the software you agree to this license. If you do not agree to this license, do not download, install,
4 * copy or use the software. 4 * copy or use the software.
5 * 5 *
6 * Intel License Agreement 6 * Intel License Agreement
7 * 7 *
8 * Copyright (c) 2000, Intel Corporation 8 * Copyright (c) 2000, Intel Corporation
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that 11 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that
12 * the following conditions are met: 12 * the following conditions are met:
13 * 13 *
14 * -Redistributions of source code must retain the above copyright notice, this list of conditions and the 14 * -Redistributions of source code must retain the above copyright notice, this list of conditions and the
15 * following disclaimer. 15 * following disclaimer.
16 * 16 *
17 * -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 17 * -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
18 * following disclaimer in the documentation and/or other materials provided with the distribution. 18 * following disclaimer in the documentation and/or other materials provided with the distribution.
19 * 19 *
20 * -The name of Intel Corporation may not be used to endorse or promote products derived from this software 20 * -The name of Intel Corporation may not be used to endorse or promote products derived from this software
21 * without specific prior written permission. 21 * without specific prior written permission.
22 * 22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE. 30 * POSSIBILITY OF SUCH DAMAGE.
31 */ 31 */
32#include "config.h" 32#include "config.h"
33 33
34#include <sys/types.h> 34#include <sys/types.h>
35 35
36#ifdef HAVE_SYS_TIME_H 36#ifdef HAVE_SYS_TIME_H
37#include <sys/time.h> 37#include <sys/time.h>
38#endif 38#endif
39  39
40#ifdef HAVE_SYS_SOCKET_H 40#ifdef HAVE_SYS_SOCKET_H
41#include <sys/socket.h> 41#include <sys/socket.h>
42#endif 42#endif
43  43
44#ifdef HAVE_NETINET_IN_H 44#ifdef HAVE_NETINET_IN_H
45#include <netinet/in.h> 45#include <netinet/in.h>
46#endif 46#endif
47  47
48#ifdef HAVE_NETINET_TCP_H 48#ifdef HAVE_NETINET_TCP_H
49#include <netinet/tcp.h> 49#include <netinet/tcp.h>
50#endif 50#endif
51  51
52#ifdef HAVE_SIGNAL_H 52#ifdef HAVE_SIGNAL_H
53#include <signal.h> 53#include <signal.h>
54#endif 54#endif
55  55
56#include <stdio.h> 56#include <stdio.h>
57#include <stdlib.h> 57#include <stdlib.h>
58  58
59#ifdef HAVE_STRING_H 59#ifdef HAVE_STRING_H
60#include <string.h> 60#include <string.h>
61#endif 61#endif
62 62
63#include <unistd.h> 63#include <unistd.h>
64 64
65#include "iscsi.h" 65#include "iscsi.h"
66#include "initiator.h" 66#include "initiator.h"
67 67
68static initiator_target_t g_target[CONFIG_INITIATOR_NUM_TARGETS]; 68static initiator_target_t g_target[CONFIG_INITIATOR_NUM_TARGETS];
69 69
70/* 70/*
71 * Globals 71 * Globals
72 */ 72 */
73static uint32_t g_tag; 73static uint32_t g_tag;
74static iscsi_spin_t g_tag_spin; 74static iscsi_spin_t g_tag_spin;
75static hash_t g_tag_hash; 75static hash_t g_tag_hash;
76static iscsi_worker_t g_enqueue_worker; 76static iscsi_worker_t g_enqueue_worker;
77static iscsi_queue_t g_enqueue_q; 77static iscsi_queue_t g_enqueue_q;
78static iscsi_queue_t g_session_q; 78static iscsi_queue_t g_session_q;
79static int g_initiator_state; 79static int g_initiator_state;
80static char *gfilename; 80static char *gfilename;
81 81
82/* Testing of initiator_abort */ 82/* Testing of initiator_abort */
83 83
84static initiator_cmd_t *g_cmd = NULL; 84static initiator_cmd_t *g_cmd = NULL;
85 85
86/* 86/*
87 * Enqueue worker functions. The enqueue worker is responsible for enqueing 87 * Enqueue worker functions. The enqueue worker is responsible for enqueing
88 * all iSCSI commands to one of the Tx workers. It is also the thread 88 * all iSCSI commands to one of the Tx workers. It is also the thread
89 * responsible for initializing sessions, discovering targets and getting 89 * responsible for initializing sessions, discovering targets and getting
90 * each session into full feature phase. 90 * each session into full feature phase.
91 */ 91 */
92 92
93static int enqueue_worker_proc(void *); 93static int enqueue_worker_proc(void *);
94static int login_phase_i(initiator_session_t *, char *, int); 94static int login_phase_i(initiator_session_t *, char *, int);
95static int logout_phase_i(initiator_session_t *); 95static int logout_phase_i(initiator_session_t *);
96 96
97/* 97/*
98 * Tx functions. initiator_cmd_t pointers are enqueued to the Tx worker 98 * Tx functions. initiator_cmd_t pointers are enqueued to the Tx worker
99 * for a given session by the enqueue worker. The Tx worker will send out these 99 * for a given session by the enqueue worker. The Tx worker will send out these
100 * commands and wait for the Rx worker to process the response. The pointer is 100 * commands and wait for the Rx worker to process the response. The pointer is
101 * inserted into the hashtable g_tag_hash, keyed by the initiator tag of the iSCSI 101 * inserted into the hashtable g_tag_hash, keyed by the initiator tag of the iSCSI
102 * commands. 102 * commands.
103 */ 103 */
104 104
105static int tx_worker_proc_i(void *); 105static int tx_worker_proc_i(void *);
106static int text_command_i(initiator_cmd_t *); 106static int text_command_i(initiator_cmd_t *);
107static int login_command_i(initiator_cmd_t *); 107static int login_command_i(initiator_cmd_t *);
108static int logout_command_i(initiator_cmd_t *); 108static int logout_command_i(initiator_cmd_t *);
109static int scsi_command_i(initiator_cmd_t *); 109static int scsi_command_i(initiator_cmd_t *);
110static int nop_out_i(initiator_cmd_t *); 110static int nop_out_i(initiator_cmd_t *);
111 111
112 112
113/* 113/*
114 * Rx functions. Upon receipt of an incoming PDU, the Rx worker will first 114 * Rx functions. Upon receipt of an incoming PDU, the Rx worker will first
115 * extract the tag (if it exists for the PDU) and then the associated 115 * extract the tag (if it exists for the PDU) and then the associated
116 * initiator_cmd_t pointer stored in the hash table. One of Rx functions 116 * initiator_cmd_t pointer stored in the hash table. One of Rx functions
117 * will be called to processs the PDU. The Rx worker will invoke the callback 117 * will be called to processs the PDU. The Rx worker will invoke the callback
118 * function associated with the command once the command has been retired. 118 * function associated with the command once the command has been retired.
119 */ 119 */
120 120
121static int rx_worker_proc_i(void *); 121static int rx_worker_proc_i(void *);
122static int login_response_i(initiator_session_t *, initiator_cmd_t *, uint8_t *); 122static int login_response_i(initiator_session_t *, initiator_cmd_t *, uint8_t *);
123static int text_response_i(initiator_session_t *, initiator_cmd_t *, uint8_t *); 123static int text_response_i(initiator_session_t *, initiator_cmd_t *, uint8_t *);
124static int logout_response_i(initiator_session_t *, initiator_cmd_t *, uint8_t *); 124static int logout_response_i(initiator_session_t *, initiator_cmd_t *, uint8_t *);
125static int scsi_response_i(initiator_session_t *, initiator_cmd_t *, uint8_t *); 125static int scsi_response_i(initiator_session_t *, initiator_cmd_t *, uint8_t *);
126static int scsi_read_data_i(initiator_session_t *, initiator_cmd_t *, uint8_t *); 126static int scsi_read_data_i(initiator_session_t *, initiator_cmd_t *, uint8_t *);
127static int scsi_r2t_i(initiator_session_t *, initiator_cmd_t *, uint8_t *); 127static int scsi_r2t_i(initiator_session_t *, initiator_cmd_t *, uint8_t *);
128static int nop_in_i(initiator_session_t *, initiator_cmd_t *, uint8_t *); 128static int nop_in_i(initiator_session_t *, initiator_cmd_t *, uint8_t *);
129static int reject_i(initiator_session_t *, uint8_t *); 129static int reject_i(initiator_session_t *, uint8_t *);
130static int async_msg_i(initiator_session_t *, uint8_t *); 130static int async_msg_i(initiator_session_t *, uint8_t *);
131 131
132 132
133/* 133/*
134 * Misc. Prototypes 134 * Misc. Prototypes
135 */ 135 */
136 136
137 137
138static int session_init_i(initiator_session_t **, uint64_t ); 138static int session_init_i(initiator_session_t **, uint64_t );
139static int session_destroy_i(initiator_session_t *); 139static int session_destroy_i(initiator_session_t *);
140static int wait_callback_i(void *); 140static int wait_callback_i(void *);
141static int discovery_phase(int, strv_t *); 141static int discovery_phase(int, strv_t *);
142 142
143 143
144/* 144/*
145 * Private Functions 145 * Private Functions
146 */ 146 */
147 147
148#if 0 148#if 0
149static void 149static void
150dump_session(initiator_session_t * sess) 150dump_session(initiator_session_t * sess)
151{ 151{
152 iscsi_parameter_value_t *vp; 152 iscsi_parameter_value_t *vp;
153 iscsi_parameter_t *ip; 153 iscsi_parameter_t *ip;
154 154
155 for (ip = sess->params ; ip ; ip = ip->next) { 155 for (ip = sess->params ; ip ; ip = ip->next) {
156 printf("Key: %s Type: %d\n",ip->key,ip->type); 156 printf("Key: %s Type: %d\n",ip->key,ip->type);
157 for (vp = ip->value_l ; vp ; vp = vp->next) { 157 for (vp = ip->value_l ; vp ; vp = vp->next) {
158 printf("Value: %s\n",vp->value); 158 printf("Value: %s\n",vp->value);
159 } 159 }
160 } 160 }
161} 161}
162#endif 162#endif
163/* This function reads the target IP and target name information */ 163/* This function reads the target IP and target name information */
164/* from the input configuration file, and populates the */ 164/* from the input configuration file, and populates the */
165/* g_target data structure fields. */ 165/* g_target data structure fields. */
166static int  166static int
167get_target_config(const char *hostname, int port) 167get_target_config(const char *hostname, int port)
168{ 168{
169 int i; 169 int i;
170 170
171 for (i = 0 ; i < CONFIG_INITIATOR_NUM_TARGETS ; i++) { 171 for (i = 0 ; i < CONFIG_INITIATOR_NUM_TARGETS ; i++) {
172 (void) strlcpy(g_target[i].name, hostname, sizeof(g_target[i].name)); 172 (void) strlcpy(g_target[i].name, hostname, sizeof(g_target[i].name));
173 g_target[i].port = port; 173 g_target[i].port = port;
174 } 174 }
175 return 0; 175 return 0;
176} 176}
177 177
178static int  178static int
179session_init_i(initiator_session_t ** sess, uint64_t isid) 179session_init_i(initiator_session_t ** sess, uint64_t isid)
180{ 180{
181 initiator_session_t *s; 181 initiator_session_t *s;
182 iscsi_parameter_t **l; 182 iscsi_parameter_t **l;
183 char *user; 183 char *user;
184 int auth_type; 184 int auth_type;
185 int mutual_auth; 185 int mutual_auth;
186 int one = 1; 186 int one = 1;
187 187
188 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "initializing session %llu\n", isid); 188 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "initializing session %llu\n", isid);
189 189
190 /* Get free session */ 190 /* Get free session */
191 if ((*sess = iscsi_queue_remove(&g_session_q)) == NULL) { 191 if ((*sess = iscsi_queue_remove(&g_session_q)) == NULL) {
192 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_remove() failed\n"); 192 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_remove() failed\n");
193 return -1; 193 return -1;
194 } 194 }
195 s = *sess; 195 s = *sess;
196 user = NULL; 196 user = NULL;
197 if (s->sess_params.cred.user) { 197 if (s->sess_params.cred.user) {
198 user = s->sess_params.cred.user; 198 user = s->sess_params.cred.user;
199 } 199 }
200 auth_type = s->sess_params.auth_type; 200 auth_type = s->sess_params.auth_type;
201 mutual_auth = s->sess_params.mutual_auth; 201 mutual_auth = s->sess_params.mutual_auth;
202 (void) memset(s, 0x0, sizeof(*s)); 202 (void) memset(s, 0x0, sizeof(*s));
203 s->state = INITIATOR_SESSION_STATE_INITIALIZING; 203 s->state = INITIATOR_SESSION_STATE_INITIALIZING;
204 s->isid = s->tx_worker.id = s->rx_worker.id = isid; 204 s->isid = s->tx_worker.id = s->rx_worker.id = isid;
205 s->cmds = NULL; 205 s->cmds = NULL;
206 s->sess_params.cred.user = user; 206 s->sess_params.cred.user = user;
207 s->sess_params.auth_type = auth_type; 207 s->sess_params.auth_type = auth_type;
208 s->sess_params.mutual_auth = mutual_auth; 208 s->sess_params.mutual_auth = mutual_auth;
209 209
210 iscsi_spin_init(&s->cmds_spin); 210 iscsi_spin_init(&s->cmds_spin);
211 g_target[isid].has_session = 1; 211 g_target[isid].has_session = 1;
212 212
213 /* Create socket */ 213 /* Create socket */
214 if (!iscsi_sock_create(&s->sock)) { 214 if (!iscsi_sock_create(&s->sock)) {
215 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_create() failed\n"); 215 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_create() failed\n");
216 return -1; 216 return -1;
217 } 217 }
218 if (!iscsi_sock_setsockopt(&s->sock, SOL_TCP, TCP_NODELAY, &one, sizeof(one))) { 218 if (!iscsi_sock_setsockopt(&s->sock, SOL_TCP, TCP_NODELAY, &one, sizeof(one))) {
219 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_setsockopt() failed\n"); 219 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_setsockopt() failed\n");
220 return -1; 220 return -1;
221 } 221 }
222 222
223 /* Initialize wait queues */ 223 /* Initialize wait queues */
224 224
225 ISCSI_MUTEX_INIT(&s->tx_worker.work_mutex, return -1); 225 ISCSI_MUTEX_INIT(&s->tx_worker.work_mutex, return -1);
226 ISCSI_COND_INIT(&s->tx_worker.work_cond, return -1); 226 ISCSI_COND_INIT(&s->tx_worker.work_cond, return -1);
227 ISCSI_MUTEX_INIT(&s->tx_worker.exit_mutex, return -1); 227 ISCSI_MUTEX_INIT(&s->tx_worker.exit_mutex, return -1);
228 ISCSI_COND_INIT(&s->tx_worker.exit_cond, return -1); 228 ISCSI_COND_INIT(&s->tx_worker.exit_cond, return -1);
229 ISCSI_MUTEX_INIT(&s->rx_worker.work_mutex, return -1); 229 ISCSI_MUTEX_INIT(&s->rx_worker.work_mutex, return -1);
230 ISCSI_COND_INIT(&s->rx_worker.work_cond, return -1); 230 ISCSI_COND_INIT(&s->rx_worker.work_cond, return -1);
231 ISCSI_MUTEX_INIT(&s->rx_worker.exit_mutex, return -1); 231 ISCSI_MUTEX_INIT(&s->rx_worker.exit_mutex, return -1);
232 ISCSI_COND_INIT(&s->rx_worker.exit_cond, return -1); 232 ISCSI_COND_INIT(&s->rx_worker.exit_cond, return -1);
233 233
234 /* Build parameter list */ 234 /* Build parameter list */
235 235
236 /* 236 /*
237 * ISCSI_PARAM_TYPE_LIST format: <type> <key> <dflt> <valid list values> 237 * ISCSI_PARAM_TYPE_LIST format: <type> <key> <dflt> <valid list values>
238 * ISCSI_PARAM_TYPE_BINARY format: <type> <key> <dflt> <valid binary values> 238 * ISCSI_PARAM_TYPE_BINARY format: <type> <key> <dflt> <valid binary values>
239 * ISCSI_PARAM_TYPE_NUMERICAL format: <type> <key> <dflt> <max> 239 * ISCSI_PARAM_TYPE_NUMERICAL format: <type> <key> <dflt> <max>
240 * ISCSI_PARAM_TYPE_DECLARATIVE format: <type> <key> <dflt> "" 240 * ISCSI_PARAM_TYPE_DECLARATIVE format: <type> <key> <dflt> ""
241 */ 241 */
242 242
243 s->params = NULL; 243 s->params = NULL;
244 l = &(s->params); 244 l = &(s->params);
245 /* CHAP Support Parameters */ 245 /* CHAP Support Parameters */
246 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_LIST, "AuthMethod", "None", "CHAP,None", return -1); 246 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_LIST, "AuthMethod", "None", "CHAP,None", return -1);
247 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_LIST, "CHAP_A", "None", "5", return -1); 247 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_LIST, "CHAP_A", "None", "5", return -1);
248 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "CHAP_N", "", "", return -1); 248 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "CHAP_N", "", "", return -1);
249 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "CHAP_R", "", "", return -1); 249 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "CHAP_R", "", "", return -1);
250 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "CHAP_I", "", "", return -1); 250 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "CHAP_I", "", "", return -1);
251 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "CHAP_C", "", "", return -1); 251 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "CHAP_C", "", "", return -1);
252 /* CHAP Support Parameters */ 252 /* CHAP Support Parameters */
253 253
254 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_LIST, "HeaderDigest", "None", "None", return -1); 254 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_LIST, "HeaderDigest", "None", "None", return -1);
255 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_LIST, "DataDigest", "None", "None", return -1); 255 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_LIST, "DataDigest", "None", "None", return -1);
256 256
257 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL, "MaxConnections", "1", "1", return -1); 257 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL, "MaxConnections", "1", "1", return -1);
258 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "SendTargets", "", "", return -1); 258 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "SendTargets", "", "", return -1);
259 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARE_MULTI, "TargetName", "", "", return -1); 259 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARE_MULTI, "TargetName", "", "", return -1);
260 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "InitiatorName", "iqn.1994-04.org.NetBSD:iscsi-initiator", "", return -1); 260 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "InitiatorName", "iqn.1994-04.org.NetBSD:iscsi-initiator", "", return -1);
261 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "TargetAlias", "", "", return -1); 261 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "TargetAlias", "", "", return -1);
262 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "InitiatorAlias", "", "", return -1); 262 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "InitiatorAlias", "", "", return -1);
263 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARE_MULTI, "TargetAddress", "", "", return -1); 263 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARE_MULTI, "TargetAddress", "", "", return -1);
264 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_BINARY_OR, "InitialR2T", "Yes", "Yes,No", return -1); 264 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_BINARY_OR, "InitialR2T", "Yes", "Yes,No", return -1);
265 265
266 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_BINARY_AND, "ImmediateData", "Yes", "Yes,No", return -1); 266 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_BINARY_AND, "ImmediateData", "Yes", "Yes,No", return -1);
267 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL_Z, "MaxRecvDataSegmentLength", "8192", "16777215", return -1); 267 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL_Z, "MaxRecvDataSegmentLength", "8192", "16777215", return -1);
268 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL_Z, "MaxBurstLength", "262144", "16777215", return -1); 268 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL_Z, "MaxBurstLength", "262144", "16777215", return -1);
269 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL_Z, "FirstBurstLength", "65536", "16777215", return -1); 269 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL_Z, "FirstBurstLength", "65536", "16777215", return -1);
270 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "TargetPortalGroupTag", "1", "65535", return -1); 270 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "TargetPortalGroupTag", "1", "65535", return -1);
271 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL, "DefaultTime2Wait", "2", "2", return -1); 271 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL, "DefaultTime2Wait", "2", "2", return -1);
272 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL, "DefaultTime2Retain", "20", "20", return -1); 272 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL, "DefaultTime2Retain", "20", "20", return -1);
273 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL, "MaxOutstandingR2T", "1", "1", return -1); 273 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL, "MaxOutstandingR2T", "1", "1", return -1);
274 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_BINARY_OR, "DataPDUInOrder", "Yes", "Yes,No", return -1); 274 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_BINARY_OR, "DataPDUInOrder", "Yes", "Yes,No", return -1);
275 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_BINARY_OR, "DataSequenceInOrder", "Yes", "Yes,No", return -1); 275 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_BINARY_OR, "DataSequenceInOrder", "Yes", "Yes,No", return -1);
276 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL, "ErrorRecoveryLevel", "0", "0", return -1); 276 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL, "ErrorRecoveryLevel", "0", "0", return -1);
277 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "SessionType", "Normal", "Normal,Discovery", return -1); 277 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "SessionType", "Normal", "Normal,Discovery", return -1);
278 278
279 /* Start Tx worker */ 279 /* Start Tx worker */
280 280
281 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "starting Tx worker %llu\n", isid); 281 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "starting Tx worker %llu\n", isid);
282 if (iscsi_queue_init(&s->tx_queue, CONFIG_INITIATOR_QUEUE_DEPTH) == -1) { 282 if (iscsi_queue_init(&s->tx_queue, CONFIG_INITIATOR_QUEUE_DEPTH) == -1) {
283 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_init() failed\n"); 283 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_init() failed\n");
284 return -1; 284 return -1;
285 } 285 }
286 ISCSI_LOCK(&s->tx_worker.exit_mutex, return -1); 286 ISCSI_LOCK(&s->tx_worker.exit_mutex, return -1);
287 if (iscsi_thread_create(&s->tx_worker.thread, (void *) tx_worker_proc_i, &s->tx_worker) != 0) { 287 if (iscsi_thread_create(&s->tx_worker.thread, (void *) tx_worker_proc_i, &s->tx_worker) != 0) {
288 iscsi_trace_error(__FILE__, __LINE__, "iscsi_threads_create() failed\n"); 288 iscsi_trace_error(__FILE__, __LINE__, "iscsi_threads_create() failed\n");
289 return -1; 289 return -1;
290 } 290 }
291 ISCSI_WAIT(&s->tx_worker.exit_cond, &s->tx_worker.exit_mutex, return -1); 291 ISCSI_WAIT(&s->tx_worker.exit_cond, &s->tx_worker.exit_mutex, return -1);
292 ISCSI_UNLOCK(&s->tx_worker.exit_mutex, return -1); 292 ISCSI_UNLOCK(&s->tx_worker.exit_mutex, return -1);
293 if (s->state == INITIATOR_SESSION_STATE_DESTROYING) { 293 if (s->state == INITIATOR_SESSION_STATE_DESTROYING) {
294 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session %llu is being destroyed, exiting\n", isid); 294 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session %llu is being destroyed, exiting\n", isid);
295 return -1; 295 return -1;
296 } 296 }
297 if (s->tx_worker.state & ISCSI_WORKER_STATE_ERROR) { 297 if (s->tx_worker.state & ISCSI_WORKER_STATE_ERROR) {
298 iscsi_trace_error(__FILE__, __LINE__, "Tx worker %llu started with an error\n", isid); 298 iscsi_trace_error(__FILE__, __LINE__, "Tx worker %llu started with an error\n", isid);
299 return -1; 299 return -1;
300 } 300 }
301 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "got signal from Tx worker\n"); 301 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "got signal from Tx worker\n");
302 s->state = INITIATOR_SESSION_STATE_INITIALIZED; 302 s->state = INITIATOR_SESSION_STATE_INITIALIZED;
303 303
304 return 0; 304 return 0;
305} 305}
306 306
307static int  307static int
308session_destroy_i(initiator_session_t * sess) 308session_destroy_i(initiator_session_t * sess)
309{ 309{
310 initiator_cmd_t *ptr; 310 initiator_cmd_t *ptr;
311 uint64_t isid = sess->isid; 311 uint64_t isid = sess->isid;
312 312
313 if (sess == NULL) { 313 if (sess == NULL) {
314 iscsi_trace_error(__FILE__, __LINE__, "session pointer is NULL\n"); 314 iscsi_trace_error(__FILE__, __LINE__, "session pointer is NULL\n");
315 return -1; 315 return -1;
316 } 316 }
317 if (g_target[sess->isid].has_session == 0) { 317 if (g_target[sess->isid].has_session == 0) {
318 iscsi_trace_error(__FILE__, __LINE__, "g_target[%llu].has_session==0??\n", sess->isid); 318 iscsi_trace_error(__FILE__, __LINE__, "g_target[%llu].has_session==0??\n", sess->isid);
319 return -1; 319 return -1;
320 } 320 }
321 sess->state = INITIATOR_SESSION_STATE_DESTROYING; 321 sess->state = INITIATOR_SESSION_STATE_DESTROYING;
322 322
323 /* Abort all outstanding commands */ 323 /* Abort all outstanding commands */
324 324
325 for (ptr = sess->cmds; ptr != NULL; ptr = ptr->next) { 325 for (ptr = sess->cmds; ptr != NULL; ptr = ptr->next) {
326 if (initiator_abort(ptr) != 0) { 326 if (initiator_abort(ptr) != 0) {
327 iscsi_trace_error(__FILE__, __LINE__, "initiator_abort() failed\n"); 327 iscsi_trace_error(__FILE__, __LINE__, "initiator_abort() failed\n");
328 return -1; 328 return -1;
329 } 329 }
330 } 330 }
331 331
332 if (sess->tx_worker.state & ISCSI_WORKER_STATE_STARTED) { 332 if (sess->tx_worker.state & ISCSI_WORKER_STATE_STARTED) {
333 if (sess->tx_worker.state & ISCSI_WORKER_STATE_EXITING) { 333 if (sess->tx_worker.state & ISCSI_WORKER_STATE_EXITING) {
334 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Tx worker %llu already signalled for exit\n", sess->isid); 334 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Tx worker %llu already signalled for exit\n", sess->isid);
335 } else { 335 } else {
336 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "signaling Tx worker %llu into exiting state\n", sess->isid); 336 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "signaling Tx worker %llu into exiting state\n", sess->isid);
337 ISCSI_LOCK(&sess->tx_worker.work_mutex, return -1); 337 ISCSI_LOCK(&sess->tx_worker.work_mutex, return -1);
338 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "signaling socket shutdown to Tx worker %llu\n", sess->isid); 338 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "signaling socket shutdown to Tx worker %llu\n", sess->isid);
339 if (iscsi_sock_shutdown(sess->sock, 1) != 0) { 339 if (iscsi_sock_shutdown(sess->sock, 1) != 0) {
340 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_shutdown() failed\n"); 340 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_shutdown() failed\n");
341 } 341 }
342 ISCSI_SIGNAL(&sess->tx_worker.work_cond, return -1); 342 ISCSI_SIGNAL(&sess->tx_worker.work_cond, return -1);
343 ISCSI_UNLOCK(&sess->tx_worker.work_mutex, return -1); 343 ISCSI_UNLOCK(&sess->tx_worker.work_mutex, return -1);
344 } 344 }
345 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Checking exit condition of Tx worker\n"); 345 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Checking exit condition of Tx worker\n");
346 while ((sess->tx_worker.state & ISCSI_WORKER_STATE_EXITING) != ISCSI_WORKER_STATE_EXITING) { 346 while ((sess->tx_worker.state & ISCSI_WORKER_STATE_EXITING) != ISCSI_WORKER_STATE_EXITING) {
347 ISCSI_SPIN; 347 ISCSI_SPIN;
348 } 348 }
349 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Tx worker %llu has exited\n", sess->isid); 349 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Tx worker %llu has exited\n", sess->isid);
350 } else { 350 } else {
351 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Tx worker was not started. Nothing to signal\n"); 351 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Tx worker was not started. Nothing to signal\n");
352 } 352 }
353 353
354 /* Destroy Tx state */ 354 /* Destroy Tx state */
355 while ((ptr = iscsi_queue_remove(&sess->tx_queue)) != NULL) { 355 while ((ptr = iscsi_queue_remove(&sess->tx_queue)) != NULL) {
356 ptr->status = -1; 356 ptr->status = -1;
357 if (ptr->callback && ((*ptr->callback)(ptr) != 0)) { 357 if (ptr->callback && ((*ptr->callback)(ptr) != 0)) {
358 iscsi_trace_error(__FILE__, __LINE__, "callback() failed\n"); 358 iscsi_trace_error(__FILE__, __LINE__, "callback() failed\n");
359 } 359 }
360 } 360 }
361 iscsi_queue_destroy(&sess->tx_queue); 361 iscsi_queue_destroy(&sess->tx_queue);
362 362
363 if (sess->rx_worker.state & ISCSI_WORKER_STATE_STARTED) { 363 if (sess->rx_worker.state & ISCSI_WORKER_STATE_STARTED) {
364 if (sess->rx_worker.state & ISCSI_WORKER_STATE_EXITING) { 364 if (sess->rx_worker.state & ISCSI_WORKER_STATE_EXITING) {
365 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Rx worker %llu already signalled for exit\n", sess->isid); 365 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Rx worker %llu already signalled for exit\n", sess->isid);
366 } else { 366 } else {
367 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "signaling Rx worker %llu into exiting state\n", sess->isid); 367 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "signaling Rx worker %llu into exiting state\n", sess->isid);
368 if (iscsi_sock_shutdown(sess->sock, 0) != 0) { 368 if (iscsi_sock_shutdown(sess->sock, 0) != 0) {
369 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_shutdown() failed\n"); 369 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_shutdown() failed\n");
370 } 370 }
371 } 371 }
372 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Checking exit condition of Rx worker\n"); 372 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Checking exit condition of Rx worker\n");
373 while ((sess->rx_worker.state & ISCSI_WORKER_STATE_EXITING) != ISCSI_WORKER_STATE_EXITING) { 373 while ((sess->rx_worker.state & ISCSI_WORKER_STATE_EXITING) != ISCSI_WORKER_STATE_EXITING) {
374 ISCSI_SPIN; 374 ISCSI_SPIN;
375 } 375 }
376 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Rx worker %llu has exited\n", sess->isid); 376 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Rx worker %llu has exited\n", sess->isid);
377 } else { 377 } else {
378 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Rx worker was not started. Nothing to signal\n"); 378 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Rx worker was not started. Nothing to signal\n");
379 } 379 }
380 380
381 /* Close socket */ 381 /* Close socket */
382 382
383 if (iscsi_sock_close(sess->sock) != 0) { 383 if (iscsi_sock_close(sess->sock) != 0) {
384 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_close() failed\n"); 384 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_close() failed\n");
385 return -1; 385 return -1;
386 } 386 }
387 /* Destroy wait queues */ 387 /* Destroy wait queues */
388 388
389 ISCSI_MUTEX_DESTROY(&sess->tx_worker.work_mutex, return -1); 389 ISCSI_MUTEX_DESTROY(&sess->tx_worker.work_mutex, return -1);
390 ISCSI_COND_DESTROY(&sess->tx_worker.work_cond, return -1); 390 ISCSI_COND_DESTROY(&sess->tx_worker.work_cond, return -1);
391 ISCSI_MUTEX_DESTROY(&sess->tx_worker.exit_mutex, return -1); 391 ISCSI_MUTEX_DESTROY(&sess->tx_worker.exit_mutex, return -1);
392 ISCSI_COND_DESTROY(&sess->tx_worker.exit_cond, return -1); 392 ISCSI_COND_DESTROY(&sess->tx_worker.exit_cond, return -1);
393 ISCSI_MUTEX_DESTROY(&sess->rx_worker.work_mutex, return -1); 393 ISCSI_MUTEX_DESTROY(&sess->rx_worker.work_mutex, return -1);
394 ISCSI_COND_DESTROY(&sess->rx_worker.work_cond, return -1); 394 ISCSI_COND_DESTROY(&sess->rx_worker.work_cond, return -1);
395 ISCSI_MUTEX_DESTROY(&sess->rx_worker.exit_mutex, return -1); 395 ISCSI_MUTEX_DESTROY(&sess->rx_worker.exit_mutex, return -1);
396 ISCSI_COND_DESTROY(&sess->rx_worker.exit_cond, return -1); 396 ISCSI_COND_DESTROY(&sess->rx_worker.exit_cond, return -1);
397 397
398 /* Destroy param list */ 398 /* Destroy param list */
399 399
400 PARAM_LIST_DESTROY(sess->params, return -1); 400 PARAM_LIST_DESTROY(sess->params, return -1);
401 401
402 /* Enqueue session to free list */ 402 /* Enqueue session to free list */
403 if (iscsi_queue_insert(&g_session_q, sess) == -1) { 403 if (iscsi_queue_insert(&g_session_q, sess) == -1) {
404 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_insert() failed\n"); 404 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_insert() failed\n");
405 return -1; 405 return -1;
406 } 406 }
407 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session %p destroyed and requeued\n", sess); 407 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session %p destroyed and requeued\n", sess);
408 408
409 g_target[isid].has_session = 0; 409 g_target[isid].has_session = 0;
410 410
411 return 0; 411 return 0;
412} 412}
413 413
414#define IS_DISCOVERY 1 414#define IS_DISCOVERY 1
415#define IS_SECURITY 1 415#define IS_SECURITY 1
416 416
417enum { 417enum {
418 SESS_TYPE_DISCOVERY = 1, 418 SESS_TYPE_DISCOVERY = 1,
419 SESS_TYPE_NORMAL = 2, 419 SESS_TYPE_NORMAL = 2,
420 SESS_TYPE_NONE = 3 420 SESS_TYPE_NONE = 3
421}; 421};
422 422
423static int  423static int
424params_out(initiator_session_t * sess, char *text, int *len, int textsize, int sess_type, int security) 424params_out(initiator_session_t * sess, char *text, int *len, int textsize, int sess_type, int security)
425{ 425{
426 if (security == IS_SECURITY) { 426 if (security == IS_SECURITY) {
427 PARAM_TEXT_ADD(sess->params, "InitiatorName", "iqn.1994-04.org.NetBSD.iscsi-initiator:agc", text, len, textsize, 1, return -1); 427 PARAM_TEXT_ADD(sess->params, "InitiatorName", "iqn.1994-04.org.NetBSD.iscsi-initiator:agc", text, len, textsize, 1, return -1);
428 PARAM_TEXT_ADD(sess->params, "InitiatorAlias", "NetBSD", text, len, textsize, 1, return -1); 428 PARAM_TEXT_ADD(sess->params, "InitiatorAlias", "NetBSD", text, len, textsize, 1, return -1);
429 PARAM_TEXT_ADD(sess->params, "AuthMethod", "CHAP,None", text, len, textsize, 1, return -1); 429 PARAM_TEXT_ADD(sess->params, "AuthMethod", "CHAP,None", text, len, textsize, 1, return -1);
430 } else { 430 } else {
431 PARAM_TEXT_ADD(sess->params, "HeaderDigest", "None", text, len, textsize, 1, return -1); 431 PARAM_TEXT_ADD(sess->params, "HeaderDigest", "None", text, len, textsize, 1, return -1);
432 PARAM_TEXT_ADD(sess->params, "DataDigest", "None", text, len, textsize, 1, return -1); 432 PARAM_TEXT_ADD(sess->params, "DataDigest", "None", text, len, textsize, 1, return -1);
433 PARAM_TEXT_ADD(sess->params, "MaxConnections", "1", text, len, textsize, 1, return -1); 433 PARAM_TEXT_ADD(sess->params, "MaxConnections", "1", text, len, textsize, 1, return -1);
434 PARAM_TEXT_ADD(sess->params, "InitialR2T", "Yes", text, len, textsize, 1, return -1); 434 PARAM_TEXT_ADD(sess->params, "InitialR2T", "Yes", text, len, textsize, 1, return -1);
435 PARAM_TEXT_ADD(sess->params, "ImmediateData", "Yes", text, len, textsize, 1, return -1); 435 PARAM_TEXT_ADD(sess->params, "ImmediateData", "Yes", text, len, textsize, 1, return -1);
436 PARAM_TEXT_ADD(sess->params, "MaxRecvDataSegmentLength", "8192", text, len, textsize, 1, return -1); 436 PARAM_TEXT_ADD(sess->params, "MaxRecvDataSegmentLength", "8192", text, len, textsize, 1, return -1);
437 PARAM_TEXT_ADD(sess->params, "FirstBurstLength", "65536", text, len, textsize, 1, return -1); 437 PARAM_TEXT_ADD(sess->params, "FirstBurstLength", "65536", text, len, textsize, 1, return -1);
438 PARAM_TEXT_ADD(sess->params, "MaxBurstLength", "262144", text, len, textsize, 1, return -1); 438 PARAM_TEXT_ADD(sess->params, "MaxBurstLength", "262144", text, len, textsize, 1, return -1);
439 PARAM_TEXT_ADD(sess->params, "DefaultTime2Wait", "2", text, len, textsize, 1, return -1); 439 PARAM_TEXT_ADD(sess->params, "DefaultTime2Wait", "2", text, len, textsize, 1, return -1);
440 PARAM_TEXT_ADD(sess->params, "DefaultTime2Retain", "20", text, len, textsize, 1, return -1); 440 PARAM_TEXT_ADD(sess->params, "DefaultTime2Retain", "20", text, len, textsize, 1, return -1);
441 PARAM_TEXT_ADD(sess->params, "MaxOutstandingR2T", "1", text, len, textsize, 1, return -1); 441 PARAM_TEXT_ADD(sess->params, "MaxOutstandingR2T", "1", text, len, textsize, 1, return -1);
442 PARAM_TEXT_ADD(sess->params, "DataPDUInOrder", "No", text, len, textsize, 1, return -1); 442 PARAM_TEXT_ADD(sess->params, "DataPDUInOrder", "No", text, len, textsize, 1, return -1);
443 PARAM_TEXT_ADD(sess->params, "DataSequenceInOrder", "No", text, len, textsize, 1, return -1); 443 PARAM_TEXT_ADD(sess->params, "DataSequenceInOrder", "No", text, len, textsize, 1, return -1);
444 PARAM_TEXT_ADD(sess->params, "ErrorRecoveryLevel", "0", text, len, textsize, 1, return -1); 444 PARAM_TEXT_ADD(sess->params, "ErrorRecoveryLevel", "0", text, len, textsize, 1, return -1);
445 } 445 }
446 switch (sess_type) { 446 switch (sess_type) {
447 case SESS_TYPE_DISCOVERY: 447 case SESS_TYPE_DISCOVERY:
448 PARAM_TEXT_ADD(sess->params, "SessionType", "Discovery", text, len, textsize, 1, return -1); 448 PARAM_TEXT_ADD(sess->params, "SessionType", "Discovery", text, len, textsize, 1, return -1);
449 break; 449 break;
450 case SESS_TYPE_NORMAL: 450 case SESS_TYPE_NORMAL:
451 PARAM_TEXT_ADD(sess->params, "SessionType", "Normal", text, len, textsize, 1, return -1); 451 PARAM_TEXT_ADD(sess->params, "SessionType", "Normal", text, len, textsize, 1, return -1);
452 PARAM_TEXT_ADD(sess->params, "TargetName", g_target[sess->isid].TargetName, text, len, textsize, 1, return -1); 452 PARAM_TEXT_ADD(sess->params, "TargetName", g_target[sess->isid].TargetName, text, len, textsize, 1, return -1);
453 break; 453 break;
454 default: 454 default:
455 break; 455 break;
456 } 456 }
457 PARAM_TEXT_PARSE(sess->params, &sess->sess_params.cred, text, *len, NULL, NULL, 0, 1, return -1); 457 PARAM_TEXT_PARSE(sess->params, &sess->sess_params.cred, text, *len, NULL, NULL, 0, 1, return -1);
458 return 0; 458 return 0;
459} 459}
460 460
461static int  461static int
462full_feature_negotiation_phase_i(initiator_session_t * sess, char *text, int text_len) 462full_feature_negotiation_phase_i(initiator_session_t * sess, char *text, int text_len)
463{ 463{
464 initiator_cmd_t *cmd = NULL; 464 initiator_cmd_t *cmd = NULL;
465 iscsi_text_cmd_args_t *text_cmd = NULL; 465 iscsi_text_cmd_args_t *text_cmd = NULL;
466 initiator_wait_t wait; 466 initiator_wait_t wait;
467 467
468 /* Allocate command pointers */ 468 /* Allocate command pointers */
469 469
470 if ((cmd = iscsi_malloc_atomic(sizeof(initiator_cmd_t))) == NULL) { 470 if ((cmd = iscsi_malloc_atomic(sizeof(initiator_cmd_t))) == NULL) {
471 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n"); 471 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n");
472 return -1; 472 return -1;
473 } 473 }
474 (void) memset(cmd, 0x0, sizeof(*cmd)); 474 (void) memset(cmd, 0x0, sizeof(*cmd));
475 if ((text_cmd = iscsi_malloc_atomic(sizeof(iscsi_text_cmd_args_t))) == NULL) { 475 if ((text_cmd = iscsi_malloc_atomic(sizeof(iscsi_text_cmd_args_t))) == NULL) {
476 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n"); 476 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n");
477 if (cmd != NULL) 477 if (cmd != NULL)
478 iscsi_free_atomic(cmd); /* initiator command */ 478 iscsi_free_atomic(cmd); /* initiator command */
479 return -1; 479 return -1;
480 } 480 }
481#define FFN_ERROR {if (cmd != NULL) iscsi_free_atomic(cmd); if (text_cmd != NULL) iscsi_free_atomic(text_cmd); return -1;} 481#define FFN_ERROR {if (cmd != NULL) iscsi_free_atomic(cmd); if (text_cmd != NULL) iscsi_free_atomic(text_cmd); return -1;}
482 (void) memset(text_cmd, 0x0, sizeof(*text_cmd)); 482 (void) memset(text_cmd, 0x0, sizeof(*text_cmd));
483 483
484 /* 484 /*
485 * Note that <final>, <length> and <text> are updated 485 * Note that <final>, <length> and <text> are updated
486 * by text_response_i when we receive offers from 486 * by text_response_i when we receive offers from
487 * the target. 487 * the target.
488 */ 488 */
489 text_cmd->text = text; 489 text_cmd->text = text;
490 text_cmd->length = text_len; 490 text_cmd->length = text_len;
491 491
492 do { 492 do {
493 493
494 /* Build text command */ 494 /* Build text command */
495 495
496 text_cmd->final = 1; 496 text_cmd->final = 1;
497 text_cmd->cont = 0; 497 text_cmd->cont = 0;
498 ISCSI_SET_TAG(&text_cmd->tag); 498 ISCSI_SET_TAG(&text_cmd->tag);
499 text_cmd->transfer_tag = 0xffffffff; 499 text_cmd->transfer_tag = 0xffffffff;
500 500
501 /* Build wait for callback */ 501 /* Build wait for callback */
502 502
503 ISCSI_MUTEX_INIT(&wait.mutex, FFN_ERROR); 503 ISCSI_MUTEX_INIT(&wait.mutex, FFN_ERROR);
504 ISCSI_COND_INIT(&wait.cond, FFN_ERROR); 504 ISCSI_COND_INIT(&wait.cond, FFN_ERROR);
505 505
506 /* Build initiator command */ 506 /* Build initiator command */
507 507
508 cmd->type = ISCSI_TEXT_CMD; 508 cmd->type = ISCSI_TEXT_CMD;
509 cmd->ptr = text_cmd; 509 cmd->ptr = text_cmd;
510 cmd->callback = wait_callback_i; 510 cmd->callback = wait_callback_i;
511 cmd->callback_arg = &wait; 511 cmd->callback_arg = &wait;
512 cmd->isid = sess->isid; 512 cmd->isid = sess->isid;
513 513
514 /* Enqueue initiator command to Tx worker */ 514 /* Enqueue initiator command to Tx worker */
515 515
516 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueing text command to tx worker %llu\n", sess->isid); 516 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueing text command to tx worker %llu\n", sess->isid);
517 ISCSI_LOCK(&wait.mutex, FFN_ERROR); 517 ISCSI_LOCK(&wait.mutex, FFN_ERROR);
518 ISCSI_LOCK(&sess->tx_worker.work_mutex, FFN_ERROR); 518 ISCSI_LOCK(&sess->tx_worker.work_mutex, FFN_ERROR);
519 if (iscsi_queue_insert(&sess->tx_queue, cmd) == -1) { 519 if (iscsi_queue_insert(&sess->tx_queue, cmd) == -1) {
520 ISCSI_UNLOCK(&wait.mutex, ); 520 ISCSI_UNLOCK(&wait.mutex, );
521 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_insert() failed\n"); 521 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_insert() failed\n");
522 FFN_ERROR; 522 FFN_ERROR;
523 } 523 }
524 ISCSI_SIGNAL(&sess->tx_worker.work_cond, FFN_ERROR); 524 ISCSI_SIGNAL(&sess->tx_worker.work_cond, FFN_ERROR);
525 ISCSI_UNLOCK(&sess->tx_worker.work_mutex, FFN_ERROR); 525 ISCSI_UNLOCK(&sess->tx_worker.work_mutex, FFN_ERROR);
526 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueued text command ok\n"); 526 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueued text command ok\n");
527 527
528 /* Wait for callback */ 528 /* Wait for callback */
529 529
530 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "waiting on text callback\n"); 530 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "waiting on text callback\n");
531 ISCSI_WAIT(&wait.cond, &wait.mutex, FFN_ERROR); 531 ISCSI_WAIT(&wait.cond, &wait.mutex, FFN_ERROR);
532 ISCSI_UNLOCK(&wait.mutex, FFN_ERROR); 532 ISCSI_UNLOCK(&wait.mutex, FFN_ERROR);
533 ISCSI_COND_DESTROY(&wait.cond, FFN_ERROR); 533 ISCSI_COND_DESTROY(&wait.cond, FFN_ERROR);
534 ISCSI_MUTEX_DESTROY(&wait.mutex, FFN_ERROR); 534 ISCSI_MUTEX_DESTROY(&wait.mutex, FFN_ERROR);
535 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "received text callback ok\n"); 535 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "received text callback ok\n");
536 536
537 /* 537 /*
538 * See if we're done. text_response_i() overwrites 538 * See if we're done. text_response_i() overwrites
539 * text_cmd->final 539 * text_cmd->final
540 */ 540 */
541 /* with the final bit in the text response from the target. */ 541 /* with the final bit in the text response from the target. */
542 542
543 if (!text_cmd->final) { 543 if (!text_cmd->final) {
544 iscsi_trace(TRACE_ISCSI_PARAM, __FILE__, __LINE__, "more negotiation needed (sending %d bytes response parameters)\n", 544 iscsi_trace(TRACE_ISCSI_PARAM, __FILE__, __LINE__, "more negotiation needed (sending %d bytes response parameters)\n",
545 text_cmd->length); 545 text_cmd->length);
546 } 546 }
547 } while (!text_cmd->final); 547 } while (!text_cmd->final);
548 548
549 /* Free command pointers */ 549 /* Free command pointers */
550 550
551 iscsi_free_atomic(cmd->ptr); /* text command */ 551 iscsi_free_atomic(cmd->ptr); /* text command */
552 iscsi_free_atomic(cmd); /* initiator command */ 552 iscsi_free_atomic(cmd); /* initiator command */
553 553
554 return 0; 554 return 0;
555} 555}
556 556
557#define DISCOVERY_PHASE_TEXT_LEN 1024 557#define DISCOVERY_PHASE_TEXT_LEN 1024
558#define DP_CLEANUP {if (text != NULL) iscsi_free_atomic(text);} 558#define DP_CLEANUP {if (text != NULL) iscsi_free_atomic(text);}
559#define DP_ERROR {DP_CLEANUP; return -1;} 559#define DP_ERROR {DP_CLEANUP; return -1;}
560 560
561int 561int
562initiator_set_target_name(int target, char *target_name) 562initiator_set_target_name(int target, char *target_name)
563{ 563{
564 (void) strlcpy(g_target[target].iqnwanted, target_name, sizeof(g_target[target].iqnwanted)); 564 (void) strlcpy(g_target[target].iqnwanted, target_name, sizeof(g_target[target].iqnwanted));
565 (void) strlcpy(g_target[target].TargetName, target_name, sizeof(g_target[target].TargetName)); 565 (void) strlcpy(g_target[target].TargetName, target_name, sizeof(g_target[target].TargetName));
566 return 0; 566 return 0;
567} 567}
568 568
569 569
570int 570int
571initiator_get_targets(int target, strv_t *svp) 571initiator_get_targets(int target, strv_t *svp)
572{ 572{
573 initiator_session_t *sess = g_target[target].sess; 573 initiator_session_t *sess = g_target[target].sess;
574 iscsi_parameter_value_t *vp; 574 iscsi_parameter_value_t *vp;
575 iscsi_parameter_t *ip; 575 iscsi_parameter_t *ip;
576 char *text = NULL; 576 char *text = NULL;
577 int text_len = 0; 577 int text_len = 0;
578 int i; 578 int i;
579 579
580 if ((text = iscsi_malloc_atomic(DISCOVERY_PHASE_TEXT_LEN)) == NULL) { 580 if ((text = iscsi_malloc_atomic(DISCOVERY_PHASE_TEXT_LEN)) == NULL) {
581 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n"); 581 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
582 return -1; 582 return -1;
583 } 583 }
584 584
585 text_len = 0; 585 text_len = 0;
586 text[0] = 0x0; 586 text[0] = 0x0;
587 587
588 PARAM_TEXT_ADD(sess->params, "SendTargets", "all", text, &text_len, DISCOVERY_PHASE_TEXT_LEN, 1, DP_ERROR); 588 PARAM_TEXT_ADD(sess->params, "SendTargets", "all", text, &text_len, DISCOVERY_PHASE_TEXT_LEN, 1, DP_ERROR);
589 PARAM_TEXT_PARSE(sess->params, &sess->sess_params.cred, text, text_len, NULL, NULL, DISCOVERY_PHASE_TEXT_LEN, 1, DP_ERROR); 589 PARAM_TEXT_PARSE(sess->params, &sess->sess_params.cred, text, text_len, NULL, NULL, DISCOVERY_PHASE_TEXT_LEN, 1, DP_ERROR);
590 if (full_feature_negotiation_phase_i(sess, text, text_len) != 0) { 590 if (full_feature_negotiation_phase_i(sess, text, text_len) != 0) {
591 iscsi_trace_error(__FILE__, __LINE__, "full_feature_negotiation_phase_i() failed\n"); 591 iscsi_trace_error(__FILE__, __LINE__, "full_feature_negotiation_phase_i() failed\n");
592 DP_ERROR; 592 DP_ERROR;
593 }  593 }
594 i=0; 594 i=0;
595 for (ip = sess->params ; ip ; ip = ip->next) { 595 for (ip = sess->params ; ip ; ip = ip->next) {
596 if (strcmp(ip->key, "TargetName") == 0) { 596 if (strcmp(ip->key, "TargetName") == 0) {
597 for (vp = ip->value_l ; vp ; vp = vp->next) { 597 for (vp = ip->value_l ; vp ; vp = vp->next) {
598 ALLOC(char *, svp->v, svp->size, svp->c, 10, 10, "igt", return -1); 598 ALLOC(char *, svp->v, svp->size, svp->c, 10, 10, "igt", return -1);
599 svp->v[svp->c++] = strdup(vp->value); 599 svp->v[svp->c++] = strdup(vp->value);
600 ALLOC(char *, svp->v, svp->size, svp->c, 10, 10, "igt2", return -1); 600 ALLOC(char *, svp->v, svp->size, svp->c, 10, 10, "igt2", return -1);
601 svp->v[svp->c++] = strdup(param_val(sess->params, "TargetAddress")); 601 svp->v[svp->c++] = strdup(param_val(sess->params, "TargetAddress"));
602 } 602 }
603 } 603 }
604 } 604 }
605 605
606 return 1; 606 return 1;
607} 607}
608 608
609 609
610static int  610static int
611discovery_phase(int target, strv_t *svp) 611discovery_phase(int target, strv_t *svp)
612{ 612{
613 initiator_session_t *sess; 613 initiator_session_t *sess;
614 iscsi_parameter_value_t *vp; 614 iscsi_parameter_value_t *vp;
615 iscsi_parameter_t *ip; 615 iscsi_parameter_t *ip;
 616 unsigned i;
616 char *ptr; 617 char *ptr;
617 char *colon_ptr; 618 char *colon_ptr;
618 char *comma_ptr; 619 char *comma_ptr;
619 char port[64]; 620 char port[64];
620 char *text = NULL; 621 char *text = NULL;
621 int text_len = 0; 622 int text_len = 0;
622 int i; 
623 623
624 if (target >= CONFIG_INITIATOR_NUM_TARGETS) { 624 if (target >= CONFIG_INITIATOR_NUM_TARGETS) {
625 iscsi_trace_error(__FILE__, __LINE__, "target (%d) out of range [0..%d]\n", target, CONFIG_INITIATOR_NUM_TARGETS); 625 iscsi_trace_error(__FILE__, __LINE__, "target (%d) out of range [0..%d]\n", target, CONFIG_INITIATOR_NUM_TARGETS);
626 return -1; 626 return -1;
627 } 627 }
628 sess = g_target[target].sess; 628 sess = g_target[target].sess;
629 if ((text = iscsi_malloc_atomic(DISCOVERY_PHASE_TEXT_LEN)) == NULL) { 629 if ((text = iscsi_malloc_atomic(DISCOVERY_PHASE_TEXT_LEN)) == NULL) {
630 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n"); 630 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
631 return -1; 631 return -1;
632 } 632 }
633 /* Login to target */ 633 /* Login to target */
634 634
635 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "entering Discovery login phase with target %d (sock %#x)\n", target, (int) sess->sock); 635 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "entering Discovery login phase with target %d (sock %#x)\n", target, (int) sess->sock);
636 text[0] = 0x0; 636 text[0] = 0x0;
637 if (params_out(sess, text, &text_len, DISCOVERY_PHASE_TEXT_LEN, SESS_TYPE_DISCOVERY, IS_SECURITY) != 0) { 637 if (params_out(sess, text, &text_len, DISCOVERY_PHASE_TEXT_LEN, SESS_TYPE_DISCOVERY, IS_SECURITY) != 0) {
638 iscsi_trace_error(__FILE__, __LINE__, "params_out() failed\n"); 638 iscsi_trace_error(__FILE__, __LINE__, "params_out() failed\n");
639 DP_ERROR; 639 DP_ERROR;
640 } 640 }
641 if (login_phase_i(sess, text, text_len) != 0) { 641 if (login_phase_i(sess, text, text_len) != 0) {
642 iscsi_trace_error(__FILE__, __LINE__, "login_phase_i() failed\n"); 642 iscsi_trace_error(__FILE__, __LINE__, "login_phase_i() failed\n");
643 DP_ERROR; 643 DP_ERROR;
644 } 644 }
645 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "now full feature for Discovery with target %d\n", target); 645 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "now full feature for Discovery with target %d\n", target);
646 646
647 /* Full Feature Phase Negotiation (for SendTargets) */ 647 /* Full Feature Phase Negotiation (for SendTargets) */
648 648
649 text_len = 0; 649 text_len = 0;
650 text[0] = 0x0; 650 text[0] = 0x0;
651 PARAM_TEXT_ADD(sess->params, "SendTargets", "all", text, &text_len, DISCOVERY_PHASE_TEXT_LEN, 1, DP_ERROR); 651 PARAM_TEXT_ADD(sess->params, "SendTargets", "all", text, &text_len, DISCOVERY_PHASE_TEXT_LEN, 1, DP_ERROR);
652 PARAM_TEXT_PARSE(sess->params, &sess->sess_params.cred, text, text_len, NULL, NULL, DISCOVERY_PHASE_TEXT_LEN, 1, DP_ERROR); 652 PARAM_TEXT_PARSE(sess->params, &sess->sess_params.cred, text, text_len, NULL, NULL, DISCOVERY_PHASE_TEXT_LEN, 1, DP_ERROR);
653 if (full_feature_negotiation_phase_i(sess, text, text_len) != 0) { 653 if (full_feature_negotiation_phase_i(sess, text, text_len) != 0) {
654 iscsi_trace_error(__FILE__, __LINE__, "full_feature_negotiation_phase_i() failed\n"); 654 iscsi_trace_error(__FILE__, __LINE__, "full_feature_negotiation_phase_i() failed\n");
655 DP_ERROR; 655 DP_ERROR;
656 } 656 }
657 657
658 /* fill in information on the targets from the TargetName values */ 658 /* fill in information on the targets from the TargetName values */
659 (void) memset(svp, 0x0, sizeof(*svp)); 659 (void) memset(svp, 0x0, sizeof(*svp));
660 for (ip = sess->params ; ip ; ip = ip->next) { 660 for (ip = sess->params ; ip ; ip = ip->next) {
661 if (strcmp(ip->key, "TargetName") == 0) { 661 if (strcmp(ip->key, "TargetName") == 0) {
662 for (vp = ip->value_l ; vp ; vp = vp->next) { 662 for (vp = ip->value_l ; vp ; vp = vp->next) {
663 ALLOC(char *, svp->v, svp->size, svp->c, 10, 10, "discovery_phase", return -1); 663 ALLOC(char *, svp->v, svp->size, svp->c, 10, 10, "discovery_phase", return -1);
664 svp->v[svp->c++] = strdup(vp->value); 664 svp->v[svp->c++] = strdup(vp->value);
665 ALLOC(char *, svp->v, svp->size, svp->c, 10, 10, "discovery_phase2", return -1); 665 ALLOC(char *, svp->v, svp->size, svp->c, 10, 10, "discovery_phase2", return -1);
666 svp->v[svp->c++] = strdup(param_val(sess->params, "TargetAddress")); 666 svp->v[svp->c++] = strdup(param_val(sess->params, "TargetAddress"));
667 } 667 }
668 } 668 }
669 } 669 }
670 670
671 if (g_target[target].iqnwanted[0] == 0x0) { 671 if (g_target[target].iqnwanted[0] == 0x0) {
672 /* 672 /*
673 * Use the first TargetName and TargetAddress sent to us (all others 673 * Use the first TargetName and TargetAddress sent to us (all others
674 * are currently ignored) 674 * are currently ignored)
675 */ 675 */
676 if (param_val(sess->params, "TargetName") != NULL) { 676 if (param_val(sess->params, "TargetName") != NULL) {
677 strlcpy(g_target[target].TargetName, param_val(sess->params, "TargetName"), sizeof(g_target[target].TargetName)); 677 strlcpy(g_target[target].TargetName, param_val(sess->params, "TargetName"), sizeof(g_target[target].TargetName));
678 } else { 678 } else {
679 iscsi_trace_error(__FILE__, __LINE__, "SendTargets failed\n"); 679 iscsi_trace_error(__FILE__, __LINE__, "SendTargets failed\n");
680 DP_ERROR; 680 DP_ERROR;
681 } 681 }
682 if ((ptr = param_val(sess->params, "TargetAddress")) == NULL) { 682 if ((ptr = param_val(sess->params, "TargetAddress")) == NULL) {
683 iscsi_trace_error(__FILE__, __LINE__, "SendTargets failed\n"); 683 iscsi_trace_error(__FILE__, __LINE__, "SendTargets failed\n");
684 DP_ERROR; 684 DP_ERROR;
685 } 685 }
686 } else { 686 } else {
687 /* the user has asked for a specific target - find it */ 687 /* the user has asked for a specific target - find it */
688 for (i = 0 ; i < svp->c ; i += 2) { 688 for (i = 0 ; i < svp->c ; i += 2) {
689 if (strcmp(g_target[target].iqnwanted, svp->v[i]) == 0) { 689 if (strcmp(g_target[target].iqnwanted, svp->v[i]) == 0) {
690 strlcpy(g_target[target].TargetName, svp->v[i], sizeof(g_target[target].TargetName)); 690 strlcpy(g_target[target].TargetName, svp->v[i], sizeof(g_target[target].TargetName));
691 ptr = svp->v[i + 1]; 691 ptr = svp->v[i + 1];
692 break; 692 break;
693 } 693 }
694 } 694 }
695 if (i >= svp->c) { 695 if (i >= svp->c) {
696 iscsi_trace_error(__FILE__, __LINE__, "SendTargets failed - target `%s' not found\n", g_target[target].iqnwanted); 696 iscsi_trace_error(__FILE__, __LINE__, "SendTargets failed - target `%s' not found\n", g_target[target].iqnwanted);
697 DP_ERROR; 697 DP_ERROR;
698 } 698 }
699 } 699 }
700 700
701 if (*ptr == 0x0) { 701 if (*ptr == 0x0) {
702 iscsi_trace_error(__FILE__, __LINE__, "Target is not allowing access\n"); 702 iscsi_trace_error(__FILE__, __LINE__, "Target is not allowing access\n");
703 DP_ERROR; 703 DP_ERROR;
704 } 704 }
705 colon_ptr = strchr(ptr, ':'); 705 colon_ptr = strchr(ptr, ':');
706 if ((comma_ptr = strchr(ptr, ',')) == NULL) { 706 if ((comma_ptr = strchr(ptr, ',')) == NULL) {
707 iscsi_trace_error(__FILE__, __LINE__, "portal group tag is missing in \"%s\"\n", param_val(sess->params, "TargetAddress")); 707 iscsi_trace_error(__FILE__, __LINE__, "portal group tag is missing in \"%s\"\n", param_val(sess->params, "TargetAddress"));
708 DP_ERROR; 708 DP_ERROR;
709 } 709 }
710 if (colon_ptr) { 710 if (colon_ptr) {
711 strncpy(g_target[target].ip, ptr, (int)(colon_ptr - ptr)); 711 strncpy(g_target[target].ip, ptr, (int)(colon_ptr - ptr));
712 strncpy(port, colon_ptr + 1, (int)(comma_ptr - colon_ptr - 1)); 712 strncpy(port, colon_ptr + 1, (int)(comma_ptr - colon_ptr - 1));
713 port[comma_ptr - colon_ptr - 1] = 0x0; 713 port[comma_ptr - colon_ptr - 1] = 0x0;
714 g_target[target].port = iscsi_atoi(port); 714 g_target[target].port = iscsi_atoi(port);
715 } else { 715 } else {
716 strncpy(g_target[target].ip, ptr, (int)(comma_ptr - ptr)); 716 strncpy(g_target[target].ip, ptr, (int)(comma_ptr - ptr));
717 g_target[target].port = ISCSI_PORT; 717 g_target[target].port = ISCSI_PORT;
718 } 718 }
719 719
720 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Discovered \"%s\" at \"%s:%u\"\n", 720 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Discovered \"%s\" at \"%s:%u\"\n",
721 g_target[target].TargetName, g_target[target].name, g_target[target].port); 721 g_target[target].TargetName, g_target[target].name, g_target[target].port);
722 722
723 /* Logout from target */ 723 /* Logout from target */
724 724
725 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "entering logout phase with target %d\n", target); 725 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "entering logout phase with target %d\n", target);
726 if (logout_phase_i(sess) != 0) { 726 if (logout_phase_i(sess) != 0) {
727 iscsi_trace_error(__FILE__, __LINE__, "logout_phase_i() failed\n"); 727 iscsi_trace_error(__FILE__, __LINE__, "logout_phase_i() failed\n");
728 DP_ERROR; 728 DP_ERROR;
729 } 729 }
730 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "target %d logout phase complete\n", target); 730 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "target %d logout phase complete\n", target);
731 731
732 DP_CLEANUP; 732 DP_CLEANUP;
733 return 0; 733 return 0;
734} 734}
735 735
736#define FULL_FEATURE_PHASE_TEXT_LEN 1024 736#define FULL_FEATURE_PHASE_TEXT_LEN 1024
737 737
738static int  738static int
739full_feature_phase(initiator_session_t * sess) 739full_feature_phase(initiator_session_t * sess)
740{ 740{
741 char *text; 741 char *text;
742 int text_len; 742 int text_len;
743 743
744 if ((text = iscsi_malloc_atomic(FULL_FEATURE_PHASE_TEXT_LEN)) == NULL) { 744 if ((text = iscsi_malloc_atomic(FULL_FEATURE_PHASE_TEXT_LEN)) == NULL) {
745 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n"); 745 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
746 return -1; 746 return -1;
747 } 747 }
748#define FFP_CLEANUP {if (text != NULL) iscsi_free_atomic(text);} 748#define FFP_CLEANUP {if (text != NULL) iscsi_free_atomic(text);}
749#define FFP_ERROR {FFP_CLEANUP; return -1;} 749#define FFP_ERROR {FFP_CLEANUP; return -1;}
750 /* Set text parameters */ 750 /* Set text parameters */
751 751
752 text[0] = 0x0; 752 text[0] = 0x0;
753 text_len = 0; 753 text_len = 0;
754 if (params_out(sess, text, &text_len, FULL_FEATURE_PHASE_TEXT_LEN, SESS_TYPE_NORMAL, IS_SECURITY) != 0) { 754 if (params_out(sess, text, &text_len, FULL_FEATURE_PHASE_TEXT_LEN, SESS_TYPE_NORMAL, IS_SECURITY) != 0) {
755 iscsi_trace_error(__FILE__, __LINE__, "params_out() failed\n"); 755 iscsi_trace_error(__FILE__, __LINE__, "params_out() failed\n");
756 FFP_ERROR; 756 FFP_ERROR;
757 } 757 }
758 /* Send login command */ 758 /* Send login command */
759 759
760 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "entering login phase\n"); 760 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "entering login phase\n");
761 if (login_phase_i(sess, text, text_len) != 0) { 761 if (login_phase_i(sess, text, text_len) != 0) {
762 iscsi_trace_error(__FILE__, __LINE__, "login_phase_i() failed\n"); 762 iscsi_trace_error(__FILE__, __LINE__, "login_phase_i() failed\n");
763 FFP_ERROR; 763 FFP_ERROR;
764 } 764 }
765 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "login phase successful\n"); 765 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "login phase successful\n");
766 766
767 FFP_CLEANUP; 767 FFP_CLEANUP;
768 return 0; 768 return 0;
769} 769}
770 770
771int  771int
772initiator_init(const char *hostname, int port, int address_family, const char *user, int auth_type, int mutual_auth, int digest_type) 772initiator_init(const char *hostname, int port, int address_family, const char *user, int auth_type, int mutual_auth, int digest_type)
773{ 773{
774 int i; 774 int i;
775 initiator_session_t *sess = NULL; 775 initiator_session_t *sess = NULL;
776 776
777#define INIT_CLEANUP {if (sess != NULL) iscsi_free_atomic(sess);} 777#define INIT_CLEANUP {if (sess != NULL) iscsi_free_atomic(sess);}
778#define INIT_ERROR {INIT_CLEANUP; return -1;} 778#define INIT_ERROR {INIT_CLEANUP; return -1;}
779 779
780 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "initializing initiator\n"); 780 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "initializing initiator\n");
781 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "target config filename to read from:%s\n", gfilename); 781 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "target config filename to read from:%s\n", gfilename);
782 if (get_target_config(hostname, port) != 0) { 782 if (get_target_config(hostname, port) != 0) {
783 iscsi_trace_error(__FILE__, __LINE__, "Error getting target configuration from config file\n"); 783 iscsi_trace_error(__FILE__, __LINE__, "Error getting target configuration from config file\n");
784 return -1; 784 return -1;
785 } 785 }
786 g_initiator_state = 0; 786 g_initiator_state = 0;
787 if (iscsi_queue_init(&g_session_q, CONFIG_INITIATOR_MAX_SESSIONS) != 0) { 787 if (iscsi_queue_init(&g_session_q, CONFIG_INITIATOR_MAX_SESSIONS) != 0) {
788 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_init() failed\n"); 788 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_init() failed\n");
789 return -1; 789 return -1;
790 } 790 }
791 for (i = 0; i < CONFIG_INITIATOR_MAX_SESSIONS; i++) { 791 for (i = 0; i < CONFIG_INITIATOR_MAX_SESSIONS; i++) {
792 if ((sess = iscsi_malloc_atomic(sizeof(initiator_session_t))) == NULL) { 792 if ((sess = iscsi_malloc_atomic(sizeof(initiator_session_t))) == NULL) {
793 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n"); 793 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
794 return -1; 794 return -1;
795 } 795 }
796 if (iscsi_queue_insert(&g_session_q, sess) != 0) { 796 if (iscsi_queue_insert(&g_session_q, sess) != 0) {
797 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_init() failed\n"); 797 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_init() failed\n");
798 INIT_CLEANUP; 798 INIT_CLEANUP;
799 return -1; 799 return -1;
800 } 800 }
801 sess->sess_params.cred.user = strdup(user); 801 sess->sess_params.cred.user = strdup(user);
802 sess->sess_params.auth_type = auth_type; 802 sess->sess_params.auth_type = auth_type;
803 sess->sess_params.mutual_auth = mutual_auth; 803 sess->sess_params.mutual_auth = mutual_auth;
804 sess->sess_params.digest_wanted = digest_type; 804 sess->sess_params.digest_wanted = digest_type;
805 } 805 }
806 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "%d free sessions available\n", CONFIG_INITIATOR_MAX_SESSIONS); 806 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "%d free sessions available\n", CONFIG_INITIATOR_MAX_SESSIONS);
807 807
808 g_tag = 0xabc123; 808 g_tag = 0xabc123;
809 if (hash_init(&g_tag_hash, CONFIG_INITIATOR_QUEUE_DEPTH) != 0) { 809 if (hash_init(&g_tag_hash, CONFIG_INITIATOR_QUEUE_DEPTH) != 0) {
810 iscsi_trace_error(__FILE__, __LINE__, "hash_init() failed\n"); 810 iscsi_trace_error(__FILE__, __LINE__, "hash_init() failed\n");
811 INIT_CLEANUP; 811 INIT_CLEANUP;
812 return -1; 812 return -1;
813 } 813 }
814 iscsi_spin_init(&g_tag_spin); 814 iscsi_spin_init(&g_tag_spin);
815 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tag hash table initialized with queue depth %d\n", CONFIG_INITIATOR_QUEUE_DEPTH); 815 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tag hash table initialized with queue depth %d\n", CONFIG_INITIATOR_QUEUE_DEPTH);
816 816
817 /* 817 /*
818 * Start enqueue worker. This thread accepts scsi commands from 818 * Start enqueue worker. This thread accepts scsi commands from
819 * initiator_enqueue() 819 * initiator_enqueue()
820 */ 820 */
821 /* and queues them onto one of the tx worker queues. */ 821 /* and queues them onto one of the tx worker queues. */
822 822
823 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "starting enqueue worker\n"); 823 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "starting enqueue worker\n");
824 if (iscsi_queue_init(&g_enqueue_q, CONFIG_INITIATOR_QUEUE_DEPTH) != 0) { 824 if (iscsi_queue_init(&g_enqueue_q, CONFIG_INITIATOR_QUEUE_DEPTH) != 0) {
825 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_init() failed\n"); 825 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_init() failed\n");
826 INIT_CLEANUP; 826 INIT_CLEANUP;
827 return -1; 827 return -1;
828 } 828 }
829 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "about to initialize mutex\n"); 829 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "about to initialize mutex\n");
830 ISCSI_MUTEX_INIT(&g_enqueue_worker.work_mutex, INIT_ERROR); 830 ISCSI_MUTEX_INIT(&g_enqueue_worker.work_mutex, INIT_ERROR);
831 ISCSI_COND_INIT(&g_enqueue_worker.work_cond, INIT_ERROR); 831 ISCSI_COND_INIT(&g_enqueue_worker.work_cond, INIT_ERROR);
832 ISCSI_MUTEX_INIT(&g_enqueue_worker.exit_mutex, INIT_ERROR); 832 ISCSI_MUTEX_INIT(&g_enqueue_worker.exit_mutex, INIT_ERROR);
833 ISCSI_COND_INIT(&g_enqueue_worker.exit_cond, INIT_ERROR); 833 ISCSI_COND_INIT(&g_enqueue_worker.exit_cond, INIT_ERROR);
834 ISCSI_LOCK(&g_enqueue_worker.exit_mutex, INIT_ERROR); 834 ISCSI_LOCK(&g_enqueue_worker.exit_mutex, INIT_ERROR);
835 835
836 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "spawning thread for enqueue worker\n"); 836 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "spawning thread for enqueue worker\n");
837 if (iscsi_thread_create(&g_enqueue_worker.thread, (void *) &enqueue_worker_proc, &g_enqueue_worker) != 0) { 837 if (iscsi_thread_create(&g_enqueue_worker.thread, (void *) &enqueue_worker_proc, &g_enqueue_worker) != 0) {
838 iscsi_trace_error(__FILE__, __LINE__, "iscsi_threads_create() failed\n"); 838 iscsi_trace_error(__FILE__, __LINE__, "iscsi_threads_create() failed\n");
839 INIT_CLEANUP; 839 INIT_CLEANUP;
840 return -1; 840 return -1;
841 } 841 }
842 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "thread spawned, waiting for signal\n"); 842 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "thread spawned, waiting for signal\n");
843 ISCSI_WAIT(&g_enqueue_worker.exit_cond, &g_enqueue_worker.exit_mutex, INIT_ERROR); 843 ISCSI_WAIT(&g_enqueue_worker.exit_cond, &g_enqueue_worker.exit_mutex, INIT_ERROR);
844 ISCSI_UNLOCK(&g_enqueue_worker.exit_mutex, INIT_ERROR); 844 ISCSI_UNLOCK(&g_enqueue_worker.exit_mutex, INIT_ERROR);
845 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully started enqueue worker\n"); 845 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully started enqueue worker\n");
846 846
847 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "initiator initialization complete\n"); 847 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "initiator initialization complete\n");
848 return 0; 848 return 0;
849} 849}
850 850
851int  851int
852initiator_shutdown(void) 852initiator_shutdown(void)
853{ 853{
854 initiator_session_t *sess; 854 initiator_session_t *sess;
855 int i; 855 int i;
856 856
857 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "shutting down initiator\n"); 857 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "shutting down initiator\n");
858 858
859 for (i = 0; i < CONFIG_INITIATOR_NUM_TARGETS; i++) { 859 for (i = 0; i < CONFIG_INITIATOR_NUM_TARGETS; i++) {
860 if (g_target[i].has_session) { 860 if (g_target[i].has_session) {
861 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "entering logout phase for target %d\n", i); 861 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "entering logout phase for target %d\n", i);
862 if (g_target[i].sess->rx_worker.state & ISCSI_WORKER_STATE_ERROR) { 862 if (g_target[i].sess->rx_worker.state & ISCSI_WORKER_STATE_ERROR) {
863 iscsi_trace_warning(__FILE__, __LINE__, "rx worker exited abnormal, skipping logout phase\n"); 863 iscsi_trace_warning(__FILE__, __LINE__, "rx worker exited abnormal, skipping logout phase\n");
864 } else { 864 } else {
865 if (logout_phase_i(g_target[i].sess) != 0) { 865 if (logout_phase_i(g_target[i].sess) != 0) {
866 iscsi_trace_error(__FILE__, __LINE__, "logout_phase_i() failed for target %d\n", i); 866 iscsi_trace_error(__FILE__, __LINE__, "logout_phase_i() failed for target %d\n", i);
867 } 867 }
868 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "logout phase complete for target %d (state %#x)\n", 868 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "logout phase complete for target %d (state %#x)\n",
869 i, g_target[i].sess->state); 869 i, g_target[i].sess->state);
870 } 870 }
871 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "destroying session for target %d\n", i); 871 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "destroying session for target %d\n", i);
872 if (session_destroy_i(g_target[i].sess) != 0) { 872 if (session_destroy_i(g_target[i].sess) != 0) {
873 iscsi_trace_error(__FILE__, __LINE__, "session_destroy_i() failed for target %d\n", i); 873 iscsi_trace_error(__FILE__, __LINE__, "session_destroy_i() failed for target %d\n", i);
874 } 874 }
875 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session destroyed for target %d\n", i); 875 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session destroyed for target %d\n", i);
876 } 876 }
877 } 877 }
878 878
879 g_initiator_state = INITIATOR_STATE_SHUTDOWN; 879 g_initiator_state = INITIATOR_STATE_SHUTDOWN;
880 if (g_enqueue_worker.state & ISCSI_WORKER_STATE_EXITING) { 880 if (g_enqueue_worker.state & ISCSI_WORKER_STATE_EXITING) {
881 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue already exiting\n"); 881 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue already exiting\n");
882 } else { 882 } else {
883 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "signaling enqueue worker into exiting state\n"); 883 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "signaling enqueue worker into exiting state\n");
884 ISCSI_LOCK(&g_enqueue_worker.work_mutex, return -1); 884 ISCSI_LOCK(&g_enqueue_worker.work_mutex, return -1);
885 ISCSI_SIGNAL(&g_enqueue_worker.work_cond, return -1); 885 ISCSI_SIGNAL(&g_enqueue_worker.work_cond, return -1);
886 ISCSI_UNLOCK(&g_enqueue_worker.work_mutex, return -1); 886 ISCSI_UNLOCK(&g_enqueue_worker.work_mutex, return -1);
887 } 887 }
888 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Checking exit condition of enqueue worker\n"); 888 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Checking exit condition of enqueue worker\n");
889 while ((g_enqueue_worker.state & ISCSI_WORKER_STATE_EXITING) != ISCSI_WORKER_STATE_EXITING) { 889 while ((g_enqueue_worker.state & ISCSI_WORKER_STATE_EXITING) != ISCSI_WORKER_STATE_EXITING) {
890 ISCSI_SPIN; 890 ISCSI_SPIN;
891 } 891 }
892 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue worker has exited\n"); 892 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue worker has exited\n");
893 893
894 iscsi_queue_destroy(&g_enqueue_q); 894 iscsi_queue_destroy(&g_enqueue_q);
895 ISCSI_MUTEX_DESTROY(&g_enqueue_worker.work_mutex, return -1); 895 ISCSI_MUTEX_DESTROY(&g_enqueue_worker.work_mutex, return -1);
896 ISCSI_COND_DESTROY(&g_enqueue_worker.work_cond, return -1); 896 ISCSI_COND_DESTROY(&g_enqueue_worker.work_cond, return -1);
897 ISCSI_MUTEX_DESTROY(&g_enqueue_worker.exit_mutex, return -1); 897 ISCSI_MUTEX_DESTROY(&g_enqueue_worker.exit_mutex, return -1);
898 ISCSI_COND_DESTROY(&g_enqueue_worker.exit_cond, return -1); 898 ISCSI_COND_DESTROY(&g_enqueue_worker.exit_cond, return -1);
899 899
900 while ((sess = iscsi_queue_remove(&g_session_q)) != NULL) { 900 while ((sess = iscsi_queue_remove(&g_session_q)) != NULL) {
901 iscsi_free_atomic(sess); 901 iscsi_free_atomic(sess);
902 } 902 }
903 iscsi_queue_destroy(&g_session_q); 903 iscsi_queue_destroy(&g_session_q);
904 iscsi_spin_destroy(&g_tag_spin); 904 iscsi_spin_destroy(&g_tag_spin);
905 hash_destroy(&g_tag_hash); 905 hash_destroy(&g_tag_hash);
906 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "initiator shutdown complete\n"); 906 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "initiator shutdown complete\n");
907 return 0; 907 return 0;
908} 908}
909 909
910static int  910static int
911wait_callback_i(void *ptr) 911wait_callback_i(void *ptr)
912{ 912{
913 initiator_wait_t *wait = (initiator_wait_t *) (((initiator_cmd_t *) ptr)->callback_arg); 913 initiator_wait_t *wait = (initiator_wait_t *) (((initiator_cmd_t *) ptr)->callback_arg);
914 914
915 ISCSI_LOCK(&wait->mutex, return -1); 915 ISCSI_LOCK(&wait->mutex, return -1);
916 ISCSI_SIGNAL(&wait->cond, return -1); 916 ISCSI_SIGNAL(&wait->cond, return -1);
917 ISCSI_UNLOCK(&wait->mutex, return -1); 917 ISCSI_UNLOCK(&wait->mutex, return -1);
918 return 0; 918 return 0;
919} 919}
920 920
921int  921int
922initiator_abort(initiator_cmd_t * cmd) 922initiator_abort(initiator_cmd_t * cmd)
923{ 923{
924 initiator_cmd_t *ptr, *prev; 924 initiator_cmd_t *ptr, *prev;
925 initiator_session_t *sess; 925 initiator_session_t *sess;
926 926
927 iscsi_trace_error(__FILE__, __LINE__, "aborting iSCSI cmd 0x%p (type %d, isid %llu)\n", 927 iscsi_trace_error(__FILE__, __LINE__, "aborting iSCSI cmd 0x%p (type %d, isid %llu)\n",
928 cmd, cmd->type, cmd->isid); 928 cmd, cmd->type, cmd->isid);
929 929
930 hash_remove(&g_tag_hash, cmd->key); 930 hash_remove(&g_tag_hash, cmd->key);
931 if (g_target[cmd->isid].has_session) { 931 if (g_target[cmd->isid].has_session) {
932 sess = g_target[cmd->isid].sess; 932 sess = g_target[cmd->isid].sess;
933 iscsi_spin_lock(&sess->cmds_spin); 933 iscsi_spin_lock(&sess->cmds_spin);
934 prev = ptr = sess->cmds; 934 prev = ptr = sess->cmds;
935 while (ptr != NULL) { 935 while (ptr != NULL) {
936 prev = ptr; 936 prev = ptr;
937 if (ptr == cmd) 937 if (ptr == cmd)
938 break; 938 break;
939 ptr = ptr->next; 939 ptr = ptr->next;
940 } 940 }
941 if (ptr != NULL) { 941 if (ptr != NULL) {
942 if (prev == sess->cmds) { 942 if (prev == sess->cmds) {
943 sess->cmds = cmd->next; 943 sess->cmds = cmd->next;
944 } else { 944 } else {
945 prev->next = cmd->next; 945 prev->next = cmd->next;
946 } 946 }
947 } 947 }
948 iscsi_spin_unlock(&sess->cmds_spin); 948 iscsi_spin_unlock(&sess->cmds_spin);
949 } else { 949 } else {
950 iscsi_trace_error(__FILE__, __LINE__, "cmd 0x%p has no session\n", cmd); 950 iscsi_trace_error(__FILE__, __LINE__, "cmd 0x%p has no session\n", cmd);
951 } 951 }
952 cmd->status = -1; 952 cmd->status = -1;
953 if (cmd->callback) { 953 if (cmd->callback) {
954 if ((*cmd->callback)(cmd) != 0) { 954 if ((*cmd->callback)(cmd) != 0) {
955 iscsi_trace_error(__FILE__, __LINE__, "cmd->callback() failed\n"); 955 iscsi_trace_error(__FILE__, __LINE__, "cmd->callback() failed\n");
956 return -1; 956 return -1;
957 } 957 }
958 } 958 }
959 iscsi_trace_error(__FILE__, __LINE__, "successfully aborted iSCSI cmd 0x%p (type %d, isid %llu)\n", 959 iscsi_trace_error(__FILE__, __LINE__, "successfully aborted iSCSI cmd 0x%p (type %d, isid %llu)\n",
960 cmd, cmd->type, cmd->isid); 960 cmd, cmd->type, cmd->isid);
961 return 0; 961 return 0;
962} 962}
963 963
964int  964int
965initiator_command(initiator_cmd_t * cmd) 965initiator_command(initiator_cmd_t * cmd)
966{ 966{
967 initiator_wait_t wait; 967 initiator_wait_t wait;
968 968
969 ISCSI_MUTEX_INIT(&wait.mutex, return -1); 969 ISCSI_MUTEX_INIT(&wait.mutex, return -1);
970 ISCSI_COND_INIT(&wait.cond, return -1); 970 ISCSI_COND_INIT(&wait.cond, return -1);
971 ISCSI_LOCK(&wait.mutex, return -1); 971 ISCSI_LOCK(&wait.mutex, return -1);
972 cmd->callback = wait_callback_i; 972 cmd->callback = wait_callback_i;
973 cmd->callback_arg = &wait; 973 cmd->callback_arg = &wait;
974 cmd->status = -1; 974 cmd->status = -1;
975 if (initiator_enqueue(cmd) != 0) { 975 if (initiator_enqueue(cmd) != 0) {
976 iscsi_trace_error(__FILE__, __LINE__, "initiator_enqueue() failed\n"); 976 iscsi_trace_error(__FILE__, __LINE__, "initiator_enqueue() failed\n");
977 return -1; 977 return -1;
978 } else { 978 } else {
979 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "command (type %d) enqueued, waiting on condition\n", cmd->type); 979 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "command (type %d) enqueued, waiting on condition\n", cmd->type);
980 ISCSI_WAIT(&wait.cond, &wait.mutex, return -1); 980 ISCSI_WAIT(&wait.cond, &wait.mutex, return -1);
981 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "condition signaled\n"); 981 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "condition signaled\n");
982 } 982 }
983 ISCSI_UNLOCK(&wait.mutex, return -1); 983 ISCSI_UNLOCK(&wait.mutex, return -1);
984 ISCSI_COND_DESTROY(&wait.cond, return -1); 984 ISCSI_COND_DESTROY(&wait.cond, return -1);
985 ISCSI_MUTEX_DESTROY(&wait.mutex, return -1); 985 ISCSI_MUTEX_DESTROY(&wait.mutex, return -1);
986 986
987 return cmd->status; 987 return cmd->status;
988} 988}
989 989
990/* 990/*
991 * initiator_enqueue() may be called from within interrupt context within 991 * initiator_enqueue() may be called from within interrupt context within
992 * the midlayer. This function cannot block or be scheduled within. 992 * the midlayer. This function cannot block or be scheduled within.
993 * All we do is enqueue the args ptr to g_enqueue_q. The thread in 993 * All we do is enqueue the args ptr to g_enqueue_q. The thread in
994 * enqueue_worker_proc will enqueue the ptr onto one of the tx queues. 994 * enqueue_worker_proc will enqueue the ptr onto one of the tx queues.
995 */ 995 */
996 996
997int  997int
998initiator_enqueue(initiator_cmd_t * cmd) 998initiator_enqueue(initiator_cmd_t * cmd)
999{ 999{
1000 initiator_session_t *sess; 1000 initiator_session_t *sess;
1001 iscsi_scsi_cmd_args_t *scsi_cmd; 1001 iscsi_scsi_cmd_args_t *scsi_cmd;
1002 iscsi_nop_out_args_t *nop_out; 1002 iscsi_nop_out_args_t *nop_out;
1003 uint64_t target; 1003 uint64_t target;
1004 uint32_t tag; 1004 uint32_t tag;
1005 1005
1006 if ((target = cmd->isid) >= CONFIG_INITIATOR_NUM_TARGETS) { 1006 if ((target = cmd->isid) >= CONFIG_INITIATOR_NUM_TARGETS) {
1007 iscsi_trace_error(__FILE__, __LINE__, "target (%d) out of range [0..%d]\n", target, CONFIG_INITIATOR_NUM_TARGETS); 1007 iscsi_trace_error(__FILE__, __LINE__, "target (%d) out of range [0..%d]\n", target, CONFIG_INITIATOR_NUM_TARGETS);
1008 return -1; 1008 return -1;
1009 } 1009 }
1010 sess = g_target[target].sess; 1010 sess = g_target[target].sess;
1011 if (g_target[target].has_session && (sess->state == INITIATOR_SESSION_STATE_LOGGED_IN_NORMAL)) { 1011 if (g_target[target].has_session && (sess->state == INITIATOR_SESSION_STATE_LOGGED_IN_NORMAL)) {
1012 1012
1013 /* Give command directly to tx worker */ 1013 /* Give command directly to tx worker */
1014 1014
1015 ISCSI_SET_TAG_IN_INTR(&tag); 1015 ISCSI_SET_TAG_IN_INTR(&tag);
1016 target = cmd->isid; 1016 target = cmd->isid;
1017 1017
1018 switch (cmd->type) { 1018 switch (cmd->type) {
1019 case ISCSI_SCSI_CMD: 1019 case ISCSI_SCSI_CMD:
1020 scsi_cmd = (iscsi_scsi_cmd_args_t *) cmd->ptr; 1020 scsi_cmd = (iscsi_scsi_cmd_args_t *) cmd->ptr;
1021 scsi_cmd->tag = tag; 1021 scsi_cmd->tag = tag;
1022 break; 1022 break;
1023 case ISCSI_NOP_OUT: 1023 case ISCSI_NOP_OUT:
1024 nop_out = (iscsi_nop_out_args_t *) cmd->ptr; 1024 nop_out = (iscsi_nop_out_args_t *) cmd->ptr;
1025 if (nop_out->tag != 0xffffffff) { 1025 if (nop_out->tag != 0xffffffff) {
1026 nop_out->tag = tag; 1026 nop_out->tag = tag;
1027 } 1027 }
1028 break; 1028 break;
1029 default: 1029 default:
1030 iscsi_trace_error(__FILE__, __LINE__, "enqueue_worker: unknown command type %d\n", cmd->type); 1030 iscsi_trace_error(__FILE__, __LINE__, "enqueue_worker: unknown command type %d\n", cmd->type);
1031 return -1; 1031 return -1;
1032 } 1032 }
1033 if (iscsi_queue_insert(&sess->tx_queue, cmd) == -1) { 1033 if (iscsi_queue_insert(&sess->tx_queue, cmd) == -1) {
1034 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_insert() failed\n"); 1034 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_insert() failed\n");
1035 return -1; 1035 return -1;
1036 } 1036 }
1037 ISCSI_LOCK(&sess->tx_worker.work_mutex, return -1); 1037 ISCSI_LOCK(&sess->tx_worker.work_mutex, return -1);
1038 ISCSI_SIGNAL(&sess->tx_worker.work_cond, return -1); 1038 ISCSI_SIGNAL(&sess->tx_worker.work_cond, return -1);
1039 ISCSI_UNLOCK(&sess->tx_worker.work_mutex, return -1); 1039 ISCSI_UNLOCK(&sess->tx_worker.work_mutex, return -1);
1040 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "initiator_cmd_t 0x%p given to tx_worker[%llu]\n", cmd, cmd->isid); 1040 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "initiator_cmd_t 0x%p given to tx_worker[%llu]\n", cmd, cmd->isid);
1041 } else { 1041 } else {
1042 1042
1043 /* 1043 /*
1044 * Give command to enqueue worker to get us into full feature 1044 * Give command to enqueue worker to get us into full feature
1045 * and then issue the command 1045 * and then issue the command
1046 */ 1046 */
1047 /* to one of the tx workers. */ 1047 /* to one of the tx workers. */
1048 1048
1049 if (iscsi_queue_insert(&g_enqueue_q, cmd) == -1) { 1049 if (iscsi_queue_insert(&g_enqueue_q, cmd) == -1) {
1050 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_insert() failed\n"); 1050 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_insert() failed\n");
1051 return -1; 1051 return -1;
1052 } 1052 }
1053 ISCSI_LOCK(&g_enqueue_worker.work_mutex, return -1); 1053 ISCSI_LOCK(&g_enqueue_worker.work_mutex, return -1);
1054 ISCSI_SIGNAL(&g_enqueue_worker.work_cond, return -1); 1054 ISCSI_SIGNAL(&g_enqueue_worker.work_cond, return -1);
1055 ISCSI_UNLOCK(&g_enqueue_worker.work_mutex, return -1); 1055 ISCSI_UNLOCK(&g_enqueue_worker.work_mutex, return -1);
1056 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "initiator_cmd_t 0x%p given to enqueue worker\n", cmd); 1056 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "initiator_cmd_t 0x%p given to enqueue worker\n", cmd);
1057 } 1057 }
1058 return 0; 1058 return 0;
1059} 1059}
1060 1060
1061static int  1061static int
1062enqueue_worker_proc(void *arg) 1062enqueue_worker_proc(void *arg)
1063{ 1063{
1064 initiator_session_t *sess; 1064 initiator_session_t *sess;
1065 initiator_cmd_t *cmd; 1065 initiator_cmd_t *cmd;
1066 iscsi_scsi_cmd_args_t *scsi_cmd; 1066 iscsi_scsi_cmd_args_t *scsi_cmd;
1067 iscsi_nop_out_args_t *nop_out; 1067 iscsi_nop_out_args_t *nop_out;
1068 iscsi_worker_t *me = (iscsi_worker_t *) arg; 1068 iscsi_worker_t *me = (iscsi_worker_t *) arg;
1069 uint64_t target; 1069 uint64_t target;
1070 uint32_t tag; 1070 uint32_t tag;
1071 strv_t sv; 1071 strv_t sv;
1072 int rc; 1072 int rc;
1073 1073
1074 1074
1075 ISCSI_THREAD_START("enqueue_worker"); 1075 ISCSI_THREAD_START("enqueue_worker");
1076 ISCSI_SET_THREAD(me) 1076 ISCSI_SET_THREAD(me)
1077 ISCSI_LOCK(&me->exit_mutex, goto done); 1077 ISCSI_LOCK(&me->exit_mutex, goto done);
1078 1078
1079 me->pid = ISCSI_GETPID; 1079 me->pid = ISCSI_GETPID;
1080 me->state = ISCSI_WORKER_STATE_STARTED; 1080 me->state = ISCSI_WORKER_STATE_STARTED;
1081 ISCSI_SIGNAL(&me->exit_cond, goto done); 1081 ISCSI_SIGNAL(&me->exit_cond, goto done);
1082 ISCSI_UNLOCK(&me->exit_mutex, goto done); 1082 ISCSI_UNLOCK(&me->exit_mutex, goto done);
1083 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: started\n"); 1083 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: started\n");
1084 ISCSI_LOCK(&g_enqueue_worker.work_mutex, goto done); 1084 ISCSI_LOCK(&g_enqueue_worker.work_mutex, goto done);
1085 for (;;) { 1085 for (;;) {
1086 if (iscsi_queue_depth(&g_enqueue_q) || (g_initiator_state == INITIATOR_STATE_SHUTDOWN)) { 1086 if (iscsi_queue_depth(&g_enqueue_q) || (g_initiator_state == INITIATOR_STATE_SHUTDOWN)) {
1087 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueu, start to work\n"); 1087 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueu, start to work\n");
1088 ISCSI_UNLOCK(&g_enqueue_worker.work_mutex, goto done); 1088 ISCSI_UNLOCK(&g_enqueue_worker.work_mutex, goto done);
1089 if (g_initiator_state == INITIATOR_STATE_SHUTDOWN) { 1089 if (g_initiator_state == INITIATOR_STATE_SHUTDOWN) {
1090 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "got shutdown signal\n"); 1090 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "got shutdown signal\n");
1091 goto done; 1091 goto done;
1092 } 1092 }
1093 if ((cmd = iscsi_queue_remove(&g_enqueue_q)) == NULL) { 1093 if ((cmd = iscsi_queue_remove(&g_enqueue_q)) == NULL) {
1094 iscsi_trace_error(__FILE__, __LINE__, "enqueue_worker: iscsi_queue_remove() failed\n"); 1094 iscsi_trace_error(__FILE__, __LINE__, "enqueue_worker: iscsi_queue_remove() failed\n");
1095 goto done; 1095 goto done;
1096 } 1096 }
1097 ISCSI_SET_TAG(&tag); 1097 ISCSI_SET_TAG(&tag);
1098 target = cmd->isid; 1098 target = cmd->isid;
1099 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "enqueue_worker: dequeued initiator_cmd_t 0x%p (type %d, target %llu)\n", cmd, cmd->type, target); 1099 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "enqueue_worker: dequeued initiator_cmd_t 0x%p (type %d, target %llu)\n", cmd, cmd->type, target);
1100 switch (cmd->type) { 1100 switch (cmd->type) {
1101 case ISCSI_SCSI_CMD: 1101 case ISCSI_SCSI_CMD:
1102 scsi_cmd = (iscsi_scsi_cmd_args_t *) cmd->ptr; 1102 scsi_cmd = (iscsi_scsi_cmd_args_t *) cmd->ptr;
1103 scsi_cmd->tag = tag; 1103 scsi_cmd->tag = tag;
1104 break; 1104 break;
1105 case ISCSI_NOP_OUT: 1105 case ISCSI_NOP_OUT:
1106 nop_out = (iscsi_nop_out_args_t *) cmd->ptr; 1106 nop_out = (iscsi_nop_out_args_t *) cmd->ptr;
1107 if (nop_out->tag != 0xffffffff) { 1107 if (nop_out->tag != 0xffffffff) {
1108 nop_out->tag = tag; 1108 nop_out->tag = tag;
1109 } 1109 }
1110 break; 1110 break;
1111 default: 1111 default:
1112 iscsi_trace_error(__FILE__, __LINE__, "enqueue_worker: unknown command type %d\n", cmd->type); 1112 iscsi_trace_error(__FILE__, __LINE__, "enqueue_worker: unknown command type %d\n", cmd->type);
1113 goto done; 1113 goto done;
1114 } 1114 }
1115 1115
1116 /* Initialize session (if not already) */ 1116 /* Initialize session (if not already) */
1117initialize: 1117initialize:
1118 if (!g_target[target].has_session) { 1118 if (!g_target[target].has_session) {
1119 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: initializing target %llu session\n", target); 1119 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: initializing target %llu session\n", target);
1120 if (session_init_i(&g_target[target].sess, target) != 0) { 1120 if (session_init_i(&g_target[target].sess, target) != 0) {
1121 iscsi_trace_error(__FILE__, __LINE__, "session_init_i() failed (ignoring command)\n"); 1121 iscsi_trace_error(__FILE__, __LINE__, "session_init_i() failed (ignoring command)\n");
1122 goto next; 1122 goto next;
1123 } 1123 }
1124 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: target %llu session initialized\n", target); 1124 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: target %llu session initialized\n", target);
1125 } else { 1125 } else {
1126 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: target %llu session already initialized\n", target); 1126 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: target %llu session already initialized\n", target);
1127 } 1127 }
1128 sess = g_target[target].sess; 1128 sess = g_target[target].sess;
1129 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: session 0x%p\n", sess); 1129 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: session 0x%p\n", sess);
1130 1130
1131 /* Discovery login if TargetName is zero length */ 1131 /* Discovery login if TargetName is zero length */
1132 1132
1133 if (strlen(g_target[target].TargetName) == 0) { 1133 if (strlen(g_target[target].TargetName) == 0) {
1134 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: entering Discovery phase with target %llu\n", target); 1134 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: entering Discovery phase with target %llu\n", target);
1135 rc = discovery_phase(target, &sv); 1135 rc = discovery_phase(target, &sv);
1136 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: Discovery phase complete\n"); 1136 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: Discovery phase complete\n");
1137 1137
1138 /* Destroy session */ 1138 /* Destroy session */
1139 1139
1140 if (sess->state != INITIATOR_SESSION_STATE_DESTROYING) { 1140 if (sess->state != INITIATOR_SESSION_STATE_DESTROYING) {
1141 if (g_target[target].has_session) { 1141 if (g_target[target].has_session) {
1142 if (session_destroy_i(g_target[target].sess) != 0) { 1142 if (session_destroy_i(g_target[target].sess) != 0) {
1143 iscsi_trace_error(__FILE__, __LINE__, "enqueue_worker: session_destroy_i() failed\n"); 1143 iscsi_trace_error(__FILE__, __LINE__, "enqueue_worker: session_destroy_i() failed\n");
1144 goto done; 1144 goto done;
1145 } 1145 }
1146 } 1146 }
1147 } 1147 }
1148 1148
1149 /* 1149 /*
1150 * If the Discovery phase was 1150 * If the Discovery phase was
1151 * successful, we re-initialize the 1151 * successful, we re-initialize the
1152 * session, enter full feature phase 1152 * session, enter full feature phase
1153 * and then execute the command. 1153 * and then execute the command.
1154 */ 1154 */
1155 1155
1156 if (rc == 0) { 1156 if (rc == 0) {
1157 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: discovery_phase() succeeded, entering full feature\n"); 1157 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: discovery_phase() succeeded, entering full feature\n");
1158 goto initialize; 1158 goto initialize;
1159 } else { 1159 } else {
1160 iscsi_trace_error(__FILE__, __LINE__, "enqueue_worker: discovery_phase() failed (ignoring command)\n"); 1160 iscsi_trace_error(__FILE__, __LINE__, "enqueue_worker: discovery_phase() failed (ignoring command)\n");
1161 goto next; 1161 goto next;
1162 } 1162 }
1163 } 1163 }
1164 /* Get into full feature if we're not already */ 1164 /* Get into full feature if we're not already */
1165 1165
1166 if (sess->state != INITIATOR_SESSION_STATE_LOGGED_IN_NORMAL) { 1166 if (sess->state != INITIATOR_SESSION_STATE_LOGGED_IN_NORMAL) {
1167 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: entering full feature with target %llu (sock %#x)\n", target, (int) sess->sock); 1167 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: entering full feature with target %llu (sock %#x)\n", target, (int) sess->sock);
1168 if (full_feature_phase(sess) != 0) { 1168 if (full_feature_phase(sess) != 0) {
1169 iscsi_trace_error(__FILE__, __LINE__, "enqueue_worker: full_feature_phase() failed (ignoring command)\n"); 1169 iscsi_trace_error(__FILE__, __LINE__, "enqueue_worker: full_feature_phase() failed (ignoring command)\n");
1170 goto next; 1170 goto next;
1171 } else { 1171 } else {
1172 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: now full feature with target %llu\n", target); 1172 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: now full feature with target %llu\n", target);
1173 } 1173 }
1174 } 1174 }
1175 /* 1175 /*
1176 * Now we are in FPP, so set the mostly 1176 * Now we are in FPP, so set the mostly
1177 * accessed parameters for easy retrieval 1177 * accessed parameters for easy retrieval
1178 * during data transfer 1178 * during data transfer
1179 */ 1179 */
1180 set_session_parameters(sess->params, &sess->sess_params); 1180 set_session_parameters(sess->params, &sess->sess_params);
1181 1181
1182 /* Add command to tx work queue and signal worker */ 1182 /* Add command to tx work queue and signal worker */
1183 1183
1184 ISCSI_LOCK(&sess->tx_worker.work_mutex, goto done); 1184 ISCSI_LOCK(&sess->tx_worker.work_mutex, goto done);
1185 if (iscsi_queue_insert(&sess->tx_queue, cmd) == -1) { 1185 if (iscsi_queue_insert(&sess->tx_queue, cmd) == -1) {
1186 ISCSI_UNLOCK(&sess->tx_worker.work_mutex, goto done); 1186 ISCSI_UNLOCK(&sess->tx_worker.work_mutex, goto done);
1187 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_insert() failed\n"); 1187 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_insert() failed\n");
1188 goto done; 1188 goto done;
1189 } 1189 }
1190 ISCSI_SIGNAL(&sess->tx_worker.work_cond, goto done); 1190 ISCSI_SIGNAL(&sess->tx_worker.work_cond, goto done);
1191 ISCSI_UNLOCK(&sess->tx_worker.work_mutex, goto done); 1191 ISCSI_UNLOCK(&sess->tx_worker.work_mutex, goto done);
1192 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "enqueue_worker: gave initiator_cmd_t 0x%p to tx_worker[%llu]\n", cmd, cmd->isid); 1192 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "enqueue_worker: gave initiator_cmd_t 0x%p to tx_worker[%llu]\n", cmd, cmd->isid);
1193next: 1193next:
1194 ISCSI_LOCK(&g_enqueue_worker.work_mutex, goto done); 1194 ISCSI_LOCK(&g_enqueue_worker.work_mutex, goto done);
1195 } else { 1195 } else {
1196 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: queue empty, awaiting condition\n"); 1196 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: queue empty, awaiting condition\n");
1197 ISCSI_WAIT(&g_enqueue_worker.work_cond, &g_enqueue_worker.work_mutex, goto done); 1197 ISCSI_WAIT(&g_enqueue_worker.work_cond, &g_enqueue_worker.work_mutex, goto done);
1198 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: condition signaled\n"); 1198 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueue_worker: condition signaled\n");
1199 } 1199 }
1200 } 1200 }
1201done: 1201done:
1202 ISCSI_WORKER_EXIT(me); 1202 ISCSI_WORKER_EXIT(me);
1203} 1203}
1204 1204
1205 1205
1206/*********** 1206/***********
1207 * Private * 1207 * Private *
1208 ***********/ 1208 ***********/
1209 1209
1210 1210
1211/* 1211/*
1212 * Tx Worker (one per connection) 1212 * Tx Worker (one per connection)
1213 */ 1213 */
1214 1214
1215static int  1215static int
1216tx_worker_proc_i(void *arg) 1216tx_worker_proc_i(void *arg)
1217{ 1217{
1218 iscsi_worker_t *me = (iscsi_worker_t *) arg; 1218 iscsi_worker_t *me = (iscsi_worker_t *) arg;
1219 initiator_cmd_t *cmd, *ptr; 1219 initiator_cmd_t *cmd, *ptr;
1220 initiator_session_t *sess = g_target[me->id].sess; 1220 initiator_session_t *sess = g_target[me->id].sess;
1221 1221
1222 ISCSI_THREAD_START("tx_worker"); 1222 ISCSI_THREAD_START("tx_worker");
1223 1223
1224 ISCSI_SET_THREAD(me) 1224 ISCSI_SET_THREAD(me)
1225 me->pid = ISCSI_GETPID; 1225 me->pid = ISCSI_GETPID;
1226 me->state = ISCSI_WORKER_STATE_STARTED; 1226 me->state = ISCSI_WORKER_STATE_STARTED;
1227 1227
1228 /* Connect to target */ 1228 /* Connect to target */
1229 1229
1230 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tx_worker[%d]: connecting to %s:%d\n", 1230 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tx_worker[%d]: connecting to %s:%d\n",
1231 me->id, g_target[me->id].name, g_target[me->id].port); 1231 me->id, g_target[me->id].name, g_target[me->id].port);
1232 sess->state = INITIATOR_SESSION_STATE_CONNECTING; 1232 sess->state = INITIATOR_SESSION_STATE_CONNECTING;
1233 if (iscsi_sock_connect(sess->sock, g_target[me->id].name, g_target[me->id].port) != 0) { 1233 if (iscsi_sock_connect(sess->sock, g_target[me->id].name, g_target[me->id].port) != 0) {
1234 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_connect() failed\n"); 1234 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_connect() failed\n");
1235 1235
1236 ISCSI_LOCK(&me->exit_mutex, return -1); 1236 ISCSI_LOCK(&me->exit_mutex, return -1);
1237 me->state |= ISCSI_WORKER_STATE_ERROR; 1237 me->state |= ISCSI_WORKER_STATE_ERROR;
1238 ISCSI_SIGNAL(&me->exit_cond, return -1); 1238 ISCSI_SIGNAL(&me->exit_cond, return -1);
1239 ISCSI_UNLOCK(&me->exit_mutex, return -1); 1239 ISCSI_UNLOCK(&me->exit_mutex, return -1);
1240 goto done; 1240 goto done;
1241 1241
1242 } 1242 }
1243 sess->state = INITIATOR_SESSION_STATE_CONNECTED; 1243 sess->state = INITIATOR_SESSION_STATE_CONNECTED;
1244 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tx_worker[%d]: connected to %s:%d\n", 1244 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tx_worker[%d]: connected to %s:%d\n",
1245 me->id, g_target[me->id].name, g_target[me->id].port); 1245 me->id, g_target[me->id].name, g_target[me->id].port);
1246 1246
1247 /* Start Rx worker */ 1247 /* Start Rx worker */
1248 1248
1249 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tx_worker[%d]: starting Rx worker\n", me->id); 1249 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tx_worker[%d]: starting Rx worker\n", me->id);
1250 ISCSI_LOCK(&sess->rx_worker.exit_mutex, return -1); 1250 ISCSI_LOCK(&sess->rx_worker.exit_mutex, return -1);
1251 if (iscsi_thread_create(&sess->rx_worker.thread, (void *) rx_worker_proc_i, sess) != 0) { 1251 if (iscsi_thread_create(&sess->rx_worker.thread, (void *) rx_worker_proc_i, sess) != 0) {
1252 iscsi_trace_error(__FILE__, __LINE__, "iscsi_thread_create() failed\n"); 1252 iscsi_trace_error(__FILE__, __LINE__, "iscsi_thread_create() failed\n");
1253 goto done; 1253 goto done;
1254 } 1254 }
1255 ISCSI_WAIT(&sess->rx_worker.exit_cond, &sess->rx_worker.exit_mutex, return -1); 1255 ISCSI_WAIT(&sess->rx_worker.exit_cond, &sess->rx_worker.exit_mutex, return -1);
1256 ISCSI_UNLOCK(&sess->rx_worker.exit_mutex, return -1); 1256 ISCSI_UNLOCK(&sess->rx_worker.exit_mutex, return -1);
1257 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tx_worker[%d]: Rx worker started\n", me->id); 1257 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tx_worker[%d]: Rx worker started\n", me->id);
1258 1258
1259 /* Signal that we've started */ 1259 /* Signal that we've started */
1260 ISCSI_LOCK(&me->exit_mutex, return -1); 1260 ISCSI_LOCK(&me->exit_mutex, return -1);
1261 ISCSI_SIGNAL(&me->exit_cond, return -1); 1261 ISCSI_SIGNAL(&me->exit_cond, return -1);
1262 ISCSI_UNLOCK(&me->exit_mutex, return -1); 1262 ISCSI_UNLOCK(&me->exit_mutex, return -1);
1263 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tx_worker[%d]: successfully started\n", me->id); 1263 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tx_worker[%d]: successfully started\n", me->id);
1264 1264
1265 /* This Tx loop will exit when both the g_tx_queue is empty and */ 1265 /* This Tx loop will exit when both the g_tx_queue is empty and */
1266 /* sess->state != INITIATOR_SESSION_STATE_DESTROYING */ 1266 /* sess->state != INITIATOR_SESSION_STATE_DESTROYING */
1267 1267
1268 ISCSI_LOCK(&me->work_mutex, return -1); 1268 ISCSI_LOCK(&me->work_mutex, return -1);
1269 for (;;) { 1269 for (;;) {
1270 1270
1271 if (iscsi_queue_depth(&g_target[me->id].sess->tx_queue) || (sess->state == INITIATOR_SESSION_STATE_DESTROYING)) { 1271 if (iscsi_queue_depth(&g_target[me->id].sess->tx_queue) || (sess->state == INITIATOR_SESSION_STATE_DESTROYING)) {
1272 1272
1273 if (sess->state == INITIATOR_SESSION_STATE_DESTROYING) { 1273 if (sess->state == INITIATOR_SESSION_STATE_DESTROYING) {
1274 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tx_worker[%d]: session is being destroyed, exiting\n", me->id); 1274 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tx_worker[%d]: session is being destroyed, exiting\n", me->id);
1275 ISCSI_UNLOCK(&me->work_mutex, return -1); 1275 ISCSI_UNLOCK(&me->work_mutex, return -1);
1276 goto done; 1276 goto done;
1277 } 1277 }
1278 /* Get initiator command */ 1278 /* Get initiator command */
1279 1279
1280 if ((cmd = iscsi_queue_remove(&g_target[me->id].sess->tx_queue)) == NULL) { 1280 if ((cmd = iscsi_queue_remove(&g_target[me->id].sess->tx_queue)) == NULL) {
1281 iscsi_trace_error(__FILE__, __LINE__, "tx_worker[%d]: iscsi_queue_remove() failed\n", me->id); 1281 iscsi_trace_error(__FILE__, __LINE__, "tx_worker[%d]: iscsi_queue_remove() failed\n", me->id);
1282 ISCSI_UNLOCK(&me->work_mutex, return -1); 1282 ISCSI_UNLOCK(&me->work_mutex, return -1);
1283 goto done; 1283 goto done;
1284 } 1284 }
1285 ISCSI_UNLOCK(&me->work_mutex, return -1); 1285 ISCSI_UNLOCK(&me->work_mutex, return -1);
1286 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "tx_worker[%d]: dequeued initiator_cmd_t 0x%p (type %d, target %llu)\n", me->id, cmd, cmd->type, cmd->isid); 1286 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "tx_worker[%d]: dequeued initiator_cmd_t 0x%p (type %d, target %llu)\n", me->id, cmd, cmd->type, cmd->isid);
1287 1287
1288 /* Make sure we've got the right command */ 1288 /* Make sure we've got the right command */
1289 1289
1290 if (cmd->isid != me->id) { 1290 if (cmd->isid != (unsigned)me->id) {
1291 iscsi_trace_error(__FILE__, __LINE__, "got command %#x for target %llu, expected %d\n", cmd->type, cmd->isid, me->id); 1291 iscsi_trace_error(__FILE__, __LINE__, "got command %#x for target %llu, expected %d\n", cmd->type, cmd->isid, me->id);
1292 goto done; 1292 goto done;
1293 } 1293 }
1294 /* 1294 /*
1295 * Add to list of oustanding commands in session 1295 * Add to list of oustanding commands in session
1296 * (unless NOP_OUT without ping) 1296 * (unless NOP_OUT without ping)
1297 */ 1297 */
1298 1298
1299 if (!((cmd->type == ISCSI_NOP_OUT) && (((iscsi_nop_out_args_t *) (cmd->ptr))->tag == 0xffffffff))) { 1299 if (!((cmd->type == ISCSI_NOP_OUT) && (((iscsi_nop_out_args_t *) (cmd->ptr))->tag == 0xffffffff))) {
1300 cmd->next = NULL; 1300 cmd->next = NULL;
1301 iscsi_spin_lock(&sess->cmds_spin); 1301 iscsi_spin_lock(&sess->cmds_spin);
1302 for (ptr = sess->cmds; ((ptr) && (ptr->next != NULL)); ptr = ptr->next) { 1302 for (ptr = sess->cmds; ((ptr) && (ptr->next != NULL)); ptr = ptr->next) {
1303 } 1303 }
1304 if (ptr) { 1304 if (ptr) {
1305 ptr->next = cmd; 1305 ptr->next = cmd;
1306 } else { 1306 } else {
1307 sess->cmds = cmd; 1307 sess->cmds = cmd;
1308 } 1308 }
1309 iscsi_spin_unlock(&sess->cmds_spin); 1309 iscsi_spin_unlock(&sess->cmds_spin);
1310 } 1310 }
1311 cmd->tx_done = 0; 1311 cmd->tx_done = 0;
1312 switch (cmd->type) { 1312 switch (cmd->type) {
1313 case ISCSI_LOGIN_CMD: 1313 case ISCSI_LOGIN_CMD:
1314 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "tx_worker[%d]: ISCSI_LOGIN_CMD\n", me->id); 1314 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "tx_worker[%d]: ISCSI_LOGIN_CMD\n", me->id);
1315 if (login_command_i(cmd) != 0) { 1315 if (login_command_i(cmd) != 0) {
1316 iscsi_trace_error(__FILE__, __LINE__, "tx_worker[%d]: login_command_i() failed\n", me->id); 1316 iscsi_trace_error(__FILE__, __LINE__, "tx_worker[%d]: login_command_i() failed\n", me->id);
1317 goto done; 1317 goto done;
1318 } 1318 }
1319 break; 1319 break;
1320 case ISCSI_TEXT_CMD: 1320 case ISCSI_TEXT_CMD:
1321 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "tx_worker[%d]: ISCSI_TEXT_CMD\n", me->id); 1321 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "tx_worker[%d]: ISCSI_TEXT_CMD\n", me->id);
1322 if (text_command_i(cmd) != 0) { 1322 if (text_command_i(cmd) != 0) {
1323 iscsi_trace_error(__FILE__, __LINE__, "tx_worker[%d]: text_command_i() failed\n", me->id); 1323 iscsi_trace_error(__FILE__, __LINE__, "tx_worker[%d]: text_command_i() failed\n", me->id);
1324 goto done; 1324 goto done;
1325 } 1325 }
1326 break; 1326 break;
1327 case ISCSI_SCSI_CMD: 1327 case ISCSI_SCSI_CMD:
1328 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "tx_worker[%d]: ISCSI_SCSI_CMD\n", me->id); 1328 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "tx_worker[%d]: ISCSI_SCSI_CMD\n", me->id);
1329 if (scsi_command_i(cmd) != 0) { 1329 if (scsi_command_i(cmd) != 0) {
1330 iscsi_trace_error(__FILE__, __LINE__, "tx_worker[%d]: scsi_command_i() failed\n", me->id); 1330 iscsi_trace_error(__FILE__, __LINE__, "tx_worker[%d]: scsi_command_i() failed\n", me->id);
1331 goto done; 1331 goto done;
1332 } 1332 }
1333 break; 1333 break;
1334 case ISCSI_NOP_OUT: 1334 case ISCSI_NOP_OUT:
1335 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "tx_worker[%d]: ISCSI_NOP_OUT\n", me->id); 1335 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "tx_worker[%d]: ISCSI_NOP_OUT\n", me->id);
1336 if (nop_out_i(cmd) != 0) { 1336 if (nop_out_i(cmd) != 0) {
1337 iscsi_trace_error(__FILE__, __LINE__, "tx_worker[%d]: nop_out_i() failed\n", me->id); 1337 iscsi_trace_error(__FILE__, __LINE__, "tx_worker[%d]: nop_out_i() failed\n", me->id);
1338 goto done; 1338 goto done;
1339 } 1339 }
1340 break; 1340 break;
1341 case ISCSI_LOGOUT_CMD: 1341 case ISCSI_LOGOUT_CMD:
1342 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "tx_worker[%d]: ISCSI_LOGOUT_CMD\n", me->id); 1342 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "tx_worker[%d]: ISCSI_LOGOUT_CMD\n", me->id);
1343 if (logout_command_i(cmd) != 0) { 1343 if (logout_command_i(cmd) != 0) {
1344 iscsi_trace_error(__FILE__, __LINE__, "tx_worker[%d]: logout_command_i() failed\n", me->id); 1344 iscsi_trace_error(__FILE__, __LINE__, "tx_worker[%d]: logout_command_i() failed\n", me->id);
1345 goto done; 1345 goto done;
1346 } 1346 }
1347 break; 1347 break;
1348 default: 1348 default:
1349 iscsi_trace_error(__FILE__, __LINE__, "tx_worker[%d]: unknown iSCSI command %#x\n", me->id, cmd->type); 1349 iscsi_trace_error(__FILE__, __LINE__, "tx_worker[%d]: unknown iSCSI command %#x\n", me->id, cmd->type);
1350 cmd->status = -1; 1350 cmd->status = -1;
1351 break; 1351 break;
1352 } 1352 }
1353 1353
1354 /* Get lock for next iteration */ 1354 /* Get lock for next iteration */
1355 1355
1356 ISCSI_LOCK(&me->work_mutex, return -1); 1356 ISCSI_LOCK(&me->work_mutex, return -1);
1357 1357
1358 /* 1358 /*
1359 * The Rx thread will receive a response for 1359 * The Rx thread will receive a response for
1360 * the command and execute the callback. We 1360 * the command and execute the callback. We
1361 * need to make sure the callback function is 1361 * need to make sure the callback function is
1362 * not executed before the Tx thread has 1362 * not executed before the Tx thread has
1363 * completed sending the command. This is 1363 * completed sending the command. This is
1364 * what tx_done is used for. The last step is 1364 * what tx_done is used for. The last step is
1365 * to set tx_done and signal the Rx thread, 1365 * to set tx_done and signal the Rx thread,
1366 * which may be block on the condition.  1366 * which may be block on the condition.
1367 * NOP_OUT (without ping) will have no 1367 * NOP_OUT (without ping) will have no
1368 * response for the Rx thread to process - so 1368 * response for the Rx thread to process - so
1369 * we execute the callback directly. */ 1369 * we execute the callback directly. */
1370 1370
1371 if ((cmd->type == ISCSI_NOP_OUT) && (((iscsi_nop_out_args_t *) (cmd->ptr))->tag == 0xffffffff)) { 1371 if ((cmd->type == ISCSI_NOP_OUT) && (((iscsi_nop_out_args_t *) (cmd->ptr))->tag == 0xffffffff)) {
1372 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "executing callback() function directly for NOP_OUT (no NOP_IN)\n"); 1372 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "executing callback() function directly for NOP_OUT (no NOP_IN)\n");
1373 if (cmd->callback(cmd) != 0) { 1373 if (cmd->callback(cmd) != 0) {
1374 iscsi_trace_error(__FILE__, __LINE__, "cmd->callback() failed\n"); 1374 iscsi_trace_error(__FILE__, __LINE__, "cmd->callback() failed\n");
1375 return -1; 1375 return -1;
1376 } 1376 }
1377 } else { 1377 } else {
1378 ISCSI_LOCK(&sess->rx_worker.work_mutex, return -1); 1378 ISCSI_LOCK(&sess->rx_worker.work_mutex, return -1);
1379 cmd->tx_done = 1; 1379 cmd->tx_done = 1;
1380 ISCSI_SIGNAL(&sess->rx_worker.work_cond, return -1); 1380 ISCSI_SIGNAL(&sess->rx_worker.work_cond, return -1);
1381 ISCSI_UNLOCK(&sess->rx_worker.work_mutex, return -1); 1381 ISCSI_UNLOCK(&sess->rx_worker.work_mutex, return -1);
1382 } 1382 }
1383 } else { 1383 } else {
1384 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tx_worker[%d]: awaiting condition\n", me->id); 1384 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tx_worker[%d]: awaiting condition\n", me->id);
1385 ISCSI_WAIT(&me->work_cond, &me->work_mutex, return -1); 1385 ISCSI_WAIT(&me->work_cond, &me->work_mutex, return -1);
1386 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tx_worker[%d]: condition signaled\n", me->id); 1386 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tx_worker[%d]: condition signaled\n", me->id);
1387 } 1387 }
1388 } 1388 }
1389done: 1389done:
1390 if (sess->state != INITIATOR_SESSION_STATE_DESTROYING) { 1390 if (sess->state != INITIATOR_SESSION_STATE_DESTROYING) {
1391 iscsi_trace_error(__FILE__, __LINE__, "tx_worker[%d]: session exited prematurely (state %#x)\n", me->id, sess->state); 1391 iscsi_trace_error(__FILE__, __LINE__, "tx_worker[%d]: session exited prematurely (state %#x)\n", me->id, sess->state);
1392 me->state |= ISCSI_WORKER_STATE_ERROR; 1392 me->state |= ISCSI_WORKER_STATE_ERROR;
1393 } 1393 }
1394 ISCSI_WORKER_EXIT(me); 1394 ISCSI_WORKER_EXIT(me);
1395 1395
1396} 1396}
1397 1397
1398/* 1398/*
1399 * There is one Rx worker per connection. 1399 * There is one Rx worker per connection.
1400 */ 1400 */
1401 1401
1402static int  1402static int
1403rx_worker_proc_i(void *arg) 1403rx_worker_proc_i(void *arg)
1404{ 1404{
1405 uint8_t header[ISCSI_HEADER_LEN]; 1405 uint8_t header[ISCSI_HEADER_LEN];
1406 initiator_session_t *sess = (initiator_session_t *) arg; 1406 initiator_session_t *sess = (initiator_session_t *) arg;
1407 iscsi_worker_t *me = &sess->rx_worker; 1407 iscsi_worker_t *me = &sess->rx_worker;
1408 initiator_cmd_t *cmd = NULL; 1408 initiator_cmd_t *cmd = NULL;
1409 initiator_cmd_t *prev, *ptr; 1409 initiator_cmd_t *prev, *ptr;
1410 uint32_t tag; 1410 uint32_t tag;
1411 1411
1412 ISCSI_THREAD_START("rx_worker"); 1412 ISCSI_THREAD_START("rx_worker");
1413 ISCSI_SET_THREAD(me) 1413 ISCSI_SET_THREAD(me)
1414 me->state = ISCSI_WORKER_STATE_STARTED; 1414 me->state = ISCSI_WORKER_STATE_STARTED;
1415 me->pid = ISCSI_GETPID; 1415 me->pid = ISCSI_GETPID;
1416 ISCSI_LOCK(&me->exit_mutex, return -1); 1416 ISCSI_LOCK(&me->exit_mutex, return -1);
1417 ISCSI_SIGNAL(&me->exit_cond, return -1); 1417 ISCSI_SIGNAL(&me->exit_cond, return -1);
1418 ISCSI_UNLOCK(&me->exit_mutex, return -1); 1418 ISCSI_UNLOCK(&me->exit_mutex, return -1);
1419 1419
1420 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: started (sess %p)\n", me->id, sess); 1420 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: started (sess %p)\n", me->id, sess);
1421 1421
1422 for (;;) { 1422 for (;;) {
1423 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: reading iscsi header (sock %#x) \n", 1423 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: reading iscsi header (sock %#x) \n",
1424 me->id, (int) sess->sock); 1424 me->id, (int) sess->sock);
1425 if (iscsi_sock_msg(sess->sock, 0, ISCSI_HEADER_LEN, header, 0) != ISCSI_HEADER_LEN) { 1425 if (iscsi_sock_msg(sess->sock, 0, ISCSI_HEADER_LEN, header, 0) != ISCSI_HEADER_LEN) {
1426 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: iscsi_sock_msg() failed\n", me->id); 1426 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: iscsi_sock_msg() failed\n", me->id);
1427 goto done; 1427 goto done;
1428 } 1428 }
1429 if (sess->state == INITIATOR_SESSION_STATE_DESTROYING) { 1429 if (sess->state == INITIATOR_SESSION_STATE_DESTROYING) {
1430 iscsi_trace_error(__FILE__, __LINE__, "rx_worker[%d]: session is being destroyed\n", me->id); 1430 iscsi_trace_error(__FILE__, __LINE__, "rx_worker[%d]: session is being destroyed\n", me->id);
1431 goto done; 1431 goto done;
1432 } 1432 }
1433 /* Get cmd ptr from hash table */ 1433 /* Get cmd ptr from hash table */
1434 1434
1435 if ((ISCSI_OPCODE(header) != ISCSI_REJECT) && (ISCSI_OPCODE(header) != ISCSI_ASYNC)) { 1435 if ((ISCSI_OPCODE(header) != ISCSI_REJECT) && (ISCSI_OPCODE(header) != ISCSI_ASYNC)) {
1436 tag = ISCSI_NTOHL(*((uint32_t *) (header + 16))); 1436 tag = ISCSI_NTOHL(*((uint32_t *) (header + 16)));
1437 if (tag != 0xffffffff) { 1437 if (tag != 0xffffffff) {
1438 1438
1439 /* 1439 /*
1440 * remove command from g_tag_hash, cmd is 1440 * remove command from g_tag_hash, cmd is
1441 * local so we only need to lock the queue 1441 * local so we only need to lock the queue
1442 * remove operation 1442 * remove operation
1443 */ 1443 */
1444 1444
1445 if ((cmd = hash_remove(&g_tag_hash, tag)) == NULL) { 1445 if ((cmd = hash_remove(&g_tag_hash, tag)) == NULL) {
1446 iscsi_trace_error(__FILE__, __LINE__, "hash_remove() failed\n"); 1446 iscsi_trace_error(__FILE__, __LINE__, "hash_remove() failed\n");
1447 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "no cmd ptr associated with tag %#x\n", tag); 1447 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "no cmd ptr associated with tag %#x\n", tag);
1448 } else { 1448 } else {
1449 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "cmd ptr %p associated with tag %#x\n", cmd, tag); 1449 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "cmd ptr %p associated with tag %#x\n", cmd, tag);
1450 1450
1451 ISCSI_LOCK(&sess->rx_worker.work_mutex, return -1); 1451 ISCSI_LOCK(&sess->rx_worker.work_mutex, return -1);
1452 if (!cmd->tx_done) { 1452 if (!cmd->tx_done) {
1453 ISCSI_WAIT(&sess->rx_worker.work_cond, &sess->rx_worker.work_mutex, return -1); 1453 ISCSI_WAIT(&sess->rx_worker.work_cond, &sess->rx_worker.work_mutex, return -1);
1454 } 1454 }
1455 ISCSI_UNLOCK(&sess->rx_worker.work_mutex, return -1); 1455 ISCSI_UNLOCK(&sess->rx_worker.work_mutex, return -1);
1456 } 1456 }
1457 } else { 1457 } else {
1458 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "no command associated with tag %#x\n", tag); 1458 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "no command associated with tag %#x\n", tag);
1459 } 1459 }
1460 } 1460 }
1461 /* Remove cmd ptr from outstanding list */ 1461 /* Remove cmd ptr from outstanding list */
1462 iscsi_spin_lock(&sess->cmds_spin); 1462 iscsi_spin_lock(&sess->cmds_spin);
1463 prev = ptr = sess->cmds; 1463 prev = ptr = sess->cmds;
1464 while (ptr != NULL) { 1464 while (ptr != NULL) {
1465 prev = ptr; 1465 prev = ptr;
1466 if (ptr == cmd) 1466 if (ptr == cmd)
1467 break; 1467 break;
1468 ptr = ptr->next; 1468 ptr = ptr->next;
1469 } 1469 }
1470 if (ptr != NULL) { 1470 if (ptr != NULL) {
1471 if (prev == sess->cmds) { 1471 if (prev == sess->cmds) {
1472 sess->cmds = cmd->next; 1472 sess->cmds = cmd->next;
1473 } else { 1473 } else {
1474 prev->next = cmd->next; 1474 prev->next = cmd->next;
1475 } 1475 }
1476 } 1476 }
1477 iscsi_spin_unlock(&sess->cmds_spin); 1477 iscsi_spin_unlock(&sess->cmds_spin);
1478 switch (ISCSI_OPCODE(header)) { 1478 switch (ISCSI_OPCODE(header)) {
1479 case ISCSI_SCSI_RSP: 1479 case ISCSI_SCSI_RSP:
1480 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: ISCSI_SCSI_RSP\n", me->id); 1480 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: ISCSI_SCSI_RSP\n", me->id);
1481 if (scsi_response_i(sess, cmd, header) != 0) { 1481 if (scsi_response_i(sess, cmd, header) != 0) {
1482 iscsi_trace_error(__FILE__, __LINE__, "rx_worker[%d]: scsi_response_i() failed\n", me->id); 1482 iscsi_trace_error(__FILE__, __LINE__, "rx_worker[%d]: scsi_response_i() failed\n", me->id);
1483 goto done; 1483 goto done;
1484 } 1484 }
1485 break; 1485 break;
1486 case ISCSI_READ_DATA: 1486 case ISCSI_READ_DATA:
1487 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: ISCSI_READ_DATA\n", me->id); 1487 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: ISCSI_READ_DATA\n", me->id);
1488 if (scsi_read_data_i(sess, cmd, header) != 0) { 1488 if (scsi_read_data_i(sess, cmd, header) != 0) {
1489 iscsi_trace_error(__FILE__, __LINE__, "rx_worker[%d]: scsi_read_data_i() failed\n", me->id); 1489 iscsi_trace_error(__FILE__, __LINE__, "rx_worker[%d]: scsi_read_data_i() failed\n", me->id);
1490 goto done; 1490 goto done;
1491 } 1491 }
1492 break; 1492 break;
1493 case ISCSI_R2T: 1493 case ISCSI_R2T:
1494 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: ISCSI_R2T\n", me->id); 1494 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: ISCSI_R2T\n", me->id);
1495 if (scsi_r2t_i(sess, cmd, header) != 0) { 1495 if (scsi_r2t_i(sess, cmd, header) != 0) {
1496 iscsi_trace_error(__FILE__, __LINE__, "rx_worker[%d]: scsi_r2t_i() failed\n", me->id); 1496 iscsi_trace_error(__FILE__, __LINE__, "rx_worker[%d]: scsi_r2t_i() failed\n", me->id);
1497 goto done; 1497 goto done;
1498 } 1498 }
1499 break; 1499 break;
1500 case ISCSI_NOP_IN: 1500 case ISCSI_NOP_IN:
1501 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: ISCSI_NOP_IN\n", me->id); 1501 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: ISCSI_NOP_IN\n", me->id);
1502 if (nop_in_i(sess, cmd, header) != 0) { 1502 if (nop_in_i(sess, cmd, header) != 0) {
1503 iscsi_trace_error(__FILE__, __LINE__, "nop_in_i() failed\n"); 1503 iscsi_trace_error(__FILE__, __LINE__, "nop_in_i() failed\n");
1504 return -1; 1504 return -1;
1505 } 1505 }
1506 break; 1506 break;
1507 case ISCSI_LOGIN_RSP: 1507 case ISCSI_LOGIN_RSP:
1508 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: ISCSI_LOGIN_RSP\n", me->id); 1508 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: ISCSI_LOGIN_RSP\n", me->id);
1509 if (login_response_i(sess, cmd, header) != 0) { 1509 if (login_response_i(sess, cmd, header) != 0) {
1510 iscsi_trace_error(__FILE__, __LINE__, "rx_worker[%d]: login_response_i() failed\n", me->id); 1510 iscsi_trace_error(__FILE__, __LINE__, "rx_worker[%d]: login_response_i() failed\n", me->id);
1511 goto done; 1511 goto done;
1512 } 1512 }
1513 break; 1513 break;
1514 case ISCSI_TEXT_RSP: 1514 case ISCSI_TEXT_RSP:
1515 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: ISCSI_TEXT_RSP\n", me->id); 1515 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: ISCSI_TEXT_RSP\n", me->id);
1516 if (text_response_i(sess, cmd, header) != 0) { 1516 if (text_response_i(sess, cmd, header) != 0) {
1517 iscsi_trace_error(__FILE__, __LINE__, "rx_worker[%d]: text_response_i() failed\n", me->id); 1517 iscsi_trace_error(__FILE__, __LINE__, "rx_worker[%d]: text_response_i() failed\n", me->id);
1518 goto done; 1518 goto done;
1519 } 1519 }
1520 break; 1520 break;
1521 case ISCSI_LOGOUT_RSP: 1521 case ISCSI_LOGOUT_RSP:
1522 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: ISCSI_LOGOUT_RSP\n", me->id); 1522 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: ISCSI_LOGOUT_RSP\n", me->id);
1523 if (logout_response_i(sess, cmd, header) != 0) { 1523 if (logout_response_i(sess, cmd, header) != 0) {
1524 iscsi_trace_error(__FILE__, __LINE__, "rx_worker[%d]: logout_response_i() failed\n", me->id); 1524 iscsi_trace_error(__FILE__, __LINE__, "rx_worker[%d]: logout_response_i() failed\n", me->id);
1525 goto done; 1525 goto done;
1526 } 1526 }
1527 break; 1527 break;
1528 case ISCSI_REJECT: 1528 case ISCSI_REJECT:
1529 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: ISCSI_REJECT\n", me->id); 1529 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: ISCSI_REJECT\n", me->id);
1530 if (reject_i(sess, header) != 0) { 1530 if (reject_i(sess, header) != 0) {
1531 iscsi_trace_error(__FILE__, __LINE__, "reject_i() failed\n"); 1531 iscsi_trace_error(__FILE__, __LINE__, "reject_i() failed\n");
1532 return -1; 1532 return -1;
1533 } 1533 }
1534 break; 1534 break;
1535 case ISCSI_ASYNC: 1535 case ISCSI_ASYNC:
1536 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: ISCSI_ASYNC\n", me->id); 1536 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: ISCSI_ASYNC\n", me->id);
1537 if (async_msg_i(sess, header) != 0) { 1537 if (async_msg_i(sess, header) != 0) {
1538 iscsi_trace_error(__FILE__, __LINE__, "async_msg_i() failed\n"); 1538 iscsi_trace_error(__FILE__, __LINE__, "async_msg_i() failed\n");
1539 goto done; 1539 goto done;
1540 } 1540 }
1541 break; 1541 break;
1542 default: 1542 default:
1543 iscsi_trace_error(__FILE__, __LINE__, "rx_worker[%d]: unexpected iSCSI op %#x\n", me->id, ISCSI_OPCODE(header)); 1543 iscsi_trace_error(__FILE__, __LINE__, "rx_worker[%d]: unexpected iSCSI op %#x\n", me->id, ISCSI_OPCODE(header));
1544 goto done; 1544 goto done;
1545 } 1545 }
1546 } 1546 }
1547done: 1547done:
1548 if (sess->state != INITIATOR_SESSION_STATE_DESTROYING) { 1548 if (sess->state != INITIATOR_SESSION_STATE_DESTROYING) {
1549 1549
1550 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: session exited prematurely (state %#x)\n", me->id, sess->state); 1550 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "rx_worker[%d]: session exited prematurely (state %#x)\n", me->id, sess->state);
1551 me->state |= ISCSI_WORKER_STATE_ERROR; 1551 me->state |= ISCSI_WORKER_STATE_ERROR;
1552 } 1552 }
1553 ISCSI_WORKER_EXIT(me); 1553 ISCSI_WORKER_EXIT(me);
1554} 1554}
1555 1555
1556static int  1556static int
1557text_command_i(initiator_cmd_t * cmd) 1557text_command_i(initiator_cmd_t * cmd)
1558{ 1558{
1559 iscsi_text_cmd_args_t *text_cmd = (iscsi_text_cmd_args_t *) cmd->ptr; 1559 iscsi_text_cmd_args_t *text_cmd = (iscsi_text_cmd_args_t *) cmd->ptr;
1560 initiator_session_t *sess = g_target[cmd->isid].sess; 1560 initiator_session_t *sess = g_target[cmd->isid].sess;
1561 uint8_t header[ISCSI_HEADER_LEN]; 1561 uint8_t header[ISCSI_HEADER_LEN];
1562 1562
1563 /* 1563 /*
1564 * Insert cmd into the hash table, keyed by the tag. The Rx thread 1564 * Insert cmd into the hash table, keyed by the tag. The Rx thread
1565 * will 1565 * will
1566 */ 1566 */
1567 /* retreive the cmd ptr using the tag from the response PDU. */ 1567 /* retreive the cmd ptr using the tag from the response PDU. */
1568 1568
1569 if (hash_insert(&g_tag_hash, cmd, text_cmd->tag) != 0) { 1569 if (hash_insert(&g_tag_hash, cmd, text_cmd->tag) != 0) {
1570 iscsi_trace_error(__FILE__, __LINE__, "hash_insert() failed\n"); 1570 iscsi_trace_error(__FILE__, __LINE__, "hash_insert() failed\n");
1571 return -1; 1571 return -1;
1572 } 1572 }
1573 /* Send text command PDU */ 1573 /* Send text command PDU */
1574 1574
1575 text_cmd->ExpStatSN = sess->ExpStatSN; 1575 text_cmd->ExpStatSN = sess->ExpStatSN;
1576 text_cmd->CmdSN = sess->CmdSN++; 1576 text_cmd->CmdSN = sess->CmdSN++;
1577 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending text command\n"); 1577 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending text command\n");
1578 if (iscsi_text_cmd_encap(header, text_cmd) != 0) { 1578 if (iscsi_text_cmd_encap(header, text_cmd) != 0) {
1579 iscsi_trace_error(__FILE__, __LINE__, "(iscsi_text_cmd_encap() failed\n"); 1579 iscsi_trace_error(__FILE__, __LINE__, "(iscsi_text_cmd_encap() failed\n");
1580 return -1; 1580 return -1;
1581 } 1581 }
1582 if (iscsi_sock_send_header_and_data(sess->sock, header, ISCSI_HEADER_LEN, text_cmd->text, text_cmd->length, 0) 1582 if ((unsigned)iscsi_sock_send_header_and_data(sess->sock, header, ISCSI_HEADER_LEN, text_cmd->text, text_cmd->length, 0)
1583 != ISCSI_HEADER_LEN + text_cmd->length) { 1583 != ISCSI_HEADER_LEN + text_cmd->length) {
1584 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed.\n"); 1584 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed.\n");
1585 return -1; 1585 return -1;
1586 } 1586 }
1587 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "text command sent ok\n"); 1587 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "text command sent ok\n");
1588 1588
1589 return 0; 1589 return 0;
1590} 1590}
1591 1591
1592static int  1592static int
1593login_command_i(initiator_cmd_t * cmd) 1593login_command_i(initiator_cmd_t * cmd)
1594{ 1594{
1595 iscsi_login_cmd_args_t *login_cmd = (iscsi_login_cmd_args_t *) cmd->ptr; 1595 iscsi_login_cmd_args_t *login_cmd = (iscsi_login_cmd_args_t *) cmd->ptr;
1596 initiator_session_t *sess = g_target[cmd->isid].sess; 1596 initiator_session_t *sess = g_target[cmd->isid].sess;
1597 uint8_t header[ISCSI_HEADER_LEN]; 1597 uint8_t header[ISCSI_HEADER_LEN];
1598 1598
1599 /* 1599 /*
1600 * Insert cmd into the hash table, keyed by the tag. The Rx thread 1600 * Insert cmd into the hash table, keyed by the tag. The Rx thread
1601 * will 1601 * will
1602 */ 1602 */
1603 /* retreive the cmd ptr using the tag from the response PDU. */ 1603 /* retreive the cmd ptr using the tag from the response PDU. */
1604 1604
1605 if (hash_insert(&g_tag_hash, cmd, login_cmd->tag) != 0) { 1605 if (hash_insert(&g_tag_hash, cmd, login_cmd->tag) != 0) {
1606 iscsi_trace_error(__FILE__, __LINE__, "hash_insert() failed\n"); 1606 iscsi_trace_error(__FILE__, __LINE__, "hash_insert() failed\n");
1607 return -1; 1607 return -1;
1608 } 1608 }
1609 /* Send login command PDU */ 1609 /* Send login command PDU */
1610 login_cmd->ExpStatSN = sess->ExpStatSN; 1610 login_cmd->ExpStatSN = sess->ExpStatSN;
1611 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending login command\n"); 1611 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending login command\n");
1612 if (iscsi_login_cmd_encap(header, login_cmd) != 0) { 1612 if (iscsi_login_cmd_encap(header, login_cmd) != 0) {
1613 iscsi_trace_error(__FILE__, __LINE__, "(iscsi_login_cmd_encap() failed\n"); 1613 iscsi_trace_error(__FILE__, __LINE__, "(iscsi_login_cmd_encap() failed\n");
1614 return -1; 1614 return -1;
1615 } 1615 }
1616 if (iscsi_sock_send_header_and_data(sess->sock, header, ISCSI_HEADER_LEN, login_cmd->text, login_cmd->length, 0) 1616 if ((unsigned)iscsi_sock_send_header_and_data(sess->sock, header, ISCSI_HEADER_LEN, login_cmd->text, login_cmd->length, 0)
1617 != ISCSI_HEADER_LEN + login_cmd->length) { 1617 != ISCSI_HEADER_LEN + login_cmd->length) {
1618 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed.\n"); 1618 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed.\n");
1619 return -1; 1619 return -1;
1620 } 1620 }
1621 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "login command sent ok\n"); 1621 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "login command sent ok\n");
1622 1622
1623 return 0; 1623 return 0;
1624} 1624}
1625 1625
1626static int  1626static int
1627logout_phase_i(initiator_session_t * sess) 1627logout_phase_i(initiator_session_t * sess)
1628{ 1628{
1629 initiator_cmd_t *cmd = NULL; 1629 initiator_cmd_t *cmd = NULL;
1630 iscsi_logout_cmd_args_t *logout_cmd = NULL; 1630 iscsi_logout_cmd_args_t *logout_cmd = NULL;
1631 initiator_wait_t wait; 1631 initiator_wait_t wait;
1632 1632
1633 sess->state = INITIATOR_SESSION_STATE_LOGGING_OUT; 1633 sess->state = INITIATOR_SESSION_STATE_LOGGING_OUT;
1634 1634
1635 /* Allocate command pointers */ 1635 /* Allocate command pointers */
1636 1636
1637 if ((cmd = iscsi_malloc_atomic(sizeof(initiator_cmd_t))) == NULL) { 1637 if ((cmd = iscsi_malloc_atomic(sizeof(initiator_cmd_t))) == NULL) {
1638 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n"); 1638 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n");
1639 return -1; 1639 return -1;
1640 } 1640 }
1641 (void) memset(cmd, 0x0, sizeof(*cmd)); 1641 (void) memset(cmd, 0x0, sizeof(*cmd));
1642 if ((logout_cmd = iscsi_malloc_atomic(sizeof(iscsi_logout_cmd_args_t))) == NULL) { 1642 if ((logout_cmd = iscsi_malloc_atomic(sizeof(iscsi_logout_cmd_args_t))) == NULL) {
1643 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n"); 1643 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n");
1644 if (cmd != NULL) 1644 if (cmd != NULL)
1645 iscsi_free_atomic(cmd); 1645 iscsi_free_atomic(cmd);
1646 return -1; 1646 return -1;
1647 } 1647 }
1648#define LO_CLEANUP {if (cmd != NULL) iscsi_free_atomic(cmd); if (logout_cmd != NULL) iscsi_free_atomic(logout_cmd); } 1648#define LO_CLEANUP {if (cmd != NULL) iscsi_free_atomic(cmd); if (logout_cmd != NULL) iscsi_free_atomic(logout_cmd); }
1649#define LO_ERROR {LO_CLEANUP; return -1;} 1649#define LO_ERROR {LO_CLEANUP; return -1;}
1650 (void) memset(logout_cmd, 0x0, sizeof(*logout_cmd)); 1650 (void) memset(logout_cmd, 0x0, sizeof(*logout_cmd));
1651 1651
1652 /* Build logout command */ 1652 /* Build logout command */
1653 1653
1654 logout_cmd->cid = sess->cid; 1654 logout_cmd->cid = sess->cid;
1655 logout_cmd->reason = ISCSI_LOGOUT_CLOSE_SESSION; 1655 logout_cmd->reason = ISCSI_LOGOUT_CLOSE_SESSION;
1656 ISCSI_SET_TAG(&logout_cmd->tag); 1656 ISCSI_SET_TAG(&logout_cmd->tag);
1657 logout_cmd->ExpStatSN = sess->ExpStatSN; 1657 logout_cmd->ExpStatSN = sess->ExpStatSN;
1658 logout_cmd->CmdSN = sess->CmdSN++; 1658 logout_cmd->CmdSN = sess->CmdSN++;
1659 1659
1660 /* Build wait for callback */ 1660 /* Build wait for callback */
1661 1661
1662 ISCSI_MUTEX_INIT(&wait.mutex, LO_ERROR); 1662 ISCSI_MUTEX_INIT(&wait.mutex, LO_ERROR);
1663 ISCSI_COND_INIT(&wait.cond, LO_ERROR); 1663 ISCSI_COND_INIT(&wait.cond, LO_ERROR);
1664 1664
1665 /* Build initiator command */ 1665 /* Build initiator command */
1666 1666
1667 cmd->type = ISCSI_LOGOUT_CMD; 1667 cmd->type = ISCSI_LOGOUT_CMD;
1668 cmd->ptr = logout_cmd; 1668 cmd->ptr = logout_cmd;
1669 cmd->callback = wait_callback_i; 1669 cmd->callback = wait_callback_i;
1670 cmd->callback_arg = &wait; 1670 cmd->callback_arg = &wait;
1671 cmd->isid = sess->isid; 1671 cmd->isid = sess->isid;
1672 1672
1673 /* Enqueue to Tx worker */ 1673 /* Enqueue to Tx worker */
1674 1674
1675 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueing logout command to tx worker %llu\n", sess->isid); 1675 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueing logout command to tx worker %llu\n", sess->isid);
1676 ISCSI_LOCK(&wait.mutex, LO_ERROR); 1676 ISCSI_LOCK(&wait.mutex, LO_ERROR);
1677 ISCSI_LOCK(&sess->tx_worker.work_mutex, LO_ERROR); 1677 ISCSI_LOCK(&sess->tx_worker.work_mutex, LO_ERROR);
1678 if (iscsi_queue_insert(&sess->tx_queue, cmd) == -1) { 1678 if (iscsi_queue_insert(&sess->tx_queue, cmd) == -1) {
1679 ISCSI_UNLOCK(&sess->tx_worker.work_mutex, LO_ERROR); 1679 ISCSI_UNLOCK(&sess->tx_worker.work_mutex, LO_ERROR);
1680 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_insert() failed\n"); 1680 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_insert() failed\n");
1681 LO_ERROR; 1681 LO_ERROR;
1682 } 1682 }
1683 ISCSI_SIGNAL(&sess->tx_worker.work_cond, LO_ERROR); 1683 ISCSI_SIGNAL(&sess->tx_worker.work_cond, LO_ERROR);
1684 ISCSI_UNLOCK(&sess->tx_worker.work_mutex, LO_ERROR); 1684 ISCSI_UNLOCK(&sess->tx_worker.work_mutex, LO_ERROR);
1685 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueued logout command ok\n"); 1685 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueued logout command ok\n");
1686 1686
1687 /* Wait for callback */ 1687 /* Wait for callback */
1688 1688
1689 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "waiting on logout callback\n"); 1689 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "waiting on logout callback\n");
1690 ISCSI_WAIT(&wait.cond, &wait.mutex, LO_ERROR); 1690 ISCSI_WAIT(&wait.cond, &wait.mutex, LO_ERROR);
1691 ISCSI_UNLOCK(&wait.mutex, LO_ERROR); 1691 ISCSI_UNLOCK(&wait.mutex, LO_ERROR);
1692 ISCSI_COND_DESTROY(&wait.cond, LO_ERROR); 1692 ISCSI_COND_DESTROY(&wait.cond, LO_ERROR);
1693 ISCSI_MUTEX_DESTROY(&wait.mutex, LO_ERROR); 1693 ISCSI_MUTEX_DESTROY(&wait.mutex, LO_ERROR);
1694 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "received logout callback ok\n"); 1694 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "received logout callback ok\n");
1695 1695
1696 sess->state = INITIATOR_SESSION_STATE_LOGGED_OUT; 1696 sess->state = INITIATOR_SESSION_STATE_LOGGED_OUT;
1697 1697
1698 LO_CLEANUP; 1698 LO_CLEANUP;
1699 return 0; 1699 return 0;
1700} 1700}
1701 1701
1702static void  1702static void
1703alarm_handler(int arg) 1703alarm_handler(int arg)
1704{ 1704{
1705 iscsi_trace_error(__FILE__, __LINE__, "***aborting cmd 0x%p***\n", g_cmd); 1705 iscsi_trace_error(__FILE__, __LINE__, "***aborting cmd 0x%p***\n", g_cmd);
1706 if (initiator_abort(g_cmd) != 0) { 1706 if (initiator_abort(g_cmd) != 0) {
1707 iscsi_trace_error(__FILE__, __LINE__, "initiator_abort() failed\n"); 1707 iscsi_trace_error(__FILE__, __LINE__, "initiator_abort() failed\n");
1708 } 1708 }
1709} 1709}
1710 1710
1711static int  1711static int
1712login_phase_i(initiator_session_t * sess, char *text, int text_len) 1712login_phase_i(initiator_session_t * sess, char *text, int text_len)
1713{ 1713{
1714 initiator_cmd_t *cmd = NULL; 1714 initiator_cmd_t *cmd = NULL;
1715 initiator_wait_t wait; 1715 initiator_wait_t wait;
1716 iscsi_login_cmd_args_t *login_cmd = NULL; 1716 iscsi_login_cmd_args_t *login_cmd = NULL;
1717 struct sigaction act; 1717 struct sigaction act;
1718 1718
1719 sess->state = INITIATOR_SESSION_STATE_LOGGING_IN; 1719 sess->state = INITIATOR_SESSION_STATE_LOGGING_IN;
1720 1720
1721 /* Allocate command pointers */ 1721 /* Allocate command pointers */
1722 1722
1723 if ((cmd = iscsi_malloc_atomic(sizeof(initiator_cmd_t))) == NULL) { 1723 if ((cmd = iscsi_malloc_atomic(sizeof(initiator_cmd_t))) == NULL) {
1724 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n"); 1724 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n");
1725 return -1; 1725 return -1;
1726 } 1726 }
1727 (void) memset(cmd, 0x0, sizeof(*cmd)); 1727 (void) memset(cmd, 0x0, sizeof(*cmd));
1728 if ((login_cmd = iscsi_malloc_atomic(sizeof(iscsi_login_cmd_args_t))) == NULL) { 1728 if ((login_cmd = iscsi_malloc_atomic(sizeof(iscsi_login_cmd_args_t))) == NULL) {
1729 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n"); 1729 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n");
1730 if (cmd != NULL) 1730 if (cmd != NULL)
1731 iscsi_free_atomic(cmd); 1731 iscsi_free_atomic(cmd);
1732 return -1; 1732 return -1;
1733 } 1733 }
1734#define LI_CLEANUP {if (cmd != NULL) iscsi_free_atomic(cmd); if (login_cmd != NULL) iscsi_free_atomic(login_cmd); } 1734#define LI_CLEANUP {if (cmd != NULL) iscsi_free_atomic(cmd); if (login_cmd != NULL) iscsi_free_atomic(login_cmd); }
1735#define LI_ERROR {LI_CLEANUP; return -1;} 1735#define LI_ERROR {LI_CLEANUP; return -1;}
1736 (void) memset(login_cmd, 0x0, sizeof(*login_cmd)); 1736 (void) memset(login_cmd, 0x0, sizeof(*login_cmd));
1737 1737
1738 /* This is the length of our original offer. */ 1738 /* This is the length of our original offer. */
1739 1739
1740 login_cmd->text = text; 1740 login_cmd->text = text;
1741 login_cmd->length = text_len; 1741 login_cmd->length = text_len;
1742 login_cmd->transit = 1; 1742 login_cmd->transit = 1;
1743 login_cmd->csg = ISCSI_LOGIN_STAGE_SECURITY; 1743 login_cmd->csg = ISCSI_LOGIN_STAGE_SECURITY;
1744 login_cmd->nsg = ISCSI_LOGIN_STAGE_NEGOTIATE; 1744 login_cmd->nsg = ISCSI_LOGIN_STAGE_NEGOTIATE;
1745 ISCSI_SET_TAG(&login_cmd->tag); 1745 ISCSI_SET_TAG(&login_cmd->tag);
1746 login_cmd->CmdSN = sess->CmdSN = 0; 1746 login_cmd->CmdSN = sess->CmdSN = 0;
1747 1747
1748 do { 1748 do {
1749 1749
1750 /* 1750 /*
1751 * Build login command. Note that the <length> and 1751 * Build login command. Note that the <length> and
1752 * <text> fields may get updated by login_response_i.  1752 * <text> fields may get updated by login_response_i.
1753 * Such is the case when we receive offers from the 1753 * Such is the case when we receive offers from the
1754 * target. The new <length> and <text> fields will 1754 * target. The new <length> and <text> fields will
1755 * represent the response that we need to send to the 1755 * represent the response that we need to send to the
1756 * target on the next login. 1756 * target on the next login.
1757 */ 1757 */
1758 1758
1759 login_cmd->cont = 0; 1759 login_cmd->cont = 0;
1760 login_cmd->version_min = ISCSI_VERSION; 1760 login_cmd->version_min = ISCSI_VERSION;
1761 login_cmd->version_max = ISCSI_VERSION; 1761 login_cmd->version_max = ISCSI_VERSION;
1762 login_cmd->cid = sess->cid = sess->isid; 1762 login_cmd->cid = sess->cid = sess->isid;
1763 login_cmd->isid = sess->isid = sess->isid; 1763 login_cmd->isid = sess->isid = sess->isid;
1764 login_cmd->tsih = 0; 1764 login_cmd->tsih = 0;
1765 1765
1766 /* Build wait for callback */ 1766 /* Build wait for callback */
1767 1767
1768 ISCSI_MUTEX_INIT(&wait.mutex, LI_ERROR); 1768 ISCSI_MUTEX_INIT(&wait.mutex, LI_ERROR);
1769 ISCSI_COND_INIT(&wait.cond, LI_ERROR); 1769 ISCSI_COND_INIT(&wait.cond, LI_ERROR);
1770 1770
1771 /* Build initiator command */ 1771 /* Build initiator command */
1772 1772
1773 cmd->type = ISCSI_LOGIN_CMD; 1773 cmd->type = ISCSI_LOGIN_CMD;
1774 cmd->ptr = login_cmd; 1774 cmd->ptr = login_cmd;
1775 cmd->callback = wait_callback_i; 1775 cmd->callback = wait_callback_i;
1776 cmd->callback_arg = &wait; 1776 cmd->callback_arg = &wait;
1777 cmd->isid = sess->isid; 1777 cmd->isid = sess->isid;
1778 1778
1779 /* Set Alarm */ 1779 /* Set Alarm */
1780 1780
1781 g_cmd = cmd; 1781 g_cmd = cmd;
1782 act.sa_handler = alarm_handler; 1782 act.sa_handler = alarm_handler;
1783 sigaction(SIGALRM, &act, NULL); 1783 sigaction(SIGALRM, &act, NULL);
1784 alarm(5); 1784 alarm(5);
1785 1785
1786 /* Enqueue initiator command to Tx worker */ 1786 /* Enqueue initiator command to Tx worker */
1787 1787
1788 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueing login command to tx worker %llu\n", sess->isid); 1788 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueing login command to tx worker %llu\n", sess->isid);
1789 ISCSI_LOCK(&wait.mutex, LI_ERROR); 1789 ISCSI_LOCK(&wait.mutex, LI_ERROR);
1790 ISCSI_LOCK(&sess->tx_worker.work_mutex, LI_ERROR); 1790 ISCSI_LOCK(&sess->tx_worker.work_mutex, LI_ERROR);
1791 if (iscsi_queue_insert(&sess->tx_queue, cmd) == -1) { 1791 if (iscsi_queue_insert(&sess->tx_queue, cmd) == -1) {
1792 ISCSI_UNLOCK(&sess->tx_worker.work_mutex, LI_ERROR); 1792 ISCSI_UNLOCK(&sess->tx_worker.work_mutex, LI_ERROR);
1793 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_insert() failed\n"); 1793 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_insert() failed\n");
1794 LI_ERROR; 1794 LI_ERROR;
1795 1795
1796 } 1796 }
1797 ISCSI_SIGNAL(&sess->tx_worker.work_cond, LI_ERROR); 1797 ISCSI_SIGNAL(&sess->tx_worker.work_cond, LI_ERROR);
1798 ISCSI_UNLOCK(&sess->tx_worker.work_mutex, LI_ERROR); 1798 ISCSI_UNLOCK(&sess->tx_worker.work_mutex, LI_ERROR);
1799 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueued login command ok\n"); 1799 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "enqueued login command ok\n");
1800 1800
1801 /* Wait for callback */ 1801 /* Wait for callback */
1802 1802
1803 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "waiting on login callback\n"); 1803 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "waiting on login callback\n");
1804 ISCSI_WAIT(&wait.cond, &wait.mutex, LI_ERROR); 1804 ISCSI_WAIT(&wait.cond, &wait.mutex, LI_ERROR);
1805 ISCSI_UNLOCK(&wait.mutex, LI_ERROR); 1805 ISCSI_UNLOCK(&wait.mutex, LI_ERROR);
1806 ISCSI_COND_DESTROY(&wait.cond, LI_ERROR); 1806 ISCSI_COND_DESTROY(&wait.cond, LI_ERROR);
1807 ISCSI_MUTEX_DESTROY(&wait.mutex, LI_ERROR); 1807 ISCSI_MUTEX_DESTROY(&wait.mutex, LI_ERROR);
1808 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "received login callback ok\n"); 1808 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "received login callback ok\n");
1809 1809
1810 alarm(0); 1810 alarm(0);
1811 1811
1812 if (cmd->status != 0) { 1812 if (cmd->status != 0) {
1813 iscsi_trace_error(__FILE__, __LINE__, "initiator_cmd_t failed\n"); 1813 iscsi_trace_error(__FILE__, __LINE__, "initiator_cmd_t failed\n");
1814 LI_ERROR; 1814 LI_ERROR;
1815 } 1815 }
1816 if (sess->state == INITIATOR_SESSION_STATE_LOGGING_IN) { 1816 if (sess->state == INITIATOR_SESSION_STATE_LOGGING_IN) {
1817 iscsi_trace(TRACE_ISCSI_PARAM, __FILE__, __LINE__, "more negotiation needed (sending %d bytes response parameters)\n", 1817 iscsi_trace(TRACE_ISCSI_PARAM, __FILE__, __LINE__, "more negotiation needed (sending %d bytes response parameters)\n",
1818 login_cmd->length); 1818 login_cmd->length);
1819 } 1819 }
1820 } while (sess->state == INITIATOR_SESSION_STATE_LOGGING_IN); 1820 } while (sess->state == INITIATOR_SESSION_STATE_LOGGING_IN);
1821 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "login phase completed successfully\n"); 1821 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "login phase completed successfully\n");
1822 1822
1823 LI_CLEANUP; 1823 LI_CLEANUP;
1824 return 0; 1824 return 0;
1825} 1825}
1826 1826
1827 1827
1828#define TEXT_RESPONSE_TEXT_LEN 2048 1828#define TEXT_RESPONSE_TEXT_LEN 2048
1829 1829
1830static int  1830static int
1831text_response_i(initiator_session_t * sess, initiator_cmd_t * cmd, uint8_t *header) 1831text_response_i(initiator_session_t * sess, initiator_cmd_t * cmd, uint8_t *header)
1832{ 1832{
1833 iscsi_text_cmd_args_t *text_cmd; 1833 iscsi_text_cmd_args_t *text_cmd;
1834 iscsi_text_rsp_args_t text_rsp; 1834 iscsi_text_rsp_args_t text_rsp;
1835 iscsi_parameter_t *l = sess->params; 1835 iscsi_parameter_t *l = sess->params;
1836 char *text_in = NULL; 1836 char *text_in = NULL;
1837 char *text_out = NULL; 1837 char *text_out = NULL;
1838 int len_in = 0; 1838 int len_in = 0;
1839 int len_out = 0; 1839 int len_out = 0;
1840 int ret = 0; 1840 int ret = 0;
1841 1841
1842#define TI_CLEANUP {if (text_in != NULL) iscsi_free_atomic(text_in); if (text_out != NULL) iscsi_free_atomic(text_out);} 1842#define TI_CLEANUP {if (text_in != NULL) iscsi_free_atomic(text_in); if (text_out != NULL) iscsi_free_atomic(text_out);}
1843#define TI_ERROR {cmd->status=-1; goto callback;} 1843#define TI_ERROR {cmd->status=-1; goto callback;}
1844 if (cmd) { 1844 if (cmd) {
1845 text_cmd = (iscsi_text_cmd_args_t *) cmd->ptr; 1845 text_cmd = (iscsi_text_cmd_args_t *) cmd->ptr;
1846 } else { 1846 } else {
1847 iscsi_trace_error(__FILE__, __LINE__, "no initiator_cmd_t specified for iscsi_text_cmd_args_t??\n"); 1847 iscsi_trace_error(__FILE__, __LINE__, "no initiator_cmd_t specified for iscsi_text_cmd_args_t??\n");
1848 return -1; 1848 return -1;
1849 } 1849 }
1850 1850
1851 /* Check arguments & update numbering */ 1851 /* Check arguments & update numbering */
1852 1852
1853 if (iscsi_text_rsp_decap(header, &text_rsp) != 0) { 1853 if (iscsi_text_rsp_decap(header, &text_rsp) != 0) {
1854 iscsi_trace_error(__FILE__, __LINE__, "text_response_decap() failed\n"); 1854 iscsi_trace_error(__FILE__, __LINE__, "text_response_decap() failed\n");
1855 TI_ERROR; 1855 TI_ERROR;
1856 } 1856 }
1857 RETURN_NOT_EQUAL("Tag", text_rsp.tag, text_cmd->tag, TI_ERROR, -1); 1857 RETURN_NOT_EQUAL("Tag", text_rsp.tag, text_cmd->tag, TI_ERROR, -1);
1858 RETURN_NOT_EQUAL("Transfer Tag", text_rsp.transfer_tag, 0xffffffff, TI_ERROR, -1); 1858 RETURN_NOT_EQUAL("Transfer Tag", text_rsp.transfer_tag, 0xffffffff, TI_ERROR, -1);
1859 RETURN_NOT_EQUAL("StatSN", text_rsp.StatSN, sess->ExpStatSN, TI_ERROR, -1); 1859 RETURN_NOT_EQUAL("StatSN", text_rsp.StatSN, sess->ExpStatSN, TI_ERROR, -1);
1860 RETURN_NOT_EQUAL("ExpCmdSN", text_rsp.ExpCmdSN, sess->CmdSN, TI_ERROR, -1); 1860 RETURN_NOT_EQUAL("ExpCmdSN", text_rsp.ExpCmdSN, sess->CmdSN, TI_ERROR, -1);
1861 sess->ExpStatSN = text_rsp.StatSN + 1; 1861 sess->ExpStatSN = text_rsp.StatSN + 1;
1862 1862
1863 /* Parse input text parameters and generate any response */ 1863 /* Parse input text parameters and generate any response */
1864 1864
1865 if ((len_in = text_rsp.length) != 0) { 1865 if ((len_in = text_rsp.length) != 0) {
1866 iscsi_trace(TRACE_ISCSI_PARAM, __FILE__, __LINE__, "allocating %d bytes input parameters\n", len_in); 1866 iscsi_trace(TRACE_ISCSI_PARAM, __FILE__, __LINE__, "allocating %d bytes input parameters\n", len_in);
1867 if ((text_in = iscsi_malloc_atomic(len_in + 1)) == NULL) { 1867 if ((text_in = iscsi_malloc_atomic(len_in + 1)) == NULL) {
1868 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n"); 1868 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
1869 TI_ERROR; 1869 TI_ERROR;
1870 } 1870 }
1871 if ((text_out = iscsi_malloc_atomic(TEXT_RESPONSE_TEXT_LEN)) == NULL) { 1871 if ((text_out = iscsi_malloc_atomic(TEXT_RESPONSE_TEXT_LEN)) == NULL) {
1872 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n"); 1872 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
1873 if (text_in != NULL) 1873 if (text_in != NULL)
1874 iscsi_free_atomic(text_in); 1874 iscsi_free_atomic(text_in);
1875 TI_ERROR; 1875 TI_ERROR;
1876 } 1876 }
1877 if (iscsi_sock_msg(sess->sock, 0, len_in, text_in, 0) != len_in) { 1877 if (iscsi_sock_msg(sess->sock, 0, len_in, text_in, 0) != len_in) {
1878 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 1878 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
1879 TI_ERROR; 1879 TI_ERROR;
1880 } 1880 }
1881 text_in[len_in] = 0x0; 1881 text_in[len_in] = 0x0;
1882 iscsi_trace(TRACE_ISCSI_PARAM, __FILE__, __LINE__, "read %d bytes input parameters ok\n", len_in); 1882 iscsi_trace(TRACE_ISCSI_PARAM, __FILE__, __LINE__, "read %d bytes input parameters ok\n", len_in);
1883 1883
1884 /* Reset the value lists for TargetName and TargetAddress */ 1884 /* Reset the value lists for TargetName and TargetAddress */
1885 1885
1886 if (param_val_reset(sess->params, "TargetName") != 0) { 1886 if (param_val_reset(sess->params, "TargetName") != 0) {
1887 iscsi_trace_error(__FILE__, __LINE__, "parm_val_reset() failed\n"); 1887 iscsi_trace_error(__FILE__, __LINE__, "parm_val_reset() failed\n");
1888 TI_ERROR; 1888 TI_ERROR;
1889 } 1889 }
1890 if (param_val_reset(sess->params, "TargetAddress") != 0) { 1890 if (param_val_reset(sess->params, "TargetAddress") != 0) {
1891 iscsi_trace_error(__FILE__, __LINE__, "parm_val_reset() failed\n"); 1891 iscsi_trace_error(__FILE__, __LINE__, "parm_val_reset() failed\n");
1892 TI_ERROR; 1892 TI_ERROR;
1893 } 1893 }
1894 /* Parse the incoming answer */ 1894 /* Parse the incoming answer */
1895 1895
1896 PARAM_TEXT_PARSE(l, &sess->sess_params.cred, text_in, len_in, text_out, &len_out, TEXT_RESPONSE_TEXT_LEN, 0, TI_ERROR); 1896 PARAM_TEXT_PARSE(l, &sess->sess_params.cred, text_in, len_in, text_out, &len_out, TEXT_RESPONSE_TEXT_LEN, 0, TI_ERROR);
1897 1897
1898 if (len_out) { 1898 if (len_out) {
1899 1899
1900 RETURN_NOT_EQUAL("text_rsp.final", text_rsp.final, 0, TI_ERROR, -1); 1900 RETURN_NOT_EQUAL("text_rsp.final", text_rsp.final, 0, TI_ERROR, -1);
1901 1901
1902 /* 1902 /*
1903 * Copy response text into text_cmd->text and 1903 * Copy response text into text_cmd->text and
1904 * update the length text_cmd->length. This 1904 * update the length text_cmd->length. This
1905 * will be sent out on the next text command.  1905 * will be sent out on the next text command.
1906 * */ 1906 * */
1907 1907
1908 PARAM_TEXT_PARSE(l, &sess->sess_params.cred, text_out, len_out, NULL, NULL, TEXT_RESPONSE_TEXT_LEN, 1, TI_ERROR); 1908 PARAM_TEXT_PARSE(l, &sess->sess_params.cred, text_out, len_out, NULL, NULL, TEXT_RESPONSE_TEXT_LEN, 1, TI_ERROR);
1909 1909
1910 iscsi_trace(TRACE_ISCSI_PARAM, __FILE__, __LINE__, "need to send %d bytes response back to target\n", len_out); 1910 iscsi_trace(TRACE_ISCSI_PARAM, __FILE__, __LINE__, "need to send %d bytes response back to target\n", len_out);
1911 text_cmd->length = len_out; 1911 text_cmd->length = len_out;
1912 memcpy(text_cmd->text, text_out, len_out); 1912 memcpy(text_cmd->text, text_out, len_out);
1913 } else { 1913 } else {
1914 text_cmd->length = 0; 1914 text_cmd->length = 0;
1915 } 1915 }
1916 } 1916 }
1917 text_cmd->final = text_rsp.final; 1917 text_cmd->final = text_rsp.final;
1918 1918
1919 /* Issue callback */ 1919 /* Issue callback */
1920 1920
1921 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "iscsi_text_cmd_args_t done\n"); 1921 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "iscsi_text_cmd_args_t done\n");
1922callback: 1922callback:
1923 if (cmd->status == -1) 1923 if (cmd->status == -1)
1924 ret = -1; 1924 ret = -1;
1925 if (cmd->callback(cmd) != 0) { 1925 if (cmd->callback(cmd) != 0) {
1926 ret = -1; 1926 ret = -1;
1927 iscsi_trace_error(__FILE__, __LINE__, "callback() failed\n"); 1927 iscsi_trace_error(__FILE__, __LINE__, "callback() failed\n");
1928 } 1928 }
1929 TI_CLEANUP; 1929 TI_CLEANUP;
1930 return ret; 1930 return ret;
1931} 1931}
1932 1932
1933#define LOGIN_RESPONSE_TEXT_LEN 2048 1933#define LOGIN_RESPONSE_TEXT_LEN 2048
1934 1934
1935static int  1935static int
1936login_response_i(initiator_session_t * sess, initiator_cmd_t * cmd, uint8_t *header) 1936login_response_i(initiator_session_t * sess, initiator_cmd_t * cmd, uint8_t *header)
1937{ 1937{
1938 iscsi_login_cmd_args_t *login_cmd; 1938 iscsi_login_cmd_args_t *login_cmd;
1939 iscsi_login_rsp_args_t login_rsp; 1939 iscsi_login_rsp_args_t login_rsp;
1940 iscsi_parameter_t *l = sess->params; 1940 iscsi_parameter_t *l = sess->params;
1941 char *text_in = NULL; 1941 char *text_in = NULL;
1942 char *text_out = NULL; 1942 char *text_out = NULL;
1943 int len_in = 0; 1943 int len_in = 0;
1944 int len_out = 0; 1944 int len_out = 0;
1945 1945
1946 if ((text_out = iscsi_malloc_atomic(LOGIN_RESPONSE_TEXT_LEN)) == NULL) { 1946 if ((text_out = iscsi_malloc_atomic(LOGIN_RESPONSE_TEXT_LEN)) == NULL) {
1947 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n"); 1947 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
1948 cmd->status = -1; 1948 cmd->status = -1;
1949 goto callback; 1949 goto callback;
1950 } 1950 }
1951#define LIR_CLEANUP {if (text_in != NULL) iscsi_free_atomic(text_in); if (text_out != NULL) iscsi_free_atomic(text_out);} 1951#define LIR_CLEANUP {if (text_in != NULL) iscsi_free_atomic(text_in); if (text_out != NULL) iscsi_free_atomic(text_out);}
1952#define LIR_ERROR {cmd->status=-1; goto callback;} 1952#define LIR_ERROR {cmd->status=-1; goto callback;}
1953 if (cmd) { 1953 if (cmd) {
1954 login_cmd = (iscsi_login_cmd_args_t *) cmd->ptr; 1954 login_cmd = (iscsi_login_cmd_args_t *) cmd->ptr;
1955 } else { 1955 } else {
1956 iscsi_trace_error(__FILE__, __LINE__, "no initiator_cmd_t specified for iscsi_login_cmd_args_t??\n"); 1956 iscsi_trace_error(__FILE__, __LINE__, "no initiator_cmd_t specified for iscsi_login_cmd_args_t??\n");
1957 LIR_ERROR; 1957 LIR_ERROR;
1958 } 1958 }
1959 1959
1960 /* Read login response */ 1960 /* Read login response */
1961 1961
1962 if (iscsi_login_rsp_decap(header, &login_rsp) != 0) { 1962 if (iscsi_login_rsp_decap(header, &login_rsp) != 0) {
1963 iscsi_trace_error(__FILE__, __LINE__, "login_response_decap() failed\n"); 1963 iscsi_trace_error(__FILE__, __LINE__, "login_response_decap() failed\n");
1964 LIR_ERROR; 1964 LIR_ERROR;
1965 } 1965 }
1966 RETURN_GREATER("Length (should this be hardcoded?)", login_rsp.length, 8192, LIR_CLEANUP, -1); /* XXX - agc */ 1966 RETURN_GREATER("Length (should this be hardcoded?)", login_rsp.length, 8192, LIR_CLEANUP, -1); /* XXX - agc */
1967 1967
1968 /* Read & parse text response */ 1968 /* Read & parse text response */
1969 1969
1970 if ((len_in = login_rsp.length) != 0) { 1970 if ((len_in = login_rsp.length) != 0) {
1971 if ((text_in = iscsi_malloc_atomic(len_in + 1)) == NULL) { 1971 if ((text_in = iscsi_malloc_atomic(len_in + 1)) == NULL) {
1972 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n"); 1972 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
1973 LIR_ERROR; 1973 LIR_ERROR;
1974 } 1974 }
1975 if (iscsi_sock_msg(sess->sock, 0, len_in, text_in, 0) != len_in) { 1975 if (iscsi_sock_msg(sess->sock, 0, len_in, text_in, 0) != len_in) {
1976 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 1976 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
1977 LIR_ERROR; 1977 LIR_ERROR;
1978 } 1978 }
1979 text_in[len_in] = 0x0; 1979 text_in[len_in] = 0x0;
1980 PARAM_TEXT_PARSE(l, &sess->sess_params.cred, text_in, len_in, text_out, &len_out, LOGIN_RESPONSE_TEXT_LEN, 0, LIR_ERROR); 1980 PARAM_TEXT_PARSE(l, &sess->sess_params.cred, text_in, len_in, text_out, &len_out, LOGIN_RESPONSE_TEXT_LEN, 0, LIR_ERROR);
1981 if (login_rsp.transit) { 1981 if (login_rsp.transit) {
1982 WARN_NOT_EQUAL("len_out", len_out, 0); 1982 WARN_NOT_EQUAL("len_out", len_out, 0);
1983 } 1983 }
1984 } 1984 }
1985 /* Check args */ 1985 /* Check args */
1986 1986
1987 if (login_rsp.status_class != 0) { 1987 if (login_rsp.status_class != 0) {
1988 iscsi_trace_error(__FILE__, __LINE__, "Bad Status-Class: got %d, expected %d\n", login_rsp.status_class, 0); 1988 iscsi_trace_error(__FILE__, __LINE__, "Bad Status-Class: got %d, expected %d\n", login_rsp.status_class, 0);
1989 LIR_ERROR; 1989 LIR_ERROR;
1990 } 1990 }
1991 if (login_rsp.tag != login_cmd->tag) { 1991 if (login_rsp.tag != login_cmd->tag) {
1992 iscsi_trace_error(__FILE__, __LINE__, "Bad Tag: got %x, expected %x\n", login_rsp.tag, login_cmd->tag); 1992 iscsi_trace_error(__FILE__, __LINE__, "Bad Tag: got %x, expected %x\n", login_rsp.tag, login_cmd->tag);
1993 LIR_ERROR; 1993 LIR_ERROR;
1994 } 1994 }
1995 sess->ExpStatSN = login_rsp.StatSN + 1; 1995 sess->ExpStatSN = login_rsp.StatSN + 1;
1996 1996
1997 1997
1998 if (login_rsp.transit) { 1998 if (login_rsp.transit) {
1999 1999
2000 if (login_cmd->transit != 1) 2000 if (login_cmd->transit != 1)
2001 iscsi_trace_warning(__FILE__, __LINE__, "incoming packet transit bit not set, csg = %d, nsg = %d\n", 2001 iscsi_trace_warning(__FILE__, __LINE__, "incoming packet transit bit not set, csg = %d, nsg = %d\n",
2002 login_cmd->csg, login_cmd->nsg); 2002 login_cmd->csg, login_cmd->nsg);
2003 2003
2004 switch (login_rsp.nsg) { 2004 switch (login_rsp.nsg) {
2005 case ISCSI_LOGIN_STAGE_NEGOTIATE: 2005 case ISCSI_LOGIN_STAGE_NEGOTIATE:
2006 login_cmd->csg = login_cmd->nsg; 2006 login_cmd->csg = login_cmd->nsg;
2007 login_cmd->nsg = ISCSI_LOGIN_STAGE_FULL_FEATURE; 2007 login_cmd->nsg = ISCSI_LOGIN_STAGE_FULL_FEATURE;
2008 if (params_out(sess, text_out, &len_out, LOGIN_RESPONSE_TEXT_LEN, SESS_TYPE_NONE, !IS_SECURITY) != 0) { 2008 if (params_out(sess, text_out, &len_out, LOGIN_RESPONSE_TEXT_LEN, SESS_TYPE_NONE, !IS_SECURITY) != 0) {
2009 iscsi_trace_error(__FILE__, __LINE__, "params_out() failed\n"); 2009 iscsi_trace_error(__FILE__, __LINE__, "params_out() failed\n");
2010 LIR_ERROR; 2010 LIR_ERROR;
2011 } 2011 }
2012 login_cmd->length = len_out; 2012 login_cmd->length = len_out;
2013 (void) memcpy(login_cmd->text, text_out, len_out); 2013 (void) memcpy(login_cmd->text, text_out, len_out);
2014 break; 2014 break;
2015 2015
2016 case ISCSI_LOGIN_STAGE_FULL_FEATURE: 2016 case ISCSI_LOGIN_STAGE_FULL_FEATURE:
2017 /* Check post conditions */ 2017 /* Check post conditions */
2018 2018
2019 RETURN_EQUAL("TSIH", 0, login_rsp.tsih, LIR_ERROR, -1); 2019 RETURN_EQUAL("TSIH", 0, login_rsp.tsih, LIR_ERROR, -1);
2020 RETURN_NOT_EQUAL("ISID", (uint32_t) login_rsp.isid, (uint32_t) login_cmd->isid, LIR_ERROR, -1); 2020 RETURN_NOT_EQUAL("ISID", (uint32_t) login_rsp.isid, (uint32_t) login_cmd->isid, LIR_ERROR, -1);
2021 RETURN_NOT_EQUAL("ExpCmdSN", login_rsp.ExpCmdSN, login_cmd->CmdSN, LIR_ERROR, -1); 2021 RETURN_NOT_EQUAL("ExpCmdSN", login_rsp.ExpCmdSN, login_cmd->CmdSN, LIR_ERROR, -1);
2022 RETURN_GREATER("MaxCmdSN", login_rsp.ExpCmdSN, login_rsp.MaxCmdSN, LIR_ERROR, -1); 2022 RETURN_GREATER("MaxCmdSN", login_rsp.ExpCmdSN, login_rsp.MaxCmdSN, LIR_ERROR, -1);
2023 2023
2024 /* Set remaining session parameters */ 2024 /* Set remaining session parameters */
2025 2025
2026 sess->CmdSN = login_rsp.ExpCmdSN; 2026 sess->CmdSN = login_rsp.ExpCmdSN;
2027 sess->MaxCmdSN = login_rsp.MaxCmdSN; 2027 sess->MaxCmdSN = login_rsp.MaxCmdSN;
2028 sess->tsih = login_rsp.tsih; 2028 sess->tsih = login_rsp.tsih;
2029 sess->isid = login_rsp.isid; 2029 sess->isid = login_rsp.isid;
2030 2030
2031 if (param_equiv(sess->params, "SessionType", "Normal")) { 2031 if (param_equiv(sess->params, "SessionType", "Normal")) {
2032 sess->state = INITIATOR_SESSION_STATE_LOGGED_IN_NORMAL; 2032 sess->state = INITIATOR_SESSION_STATE_LOGGED_IN_NORMAL;
2033 } else if (param_equiv(sess->params, "SessionType", "Discovery")) { 2033 } else if (param_equiv(sess->params, "SessionType", "Discovery")) {
2034 sess->state = INITIATOR_SESSION_STATE_LOGGED_IN_DISCOVERY; 2034 sess->state = INITIATOR_SESSION_STATE_LOGGED_IN_DISCOVERY;
2035 } else { 2035 } else {
2036 iscsi_trace_error(__FILE__, __LINE__, "Unknown SessionType \"%s\"\n", param_val(sess->params, "SessionType")); 2036 iscsi_trace_error(__FILE__, __LINE__, "Unknown SessionType \"%s\"\n", param_val(sess->params, "SessionType"));
2037 LIR_ERROR; 2037 LIR_ERROR;
2038 } 2038 }
2039 2039
2040 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "*********************************************\n"); 2040 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "*********************************************\n");
2041 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* LOGIN SUCCESSFUL *\n"); 2041 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* LOGIN SUCCESSFUL *\n");
2042 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* %20s:%20u *\n", "CID", sess->cid); 2042 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* %20s:%20u *\n", "CID", sess->cid);
2043 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* %20s:%20llu *\n", "ISID", sess->isid); 2043 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* %20s:%20llu *\n", "ISID", sess->isid);
2044 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* %20s:%20u *\n", "TSIH", sess->tsih); 2044 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* %20s:%20u *\n", "TSIH", sess->tsih);
2045 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* %20s:%20u *\n", "CmdSN", sess->CmdSN); 2045 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* %20s:%20u *\n", "CmdSN", sess->CmdSN);
2046 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* %20s:%20u *\n", "MaxCmdSN", sess->MaxCmdSN); 2046 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* %20s:%20u *\n", "MaxCmdSN", sess->MaxCmdSN);
2047 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* %20s:%20u *\n", "ExpStatSN", sess->ExpStatSN); 2047 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* %20s:%20u *\n", "ExpStatSN", sess->ExpStatSN);
2048 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "*********************************************\n"); 2048 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "*********************************************\n");
2049 break; 2049 break;
2050 default: 2050 default:
2051 LIR_ERROR; 2051 LIR_ERROR;
2052 } 2052 }
2053 } else { 2053 } else {
2054 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "received partial login response\n"); 2054 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "received partial login response\n");
2055 2055
2056 /* Copy response text into login_cmd->text and update the */ 2056 /* Copy response text into login_cmd->text and update the */
2057 /* length login_cmd->length. This will be sent out on the */ 2057 /* length login_cmd->length. This will be sent out on the */
2058 /* next login command. */ 2058 /* next login command. */
2059 2059
2060 if (len_out) { 2060 if (len_out) {
2061 PARAM_TEXT_PARSE(l, &sess->sess_params.cred, text_out, len_out, NULL, NULL, 0, 1, LIR_ERROR); 2061 PARAM_TEXT_PARSE(l, &sess->sess_params.cred, text_out, len_out, NULL, NULL, 0, 1, LIR_ERROR);
2062 iscsi_trace(TRACE_ISCSI_PARAM, __FILE__, __LINE__, "need to send %d bytes response back to target\n", len_out); 2062 iscsi_trace(TRACE_ISCSI_PARAM, __FILE__, __LINE__, "need to send %d bytes response back to target\n", len_out);
2063 2063
2064 login_cmd->length = len_out; 2064 login_cmd->length = len_out;
2065 memcpy(login_cmd->text, text_out, len_out); 2065 memcpy(login_cmd->text, text_out, len_out);
2066 if (strncmp(text_out, "CHAP_N=", strlen("CHAP_N=")) == 0) { 2066 if (strncmp(text_out, "CHAP_N=", strlen("CHAP_N=")) == 0) {
2067 login_cmd->nsg = ISCSI_LOGIN_STAGE_NEGOTIATE; 2067 login_cmd->nsg = ISCSI_LOGIN_STAGE_NEGOTIATE;
2068 login_cmd->transit = 1; 2068 login_cmd->transit = 1;
2069 } 2069 }
2070 } else { 2070 } else {
2071 login_cmd->length = 0; 2071 login_cmd->length = 0;
2072 } 2072 }
2073 } 2073 }
2074 2074
2075 /* Callback */ 2075 /* Callback */
2076 2076
2077callback: 2077callback:
2078 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "iscsi_login_cmd_args_t done (cmd status %d, iscsi status %d)\n", 2078 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "iscsi_login_cmd_args_t done (cmd status %d, iscsi status %d)\n",
2079 cmd->status, login_rsp.status_class); 2079 cmd->status, login_rsp.status_class);
2080 if ((*cmd->callback)(cmd) != 0) { 2080 if ((*cmd->callback)(cmd) != 0) {
2081 iscsi_trace_error(__FILE__, __LINE__, "callback() failed\n"); 2081 iscsi_trace_error(__FILE__, __LINE__, "callback() failed\n");
2082 LIR_CLEANUP; 2082 LIR_CLEANUP;
2083 return -1; 2083 return -1;
2084 } 2084 }
2085 LIR_CLEANUP; 2085 LIR_CLEANUP;
2086 return 0; 2086 return 0;
2087} 2087}
2088 2088
2089static int  2089static int
2090logout_command_i(initiator_cmd_t * cmd) 2090logout_command_i(initiator_cmd_t * cmd)
2091{ 2091{
2092 iscsi_logout_cmd_args_t *logout_cmd = (iscsi_logout_cmd_args_t *) cmd->ptr; 2092 iscsi_logout_cmd_args_t *logout_cmd = (iscsi_logout_cmd_args_t *) cmd->ptr;
2093 initiator_session_t *sess = g_target[cmd->isid].sess; 2093 initiator_session_t *sess = g_target[cmd->isid].sess;
2094 uint8_t header[ISCSI_HEADER_LEN]; 2094 uint8_t header[ISCSI_HEADER_LEN];
2095 2095
2096 /* 2096 /*
2097 * Insert cmd into the hash table, keyed by the tag. The Rx thread 2097 * Insert cmd into the hash table, keyed by the tag. The Rx thread
2098 * will 2098 * will
2099 */ 2099 */
2100 /* retreive the cmd ptr using the tag from the response PDU. */ 2100 /* retreive the cmd ptr using the tag from the response PDU. */
2101 2101
2102 if (hash_insert(&g_tag_hash, cmd, logout_cmd->tag) != 0) { 2102 if (hash_insert(&g_tag_hash, cmd, logout_cmd->tag) != 0) {
2103 iscsi_trace_error(__FILE__, __LINE__, "hash_insert() failed\n"); 2103 iscsi_trace_error(__FILE__, __LINE__, "hash_insert() failed\n");
2104 return -1; 2104 return -1;
2105 } 2105 }
2106 /* Send logout command PDU */ 2106 /* Send logout command PDU */
2107 2107
2108 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending logout command\n"); 2108 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending logout command\n");
2109 if (iscsi_logout_cmd_encap(header, logout_cmd) != 0) { 2109 if (iscsi_logout_cmd_encap(header, logout_cmd) != 0) {
2110 iscsi_trace_error(__FILE__, __LINE__, "iscsi_logout_cmd_encap() failed\n"); 2110 iscsi_trace_error(__FILE__, __LINE__, "iscsi_logout_cmd_encap() failed\n");
2111 return -1; 2111 return -1;
2112 } 2112 }
2113 if (iscsi_sock_msg(sess->sock, 1, ISCSI_HEADER_LEN, header, 0) != ISCSI_HEADER_LEN) { 2113 if (iscsi_sock_msg(sess->sock, 1, ISCSI_HEADER_LEN, header, 0) != ISCSI_HEADER_LEN) {
2114 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed.\n"); 2114 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed.\n");
2115 return -1; 2115 return -1;
2116 } 2116 }
2117 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "logout command sent ok\n"); 2117 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "logout command sent ok\n");
2118 2118
2119 return 0; 2119 return 0;
2120} 2120}
2121 2121
2122 2122
2123static int  2123static int
2124logout_response_i(initiator_session_t * sess, initiator_cmd_t * cmd, uint8_t *header) 2124logout_response_i(initiator_session_t * sess, initiator_cmd_t * cmd, uint8_t *header)
2125{ 2125{
2126 iscsi_logout_cmd_args_t *logout_cmd; 2126 iscsi_logout_cmd_args_t *logout_cmd;
2127 iscsi_logout_rsp_args_t logout_rsp; 2127 iscsi_logout_rsp_args_t logout_rsp;
2128 2128
2129#define LOR_ERROR {cmd->status=-1; goto callback;} 2129#define LOR_ERROR {cmd->status=-1; goto callback;}
2130 if (cmd) { 2130 if (cmd) {
2131 if (cmd->ptr) { 2131 if (cmd->ptr) {
2132 logout_cmd = (iscsi_logout_cmd_args_t *) cmd->ptr; 2132 logout_cmd = (iscsi_logout_cmd_args_t *) cmd->ptr;
2133 } else { 2133 } else {
2134 iscsi_trace_error(__FILE__, __LINE__, "no iscsi_logout_cmd_args_t specified for initiator_cmd_t??\n"); 2134 iscsi_trace_error(__FILE__, __LINE__, "no iscsi_logout_cmd_args_t specified for initiator_cmd_t??\n");
2135 LOR_ERROR; 2135 LOR_ERROR;
2136 } 2136 }
2137 } else { 2137 } else {
2138 iscsi_trace_error(__FILE__, __LINE__, "no initiator_cmd_t specified for iscsi_logout_cmd_args_t??\n"); 2138 iscsi_trace_error(__FILE__, __LINE__, "no initiator_cmd_t specified for iscsi_logout_cmd_args_t??\n");
2139 return -1; 2139 return -1;
2140 } 2140 }
2141 if (iscsi_logout_rsp_decap(header, &logout_rsp) != 0) { 2141 if (iscsi_logout_rsp_decap(header, &logout_rsp) != 0) {
2142 iscsi_trace_error(__FILE__, __LINE__, "iscsi_logout_rsp_decap() failed\n"); 2142 iscsi_trace_error(__FILE__, __LINE__, "iscsi_logout_rsp_decap() failed\n");
2143 LOR_ERROR; 2143 LOR_ERROR;
2144 } 2144 }
2145 RETURN_NOT_EQUAL("Response", logout_rsp.response, ISCSI_LOGOUT_STATUS_SUCCESS, LOR_ERROR, -1); 2145 RETURN_NOT_EQUAL("Response", logout_rsp.response, ISCSI_LOGOUT_STATUS_SUCCESS, LOR_ERROR, -1);
2146 RETURN_NOT_EQUAL("Tag", logout_rsp.tag, logout_cmd->tag, LOR_ERROR, -1); 2146 RETURN_NOT_EQUAL("Tag", logout_rsp.tag, logout_cmd->tag, LOR_ERROR, -1);
2147 2147
2148 /* Check and update numbering */ 2148 /* Check and update numbering */
2149 2149
2150 RETURN_NOT_EQUAL("StatSN", logout_rsp.StatSN, sess->ExpStatSN, LOR_ERROR, -1); 2150 RETURN_NOT_EQUAL("StatSN", logout_rsp.StatSN, sess->ExpStatSN, LOR_ERROR, -1);
2151 sess->ExpStatSN++; 2151 sess->ExpStatSN++;
2152 2152
2153 RETURN_NOT_EQUAL("ExpCmdSN", logout_rsp.ExpCmdSN, sess->CmdSN, LOR_ERROR, -1); 2153 RETURN_NOT_EQUAL("ExpCmdSN", logout_rsp.ExpCmdSN, sess->CmdSN, LOR_ERROR, -1);
2154 sess->MaxCmdSN = logout_rsp.MaxCmdSN; 2154 sess->MaxCmdSN = logout_rsp.MaxCmdSN;
2155 2155
2156 /* Callback */ 2156 /* Callback */
2157 2157
2158 cmd->status = 0; 2158 cmd->status = 0;
2159 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "LOGOUT_CMD_T done (cmd status %d, iscsi status %d)\n", 2159 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "LOGOUT_CMD_T done (cmd status %d, iscsi status %d)\n",
2160 cmd->status, logout_rsp.response); 2160 cmd->status, logout_rsp.response);
2161callback: 2161callback:
2162 if ((*cmd->callback)(cmd) != 0) { 2162 if ((*cmd->callback)(cmd) != 0) {
2163 iscsi_trace_error(__FILE__, __LINE__, "callback() failed\n"); 2163 iscsi_trace_error(__FILE__, __LINE__, "callback() failed\n");
2164 return -1; 2164 return -1;
2165 } 2165 }
2166 2166
2167 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "*********************************************\n"); 2167 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "*********************************************\n");
2168 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* LOGOUT SUCCESSFUL *\n"); 2168 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* LOGOUT SUCCESSFUL *\n");
2169 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* %20s:%20u *\n", "CID", sess->cid); 2169 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* %20s:%20u *\n", "CID", sess->cid);
2170 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* %20s:%20llu *\n", "ISID", sess->isid); 2170 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* %20s:%20llu *\n", "ISID", sess->isid);
2171 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* %20s:%20u *\n", "TSIH", sess->tsih); 2171 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "* %20s:%20u *\n", "TSIH", sess->tsih);
2172 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "*********************************************\n"); 2172 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "*********************************************\n");
2173 2173
2174 return 0; 2174 return 0;
2175} 2175}
2176 2176
2177static int  2177static int
2178nop_out_i(initiator_cmd_t * cmd) 2178nop_out_i(initiator_cmd_t * cmd)
2179{ 2179{
2180 uint8_t header[ISCSI_HEADER_LEN]; 2180 uint8_t header[ISCSI_HEADER_LEN];
2181 iscsi_nop_out_args_t *nop_out = cmd->ptr; 2181 iscsi_nop_out_args_t *nop_out = cmd->ptr;
2182 initiator_session_t *sess = g_target[cmd->isid].sess; 2182 initiator_session_t *sess = g_target[cmd->isid].sess;
2183 int rc, length = nop_out->length; 2183 int rc, length = nop_out->length;
2184 2184
2185 if (nop_out->tag != 0xffffffff) { 2185 if (nop_out->tag != 0xffffffff) {
2186 2186
2187 /* 2187 /*
2188 * Insert cmd into the hash table, keyed by 2188 * Insert cmd into the hash table, keyed by
2189 * nop_out->tag. Upon receipt of the NOP_IN_T, the Rx 2189 * nop_out->tag. Upon receipt of the NOP_IN_T, the Rx
2190 * thread will retreive the cmd ptr using the tag from 2190 * thread will retreive the cmd ptr using the tag from
2191 * the NOP_IN_T PDU. */ 2191 * the NOP_IN_T PDU. */
2192 2192
2193 if (hash_insert(&g_tag_hash, cmd, nop_out->tag) != 0) { 2193 if (hash_insert(&g_tag_hash, cmd, nop_out->tag) != 0) {
2194 iscsi_trace_error(__FILE__, __LINE__, "hash_insert() failed\n"); 2194 iscsi_trace_error(__FILE__, __LINE__, "hash_insert() failed\n");
2195 return -1; 2195 return -1;
2196 } 2196 }
2197 } 2197 }
2198 /* Encapsulate and send NOP */ 2198 /* Encapsulate and send NOP */
2199 2199
2200 nop_out->ExpStatSN = sess->ExpStatSN; 2200 nop_out->ExpStatSN = sess->ExpStatSN;
2201 /* nop_out->CmdSN = sess->CmdSN++; */ 2201 /* nop_out->CmdSN = sess->CmdSN++; */
2202 nop_out->transfer_tag = 0xffffffff; 2202 nop_out->transfer_tag = 0xffffffff;
2203 if (iscsi_nop_out_encap(header, nop_out) != 0) { 2203 if (iscsi_nop_out_encap(header, nop_out) != 0) {
2204 iscsi_trace_error(__FILE__, __LINE__, "iscsi_nop_out_encap() failed\n"); 2204 iscsi_trace_error(__FILE__, __LINE__, "iscsi_nop_out_encap() failed\n");
2205 return -1; 2205 return -1;
2206 } 2206 }
2207 /* 2207 /*
2208 * We need to make a copy of nop_out->length and save in the 2208 * We need to make a copy of nop_out->length and save in the
2209 * variable length. Otherwise, we may get a seg fault - as if 2209 * variable length. Otherwise, we may get a seg fault - as if
2210 * this is a NOP_OUT without ping, the Tx thread will issue 2210 * this is a NOP_OUT without ping, the Tx thread will issue
2211 * the callback function immediately after we return - thereby 2211 * the callback function immediately after we return - thereby
2212 * de-allocating the NOP_OUT and initiator command structures.  2212 * de-allocating the NOP_OUT and initiator command structures.
2213 * */ 2213 * */
2214 2214
2215 if ((rc = iscsi_sock_send_header_and_data(sess->sock, header, ISCSI_HEADER_LEN, nop_out->data, 2215 if ((rc = iscsi_sock_send_header_and_data(sess->sock, header, ISCSI_HEADER_LEN, nop_out->data,
2216 length, 0)) != ISCSI_HEADER_LEN + length) { 2216 length, 0)) != ISCSI_HEADER_LEN + length) {
2217 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed: got %d expected %d\n", rc, ISCSI_HEADER_LEN + length); 2217 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed: got %d expected %d\n", rc, ISCSI_HEADER_LEN + length);
2218 return -1; 2218 return -1;
2219 } 2219 }
2220 cmd->status = 0; 2220 cmd->status = 0;
2221 return 0; 2221 return 0;
2222} 2222}
2223 2223
2224static int  2224static int
2225scsi_command_i(initiator_cmd_t * cmd) 2225scsi_command_i(initiator_cmd_t * cmd)
2226{ 2226{
2227 iscsi_scsi_cmd_args_t *scsi_cmd = (iscsi_scsi_cmd_args_t *) cmd->ptr; 2227 iscsi_scsi_cmd_args_t *scsi_cmd = (iscsi_scsi_cmd_args_t *) cmd->ptr;
2228 uint8_t header[ISCSI_HEADER_LEN]; 2228 uint8_t header[ISCSI_HEADER_LEN];
2229 uint64_t target = cmd->isid; 2229 uint64_t target = cmd->isid;
2230 initiator_session_t *sess = g_target[target].sess; 2230 initiator_session_t *sess = g_target[target].sess;
2231 iscsi_write_data_t data; 2231 iscsi_write_data_t data;
2232 struct iovec sg_singleton; 2232 struct iovec sg_singleton;
2233 struct iovec *sg, *sg_copy, *sg_copy_orig, *sg_which; 2233 struct iovec *sg, *sg_copy, *sg_copy_orig, *sg_which;
2234 int sg_len, sg_len_copy, sg_len_which; 2234 int sg_len, sg_len_copy, sg_len_which;
2235 int fragment_flag = 0; 2235 int fragment_flag = 0;
2236 2236
2237 sg = sg_copy = sg_copy_orig = sg_which = NULL; 2237 sg = sg_copy = sg_copy_orig = sg_which = NULL;
2238 sg_len = sg_len_copy = sg_len_which = 0; 2238 sg_len = sg_len_copy = sg_len_which = 0;
2239 scsi_cmd->status = 0; 2239 scsi_cmd->status = 0;
2240 2240
2241 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tx_worker[%llu]: scsi op %#x lun %llu trans_len %d length %d send_sg_len %d recv_sg_len %d\n", target, scsi_cmd->cdb[0], scsi_cmd->lun, scsi_cmd->trans_len, scsi_cmd->length, scsi_cmd->send_sg_len, scsi_cmd->recv_sg_len); 2241 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tx_worker[%llu]: scsi op %#x lun %llu trans_len %d length %d send_sg_len %d recv_sg_len %d\n", target, scsi_cmd->cdb[0], scsi_cmd->lun, scsi_cmd->trans_len, scsi_cmd->length, scsi_cmd->send_sg_len, scsi_cmd->recv_sg_len);
2242 2242
2243 RETURN_GREATER("target id", (uint32_t) target, CONFIG_INITIATOR_NUM_TARGETS - 1, NO_CLEANUP, -1); 2243 RETURN_GREATER("target id", (uint32_t) target, CONFIG_INITIATOR_NUM_TARGETS - 1, NO_CLEANUP, -1);
2244 2244
2245 /* Set and check scsi_cmd */ 2245 /* Set and check scsi_cmd */
2246 2246
2247 if (scsi_cmd->trans_len > sess->sess_params.max_burst_length) { 2247 if (scsi_cmd->trans_len > sess->sess_params.max_burst_length) {
2248 iscsi_trace_error(__FILE__, __LINE__, "scsi_cmd->trans_len (%u) > MaxBurstLength (%u)\n", 2248 iscsi_trace_error(__FILE__, __LINE__, "scsi_cmd->trans_len (%u) > MaxBurstLength (%u)\n",
2249 scsi_cmd->trans_len, sess->sess_params.max_burst_length); 2249 scsi_cmd->trans_len, sess->sess_params.max_burst_length);
2250 return -1; 2250 return -1;
2251 } 2251 }
2252 if (scsi_cmd->length > scsi_cmd->trans_len) { 2252 if (scsi_cmd->length > scsi_cmd->trans_len) {
2253 iscsi_trace_error(__FILE__, __LINE__, "scsi_cmd->length (%u) > scsi_cmd->trans_len (%u)\n", 2253 iscsi_trace_error(__FILE__, __LINE__, "scsi_cmd->length (%u) > scsi_cmd->trans_len (%u)\n",
2254 scsi_cmd->length, scsi_cmd->trans_len); 2254 scsi_cmd->length, scsi_cmd->trans_len);
2255 return -1; 2255 return -1;
2256 } 2256 }
2257 scsi_cmd->ExpStatSN = sess->ExpStatSN; 2257 scsi_cmd->ExpStatSN = sess->ExpStatSN;
2258 scsi_cmd->CmdSN = sess->CmdSN; 2258 scsi_cmd->CmdSN = sess->CmdSN;
2259 scsi_cmd->bytes_sent = scsi_cmd->bytes_recv = 0; 2259 scsi_cmd->bytes_sent = scsi_cmd->bytes_recv = 0;
2260 2260
2261 /* Always use iovec for data */ 2261 /* Always use iovec for data */
2262 2262
2263 if (scsi_cmd->output) { 2263 if (scsi_cmd->output) {
2264 if (scsi_cmd->send_sg_len) { /* Data already an iovec */ 2264 if (scsi_cmd->send_sg_len) { /* Data already an iovec */
2265 sg = (struct iovec *) scsi_cmd->send_data; 2265 sg = (struct iovec *) scsi_cmd->send_data;
2266 sg_len = scsi_cmd->send_sg_len; 2266 sg_len = scsi_cmd->send_sg_len;
2267 } else { /* Make iovec for data */ 2267 } else { /* Make iovec for data */
2268 sg_singleton.iov_base = scsi_cmd->send_data; 2268 sg_singleton.iov_base = scsi_cmd->send_data;
2269 sg_singleton.iov_len = scsi_cmd->trans_len; 2269 sg_singleton.iov_len = scsi_cmd->trans_len;
2270 sg = &sg_singleton; 2270 sg = &sg_singleton;
2271 sg_len = 1; 2271 sg_len = 1;
2272 } 2272 }
2273 } 2273 }
2274 /* 2274 /*
2275 * Insert cmd into the hash table, keyed by scsi_cmd->tag. The Rx 2275 * Insert cmd into the hash table, keyed by scsi_cmd->tag. The Rx
2276 * thread will 2276 * thread will
2277 */ 2277 */
2278 /* retreive the cmd ptr using the tag from the response PDU. */ 2278 /* retreive the cmd ptr using the tag from the response PDU. */
2279 2279
2280 if (hash_insert(&g_tag_hash, cmd, scsi_cmd->tag) != 0) { 2280 if (hash_insert(&g_tag_hash, cmd, scsi_cmd->tag) != 0) {
2281 iscsi_trace_error(__FILE__, __LINE__, "hash_insert() failed\n"); 2281 iscsi_trace_error(__FILE__, __LINE__, "hash_insert() failed\n");
2282 goto error; 2282 goto error;
2283 } 2283 }
2284 /* Send command PDU */ 2284 /* Send command PDU */
2285 2285
2286 if (scsi_cmd->output && sess->sess_params.immediate_data) { 2286 if (scsi_cmd->output && sess->sess_params.immediate_data) {
2287 if (sess->sess_params.max_data_seg_length) { 2287 if (sess->sess_params.max_data_seg_length) {
2288 scsi_cmd->length = MIN(sess->sess_params.max_data_seg_length, 2288 scsi_cmd->length = MIN(sess->sess_params.max_data_seg_length,
2289 scsi_cmd->trans_len); 2289 scsi_cmd->trans_len);
2290 } else { 2290 } else {
2291 scsi_cmd->length = scsi_cmd->trans_len; 2291 scsi_cmd->length = scsi_cmd->trans_len;
2292 } 2292 }
2293 if (scsi_cmd->length == scsi_cmd->trans_len) 2293 if (scsi_cmd->length == scsi_cmd->trans_len)
2294 scsi_cmd->final = 1; 2294 scsi_cmd->final = 1;
2295 } else { 2295 } else {
2296 scsi_cmd->length = 0; 2296 scsi_cmd->length = 0;
2297 scsi_cmd->final = 1; 2297 scsi_cmd->final = 1;
2298 } 2298 }
2299 if (iscsi_scsi_cmd_encap(header, scsi_cmd) != 0) { 2299 if (iscsi_scsi_cmd_encap(header, scsi_cmd) != 0) {
2300 iscsi_trace_error(__FILE__, __LINE__, "iscsi_scsi_cmd_encap() failed\n"); 2300 iscsi_trace_error(__FILE__, __LINE__, "iscsi_scsi_cmd_encap() failed\n");
2301 goto error; 2301 goto error;
2302 } 2302 }
2303 /* 2303 /*
2304 * If we're sending any immediate data, we need to make a new 2304 * If we're sending any immediate data, we need to make a new
2305 * iovec that contains only the immediata data (a subset of 2305 * iovec that contains only the immediata data (a subset of
2306 * the original iovec). */ 2306 * the original iovec). */
2307 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending command PDU with %u bytes immediate data\n", scsi_cmd->length); 2307 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending command PDU with %u bytes immediate data\n", scsi_cmd->length);
2308 if (scsi_cmd->length && sess->sess_params.immediate_data) { 2308 if (scsi_cmd->length && sess->sess_params.immediate_data) {
2309 if ((sg_copy = iscsi_malloc_atomic(sg_len * sizeof(struct iovec))) == NULL) { 2309 if ((sg_copy = iscsi_malloc_atomic(sg_len * sizeof(struct iovec))) == NULL) {
2310 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n"); 2310 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
2311 goto error; 2311 goto error;
2312 } 2312 }
2313 fragment_flag++; 2313 fragment_flag++;
2314 sg_copy_orig = sg_copy; 2314 sg_copy_orig = sg_copy;
2315 memcpy(sg_copy, sg, sizeof(struct iovec) * sg_len); 2315 memcpy(sg_copy, sg, sizeof(struct iovec) * sg_len);
2316 sg_len_copy = sg_len; 2316 sg_len_copy = sg_len;
2317 if (modify_iov(&sg_copy, &sg_len_copy, 0, scsi_cmd->length) != 0) { 2317 if (modify_iov(&sg_copy, &sg_len_copy, 0, scsi_cmd->length) != 0) {
2318 iscsi_trace_error(__FILE__, __LINE__, "modify_iov() failed\n"); 2318 iscsi_trace_error(__FILE__, __LINE__, "modify_iov() failed\n");
2319 goto error; 2319 goto error;
2320 } 2320 }
2321 if (scsi_cmd->ahs) { 2321 if (scsi_cmd->ahs) {
2322 if (iscsi_sock_msg(sess->sock, 1, ISCSI_HEADER_LEN, header, 0) != ISCSI_HEADER_LEN) { 2322 if (iscsi_sock_msg(sess->sock, 1, ISCSI_HEADER_LEN, header, 0) != ISCSI_HEADER_LEN) {
2323 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 2323 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
2324 goto error; 2324 goto error;
2325 } 2325 }
2326 if (iscsi_sock_msg(sess->sock, 1, scsi_cmd->ahs_len, scsi_cmd->ahs, 0) != scsi_cmd->ahs_len) { 2326 if (iscsi_sock_msg(sess->sock, 1, scsi_cmd->ahs_len, scsi_cmd->ahs, 0) != scsi_cmd->ahs_len) {
2327 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 2327 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
2328 goto error; 2328 goto error;
2329 } 2329 }
2330 if (iscsi_sock_msg(sess->sock, 1, scsi_cmd->length, sg_copy, sg_len_copy) != scsi_cmd->length) { 2330 if ((unsigned)iscsi_sock_msg(sess->sock, 1, scsi_cmd->length, sg_copy, sg_len_copy) != scsi_cmd->length) {
2331 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 2331 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
2332 goto error; 2332 goto error;
2333 } 2333 }
2334 } else { 2334 } else {
2335 if (iscsi_sock_send_header_and_data(sess->sock, header, ISCSI_HEADER_LEN, sg_copy, scsi_cmd->length, sg_len_copy) 2335 if ((unsigned)iscsi_sock_send_header_and_data(sess->sock, header, ISCSI_HEADER_LEN, sg_copy, scsi_cmd->length, sg_len_copy)
2336 != ISCSI_HEADER_LEN + scsi_cmd->length) { 2336 != ISCSI_HEADER_LEN + scsi_cmd->length) {
2337 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed\n"); 2337 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed\n");
2338 goto error; 2338 goto error;
2339 } 2339 }
2340 } 2340 }
2341 scsi_cmd->bytes_sent += scsi_cmd->length; 2341 scsi_cmd->bytes_sent += scsi_cmd->length;
2342 } else { 2342 } else {
2343 if (iscsi_sock_msg(sess->sock, 1, ISCSI_HEADER_LEN, header, 0) != ISCSI_HEADER_LEN) { 2343 if (iscsi_sock_msg(sess->sock, 1, ISCSI_HEADER_LEN, header, 0) != ISCSI_HEADER_LEN) {
2344 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 2344 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
2345 goto error; 2345 goto error;
2346 } 2346 }
2347 if (scsi_cmd->ahs_len) { 2347 if (scsi_cmd->ahs_len) {
2348 if (iscsi_sock_msg(sess->sock, 1, scsi_cmd->ahs_len, scsi_cmd->ahs, 0) != scsi_cmd->ahs_len) { 2348 if (iscsi_sock_msg(sess->sock, 1, scsi_cmd->ahs_len, scsi_cmd->ahs, 0) != scsi_cmd->ahs_len) {
2349 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 2349 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
2350 goto error; 2350 goto error;
2351 } 2351 }
2352 } 2352 }
2353 } 2353 }
2354 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "command PDU sent with %u bytes immediate data (%u bytes AHS)\n", scsi_cmd->length, scsi_cmd->ahs_len); 2354 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "command PDU sent with %u bytes immediate data (%u bytes AHS)\n", scsi_cmd->length, scsi_cmd->ahs_len);
2355 2355
2356 /* 2356 /*
2357 * Send data PDUS if 1) we're not in R2T mode and 2) we 2357 * Send data PDUS if 1) we're not in R2T mode and 2) we
2358 * haven't sent everything as immediate data and 3) we have 2358 * haven't sent everything as immediate data and 3) we have
2359 * not reached the first burst when sending immediate data 2359 * not reached the first burst when sending immediate data
2360 */ 2360 */
2361 if (scsi_cmd->output 2361 if (scsi_cmd->output
2362 && (!sess->sess_params.initial_r2t) 2362 && (!sess->sess_params.initial_r2t)
2363 && (scsi_cmd->bytes_sent != scsi_cmd->trans_len) 2363 && (scsi_cmd->bytes_sent != scsi_cmd->trans_len)
2364 && ((!sess->sess_params.first_burst_length) 2364 && ((!sess->sess_params.first_burst_length)
2365 || (scsi_cmd->bytes_sent < sess->sess_params.first_burst_length))) { 2365 || (scsi_cmd->bytes_sent < sess->sess_params.first_burst_length))) {
2366 2366
2367 uint32_t DataSN = 0; 2367 uint32_t DataSN = 0;
2368 2368
2369 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "preparing to send %d bytes write data\n", scsi_cmd->trans_len - scsi_cmd->bytes_sent); 2369 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "preparing to send %d bytes write data\n", scsi_cmd->trans_len - scsi_cmd->bytes_sent);
2370 2370
2371 do { 2371 do {
2372 (void) memset(&data, 0x0, sizeof(data)); 2372 (void) memset(&data, 0x0, sizeof(data));
2373 2373
2374 /* 2374 /*
2375 * Take into account that MaxRecvPDULength and 2375 * Take into account that MaxRecvPDULength and
2376 * FirstBurstLength could both be "0" (no limit) 2376 * FirstBurstLength could both be "0" (no limit)
2377 */ 2377 */
2378 if (sess->sess_params.max_data_seg_length) { 2378 if (sess->sess_params.max_data_seg_length) {
2379 if (sess->sess_params.first_burst_length) { 2379 if (sess->sess_params.first_burst_length) {
2380 data.length = MIN_3( 2380 data.length = MIN_3(
2381 sess->sess_params.first_burst_length - scsi_cmd->bytes_sent, 2381 sess->sess_params.first_burst_length - scsi_cmd->bytes_sent,
2382 sess->sess_params.max_data_seg_length, 2382 sess->sess_params.max_data_seg_length,
2383 scsi_cmd->trans_len - scsi_cmd->bytes_sent); 2383 scsi_cmd->trans_len - scsi_cmd->bytes_sent);
2384 } else { 2384 } else {
2385 data.length = MIN( 2385 data.length = MIN(
2386 sess->sess_params.max_data_seg_length, 2386 sess->sess_params.max_data_seg_length,
2387 scsi_cmd->trans_len - scsi_cmd->bytes_sent); 2387 scsi_cmd->trans_len - scsi_cmd->bytes_sent);
2388 } 2388 }
2389 } else { 2389 } else {
2390 if (sess->sess_params.first_burst_length) { 2390 if (sess->sess_params.first_burst_length) {
2391 data.length = MIN( 2391 data.length = MIN(
2392 sess->sess_params.first_burst_length - scsi_cmd->bytes_sent, 2392 sess->sess_params.first_burst_length - scsi_cmd->bytes_sent,
2393 scsi_cmd->trans_len - scsi_cmd->bytes_sent); 2393 scsi_cmd->trans_len - scsi_cmd->bytes_sent);
2394 } else { 2394 } else {
2395 data.length = scsi_cmd->trans_len - scsi_cmd->bytes_sent; 2395 data.length = scsi_cmd->trans_len - scsi_cmd->bytes_sent;
2396 } 2396 }
2397 } 2397 }
2398#define FRAG_CLEANUP {if (fragment_flag) iscsi_free_atomic(sg_copy);} 2398#define FRAG_CLEANUP {if (fragment_flag) iscsi_free_atomic(sg_copy);}
2399 RETURN_EQUAL("data.length", data.length, 0, FRAG_CLEANUP, -1); 2399 RETURN_EQUAL("data.length", data.length, 0, FRAG_CLEANUP, -1);
2400 2400
2401 if (scsi_cmd->bytes_sent + data.length == scsi_cmd->trans_len) 2401 if (scsi_cmd->bytes_sent + data.length == scsi_cmd->trans_len)
2402 data.final = 1; 2402 data.final = 1;
2403 data.tag = scsi_cmd->tag; 2403 data.tag = scsi_cmd->tag;
2404 data.transfer_tag = 0xffffffff; 2404 data.transfer_tag = 0xffffffff;
2405 data.ExpStatSN = sess->ExpStatSN; 2405 data.ExpStatSN = sess->ExpStatSN;
2406 data.DataSN = DataSN++; 2406 data.DataSN = DataSN++;
2407 data.offset = scsi_cmd->bytes_sent; 2407 data.offset = scsi_cmd->bytes_sent;
2408 2408
2409 if (iscsi_write_data_encap(header, &data) != 0) { 2409 if (iscsi_write_data_encap(header, &data) != 0) {
2410 iscsi_trace_error(__FILE__, __LINE__, "iscsi_write_data_encap() failed\n"); 2410 iscsi_trace_error(__FILE__, __LINE__, "iscsi_write_data_encap() failed\n");
2411 goto error; 2411 goto error;
2412 } 2412 }
2413 if (data.length != scsi_cmd->trans_len) { 2413 if (data.length != scsi_cmd->trans_len) {
2414 2414
2415 /* 2415 /*
2416 * Make copy of iovec and modify with offset 2416 * Make copy of iovec and modify with offset
2417 * and length 2417 * and length
2418 */ 2418 */
2419 2419
2420 if (!fragment_flag) { 2420 if (!fragment_flag) {
2421 if ((sg_copy = iscsi_malloc_atomic(sg_len * sizeof(struct iovec))) == NULL) { 2421 if ((sg_copy = iscsi_malloc_atomic(sg_len * sizeof(struct iovec))) == NULL) {
2422 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n"); 2422 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
2423 goto error; 2423 goto error;
2424 } 2424 }
2425 sg_copy_orig = sg_copy; 2425 sg_copy_orig = sg_copy;
2426 fragment_flag++; 2426 fragment_flag++;
2427 } 2427 }
2428 sg_copy = sg_copy_orig; 2428 sg_copy = sg_copy_orig;
2429 memcpy(sg_copy, sg, sizeof(struct iovec) * sg_len); 2429 memcpy(sg_copy, sg, sizeof(struct iovec) * sg_len);
2430 sg_len_copy = sg_len; 2430 sg_len_copy = sg_len;
2431 if (modify_iov(&sg_copy, &sg_len_copy, scsi_cmd->bytes_sent, data.length) != 0) { 2431 if (modify_iov(&sg_copy, &sg_len_copy, scsi_cmd->bytes_sent, data.length) != 0) {
2432 iscsi_trace_error(__FILE__, __LINE__, "modify_iov() failed\n"); 2432 iscsi_trace_error(__FILE__, __LINE__, "modify_iov() failed\n");
2433 goto error; 2433 goto error;
2434 } 2434 }
2435 sg_which = sg_copy; 2435 sg_which = sg_copy;
2436 sg_len_which = sg_len_copy; 2436 sg_len_which = sg_len_copy;
2437 2437
2438 } else { 2438 } else {
2439 2439
2440 /* 2440 /*
2441 * Data was not fragmented; use the original 2441 * Data was not fragmented; use the original
2442 * iovec. 2442 * iovec.
2443 */ 2443 */
2444 2444
2445 sg_which = sg; 2445 sg_which = sg;
2446 sg_len_which = sg_len; 2446 sg_len_which = sg_len;
2447 } 2447 }
2448 2448
2449 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending write data PDU (offset %u, len %u, sg_len %u)\n", 2449 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending write data PDU (offset %u, len %u, sg_len %u)\n",
2450 data.offset, data.length, sg_len_which); 2450 data.offset, data.length, sg_len_which);
2451 2451
2452 if (iscsi_sock_send_header_and_data(sess->sock, header, ISCSI_HEADER_LEN, sg_which, data.length, sg_len_which) 2452 if ((unsigned)iscsi_sock_send_header_and_data(sess->sock, header, ISCSI_HEADER_LEN, sg_which, data.length, sg_len_which)
2453 != ISCSI_HEADER_LEN + data.length) { 2453 != ISCSI_HEADER_LEN + data.length) {
2454 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed\n"); 2454 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed\n");
2455 goto error; 2455 goto error;
2456 } 2456 }
2457 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sent write data PDU (offset %u, len %u)\n", data.offset, data.length); 2457 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sent write data PDU (offset %u, len %u)\n", data.offset, data.length);
2458 scsi_cmd->bytes_sent += data.length; 2458 scsi_cmd->bytes_sent += data.length;
2459 } while ((scsi_cmd->bytes_sent < scsi_cmd->trans_len) 2459 } while ((scsi_cmd->bytes_sent < scsi_cmd->trans_len)
2460 && ((scsi_cmd->bytes_sent < sess->sess_params.first_burst_length) 2460 && ((scsi_cmd->bytes_sent < sess->sess_params.first_burst_length)
2461 || (!sess->sess_params.first_burst_length))); 2461 || (!sess->sess_params.first_burst_length)));
2462 if (scsi_cmd->trans_len - scsi_cmd->bytes_sent) { 2462 if (scsi_cmd->trans_len - scsi_cmd->bytes_sent) {
2463 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "REACHED FIRST BURST\n"); 2463 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "REACHED FIRST BURST\n");
2464 } 2464 }
2465 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully sent %u of %u bytes write data\n", scsi_cmd->bytes_sent, scsi_cmd->trans_len); 2465 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully sent %u of %u bytes write data\n", scsi_cmd->bytes_sent, scsi_cmd->trans_len);
2466 } 2466 }
2467 if (scsi_cmd->output && (scsi_cmd->trans_len - scsi_cmd->bytes_sent)) { 2467 if (scsi_cmd->output && (scsi_cmd->trans_len - scsi_cmd->bytes_sent)) {
2468 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "expecting R2T for remaining %u bytes write data\n", scsi_cmd->trans_len - scsi_cmd->bytes_sent); 2468 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "expecting R2T for remaining %u bytes write data\n", scsi_cmd->trans_len - scsi_cmd->bytes_sent);
2469 } 2469 }
2470 if (fragment_flag) 2470 if (fragment_flag)
2471 iscsi_free_atomic(sg_copy_orig); 2471 iscsi_free_atomic(sg_copy_orig);
2472 sess->CmdSN++; 2472 sess->CmdSN++;
2473 2473
2474 return 0; 2474 return 0;
2475 2475
2476error: 2476error:
2477 if (fragment_flag) 2477 if (fragment_flag)
2478 iscsi_free_atomic(sg_copy); 2478 iscsi_free_atomic(sg_copy);
2479 return -1; 2479 return -1;
2480} 2480}
2481 2481
2482static int  2482static int
2483reject_i(initiator_session_t * sess, uint8_t *header) 2483reject_i(initiator_session_t * sess, uint8_t *header)
2484{ 2484{
2485 initiator_cmd_t *cmd = NULL; 2485 initiator_cmd_t *cmd = NULL;
2486 iscsi_reject_t reject; 2486 iscsi_reject_t reject;
2487 uint8_t bad_header[ISCSI_HEADER_LEN]; 2487 uint8_t bad_header[ISCSI_HEADER_LEN];
2488 uint32_t tag; 2488 uint32_t tag;
2489 2489
2490 /* Get & check args */ 2490 /* Get & check args */
2491 2491
2492 if (iscsi_reject_decap(header, &reject) != 0) { 2492 if (iscsi_reject_decap(header, &reject) != 0) {
2493 iscsi_trace_error(__FILE__, __LINE__, "iscsi_reject_decap() failed\n"); 2493 iscsi_trace_error(__FILE__, __LINE__, "iscsi_reject_decap() failed\n");
2494 return -1; 2494 return -1;
2495 } 2495 }
2496 RETURN_NOT_EQUAL("reject.length", reject.length, ISCSI_HEADER_LEN, NO_CLEANUP, -1); 2496 RETURN_NOT_EQUAL("reject.length", reject.length, ISCSI_HEADER_LEN, NO_CLEANUP, -1);
2497 2497
2498 /* Read bad header, extract tag, and get cmd from hash table */ 2498 /* Read bad header, extract tag, and get cmd from hash table */
2499 2499
2500 if (iscsi_sock_msg(sess->sock, 0, ISCSI_HEADER_LEN, bad_header, 0) != ISCSI_HEADER_LEN) { 2500 if (iscsi_sock_msg(sess->sock, 0, ISCSI_HEADER_LEN, bad_header, 0) != ISCSI_HEADER_LEN) {
2501 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 2501 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
2502 return -1; 2502 return -1;
2503 } 2503 }
2504 tag = ISCSI_NTOHL(*((uint32_t *) (bad_header + 16))); 2504 tag = ISCSI_NTOHL(*((uint32_t *) (bad_header + 16)));
2505 iscsi_trace_error(__FILE__, __LINE__, "REJECT PDU: tag %#x (reason %#x)\n", tag, reject.reason); 2505 iscsi_trace_error(__FILE__, __LINE__, "REJECT PDU: tag %#x (reason %#x)\n", tag, reject.reason);
2506 if (tag != 0xffffffff) { 2506 if (tag != 0xffffffff) {
2507 if ((cmd = hash_remove(&g_tag_hash, tag)) == NULL) { 2507 if ((cmd = hash_remove(&g_tag_hash, tag)) == NULL) {
2508 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "no cmd ptr associated with tag %#x\n", tag); 2508 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "no cmd ptr associated with tag %#x\n", tag);
2509 } else { 2509 } else {
2510 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "cmd %p associated with tag %#x\n", cmd, tag); 2510 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "cmd %p associated with tag %#x\n", cmd, tag);
2511 ISCSI_LOCK(&sess->rx_worker.work_mutex, return -1); 2511 ISCSI_LOCK(&sess->rx_worker.work_mutex, return -1);
2512 if (!cmd->tx_done) 2512 if (!cmd->tx_done)
2513 ISCSI_WAIT(&sess->rx_worker.work_cond, &sess->rx_worker.work_mutex, return -1); 2513 ISCSI_WAIT(&sess->rx_worker.work_cond, &sess->rx_worker.work_mutex, return -1);
2514 ISCSI_UNLOCK(&sess->rx_worker.work_mutex, return -1); 2514 ISCSI_UNLOCK(&sess->rx_worker.work_mutex, return -1);
2515 } 2515 }
2516 } else { 2516 } else {
2517 iscsi_trace_error(__FILE__, __LINE__, "no command associated with tag %#x\n", tag); 2517 iscsi_trace_error(__FILE__, __LINE__, "no command associated with tag %#x\n", tag);
2518 } 2518 }
2519 2519
2520 /* Execute callback to complete initiator_cmd_t */ 2520 /* Execute callback to complete initiator_cmd_t */
2521 2521
2522 if (cmd) { 2522 if (cmd) {
2523 cmd->status = -1; 2523 cmd->status = -1;
2524 if (cmd->callback) { 2524 if (cmd->callback) {
2525 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "issuing callback for cmd associated with tag %#x\n", tag); 2525 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "issuing callback for cmd associated with tag %#x\n", tag);
2526 if ((*cmd->callback)(cmd) != 0) { 2526 if ((*cmd->callback)(cmd) != 0) {
2527 iscsi_trace_error(__FILE__, __LINE__, "callback() failed\n"); 2527 iscsi_trace_error(__FILE__, __LINE__, "callback() failed\n");
2528 return -1; 2528 return -1;
2529 } 2529 }
2530 } else { 2530 } else {
2531 iscsi_trace_error(__FILE__, __LINE__, "no callback associated with tag %#x\n", tag); 2531 iscsi_trace_error(__FILE__, __LINE__, "no callback associated with tag %#x\n", tag);
2532 } 2532 }
2533 } 2533 }
2534 return 0; 2534 return 0;
2535} 2535}
2536 2536
2537static int  2537static int
2538async_msg_i(initiator_session_t * sess, uint8_t *header) 2538async_msg_i(initiator_session_t * sess, uint8_t *header)
2539{ 2539{
2540 iscsi_async_msg_t msg; 2540 iscsi_async_msg_t msg;
2541 2541
2542 /* Get & check args */ 2542 /* Get & check args */
2543 if (iscsi_amsg_decap(header, &msg) != 0) { 2543 if (iscsi_amsg_decap(header, &msg) != 0) {
2544 iscsi_trace_error(__FILE__, __LINE__, "iscsi_amsg_decap() failed\n"); 2544 iscsi_trace_error(__FILE__, __LINE__, "iscsi_amsg_decap() failed\n");
2545 return -1; 2545 return -1;
2546 } 2546 }
2547 sess->CmdSN = msg.ExpCmdSN; 2547 sess->CmdSN = msg.ExpCmdSN;
2548 sess->MaxCmdSN = msg.MaxCmdSN; 2548 sess->MaxCmdSN = msg.MaxCmdSN;
2549 sess->ExpStatSN = msg.StatSN + 1; 2549 sess->ExpStatSN = msg.StatSN + 1;
2550 2550
2551 /* Read Sense Data */ 2551 /* Read Sense Data */
2552 if (msg.length) { 2552 if (msg.length) {
2553 uint8_t *sense_data = NULL; 2553 uint8_t *sense_data = NULL;
2554 if ((sense_data = iscsi_malloc(msg.length)) == NULL) { 2554 if ((sense_data = iscsi_malloc(msg.length)) == NULL) {
2555 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n"); 2555 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n");
2556 return -1; 2556 return -1;
2557 } 2557 }
2558 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "reading %d bytes sense data \n", msg.length); 2558 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "reading %d bytes sense data \n", msg.length);
2559 if (iscsi_sock_msg(sess->sock, 0, msg.length, sense_data, 0) != msg.length) { 2559 if ((unsigned)iscsi_sock_msg(sess->sock, 0, msg.length, sense_data, 0) != msg.length) {
2560 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 2560 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
2561 if (sense_data != NULL) 2561 if (sense_data != NULL)
2562 iscsi_free(sense_data); 2562 iscsi_free(sense_data);
2563 return -1; 2563 return -1;
2564 } 2564 }
2565 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "read %d bytes sense data ok (currently discarding)\n", msg.length); 2565 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "read %d bytes sense data ok (currently discarding)\n", msg.length);
2566 if (sense_data != NULL) 2566 if (sense_data != NULL)
2567 iscsi_free(sense_data); 2567 iscsi_free(sense_data);
2568 } else { 2568 } else {
2569 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "no sense data available\n"); 2569 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "no sense data available\n");
2570 } 2570 }
2571 2571
2572 switch (msg.AsyncEvent) { 2572 switch (msg.AsyncEvent) {
2573 case 0: 2573 case 0:
2574 /* Ignore SCSI asyn messages for now */ 2574 /* Ignore SCSI asyn messages for now */
2575 break; 2575 break;
2576 case 1: 2576 case 1:
2577 case 4: 2577 case 4:
2578 /* Ignore Parameter Negotiation. Send Logout */ 2578 /* Ignore Parameter Negotiation. Send Logout */
2579 logout_phase_i(sess); 2579 logout_phase_i(sess);
2580 /* FALLTHROUGH */ 2580 /* FALLTHROUGH */
2581 case 2: 2581 case 2:
2582 case 3: 2582 case 3:
2583 if (iscsi_sock_shutdown(sess->sock, 1) != 0) { 2583 if (iscsi_sock_shutdown(sess->sock, 1) != 0) {
2584 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_shutdown() failed\n"); 2584 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_shutdown() failed\n");
2585 } 2585 }
2586 return -1; 2586 return -1;
2587 case 255: 2587 case 255:
2588 break; 2588 break;
2589 default: 2589 default:
2590 break; 2590 break;
2591 } 2591 }
2592 2592
2593 return 0; 2593 return 0;
2594} 2594}
2595 2595
2596static int  2596static int
2597nop_in_i(initiator_session_t * sess, initiator_cmd_t * cmd, uint8_t *header) 2597nop_in_i(initiator_session_t * sess, initiator_cmd_t * cmd, uint8_t *header)
2598{ 2598{
2599 iscsi_nop_out_args_t *nop_out = NULL; 2599 iscsi_nop_out_args_t *nop_out = NULL;
2600 iscsi_nop_in_args_t nop_in; 2600 iscsi_nop_in_args_t nop_in;
2601 uint8_t *ping_data = NULL; 2601 uint8_t *ping_data = NULL;
2602 int i; 2602 unsigned i;
2603 2603
2604 if (cmd) { 2604 if (cmd) {
2605 nop_out = (iscsi_nop_out_args_t *) cmd->ptr; 2605 nop_out = (iscsi_nop_out_args_t *) cmd->ptr;
2606 } else { 2606 } else {
2607 iscsi_trace_error(__FILE__, __LINE__, "no initiator_cmd_t associated with this NOP_IN\n"); 2607 iscsi_trace_error(__FILE__, __LINE__, "no initiator_cmd_t associated with this NOP_IN\n");
2608 } 2608 }
2609 if (iscsi_nop_in_decap(header, &nop_in) != 0) { 2609 if (iscsi_nop_in_decap(header, &nop_in) != 0) {
2610 iscsi_trace_error(__FILE__, __LINE__, "iscsi_nop_in() failed\n"); 2610 iscsi_trace_error(__FILE__, __LINE__, "iscsi_nop_in() failed\n");
2611 return -1; 2611 return -1;
2612 } 2612 }
2613 if (cmd) 2613 if (cmd)
2614 RETURN_NOT_EQUAL("nop_in.length", nop_in.length, nop_out->length, NO_CLEANUP, -1); 2614 RETURN_NOT_EQUAL("nop_in.length", nop_in.length, nop_out->length, NO_CLEANUP, -1);
2615 if (nop_in.length) { 2615 if (nop_in.length) {
2616 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "reading %d bytes ping data\n", nop_in.length); 2616 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "reading %d bytes ping data\n", nop_in.length);
2617 if ((ping_data = iscsi_malloc_atomic(nop_in.length)) == NULL) { 2617 if ((ping_data = iscsi_malloc_atomic(nop_in.length)) == NULL) {
2618 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n"); 2618 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
2619 return -1; 2619 return -1;
2620 } 2620 }
2621#define NOI_CLEANUP {if (ping_data) iscsi_free_atomic(ping_data);} 2621#define NOI_CLEANUP {if (ping_data) iscsi_free_atomic(ping_data);}
2622#define NOI_ERROR {NOI_CLEANUP; return -1;} 2622#define NOI_ERROR {NOI_CLEANUP; return -1;}
2623 if (iscsi_sock_msg(sess->sock, 0, nop_in.length, ping_data, 0) != nop_in.length) { 2623 if ((unsigned)iscsi_sock_msg(sess->sock, 0, nop_in.length, ping_data, 0) != nop_in.length) {
2624 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 2624 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
2625 NOI_ERROR; 2625 NOI_ERROR;
2626 } 2626 }
2627 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully read %d bytes ping data\n", nop_in.length); 2627 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully read %d bytes ping data\n", nop_in.length);
2628 if (cmd) { 2628 if (cmd) {
2629 for (i = 0; i < nop_in.length; i++) { 2629 for (i = 0; i < nop_in.length; i++) {
2630 if (nop_out->data[i] != ping_data[i]) { 2630 if (nop_out->data[i] != ping_data[i]) {
2631 iscsi_trace_error(__FILE__, __LINE__, "Bad ping data[%d]. Got %#x, expected %#x\n", i, ping_data[i], nop_out->data[i]); 2631 iscsi_trace_error(__FILE__, __LINE__, "Bad ping data[%d]. Got %#x, expected %#x\n", i, ping_data[i], nop_out->data[i]);
2632 NOI_ERROR; 2632 NOI_ERROR;
2633 } 2633 }
2634 } 2634 }
2635 } 2635 }
2636 } 2636 }
2637 /* Send ping response (if initiated by target) */ 2637 /* Send ping response (if initiated by target) */
2638 2638
2639 if (nop_in.transfer_tag != 0xffffffff) { 2639 if (nop_in.transfer_tag != 0xffffffff) {
2640 2640
2641 uint8_t nop_header[ISCSI_HEADER_LEN]; 2641 uint8_t nop_header[ISCSI_HEADER_LEN];
2642 iscsi_nop_out_args_t nop_out_args; 2642 iscsi_nop_out_args_t nop_out_args;
2643 2643
2644 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending %d byte ping response\n", nop_in.length); 2644 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending %d byte ping response\n", nop_in.length);
2645 (void) memset(&nop_out_args, 0x0, sizeof(nop_out_args)); 2645 (void) memset(&nop_out_args, 0x0, sizeof(nop_out_args));
2646 nop_out_args.tag = 0xffffffff; 2646 nop_out_args.tag = 0xffffffff;
2647 nop_out_args.immediate = 0x40; 2647 nop_out_args.immediate = 0x40;
2648 nop_out_args.transfer_tag = nop_in.transfer_tag; 2648 nop_out_args.transfer_tag = nop_in.transfer_tag;
2649 nop_out_args.length = nop_in.length; 2649 nop_out_args.length = nop_in.length;
2650 nop_out_args.lun = nop_in.lun; 2650 nop_out_args.lun = nop_in.lun;
2651 nop_out_args.ExpStatSN = sess->ExpStatSN; 2651 nop_out_args.ExpStatSN = sess->ExpStatSN;
2652 nop_out_args.CmdSN = sess->CmdSN; 2652 nop_out_args.CmdSN = sess->CmdSN;
2653 if (iscsi_nop_out_encap(nop_header, &nop_out_args) != 0) { 2653 if (iscsi_nop_out_encap(nop_header, &nop_out_args) != 0) {
2654 iscsi_trace_error(__FILE__, __LINE__, "iscsi_nop_out_encap() failed\n"); 2654 iscsi_trace_error(__FILE__, __LINE__, "iscsi_nop_out_encap() failed\n");
2655 NOI_ERROR; 2655 NOI_ERROR;
2656 } 2656 }
2657 if (iscsi_sock_send_header_and_data(sess->sock, nop_header, nop_out_args.length, ping_data, nop_in.length, 0) != nop_in.length) { 2657 if ((unsigned)iscsi_sock_send_header_and_data(sess->sock, nop_header, nop_out_args.length, ping_data, nop_in.length, 0) != nop_in.length) {
2658 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 2658 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
2659 NOI_ERROR; 2659 NOI_ERROR;
2660 } 2660 }
2661 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully sent %d byte ping response\n", nop_in.length); 2661 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully sent %d byte ping response\n", nop_in.length);
2662 } 2662 }
2663 NOI_CLEANUP; 2663 NOI_CLEANUP;
2664 /* Check and update numbering */ 2664 /* Check and update numbering */
2665 sess->ExpStatSN = nop_in.StatSN + 1; 2665 sess->ExpStatSN = nop_in.StatSN + 1;
2666 /* 2666 /*
2667 * RETURN_NOT_EQUAL("StatSN", nop_in.StatSN, sess->ExpStatSN++, 2667 * RETURN_NOT_EQUAL("StatSN", nop_in.StatSN, sess->ExpStatSN++,
2668 * NO_CLEANUP, -1); 2668 * NO_CLEANUP, -1);
2669 */ 2669 */
2670 sess->CmdSN = nop_in.ExpCmdSN; 2670 sess->CmdSN = nop_in.ExpCmdSN;
2671 /* 2671 /*
2672 * RETURN_NOT_EQUAL("ExpCmdSN", nop_in.ExpCmdSN, sess->CmdSN, 2672 * RETURN_NOT_EQUAL("ExpCmdSN", nop_in.ExpCmdSN, sess->CmdSN,
2673 * NO_CLEANUP, -1); 2673 * NO_CLEANUP, -1);
2674 */ 2674 */
2675 sess->MaxCmdSN = nop_in.MaxCmdSN; 2675 sess->MaxCmdSN = nop_in.MaxCmdSN;
2676 2676
2677 /* Callback */ 2677 /* Callback */
2678 2678
2679 if (cmd) { 2679 if (cmd) {
2680 cmd->status = 0; 2680 cmd->status = 0;
2681 if (cmd->callback) { 2681 if (cmd->callback) {
2682 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "NOP_OUT_T done (cmd status %d)\n", cmd->status); 2682 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "NOP_OUT_T done (cmd status %d)\n", cmd->status);
2683 if ((*cmd->callback)(cmd) != 0) { 2683 if ((*cmd->callback)(cmd) != 0) {
2684 iscsi_trace_error(__FILE__, __LINE__, "callback() failed\n"); 2684 iscsi_trace_error(__FILE__, __LINE__, "callback() failed\n");
2685 return -1; 2685 return -1;
2686 } 2686 }
2687 } else { 2687 } else {
2688 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "no callback associated with NOP_IN_T??\n"); 2688 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "no callback associated with NOP_IN_T??\n");
2689 return -1; 2689 return -1;
2690 } 2690 }
2691 } 2691 }
2692 return 0; 2692 return 0;
2693} 2693}
2694 2694
2695static int  2695static int
2696scsi_r2t_i(initiator_session_t * sess, initiator_cmd_t * cmd, uint8_t *header) 2696scsi_r2t_i(initiator_session_t * sess, initiator_cmd_t * cmd, uint8_t *header)
2697{ 2697{
2698 iscsi_r2t_t r2t; 2698 iscsi_r2t_t r2t;
2699 iscsi_scsi_cmd_args_t *scsi_cmd; 2699 iscsi_scsi_cmd_args_t *scsi_cmd;
2700 iscsi_write_data_t data; 2700 iscsi_write_data_t data;
2701 uint32_t bytes_sent; 2701 uint32_t bytes_sent;
2702 uint32_t DataSN; 2702 uint32_t DataSN;
2703 struct iovec sg_singleton; 2703 struct iovec sg_singleton;
2704 struct iovec *sg, *sg_copy, *sg_copy_orig, *sg_which; 2704 struct iovec *sg, *sg_copy, *sg_copy_orig, *sg_which;
2705 int sg_len, sg_len_copy, sg_len_which; 2705 int sg_len, sg_len_copy, sg_len_which;
2706 int fragment_flag; 2706 int fragment_flag;
2707 2707
2708 /* Make sure an initiator_cmd_t was specified, that it has a 2708 /* Make sure an initiator_cmd_t was specified, that it has a
2709 * callback function specified and that it also has a 2709 * callback function specified and that it also has a
2710 * iscsi_scsi_cmd_args_t associated with it. */ 2710 * iscsi_scsi_cmd_args_t associated with it. */
2711 2711
2712 if (cmd) { 2712 if (cmd) {
2713 if ((scsi_cmd = (iscsi_scsi_cmd_args_t *) cmd->ptr) == NULL) { 2713 if ((scsi_cmd = (iscsi_scsi_cmd_args_t *) cmd->ptr) == NULL) {
2714 iscsi_trace_error(__FILE__, __LINE__, "no iscsi_scsi_cmd_args_t associated with this initiator_cmd_t??\n"); 2714 iscsi_trace_error(__FILE__, __LINE__, "no iscsi_scsi_cmd_args_t associated with this initiator_cmd_t??\n");
2715 return -1; 2715 return -1;
2716 } else if (cmd->callback == NULL) { 2716 } else if (cmd->callback == NULL) {
2717 iscsi_trace_error(__FILE__, __LINE__, "no callback associated with this initiator_cmd_t??\n"); 2717 iscsi_trace_error(__FILE__, __LINE__, "no callback associated with this initiator_cmd_t??\n");
2718 return -1; 2718 return -1;
2719 } 2719 }
2720 } else { 2720 } else {
2721 iscsi_trace_error(__FILE__, __LINE__, "no initiator_cmd_t associated with this iscsi_r2t_t??\n"); 2721 iscsi_trace_error(__FILE__, __LINE__, "no initiator_cmd_t associated with this iscsi_r2t_t??\n");
2722 return -1; 2722 return -1;
2723 } 2723 }
2724 2724
2725 sg = sg_copy = sg_copy_orig = sg_which = NULL; 2725 sg = sg_copy = sg_copy_orig = sg_which = NULL;
2726 sg_len = sg_len_copy = sg_len_which = 0; 2726 sg_len = sg_len_copy = sg_len_which = 0;
2727 if (iscsi_r2t_decap(header, &r2t) != 0) { 2727 if (iscsi_r2t_decap(header, &r2t) != 0) {
2728 iscsi_trace_error(__FILE__, __LINE__, "iscsi_r2t_decap() failed\n"); 2728 iscsi_trace_error(__FILE__, __LINE__, "iscsi_r2t_decap() failed\n");
2729 return -1; 2729 return -1;
2730 } 2730 }
2731 /* Check args */ 2731 /* Check args */
2732 2732
2733 RETURN_EQUAL("r2t.length", r2t.length, 0, NO_CLEANUP, -1); 2733 RETURN_EQUAL("r2t.length", r2t.length, 0, NO_CLEANUP, -1);
2734 2734
2735 /* Check and update numbering */ 2735 /* Check and update numbering */
2736 2736
2737 RETURN_NOT_EQUAL("StatSN", r2t.StatSN, sess->ExpStatSN, NO_CLEANUP, -1); 2737 RETURN_NOT_EQUAL("StatSN", r2t.StatSN, sess->ExpStatSN, NO_CLEANUP, -1);
2738 RETURN_NOT_EQUAL("ExpCmdSN", r2t.ExpCmdSN, sess->CmdSN, NO_CLEANUP, -1); 2738 RETURN_NOT_EQUAL("ExpCmdSN", r2t.ExpCmdSN, sess->CmdSN, NO_CLEANUP, -1);
2739 sess->MaxCmdSN = r2t.MaxCmdSN; 2739 sess->MaxCmdSN = r2t.MaxCmdSN;
2740 2740
2741 /* Send back requested data */ 2741 /* Send back requested data */
2742 2742
2743 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending %d bytes R2T write data (offset %u)\n", r2t.length, r2t.offset); 2743 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending %d bytes R2T write data (offset %u)\n", r2t.length, r2t.offset);
2744 if (scsi_cmd->send_sg_len) { 2744 if (scsi_cmd->send_sg_len) {
2745 sg = (struct iovec *) scsi_cmd->send_data; 2745 sg = (struct iovec *) scsi_cmd->send_data;
2746 sg_len = scsi_cmd->send_sg_len; 2746 sg_len = scsi_cmd->send_sg_len;
2747 } else { 2747 } else {
2748 sg_singleton.iov_base = scsi_cmd->send_data; 2748 sg_singleton.iov_base = scsi_cmd->send_data;
2749 sg_singleton.iov_len = scsi_cmd->trans_len; 2749 sg_singleton.iov_len = scsi_cmd->trans_len;
2750 sg = &sg_singleton; 2750 sg = &sg_singleton;
2751 sg_len = 1; 2751 sg_len = 1;
2752 } 2752 }
2753 fragment_flag = 0; 2753 fragment_flag = 0;
2754 bytes_sent = 0; 2754 bytes_sent = 0;
2755 DataSN = 0; 2755 DataSN = 0;
2756#define FF_CLEANUP {if (fragment_flag) iscsi_free_atomic(sg_copy_orig);} 2756#define FF_CLEANUP {if (fragment_flag) iscsi_free_atomic(sg_copy_orig);}
2757 do { 2757 do {
2758 (void) memset(&data, 0x0, sizeof(data)); 2758 (void) memset(&data, 0x0, sizeof(data));
2759 if (sess->sess_params.max_data_seg_length) { 2759 if (sess->sess_params.max_data_seg_length) {
2760 data.length = MIN(sess->sess_params.max_data_seg_length, 2760 data.length = MIN(sess->sess_params.max_data_seg_length,
2761 r2t.length - bytes_sent); 2761 r2t.length - bytes_sent);
2762 } else { 2762 } else {
2763 data.length = r2t.length - bytes_sent; 2763 data.length = r2t.length - bytes_sent;
2764 } 2764 }
2765 if (bytes_sent + data.length == r2t.length) { 2765 if (bytes_sent + data.length == r2t.length) {
2766 data.final = 1; 2766 data.final = 1;
2767 } 2767 }
2768 data.tag = r2t.tag; 2768 data.tag = r2t.tag;
2769 data.transfer_tag = r2t.transfer_tag; 2769 data.transfer_tag = r2t.transfer_tag;
2770 data.ExpStatSN = sess->ExpStatSN; 2770 data.ExpStatSN = sess->ExpStatSN;
2771 data.DataSN = DataSN++; 2771 data.DataSN = DataSN++;
2772 data.offset = r2t.offset + bytes_sent; 2772 data.offset = r2t.offset + bytes_sent;
2773 data.lun = scsi_cmd->lun; 2773 data.lun = scsi_cmd->lun;
2774 if (iscsi_write_data_encap(header, &data) != 0) { 2774 if (iscsi_write_data_encap(header, &data) != 0) {
2775 iscsi_trace_error(__FILE__, __LINE__, "iscsi_write_data_encap() failed\n"); 2775 iscsi_trace_error(__FILE__, __LINE__, "iscsi_write_data_encap() failed\n");
2776 FF_CLEANUP; 2776 FF_CLEANUP;
2777 return -1; 2777 return -1;
2778 } 2778 }
2779 if ((data.length < r2t.length) || (r2t.offset)) { 2779 if ((data.length < r2t.length) || (r2t.offset)) {
2780 if (data.length < r2t.length) { 2780 if (data.length < r2t.length) {
2781 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "R2T data is being fragmented: sending %u bytes of %u requested\n", 2781 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "R2T data is being fragmented: sending %u bytes of %u requested\n",
2782 data.length, r2t.length); 2782 data.length, r2t.length);
2783 } else { 2783 } else {
2784 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "R2T data starts at offset %u, desired length %u\n", 2784 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "R2T data starts at offset %u, desired length %u\n",
2785 r2t.offset, r2t.length); 2785 r2t.offset, r2t.length);
2786 } 2786 }
2787 2787
2788 /* Allocate space for a copy of the original iovec */ 2788 /* Allocate space for a copy of the original iovec */
2789 2789
2790 if (!fragment_flag) { 2790 if (!fragment_flag) {
2791 if ((sg_copy_orig = iscsi_malloc_atomic(sg_len * sizeof(struct iovec))) == NULL) { 2791 if ((sg_copy_orig = iscsi_malloc_atomic(sg_len * sizeof(struct iovec))) == NULL) {
2792 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n"); 2792 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
2793 return -1; 2793 return -1;
2794 } 2794 }
2795 fragment_flag++; 2795 fragment_flag++;
2796 } 2796 }
2797 /* 2797 /*
2798 * Copy and modify original iovec with new offset and 2798 * Copy and modify original iovec with new offset and
2799 * length 2799 * length
2800 */ 2800 */
2801 2801
2802 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "modifying original iovec with offset %u length %u\n", 2802 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "modifying original iovec with offset %u length %u\n",
2803 r2t.offset + bytes_sent, data.length); 2803 r2t.offset + bytes_sent, data.length);
2804 sg_copy = sg_copy_orig; 2804 sg_copy = sg_copy_orig;
2805 sg_len_copy = sg_len; 2805 sg_len_copy = sg_len;
2806 memcpy(sg_copy, sg, sizeof(struct iovec) * sg_len); 2806 memcpy(sg_copy, sg, sizeof(struct iovec) * sg_len);
2807 if (modify_iov(&sg_copy, &sg_len_copy, r2t.offset + bytes_sent, data.length) != 0) { 2807 if (modify_iov(&sg_copy, &sg_len_copy, r2t.offset + bytes_sent, data.length) != 0) {
2808 iscsi_trace_error(__FILE__, __LINE__, "modify_iov() failed\n"); 2808 iscsi_trace_error(__FILE__, __LINE__, "modify_iov() failed\n");
2809 FF_CLEANUP; 2809 FF_CLEANUP;
2810 return -1; 2810 return -1;
2811 } 2811 }
2812 sg_which = sg_copy; 2812 sg_which = sg_copy;
2813 sg_len_which = sg_len_copy; 2813 sg_len_which = sg_len_copy;
2814 } else { 2814 } else {
2815 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "using original iovec for R2T transfer (offset %u, length %u)\n", 2815 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "using original iovec for R2T transfer (offset %u, length %u)\n",
2816 r2t.offset, r2t.length); 2816 r2t.offset, r2t.length);
2817 sg_which = sg; 2817 sg_which = sg;
2818 sg_len_which = sg_len; 2818 sg_len_which = sg_len;
2819 } 2819 }
2820 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending R2T write data PDU (offset %u, len %u, sg_len %u)\n", 2820 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending R2T write data PDU (offset %u, len %u, sg_len %u)\n",
2821 data.offset, data.length, sg_len_which); 2821 data.offset, data.length, sg_len_which);
2822 if (iscsi_sock_send_header_and_data(sess->sock, header, ISCSI_HEADER_LEN, sg_which, data.length, sg_len_which) 2822 if ((unsigned)iscsi_sock_send_header_and_data(sess->sock, header, ISCSI_HEADER_LEN, sg_which, data.length, sg_len_which)
2823 != ISCSI_HEADER_LEN + data.length) { 2823 != ISCSI_HEADER_LEN + data.length) {
2824 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed\n"); 2824 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed\n");
2825 FF_CLEANUP; 2825 FF_CLEANUP;
2826 return -1; 2826 return -1;
2827 } 2827 }
2828 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sent write data PDU OK (offset %u, len %u)\n", data.offset, data.length); 2828 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sent write data PDU OK (offset %u, len %u)\n", data.offset, data.length);
2829 bytes_sent += data.length; 2829 bytes_sent += data.length;
2830 scsi_cmd->bytes_sent += data.length; 2830 scsi_cmd->bytes_sent += data.length;
2831 } while (bytes_sent < r2t.length); 2831 } while (bytes_sent < r2t.length);
2832 FF_CLEANUP; 2832 FF_CLEANUP;
2833 if (hash_insert(&g_tag_hash, cmd, scsi_cmd->tag) != 0) { 2833 if (hash_insert(&g_tag_hash, cmd, scsi_cmd->tag) != 0) {
2834 iscsi_trace_error(__FILE__, __LINE__, "hash_insert() failed\n"); 2834 iscsi_trace_error(__FILE__, __LINE__, "hash_insert() failed\n");
2835 return -1; 2835 return -1;
2836 } 2836 }
2837 return 0; 2837 return 0;
2838} 2838}
2839 2839
2840static int  2840static int
2841scsi_response_i(initiator_session_t * sess, initiator_cmd_t * cmd, uint8_t *header) 2841scsi_response_i(initiator_session_t * sess, initiator_cmd_t * cmd, uint8_t *header)
2842{ 2842{
2843 iscsi_scsi_cmd_args_t *scsi_cmd; 2843 iscsi_scsi_cmd_args_t *scsi_cmd;
2844 iscsi_scsi_rsp_t scsi_rsp; 2844 iscsi_scsi_rsp_t scsi_rsp;
2845 2845
2846 /* Make sure an initiator_cmd_t was specified, that it has a 2846 /* Make sure an initiator_cmd_t was specified, that it has a
2847 * callback function specified and that it also has a 2847 * callback function specified and that it also has a
2848 * iscsi_scsi_cmd_args_t associated with it. */ 2848 * iscsi_scsi_cmd_args_t associated with it. */
2849 2849
2850 if (cmd) { 2850 if (cmd) {
2851 if ((scsi_cmd = (iscsi_scsi_cmd_args_t *) cmd->ptr) == NULL) { 2851 if ((scsi_cmd = (iscsi_scsi_cmd_args_t *) cmd->ptr) == NULL) {
2852 iscsi_trace_error(__FILE__, __LINE__, "no iscsi_scsi_cmd_args_t associated with this initiator_cmd_t??\n"); 2852 iscsi_trace_error(__FILE__, __LINE__, "no iscsi_scsi_cmd_args_t associated with this initiator_cmd_t??\n");
2853 return -1; 2853 return -1;
2854 } else if (cmd->callback == NULL) { 2854 } else if (cmd->callback == NULL) {
2855 iscsi_trace_error(__FILE__, __LINE__, "no callback associated with this initiator_cmd_t??\n"); 2855 iscsi_trace_error(__FILE__, __LINE__, "no callback associated with this initiator_cmd_t??\n");
2856 return -1; 2856 return -1;
2857 } 2857 }
2858 } else { 2858 } else {
2859 iscsi_trace_error(__FILE__, __LINE__, "no initiator_cmd_t associated with this iscsi_scsi_rsp_t??\n"); 2859 iscsi_trace_error(__FILE__, __LINE__, "no initiator_cmd_t associated with this iscsi_scsi_rsp_t??\n");
2860 return -1; 2860 return -1;
2861 } 2861 }
2862 2862
2863 /* 2863 /*
2864 * Read SCSI response and check return args. Those marked 2864 * Read SCSI response and check return args. Those marked
2865 * "FIX ME" are not yet implemented. */ 2865 * "FIX ME" are not yet implemented. */
2866 2866
2867 if (iscsi_scsi_rsp_decap(header, &scsi_rsp) != 0) { 2867 if (iscsi_scsi_rsp_decap(header, &scsi_rsp) != 0) {
2868 iscsi_trace_error(__FILE__, __LINE__, "iscsi_scsi_rsp_decap() failed\n"); 2868 iscsi_trace_error(__FILE__, __LINE__, "iscsi_scsi_rsp_decap() failed\n");
2869 return -1; 2869 return -1;
2870 } 2870 }
2871 RETURN_NOT_EQUAL("o bit (FIX ME)", scsi_rsp.bidi_overflow, 0, NO_CLEANUP, -1); 2871 RETURN_NOT_EQUAL("o bit (FIX ME)", scsi_rsp.bidi_overflow, 0, NO_CLEANUP, -1);
2872 RETURN_NOT_EQUAL("u bit (FIX ME)", scsi_rsp.bidi_underflow, 0, NO_CLEANUP, -1); 2872 RETURN_NOT_EQUAL("u bit (FIX ME)", scsi_rsp.bidi_underflow, 0, NO_CLEANUP, -1);
2873 RETURN_NOT_EQUAL("O bit (FIX ME)", scsi_rsp.overflow, 0, NO_CLEANUP, -1); 2873 RETURN_NOT_EQUAL("O bit (FIX ME)", scsi_rsp.overflow, 0, NO_CLEANUP, -1);
2874 RETURN_NOT_EQUAL("iSCSI Response (FIX ME)", scsi_rsp.response, 0, NO_CLEANUP, -1); 2874 RETURN_NOT_EQUAL("iSCSI Response (FIX ME)", scsi_rsp.response, 0, NO_CLEANUP, -1);
2875 RETURN_NOT_EQUAL("Tag", scsi_rsp.tag, scsi_cmd->tag, NO_CLEANUP, -1); 2875 RETURN_NOT_EQUAL("Tag", scsi_rsp.tag, scsi_cmd->tag, NO_CLEANUP, -1);
2876 RETURN_NOT_EQUAL("Bidi Residual Count", scsi_rsp.bidi_res_cnt, 0, NO_CLEANUP, -1); 2876 RETURN_NOT_EQUAL("Bidi Residual Count", scsi_rsp.bidi_res_cnt, 0, NO_CLEANUP, -1);
2877 RETURN_NOT_EQUAL("StatSN", scsi_rsp.StatSN, sess->ExpStatSN, NO_CLEANUP, -1); 2877 RETURN_NOT_EQUAL("StatSN", scsi_rsp.StatSN, sess->ExpStatSN, NO_CLEANUP, -1);
2878 sess->ExpStatSN = scsi_rsp.StatSN + 1; 2878 sess->ExpStatSN = scsi_rsp.StatSN + 1;
2879 2879
2880 if (sess->sess_params.max_data_seg_length) { 2880 if (sess->sess_params.max_data_seg_length) {
2881 RETURN_GREATER("DataSegmentLength (FIX ME)", scsi_rsp.length, 2881 RETURN_GREATER("DataSegmentLength (FIX ME)", scsi_rsp.length,
2882 sess->sess_params.max_data_seg_length, NO_CLEANUP, -1); 2882 sess->sess_params.max_data_seg_length, NO_CLEANUP, -1);
2883 } 2883 }
2884 if ((scsi_rsp.status == 0) && (scsi_rsp.length != 0)) { 2884 if ((scsi_rsp.status == 0) && (scsi_rsp.length != 0)) {
2885 iscsi_trace_error(__FILE__, __LINE__, "Unexpected DataSegmentLength %u with GOOD SCSI status\n", scsi_rsp.length); 2885 iscsi_trace_error(__FILE__, __LINE__, "Unexpected DataSegmentLength %u with GOOD SCSI status\n", scsi_rsp.length);
2886 return -1; 2886 return -1;
2887 } 2887 }
2888 /* 2888 /*
2889 * Make sure all data was successfully transferred if command 2889 * Make sure all data was successfully transferred if command
2890 * completed successfully, otherwise read sense data. */ 2890 * completed successfully, otherwise read sense data. */
2891 2891
2892 if (scsi_rsp.status == 0) { 2892 if (scsi_rsp.status == 0) {
2893 if (scsi_cmd->output) { 2893 if (scsi_cmd->output) {
2894 RETURN_NOT_EQUAL("scsi_cmd->bytes_sent", scsi_cmd->bytes_sent, scsi_cmd->trans_len, NO_CLEANUP, -1); 2894 RETURN_NOT_EQUAL("scsi_cmd->bytes_sent", scsi_cmd->bytes_sent, scsi_cmd->trans_len, NO_CLEANUP, -1);
2895 if (scsi_cmd->input) { 2895 if (scsi_cmd->input) {
2896 2896
2897 RETURN_NOT_EQUAL("scsi_cmd->bytes_recv", scsi_cmd->bytes_recv, scsi_cmd->bidi_trans_len, NO_CLEANUP, -1); 2897 RETURN_NOT_EQUAL("scsi_cmd->bytes_recv", scsi_cmd->bytes_recv, scsi_cmd->bidi_trans_len, NO_CLEANUP, -1);
2898 } 2898 }
2899 } else if (scsi_cmd->input) { 2899 } else if (scsi_cmd->input) {
2900 2900
2901 2901
2902 } 2902 }
2903 } else if (scsi_rsp.length) { 2903 } else if (scsi_rsp.length) {
2904 uint8_t *sense_data = NULL; 2904 uint8_t *sense_data = NULL;
2905 2905
2906 if ((sense_data = iscsi_malloc(scsi_rsp.length)) == NULL) { 2906 if ((sense_data = iscsi_malloc(scsi_rsp.length)) == NULL) {
2907 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n"); 2907 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n");
2908 return -1; 2908 return -1;
2909 } 2909 }
2910 iscsi_trace_error(__FILE__, __LINE__, "reading %d bytes sense data (recv_sg_len %u)\n", 2910 iscsi_trace_error(__FILE__, __LINE__, "reading %d bytes sense data (recv_sg_len %u)\n",
2911 scsi_rsp.length, scsi_cmd->recv_sg_len); 2911 scsi_rsp.length, scsi_cmd->recv_sg_len);
2912 if (iscsi_sock_msg(sess->sock, 0, scsi_rsp.length, sense_data, 0) != scsi_rsp.length) { 2912 if ((unsigned)iscsi_sock_msg(sess->sock, 0, scsi_rsp.length, sense_data, 0) != scsi_rsp.length) {
2913 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 2913 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
2914 if (sense_data != NULL) 2914 if (sense_data != NULL)
2915 iscsi_free(sense_data); 2915 iscsi_free(sense_data);
2916 return -1; 2916 return -1;
2917 } 2917 }
2918 iscsi_trace_error(__FILE__, __LINE__, "read %d bytes sense data ok (currently discarding)\n", scsi_rsp.length); 2918 iscsi_trace_error(__FILE__, __LINE__, "read %d bytes sense data ok (currently discarding)\n", scsi_rsp.length);
2919 if (sense_data != NULL) 2919 if (sense_data != NULL)
2920 iscsi_free(sense_data); 2920 iscsi_free(sense_data);
2921 } else { 2921 } else {
2922 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "no sense data available\n"); 2922 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "no sense data available\n");
2923 } 2923 }
2924 2924
2925 /* Check and update numbering */ 2925 /* Check and update numbering */
2926 2926
2927 /* 2927 /*
2928 * RETURN_NOT_EQUAL("ExpCmdSN", scsi_rsp.ExpCmdSN, sess->CmdSN, 2928 * RETURN_NOT_EQUAL("ExpCmdSN", scsi_rsp.ExpCmdSN, sess->CmdSN,
2929 * NO_CLEANUP, -1); 2929 * NO_CLEANUP, -1);
2930 */ 2930 */
2931 sess->MaxCmdSN = scsi_rsp.MaxCmdSN; 2931 sess->MaxCmdSN = scsi_rsp.MaxCmdSN;
2932 2932
2933 /* Set initiator_cmd_t status, iscsi_scsi_cmd_args_t status */ 2933 /* Set initiator_cmd_t status, iscsi_scsi_cmd_args_t status */
2934 /* and execute callback function */ 2934 /* and execute callback function */
2935 2935
2936 cmd->status = 0; 2936 cmd->status = 0;
2937 scsi_cmd->status = scsi_rsp.status; 2937 scsi_cmd->status = scsi_rsp.status;
2938 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "iscsi_scsi_cmd_args_t done (cmd status %d, iscsi status %d, scsi status %d)\n", 2938 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "iscsi_scsi_cmd_args_t done (cmd status %d, iscsi status %d, scsi status %d)\n",
2939 cmd->status, scsi_rsp.response, scsi_rsp.status); 2939 cmd->status, scsi_rsp.response, scsi_rsp.status);
2940 if ((*cmd->callback)(cmd) != 0) { 2940 if ((*cmd->callback)(cmd) != 0) {
2941 iscsi_trace_error(__FILE__, __LINE__, "callback() failed\n"); 2941 iscsi_trace_error(__FILE__, __LINE__, "callback() failed\n");
2942 return -1; 2942 return -1;
2943 2943
2944 } 2944 }
2945 return 0; 2945 return 0;
2946} 2946}
2947 2947
2948static int  2948static int
2949scsi_read_data_i(initiator_session_t * sess, initiator_cmd_t * cmd, uint8_t *header) 2949scsi_read_data_i(initiator_session_t * sess, initiator_cmd_t * cmd, uint8_t *header)
2950{ 2950{
2951 iscsi_read_data_t data; 2951 iscsi_read_data_t data;
2952 iscsi_scsi_cmd_args_t *scsi_cmd; 2952 iscsi_scsi_cmd_args_t *scsi_cmd;
2953 int rc; 2953 int rc;
2954 2954
2955 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "processing read data\n"); 2955 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "processing read data\n");
2956 2956
2957 /* Make sure an initiator_cmd_t was specified, that it has a 2957 /* Make sure an initiator_cmd_t was specified, that it has a
2958 * callback function specified and that it also has a 2958 * callback function specified and that it also has a
2959 * iscsi_scsi_cmd_args_t associated with it. */ 2959 * iscsi_scsi_cmd_args_t associated with it. */
2960 2960
2961 if (cmd) { 2961 if (cmd) {
2962 if (cmd->type != ISCSI_SCSI_CMD) { 2962 if (cmd->type != ISCSI_SCSI_CMD) {
2963 iscsi_trace_error(__FILE__, __LINE__, "Invalid response from target for cmd type (%#x)\n", cmd->type); 2963 iscsi_trace_error(__FILE__, __LINE__, "Invalid response from target for cmd type (%#x)\n", cmd->type);
2964 cmd->status = -1; 2964 cmd->status = -1;
2965 if (cmd->callback) { 2965 if (cmd->callback) {
2966 (*cmd->callback)(cmd); 2966 (*cmd->callback)(cmd);
2967 } 2967 }
2968 return -1; 2968 return -1;
2969 } 2969 }
2970 if ((scsi_cmd = (iscsi_scsi_cmd_args_t *) cmd->ptr) == NULL) { 2970 if ((scsi_cmd = (iscsi_scsi_cmd_args_t *) cmd->ptr) == NULL) {
2971 iscsi_trace_error(__FILE__, __LINE__, "no iscsi_scsi_cmd_args_t associated with this initiator_cmd_t??\n"); 2971 iscsi_trace_error(__FILE__, __LINE__, "no iscsi_scsi_cmd_args_t associated with this initiator_cmd_t??\n");
2972 return -1; 2972 return -1;
2973 } else if (cmd->callback == NULL) { 2973 } else if (cmd->callback == NULL) {
2974 iscsi_trace_error(__FILE__, __LINE__, "no callback associated with this initiator_cmd_t??\n"); 2974 iscsi_trace_error(__FILE__, __LINE__, "no callback associated with this initiator_cmd_t??\n");
2975 return -1; 2975 return -1;
2976 } 2976 }
2977 } else { 2977 } else {
2978 iscsi_trace_error(__FILE__, __LINE__, "no initiator_cmd_t associated with this iscsi_read_data_t??\n"); 2978 iscsi_trace_error(__FILE__, __LINE__, "no initiator_cmd_t associated with this iscsi_read_data_t??\n");
2979 return -1; 2979 return -1;
2980 } 2980 }
2981 if (iscsi_read_data_decap(header, &data) != 0) { 2981 if (iscsi_read_data_decap(header, &data) != 0) {
2982 iscsi_trace_error(__FILE__, __LINE__, "iscsi_scsi_rsp_decap() failed\n"); 2982 iscsi_trace_error(__FILE__, __LINE__, "iscsi_scsi_rsp_decap() failed\n");
2983 return -1; 2983 return -1;
2984 } 2984 }
2985 /* Check args */ 2985 /* Check args */
2986 2986
2987 RETURN_NOT_EQUAL("Overflow bit", data.overflow, 0, NO_CLEANUP, -1); 2987 RETURN_NOT_EQUAL("Overflow bit", data.overflow, 0, NO_CLEANUP, -1);
2988 RETURN_NOT_EQUAL("Underflow bit", data.underflow, 0, NO_CLEANUP, -1); 2988 RETURN_NOT_EQUAL("Underflow bit", data.underflow, 0, NO_CLEANUP, -1);
2989 RETURN_NOT_EQUAL("Tag", data.task_tag, scsi_cmd->tag, NO_CLEANUP, -1); 2989 RETURN_NOT_EQUAL("Tag", data.task_tag, scsi_cmd->tag, NO_CLEANUP, -1);
2990 RETURN_NOT_EQUAL("Residual Count", data.res_count, 0, NO_CLEANUP, -1); 2990 RETURN_NOT_EQUAL("Residual Count", data.res_count, 0, NO_CLEANUP, -1);
2991 2991
2992 if (sess->sess_params.max_data_seg_length) { 2992 if (sess->sess_params.max_data_seg_length) {
2993 RETURN_GREATER("Length", data.length, sess->sess_params.max_data_seg_length, NO_CLEANUP, -1); 2993 RETURN_GREATER("Length", data.length, sess->sess_params.max_data_seg_length, NO_CLEANUP, -1);
2994 } 2994 }
2995 /* Check and update numbering */ 2995 /* Check and update numbering */
2996 2996
2997 WARN_NOT_EQUAL("ExpCmdSN", data.ExpCmdSN, sess->CmdSN); 2997 WARN_NOT_EQUAL("ExpCmdSN", data.ExpCmdSN, sess->CmdSN);
2998 sess->MaxCmdSN = data.MaxCmdSN; 2998 sess->MaxCmdSN = data.MaxCmdSN;
2999 2999
3000 /* Need to optimize this section */ 3000 /* Need to optimize this section */
3001 3001
3002 if (scsi_cmd->recv_sg_len) { 3002 if (scsi_cmd->recv_sg_len) {
3003 int sg_len = scsi_cmd->recv_sg_len; 3003 int sg_len = scsi_cmd->recv_sg_len;
3004 struct iovec *sg; 3004 struct iovec *sg;
3005 struct iovec *sg_orig = NULL; 3005 struct iovec *sg_orig = NULL;
3006 char *sgp; 3006 char *sgp;
3007 uint32_t total_len, disp; 3007 uint32_t total_len, disp;
3008 int i; 3008 int i;
3009 3009
3010 if (data.length != scsi_cmd->trans_len) { 3010 if (data.length != scsi_cmd->trans_len) {
3011 3011
3012 /* Make a copy of the iovec */ 3012 /* Make a copy of the iovec */
3013 3013
3014 if ((sg_orig = sg = iscsi_malloc_atomic(sizeof(struct iovec) * sg_len)) == NULL) { 3014 if ((sg_orig = sg = iscsi_malloc_atomic(sizeof(struct iovec) * sg_len)) == NULL) {
3015 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n"); 3015 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
3016 return -1; 3016 return -1;
3017 3017
3018 } 3018 }
3019 memcpy(sg, scsi_cmd->recv_data, sizeof(struct iovec) * sg_len); 3019 memcpy(sg, scsi_cmd->recv_data, sizeof(struct iovec) * sg_len);
3020 3020
3021 /* Find offset in iovecs */ 3021 /* Find offset in iovecs */
3022 3022
3023 total_len = 0; 3023 total_len = 0;
3024 disp = data.offset; 3024 disp = data.offset;
3025 for (i = 0; i < sg_len; i++) { 3025 for (i = 0; i < sg_len; i++) {
3026 total_len += sg[i].iov_len; 3026 total_len += sg[i].iov_len;
3027 if (total_len > data.offset) { 3027 if (total_len > data.offset) {
3028 break; 3028 break;
3029 } 3029 }
3030 disp -= sg[i].iov_len; 3030 disp -= sg[i].iov_len;
3031 } 3031 }
3032 sg[i].iov_len -= disp; 3032 sg[i].iov_len -= disp;
3033 sgp = sg[i].iov_base; 3033 sgp = sg[i].iov_base;
3034 sgp += disp; 3034 sgp += disp;
3035 sg[i].iov_base = sgp; 3035 sg[i].iov_base = sgp;
3036 sg_len -= i; 3036 sg_len -= i;
3037 sg = &sg[i]; 3037 sg = &sg[i];
3038 3038
3039 /* Find last iovec needed for read */ 3039 /* Find last iovec needed for read */
3040 3040
3041 total_len = 0; 3041 total_len = 0;
3042 for (i = 0; i < sg_len; i++) { 3042 for (i = 0; i < sg_len; i++) {
3043 total_len += sg[i].iov_len; 3043 total_len += sg[i].iov_len;
3044 if (total_len >= data.length) { 3044 if (total_len >= data.length) {
3045 break; 3045 break;
3046 } 3046 }
3047 } 3047 }
3048 sg[i].iov_len -= (total_len - data.length); 3048 sg[i].iov_len -= (total_len - data.length);
3049 sg_len = i + 1; 3049 sg_len = i + 1;
3050 } else { 3050 } else {
3051 sg = (struct iovec *) scsi_cmd->recv_data; 3051 sg = (struct iovec *) scsi_cmd->recv_data;
3052 } 3052 }
3053 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "reading %d bytes into sg buffer (total offset %u)\n", data.length, data.offset); 3053 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "reading %d bytes into sg buffer (total offset %u)\n", data.length, data.offset);
3054 if ((rc = iscsi_sock_msg(sess->sock, 0, data.length, (uint8_t *) sg, sg_len)) != data.length) { 3054 if ((rc = iscsi_sock_msg(sess->sock, 0, data.length, (uint8_t *) sg, sg_len)) != (int)data.length) {
3055 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed: got %u, expected %u\n", rc, data.length); 3055 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed: got %u, expected %u\n", rc, data.length);
3056 if (sg_orig) 3056 if (sg_orig)
3057 iscsi_free_atomic(sg_orig); 3057 iscsi_free_atomic(sg_orig);
3058 return -1; 3058 return -1;
3059 } 3059 }
3060 scsi_cmd->bytes_recv += data.length; 3060 scsi_cmd->bytes_recv += data.length;
3061 if (sg_orig) 3061 if (sg_orig)
3062 iscsi_free_atomic(sg_orig); 3062 iscsi_free_atomic(sg_orig);
3063 } else { 3063 } else {
3064 if (data.length) { 3064 if (data.length) {
3065 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "reading %d bytes into dest buffer (offset %u)\n", data.length, data.offset); 3065 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "reading %d bytes into dest buffer (offset %u)\n", data.length, data.offset);
3066 if (iscsi_sock_msg(sess->sock, 0, data.length, scsi_cmd->recv_data + data.offset, 0) != data.length) { 3066 if (iscsi_sock_msg(sess->sock, 0, data.length, scsi_cmd->recv_data + data.offset, 0) != (int)data.length) {
3067 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 3067 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
3068 return -1; 3068 return -1;
3069 } 3069 }
3070 scsi_cmd->bytes_recv += data.length; 3070 scsi_cmd->bytes_recv += data.length;
3071 } 3071 }
3072 } 3072 }
3073 3073
3074 3074
3075 /* Check for status */ 3075 /* Check for status */
3076 3076
3077 if (data.S_bit) { 3077 if (data.S_bit) {
3078 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "received status with final PDU\n"); 3078 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "received status with final PDU\n");
3079 RETURN_NOT_EQUAL("Final Bit", data.final, 1, NO_CLEANUP, -1); 3079 RETURN_NOT_EQUAL("Final Bit", data.final, 1, NO_CLEANUP, -1);
3080 RETURN_NOT_EQUAL("StatSN", data.StatSN, sess->ExpStatSN++, NO_CLEANUP, -1); 3080 RETURN_NOT_EQUAL("StatSN", data.StatSN, sess->ExpStatSN++, NO_CLEANUP, -1);
3081 scsi_cmd->status = data.status = 0; 3081 scsi_cmd->status = data.status = 0;
3082 cmd->status = 0; 3082 cmd->status = 0;
3083 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "scsi op %#x done (tag %u, status %d)\n", scsi_cmd->cdb[0], scsi_cmd->tag, scsi_cmd->status); 3083 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "scsi op %#x done (tag %u, status %d)\n", scsi_cmd->cdb[0], scsi_cmd->tag, scsi_cmd->status);
3084 if ((*cmd->callback)(cmd) != 0) { 3084 if ((*cmd->callback)(cmd) != 0) {
3085 iscsi_trace_error(__FILE__, __LINE__, "callback() failed\n"); 3085 iscsi_trace_error(__FILE__, __LINE__, "callback() failed\n");
3086 return -1; 3086 return -1;
3087 } 3087 }
3088 } else { 3088 } else {
3089 if (hash_insert(&g_tag_hash, cmd, scsi_cmd->tag) != 0) { 3089 if (hash_insert(&g_tag_hash, cmd, scsi_cmd->tag) != 0) {
3090 iscsi_trace_error(__FILE__, __LINE__, "hash_insert() failed\n"); 3090 iscsi_trace_error(__FILE__, __LINE__, "hash_insert() failed\n");
3091 return -1; 3091 return -1;
3092 } 3092 }
3093 } 3093 }
3094 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "read data processed\n"); 3094 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "read data processed\n");
3095 return 0; 3095 return 0;
3096} 3096}
3097 3097
3098int  3098int
3099initiator_info(char *ptr, int size, int len) 3099initiator_info(char *ptr, int size, int len)
3100{ 3100{
3101 initiator_session_t *sess; 3101 initiator_session_t *sess;
3102 int i; 3102 int i;
3103 3103
3104 ptr[0] = 0x0; 3104 ptr[0] = 0x0;
3105 len += snprintf(ptr, size - len, " %3s %30s %25s\n\n", "TID", "TargetName", "TargetAddress"); 3105 len += snprintf(ptr, size - len, " %3s %30s %25s\n\n", "TID", "TargetName", "TargetAddress");
3106 for (i = 0; i < CONFIG_INITIATOR_NUM_TARGETS; i++) { 3106 for (i = 0; i < CONFIG_INITIATOR_NUM_TARGETS; i++) {
3107 len += snprintf(ptr + len, size - len, " %3i %30s %20s:%d (", 3107 len += snprintf(ptr + len, size - len, " %3i %30s %20s:%d (",
3108 i, g_target[i].TargetName, g_target[i].ip, g_target[i].port); 3108 i, g_target[i].TargetName, g_target[i].ip, g_target[i].port);
3109 if (g_target[i].has_session) { 3109 if (g_target[i].has_session) {
3110 sess = g_target[i].sess; 3110 sess = g_target[i].sess;
3111 if (sess->state & INITIATOR_SESSION_STATE_INITIALIZING) 3111 if (sess->state & INITIATOR_SESSION_STATE_INITIALIZING)
3112 len += snprintf(ptr + len, size - len, "%s", "initializing"); 3112 len += snprintf(ptr + len, size - len, "%s", "initializing");
3113 if (sess->state & INITIATOR_SESSION_STATE_INITIALIZED) 3113 if (sess->state & INITIATOR_SESSION_STATE_INITIALIZED)
3114 len += snprintf(ptr + len, size - len, "%s", "initialized"); 3114 len += snprintf(ptr + len, size - len, "%s", "initialized");
3115 if (sess->state & INITIATOR_SESSION_STATE_CONNECTING) 3115 if (sess->state & INITIATOR_SESSION_STATE_CONNECTING)
3116 len += snprintf(ptr + len, size - len, "%s", "connecting"); 3116 len += snprintf(ptr + len, size - len, "%s", "connecting");
3117 if (sess->state & INITIATOR_SESSION_STATE_CONNECTED) 3117 if (sess->state & INITIATOR_SESSION_STATE_CONNECTED)
3118 len += snprintf(ptr + len, size - len, "%s", "connected"); 3118 len += snprintf(ptr + len, size - len, "%s", "connected");
3119 if (sess->state & INITIATOR_SESSION_STATE_LOGGING_IN) 3119 if (sess->state & INITIATOR_SESSION_STATE_LOGGING_IN)
3120 len += snprintf(ptr + len, size - len, "%s", "logging in"); 3120 len += snprintf(ptr + len, size - len, "%s", "logging in");
3121 if (sess->state & INITIATOR_SESSION_STATE_LOGGED_IN_NORMAL) 3121 if (sess->state & INITIATOR_SESSION_STATE_LOGGED_IN_NORMAL)
3122 len += snprintf(ptr + len, size - len, "%s", "Normal session"); 3122 len += snprintf(ptr + len, size - len, "%s", "Normal session");
3123 if (sess->state & INITIATOR_SESSION_STATE_LOGGED_IN_DISCOVERY) 3123 if (sess->state & INITIATOR_SESSION_STATE_LOGGED_IN_DISCOVERY)
3124 len += snprintf(ptr + len, size - len, "%s", "Discovery session"); 3124 len += snprintf(ptr + len, size - len, "%s", "Discovery session");
3125 if (sess->state & INITIATOR_SESSION_STATE_LOGGING_OUT) 3125 if (sess->state & INITIATOR_SESSION_STATE_LOGGING_OUT)
3126 len += snprintf(ptr + len, size - len, "%s", "logging out"); 3126 len += snprintf(ptr + len, size - len, "%s", "logging out");
3127 if (sess->state & INITIATOR_SESSION_STATE_LOGGED_OUT) 3127 if (sess->state & INITIATOR_SESSION_STATE_LOGGED_OUT)
3128 len += snprintf(ptr + len, size - len, "%s", "logged out"); 3128 len += snprintf(ptr + len, size - len, "%s", "logged out");
3129 if (sess->state & INITIATOR_SESSION_STATE_DESTROYING) 3129 if (sess->state & INITIATOR_SESSION_STATE_DESTROYING)
3130 len += snprintf(ptr + len, size - len, "%s", "destroying"); 3130 len += snprintf(ptr + len, size - len, "%s", "destroying");
3131 if (sess->tx_worker.state & ISCSI_WORKER_STATE_ERROR) 3131 if (sess->tx_worker.state & ISCSI_WORKER_STATE_ERROR)
3132 len += snprintf(ptr + len, size - len, "%s", " **Tx Error** "); 3132 len += snprintf(ptr + len, size - len, "%s", " **Tx Error** ");
3133 if (sess->rx_worker.state & ISCSI_WORKER_STATE_ERROR) 3133 if (sess->rx_worker.state & ISCSI_WORKER_STATE_ERROR)
3134 len += snprintf(ptr + len, size - len, "%s", " **Rx Error** "); 3134 len += snprintf(ptr + len, size - len, "%s", " **Rx Error** ");
3135 } else { 3135 } else {
3136 len += snprintf(ptr + len, size - len, "%s", "No Session"); 3136 len += snprintf(ptr + len, size - len, "%s", "No Session");
3137 } 3137 }
3138 len += snprintf(ptr + len, size - len, ")\n"); 3138 len += snprintf(ptr + len, size - len, ")\n");
3139 } 3139 }
3140 return len; 3140 return len;
3141} 3141}
3142 3142
3143int  3143int
3144initiator_discover(char *host, uint64_t target, int lun) 3144initiator_discover(char *host, uint64_t target, int lun)
3145{ 3145{
3146 iscsi_nop_out_args_t discover_cmd; 3146 iscsi_nop_out_args_t discover_cmd;
3147 initiator_cmd_t cmd; 3147 initiator_cmd_t cmd;
3148 3148
3149 cmd.type = ISCSI_NOP_OUT; 3149 cmd.type = ISCSI_NOP_OUT;
3150 cmd.ptr = &discover_cmd; 3150 cmd.ptr = &discover_cmd;
3151 cmd.isid = target; 3151 cmd.isid = target;
3152 (void) strlcpy(cmd.targetname, host, sizeof(cmd.targetname)); 3152 (void) strlcpy(cmd.targetname, host, sizeof(cmd.targetname));
3153 (void) memset(&discover_cmd, 0x0, sizeof(iscsi_nop_out_args_t)); 3153 (void) memset(&discover_cmd, 0x0, sizeof(iscsi_nop_out_args_t));
3154 discover_cmd.length = 1; 3154 discover_cmd.length = 1;
3155 discover_cmd.data = (const uint8_t *) ""; 3155 discover_cmd.data = (const uint8_t *) "";
3156 discover_cmd.lun = lun; 3156 discover_cmd.lun = lun;
3157 discover_cmd.tag = 0xffffffff; 3157 discover_cmd.tag = 0xffffffff;
3158 if (initiator_command(&cmd) != 0) { 3158 if (initiator_command(&cmd) != 0) {
3159 iscsi_trace_error(__FILE__, __LINE__, "initiator_command() failed\n"); 3159 iscsi_trace_error(__FILE__, __LINE__, "initiator_command() failed\n");
3160 return -1; 3160 return -1;
3161 } 3161 }
3162 return 0; 3162 return 0;
3163} 3163}
3164 3164
3165void 3165void
3166get_target_info(uint64_t target, initiator_target_t *ip) 3166get_target_info(uint64_t target, initiator_target_t *ip)
3167{ 3167{
3168 (void) memcpy(ip, &g_target[target], sizeof(*ip)); 3168 (void) memcpy(ip, &g_target[target], sizeof(*ip));
3169} 3169}
3170 3170
3171int  3171int
3172ii_initiator_init(const char *hostname, int port, int address_family, const char *user, char *lun, int auth_type, int mutual_auth, int digest_type) 3172ii_initiator_init(const char *hostname, int port, int address_family, const char *user, char *lun, int auth_type, int mutual_auth, int digest_type)
3173{ 3173{
3174 initiator_session_t *sess = NULL; 3174 initiator_session_t *sess = NULL;
3175 3175
3176#define INIT_CLEANUP {if (sess != NULL) iscsi_free_atomic(sess);} 3176#define INIT_CLEANUP {if (sess != NULL) iscsi_free_atomic(sess);}
3177#define INIT_ERROR {INIT_CLEANUP; return -1;} 3177#define INIT_ERROR {INIT_CLEANUP; return -1;}
3178 3178
3179 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "initializing initiator\n"); 3179 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "initializing initiator\n");
3180 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "target config filename to read from:%s\n", gfilename); 3180 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "target config filename to read from:%s\n", gfilename);
3181 if (get_target_config(hostname, port) != 0) { 3181 if (get_target_config(hostname, port) != 0) {
3182 iscsi_trace_error(__FILE__, __LINE__, "Error getting target configuration from config file\n"); 3182 iscsi_trace_error(__FILE__, __LINE__, "Error getting target configuration from config file\n");
3183 return -1; 3183 return -1;
3184 } 3184 }
3185 (void) strlcpy(g_target[0].iqnwanted, lun, sizeof(g_target[0].iqnwanted)); 3185 (void) strlcpy(g_target[0].iqnwanted, lun, sizeof(g_target[0].iqnwanted));
3186 g_initiator_state = 0; 3186 g_initiator_state = 0;
3187 if (iscsi_queue_init(&g_session_q, CONFIG_INITIATOR_MAX_SESSIONS) != 0) { 3187 if (iscsi_queue_init(&g_session_q, CONFIG_INITIATOR_MAX_SESSIONS) != 0) {
3188 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_init() failed\n"); 3188 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_init() failed\n");
3189 return -1; 3189 return -1;
3190 } 3190 }
3191 if ((sess = iscsi_malloc_atomic(sizeof(initiator_session_t))) == NULL) { 3191 if ((sess = iscsi_malloc_atomic(sizeof(initiator_session_t))) == NULL) {
3192 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n"); 3192 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
3193 return -1; 3193 return -1;
3194 } 3194 }
3195 if (iscsi_queue_insert(&g_session_q, sess) != 0) { 3195 if (iscsi_queue_insert(&g_session_q, sess) != 0) {
3196 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_init() failed\n"); 3196 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_init() failed\n");
3197 INIT_CLEANUP; 3197 INIT_CLEANUP;
3198 return -1; 3198 return -1;
3199 } 3199 }
3200 sess->sess_params.cred.user = strdup(user); 3200 sess->sess_params.cred.user = strdup(user);
3201 sess->sess_params.auth_type = auth_type; 3201 sess->sess_params.auth_type = auth_type;
3202 sess->sess_params.mutual_auth = mutual_auth; 3202 sess->sess_params.mutual_auth = mutual_auth;
3203 sess->sess_params.digest_wanted = digest_type; 3203 sess->sess_params.digest_wanted = digest_type;
3204 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "%d free sessions available\n", CONFIG_INITIATOR_MAX_SESSIONS); 3204 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "%d free sessions available\n", CONFIG_INITIATOR_MAX_SESSIONS);
3205 3205
3206 g_tag = 0xabc123; 3206 g_tag = 0xabc123;
3207 if (hash_init(&g_tag_hash, CONFIG_INITIATOR_QUEUE_DEPTH) != 0) { 3207 if (hash_init(&g_tag_hash, CONFIG_INITIATOR_QUEUE_DEPTH) != 0) {
3208 iscsi_trace_error(__FILE__, __LINE__, "hash_init() failed\n"); 3208 iscsi_trace_error(__FILE__, __LINE__, "hash_init() failed\n");
3209 INIT_CLEANUP; 3209 INIT_CLEANUP;
3210 return -1; 3210 return -1;
3211 } 3211 }
3212 iscsi_spin_init(&g_tag_spin); 3212 iscsi_spin_init(&g_tag_spin);
3213 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tag hash table initialized with queue depth %d\n", CONFIG_INITIATOR_QUEUE_DEPTH); 3213 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "tag hash table initialized with queue depth %d\n", CONFIG_INITIATOR_QUEUE_DEPTH);
3214 3214
3215 /* 3215 /*
3216 * Start enqueue worker. This thread accepts scsi commands 3216 * Start enqueue worker. This thread accepts scsi commands
3217 * from initiator_enqueue() and queues them onto one of the tx 3217 * from initiator_enqueue() and queues them onto one of the tx
3218 * worker queues. 3218 * worker queues.
3219 */ 3219 */
3220 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "starting enqueue worker\n"); 3220 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "starting enqueue worker\n");
3221 if (iscsi_queue_init(&g_enqueue_q, CONFIG_INITIATOR_QUEUE_DEPTH) != 0) { 3221 if (iscsi_queue_init(&g_enqueue_q, CONFIG_INITIATOR_QUEUE_DEPTH) != 0) {
3222 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_init() failed\n"); 3222 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_init() failed\n");
3223 INIT_CLEANUP; 3223 INIT_CLEANUP;
3224 return -1; 3224 return -1;
3225 } 3225 }
3226 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "about to initialize mutex\n"); 3226 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "about to initialize mutex\n");
3227 ISCSI_MUTEX_INIT(&g_enqueue_worker.work_mutex, INIT_ERROR); 3227 ISCSI_MUTEX_INIT(&g_enqueue_worker.work_mutex, INIT_ERROR);
3228 ISCSI_COND_INIT(&g_enqueue_worker.work_cond, INIT_ERROR); 3228 ISCSI_COND_INIT(&g_enqueue_worker.work_cond, INIT_ERROR);
3229 ISCSI_MUTEX_INIT(&g_enqueue_worker.exit_mutex, INIT_ERROR); 3229 ISCSI_MUTEX_INIT(&g_enqueue_worker.exit_mutex, INIT_ERROR);
3230 ISCSI_COND_INIT(&g_enqueue_worker.exit_cond, INIT_ERROR); 3230 ISCSI_COND_INIT(&g_enqueue_worker.exit_cond, INIT_ERROR);
3231 ISCSI_LOCK(&g_enqueue_worker.exit_mutex, INIT_ERROR); 3231 ISCSI_LOCK(&g_enqueue_worker.exit_mutex, INIT_ERROR);
3232 3232
3233 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "spawning thread for enqueue worker\n"); 3233 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "spawning thread for enqueue worker\n");
3234 if (iscsi_thread_create(&g_enqueue_worker.thread, (void *) &enqueue_worker_proc, &g_enqueue_worker) != 0) { 3234 if (iscsi_thread_create(&g_enqueue_worker.thread, (void *) &enqueue_worker_proc, &g_enqueue_worker) != 0) {
3235 iscsi_trace_error(__FILE__, __LINE__, "iscsi_threads_create() failed\n"); 3235 iscsi_trace_error(__FILE__, __LINE__, "iscsi_threads_create() failed\n");
3236 INIT_CLEANUP; 3236 INIT_CLEANUP;
3237 return -1; 3237 return -1;
3238 } 3238 }
3239 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "thread spawned, waiting for signal\n"); 3239 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "thread spawned, waiting for signal\n");
3240 ISCSI_WAIT(&g_enqueue_worker.exit_cond, &g_enqueue_worker.exit_mutex, INIT_ERROR); 3240 ISCSI_WAIT(&g_enqueue_worker.exit_cond, &g_enqueue_worker.exit_mutex, INIT_ERROR);
3241 ISCSI_UNLOCK(&g_enqueue_worker.exit_mutex, INIT_ERROR); 3241 ISCSI_UNLOCK(&g_enqueue_worker.exit_mutex, INIT_ERROR);
3242 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully started enqueue worker\n"); 3242 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully started enqueue worker\n");
3243 3243
3244 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "initiator initialization complete\n"); 3244 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "initiator initialization complete\n");
3245 return 0; 3245 return 0;
3246} 3246}