xref: /spdk/lib/iscsi/conn.c (revision d1165a653907c85812beba21bf9cb6c657cf3bf1)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
5  *   Copyright (c) Intel Corporation.
6  *   All rights reserved.
7  *
8  *   Redistribution and use in source and binary forms, with or without
9  *   modification, are permitted provided that the following conditions
10  *   are met:
11  *
12  *     * Redistributions of source code must retain the above copyright
13  *       notice, this list of conditions and the following disclaimer.
14  *     * Redistributions in binary form must reproduce the above copyright
15  *       notice, this list of conditions and the following disclaimer in
16  *       the documentation and/or other materials provided with the
17  *       distribution.
18  *     * Neither the name of Intel Corporation nor the names of its
19  *       contributors may be used to endorse or promote products derived
20  *       from this software without specific prior written permission.
21  *
22  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include "spdk/stdinc.h"
36 
37 #if defined(__FreeBSD__)
38 #include <sys/event.h>
39 #else
40 #include <sys/epoll.h>
41 #endif
42 
43 #include "spdk/endian.h"
44 #include "spdk/env.h"
45 #include "spdk/event.h"
46 #include "spdk/io_channel.h"
47 #include "spdk/queue.h"
48 #include "spdk/trace.h"
49 #include "spdk/net.h"
50 #include "spdk/sock.h"
51 #include "spdk/string.h"
52 
53 #include "spdk_internal/log.h"
54 
55 #include "iscsi/task.h"
56 #include "iscsi/conn.h"
57 #include "iscsi/tgt_node.h"
58 #include "iscsi/portal_grp.h"
59 #include "spdk/scsi.h"
60 
61 #define SPDK_ISCSI_CONNECTION_MEMSET(conn)		\
62 	memset(&(conn)->portal, 0, sizeof(*(conn)) -	\
63 		offsetof(struct spdk_iscsi_conn, portal));
64 
65 #define DEFAULT_CONNECTIONS_PER_LCORE	4
66 #define SPDK_MAX_POLLERS_PER_CORE	4096
67 static int g_connections_per_lcore = DEFAULT_CONNECTIONS_PER_LCORE;
68 static uint32_t *g_num_connections;
69 
70 struct spdk_iscsi_conn *g_conns_array;
71 static char g_shm_name[64];
72 
73 static pthread_mutex_t g_conns_mutex;
74 
75 static struct spdk_poller *g_shutdown_timer = NULL;
76 
77 static uint32_t spdk_iscsi_conn_allocate_reactor(const struct spdk_cpuset *cpumask);
78 
79 void spdk_iscsi_conn_login_do_work(void *arg);
80 void spdk_iscsi_conn_full_feature_do_work(void *arg);
81 
82 static void spdk_iscsi_conn_full_feature_migrate(void *arg1, void *arg2);
83 static void spdk_iscsi_conn_stop(struct spdk_iscsi_conn *conn);
84 static void spdk_iscsi_conn_sock_cb(void *arg, struct spdk_sock_group *group,
85 				    struct spdk_sock *sock);
86 
87 static struct spdk_iscsi_conn *
88 allocate_conn(void)
89 {
90 	struct spdk_iscsi_conn	*conn;
91 	int				i;
92 
93 	pthread_mutex_lock(&g_conns_mutex);
94 	for (i = 0; i < MAX_ISCSI_CONNECTIONS; i++) {
95 		conn = &g_conns_array[i];
96 		if (!conn->is_valid) {
97 			SPDK_ISCSI_CONNECTION_MEMSET(conn);
98 			conn->is_valid = 1;
99 			pthread_mutex_unlock(&g_conns_mutex);
100 			return conn;
101 		}
102 	}
103 	pthread_mutex_unlock(&g_conns_mutex);
104 
105 	return NULL;
106 }
107 
108 static void
109 free_conn(struct spdk_iscsi_conn *conn)
110 {
111 	free(conn->portal_host);
112 	free(conn->portal_port);
113 	conn->is_valid = 0;
114 }
115 
116 static struct spdk_iscsi_conn *
117 spdk_find_iscsi_connection_by_id(int cid)
118 {
119 	if (g_conns_array[cid].is_valid == 1) {
120 		return &g_conns_array[cid];
121 	} else {
122 		return NULL;
123 	}
124 }
125 
126 int spdk_initialize_iscsi_conns(void)
127 {
128 	size_t conns_size;
129 	int conns_array_fd, rc;
130 	uint32_t i, last_core;
131 
132 	SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "spdk_iscsi_init\n");
133 
134 	rc = pthread_mutex_init(&g_conns_mutex, NULL);
135 	if (rc != 0) {
136 		SPDK_ERRLOG("mutex_init() failed\n");
137 		return -1;
138 	}
139 
140 	snprintf(g_shm_name, sizeof(g_shm_name), "/spdk_iscsi_conns.%d", spdk_app_get_shm_id());
141 	conns_array_fd = shm_open(g_shm_name, O_RDWR | O_CREAT, 0600);
142 	if (conns_array_fd < 0) {
143 		SPDK_ERRLOG("could not shm_open %s\n", g_shm_name);
144 		return -1;
145 	}
146 
147 	conns_size = sizeof(struct spdk_iscsi_conn) * MAX_ISCSI_CONNECTIONS;
148 
149 	if (ftruncate(conns_array_fd, conns_size) != 0) {
150 		SPDK_ERRLOG("could not ftruncate\n");
151 		close(conns_array_fd);
152 		shm_unlink(g_shm_name);
153 		return -1;
154 	}
155 	g_conns_array = mmap(0, conns_size, PROT_READ | PROT_WRITE, MAP_SHARED,
156 			     conns_array_fd, 0);
157 
158 	memset(g_conns_array, 0, conns_size);
159 
160 	for (i = 0; i < MAX_ISCSI_CONNECTIONS; i++) {
161 		g_conns_array[i].id = i;
162 	}
163 
164 	last_core = spdk_env_get_last_core();
165 	g_num_connections = calloc(last_core + 1, sizeof(uint32_t));
166 	if (!g_num_connections) {
167 		SPDK_ERRLOG("Could not allocate array size=%u for g_num_connections\n",
168 			    last_core + 1);
169 		return -1;
170 	}
171 
172 	return 0;
173 }
174 
175 static void
176 spdk_iscsi_poll_group_add_conn_sock(struct spdk_iscsi_conn *conn)
177 {
178 	struct spdk_iscsi_poll_group *poll_group = &g_spdk_iscsi.poll_group[spdk_env_get_current_core()];
179 	int rc;
180 
181 	rc = spdk_sock_group_add_sock(poll_group->sock_group, conn->sock, spdk_iscsi_conn_sock_cb, conn);
182 	if (rc < 0) {
183 		SPDK_ERRLOG("Failed to add sock=%p of conn=%p\n", conn->sock, conn);
184 	}
185 }
186 
187 static void
188 spdk_iscsi_poll_group_remove_conn_sock(struct spdk_iscsi_conn *conn)
189 {
190 	struct spdk_iscsi_poll_group *poll_group = &g_spdk_iscsi.poll_group[spdk_env_get_current_core()];
191 	int rc;
192 
193 	rc = spdk_sock_group_remove_sock(poll_group->sock_group, conn->sock);
194 	if (rc < 0) {
195 		SPDK_ERRLOG("Failed to remove sock=%p of conn=%p\n", conn->sock, conn);
196 	}
197 }
198 
199 static void
200 spdk_iscsi_poll_group_add_conn(struct spdk_iscsi_conn *conn,
201 			       spdk_iscsi_conn_fn fn)
202 {
203 	struct spdk_iscsi_poll_group *poll_group = &g_spdk_iscsi.poll_group[spdk_env_get_current_core()];
204 
205 	conn->fn = fn;
206 	STAILQ_INSERT_TAIL(&poll_group->connections, conn, link);
207 	spdk_iscsi_poll_group_add_conn_sock(conn);
208 }
209 
210 static void
211 spdk_iscsi_poll_group_remove_conn(struct spdk_iscsi_conn *conn)
212 {
213 	struct spdk_iscsi_poll_group *poll_group = &g_spdk_iscsi.poll_group[spdk_env_get_current_core()];
214 
215 	STAILQ_REMOVE(&poll_group->connections, conn, spdk_iscsi_conn, link);
216 }
217 
218 /**
219  * \brief Create an iSCSI connection from the given parameters and schedule it
220  *        on a reactor.
221  *
222  * \code
223  *
224  * # identify reactor where the new connections work item will be scheduled
225  * reactor = spdk_iscsi_conn_allocate_reactor()
226  * allocate spdk_iscsi_conn object
227  * initialize spdk_iscsi_conn object
228  * schedule iSCSI connection work item on reactor
229  *
230  * \endcode
231  */
232 int
233 spdk_iscsi_conn_construct(struct spdk_iscsi_portal *portal,
234 			  struct spdk_sock *sock)
235 {
236 	struct spdk_iscsi_conn *conn;
237 	int bufsize, i, rc;
238 
239 	conn = allocate_conn();
240 	if (conn == NULL) {
241 		SPDK_ERRLOG("Could not allocate connection.\n");
242 		return -1;
243 	}
244 
245 	pthread_mutex_lock(&g_spdk_iscsi.mutex);
246 	conn->timeout = g_spdk_iscsi.timeout;
247 	conn->nopininterval = g_spdk_iscsi.nopininterval;
248 	conn->nopininterval *= spdk_get_ticks_hz(); /* seconds to TSC */
249 	conn->nop_outstanding = false;
250 	conn->data_out_cnt = 0;
251 	conn->data_in_cnt = 0;
252 	pthread_mutex_unlock(&g_spdk_iscsi.mutex);
253 	conn->MaxRecvDataSegmentLength = 8192; // RFC3720(12.12)
254 
255 	conn->portal = portal;
256 	conn->pg_tag = portal->group->tag;
257 	conn->portal_host = strdup(portal->host);
258 	conn->portal_port = strdup(portal->port);
259 	conn->portal_cpumask = portal->cpumask;
260 	conn->sock = sock;
261 
262 	conn->state = ISCSI_CONN_STATE_INVALID;
263 	conn->login_phase = ISCSI_SECURITY_NEGOTIATION_PHASE;
264 	conn->ttt = 0;
265 
266 	conn->partial_text_parameter = NULL;
267 
268 	for (i = 0; i < MAX_CONNECTION_PARAMS; i++) {
269 		conn->conn_param_state_negotiated[i] = false;
270 	}
271 
272 	for (i = 0; i < MAX_SESSION_PARAMS; i++) {
273 		conn->sess_param_state_negotiated[i] = false;
274 	}
275 
276 	for (i = 0; i < DEFAULT_MAXR2T; i++) {
277 		conn->outstanding_r2t_tasks[i] = NULL;
278 	}
279 
280 	TAILQ_INIT(&conn->write_pdu_list);
281 	TAILQ_INIT(&conn->snack_pdu_list);
282 	TAILQ_INIT(&conn->queued_r2t_tasks);
283 	TAILQ_INIT(&conn->active_r2t_tasks);
284 	TAILQ_INIT(&conn->queued_datain_tasks);
285 
286 	rc = spdk_sock_getaddr(sock, conn->target_addr,
287 			       sizeof conn->target_addr,
288 			       conn->initiator_addr, sizeof conn->initiator_addr);
289 	if (rc < 0) {
290 		SPDK_ERRLOG("spdk_sock_getaddr() failed\n");
291 		goto error_return;
292 	}
293 
294 	bufsize = 2 * 1024 * 1024;
295 	rc = spdk_sock_set_recvbuf(conn->sock, bufsize);
296 	if (rc != 0) {
297 		SPDK_ERRLOG("spdk_sock_set_recvbuf failed\n");
298 	}
299 
300 	bufsize = 32 * 1024 * 1024 / g_spdk_iscsi.MaxConnections;
301 	if (bufsize > 2 * 1024 * 1024) {
302 		bufsize = 2 * 1024 * 1024;
303 	}
304 	rc = spdk_sock_set_sendbuf(conn->sock, bufsize);
305 	if (rc != 0) {
306 		SPDK_ERRLOG("spdk_sock_set_sendbuf failed\n");
307 	}
308 
309 	/* set low water mark */
310 	rc = spdk_sock_set_recvlowat(conn->sock, 1);
311 	if (rc != 0) {
312 		SPDK_ERRLOG("spdk_sock_set_recvlowat() failed\n");
313 		goto error_return;
314 	}
315 
316 	/* set default params */
317 	rc = spdk_iscsi_conn_params_init(&conn->params);
318 	if (rc < 0) {
319 		SPDK_ERRLOG("iscsi_conn_params_init() failed\n");
320 error_return:
321 		spdk_iscsi_param_free(conn->params);
322 		free_conn(conn);
323 		return -1;
324 	}
325 	conn->logout_timer = NULL;
326 	conn->shutdown_timer = NULL;
327 	SPDK_NOTICELOG("Launching connection on acceptor thread\n");
328 	conn->pending_task_cnt = 0;
329 	conn->pending_activate_event = false;
330 
331 	conn->lcore = spdk_env_get_current_core();
332 	__sync_fetch_and_add(&g_num_connections[conn->lcore], 1);
333 
334 	spdk_iscsi_poll_group_add_conn(conn, spdk_iscsi_conn_login_do_work);
335 	return 0;
336 }
337 
338 void
339 spdk_iscsi_conn_free_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
340 {
341 	if (pdu->task) {
342 		if (pdu->bhs.opcode == ISCSI_OP_SCSI_DATAIN) {
343 			if (pdu->task->scsi.offset > 0) {
344 				conn->data_in_cnt--;
345 				if (pdu->bhs.flags & ISCSI_DATAIN_STATUS) {
346 					/* Free the primary task after the last subtask done */
347 					conn->data_in_cnt--;
348 					spdk_iscsi_task_put(spdk_iscsi_task_get_primary(pdu->task));
349 				}
350 			}
351 		} else if (pdu->bhs.opcode == ISCSI_OP_SCSI_RSP &&
352 			   pdu->task->scsi.status != SPDK_SCSI_STATUS_GOOD) {
353 			if (pdu->task->scsi.offset > 0) {
354 				spdk_iscsi_task_put(spdk_iscsi_task_get_primary(pdu->task));
355 			}
356 		}
357 		spdk_iscsi_task_put(pdu->task);
358 	}
359 	spdk_put_pdu(pdu);
360 }
361 
362 static int spdk_iscsi_conn_free_tasks(struct spdk_iscsi_conn *conn)
363 {
364 	struct spdk_iscsi_pdu *pdu;
365 	struct spdk_iscsi_task *iscsi_task;
366 
367 	while (!TAILQ_EMPTY(&conn->write_pdu_list)) {
368 		pdu = TAILQ_FIRST(&conn->write_pdu_list);
369 		TAILQ_REMOVE(&conn->write_pdu_list, pdu, tailq);
370 		if (pdu->task) {
371 			spdk_iscsi_task_put(pdu->task);
372 		}
373 		spdk_put_pdu(pdu);
374 	}
375 
376 	while (!TAILQ_EMPTY(&conn->snack_pdu_list)) {
377 		pdu = TAILQ_FIRST(&conn->snack_pdu_list);
378 		TAILQ_REMOVE(&conn->snack_pdu_list, pdu, tailq);
379 		if (pdu->task) {
380 			spdk_iscsi_task_put(pdu->task);
381 		}
382 		spdk_put_pdu(pdu);
383 	}
384 
385 	while (!TAILQ_EMPTY(&conn->queued_datain_tasks)) {
386 		iscsi_task = TAILQ_FIRST(&conn->queued_datain_tasks);
387 		TAILQ_REMOVE(&conn->queued_datain_tasks, iscsi_task, link);
388 		pdu = iscsi_task->pdu;
389 		spdk_iscsi_task_put(iscsi_task);
390 		spdk_put_pdu(pdu);
391 	}
392 
393 	if (conn->pending_task_cnt) {
394 		return -1;
395 	}
396 
397 	return 0;
398 
399 }
400 
401 static void spdk_iscsi_conn_free(struct spdk_iscsi_conn *conn)
402 {
403 
404 	if (conn == NULL) {
405 		return;
406 	}
407 
408 	spdk_iscsi_param_free(conn->params);
409 
410 	/*
411 	 * Each connection pre-allocates its next PDU - make sure these get
412 	 *  freed here.
413 	 */
414 	spdk_put_pdu(conn->pdu_in_progress);
415 
416 	free(conn->auth.user);
417 	free(conn->auth.secret);
418 	free(conn->auth.muser);
419 	free(conn->auth.msecret);
420 	free_conn(conn);
421 }
422 
423 static void spdk_iscsi_remove_conn(struct spdk_iscsi_conn *conn)
424 {
425 	struct spdk_iscsi_sess *sess;
426 	int idx;
427 	uint32_t i, j;
428 
429 	idx = -1;
430 	sess = conn->sess;
431 	conn->sess = NULL;
432 	if (sess == NULL) {
433 		spdk_iscsi_conn_free(conn);
434 		return;
435 	}
436 
437 	for (i = 0; i < sess->connections; i++) {
438 		if (sess->conns[i] == conn) {
439 			idx = i;
440 			break;
441 		}
442 	}
443 
444 	if (sess->connections < 1) {
445 		SPDK_ERRLOG("zero connection\n");
446 		sess->connections = 0;
447 	} else {
448 		if (idx < 0) {
449 			SPDK_ERRLOG("remove conn not found\n");
450 		} else {
451 			for (j = idx; j < sess->connections - 1; j++) {
452 				sess->conns[j] = sess->conns[j + 1];
453 			}
454 			sess->conns[sess->connections - 1] = NULL;
455 		}
456 		sess->connections--;
457 	}
458 
459 	SPDK_NOTICELOG("Terminating connections(tsih %d): %d\n", sess->tsih, sess->connections);
460 
461 	if (sess->connections == 0) {
462 		/* cleanup last connection */
463 		SPDK_DEBUGLOG(SPDK_LOG_ISCSI,
464 			      "cleanup last conn free sess\n");
465 		spdk_free_sess(sess);
466 	}
467 
468 
469 	SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "cleanup free conn\n");
470 	spdk_iscsi_conn_free(conn);
471 }
472 
473 static void
474 spdk_iscsi_conn_cleanup_backend(struct spdk_iscsi_conn *conn)
475 {
476 	int rc;
477 
478 	if (conn->sess->connections > 1) {
479 		/* connection specific cleanup */
480 	} else if (!g_spdk_iscsi.AllowDuplicateIsid) {
481 		/* clean up all tasks to all LUNs for session */
482 		rc = spdk_iscsi_tgt_node_cleanup_luns(conn,
483 						      conn->sess->target);
484 		if (rc < 0) {
485 			SPDK_ERRLOG("target abort failed\n");
486 		}
487 	}
488 }
489 
490 static void
491 _spdk_iscsi_conn_free(struct spdk_iscsi_conn *conn)
492 {
493 	pthread_mutex_lock(&g_conns_mutex);
494 	spdk_iscsi_remove_conn(conn);
495 	pthread_mutex_unlock(&g_conns_mutex);
496 }
497 
498 static void
499 _spdk_iscsi_conn_check_shutdown(void *arg)
500 {
501 	struct spdk_iscsi_conn *conn = arg;
502 	int rc;
503 
504 	rc = spdk_iscsi_conn_free_tasks(conn);
505 	if (rc < 0) {
506 		return;
507 	}
508 
509 	spdk_poller_unregister(&conn->shutdown_timer);
510 
511 	spdk_iscsi_conn_stop(conn);
512 	_spdk_iscsi_conn_free(conn);
513 }
514 
515 void spdk_iscsi_conn_destruct(struct spdk_iscsi_conn *conn)
516 {
517 	struct spdk_iscsi_tgt_node	*target;
518 	int				rc;
519 
520 	conn->state = ISCSI_CONN_STATE_EXITED;
521 
522 	if (conn->sess != NULL && conn->pending_task_cnt > 0) {
523 		target = conn->sess->target;
524 		if (target != NULL) {
525 			spdk_iscsi_conn_cleanup_backend(conn);
526 		}
527 	}
528 
529 	spdk_clear_all_transfer_task(conn, NULL);
530 	spdk_iscsi_poll_group_remove_conn_sock(conn);
531 	spdk_sock_close(&conn->sock);
532 	spdk_poller_unregister(&conn->logout_timer);
533 	spdk_poller_unregister(&conn->flush_poller);
534 
535 	rc = spdk_iscsi_conn_free_tasks(conn);
536 	if (rc < 0) {
537 		/* The connection cannot be freed yet. Check back later. */
538 		conn->shutdown_timer = spdk_poller_register(_spdk_iscsi_conn_check_shutdown, conn, 1000);
539 	} else {
540 		spdk_iscsi_conn_stop(conn);
541 		_spdk_iscsi_conn_free(conn);
542 	}
543 }
544 
545 static int
546 spdk_iscsi_get_active_conns(void)
547 {
548 	struct spdk_iscsi_conn *conn;
549 	int num = 0;
550 	int i;
551 
552 	pthread_mutex_lock(&g_conns_mutex);
553 	for (i = 0; i < MAX_ISCSI_CONNECTIONS; i++) {
554 		conn = spdk_find_iscsi_connection_by_id(i);
555 		if (conn == NULL) {
556 			continue;
557 		}
558 		num++;
559 	}
560 	pthread_mutex_unlock(&g_conns_mutex);
561 	return num;
562 }
563 
564 static void
565 spdk_iscsi_conns_cleanup(void)
566 {
567 	free(g_num_connections);
568 	munmap(g_conns_array, sizeof(struct spdk_iscsi_conn) *
569 	       MAX_ISCSI_CONNECTIONS);
570 	shm_unlink(g_shm_name);
571 }
572 
573 static void
574 spdk_iscsi_conn_check_shutdown_cb(void *arg1, void *arg2)
575 {
576 	spdk_iscsi_conns_cleanup();
577 	spdk_shutdown_iscsi_conns_done();
578 }
579 
580 static void
581 spdk_iscsi_conn_check_shutdown(void *arg)
582 {
583 	struct spdk_event *event;
584 
585 	if (spdk_iscsi_get_active_conns() == 0) {
586 		spdk_poller_unregister(&g_shutdown_timer);
587 		event = spdk_event_allocate(spdk_env_get_current_core(), spdk_iscsi_conn_check_shutdown_cb, NULL,
588 					    NULL);
589 		spdk_event_call(event);
590 	}
591 }
592 
593 /**
594  *  This function will stop executing the specified connection.
595  */
596 static void
597 spdk_iscsi_conn_stop(struct spdk_iscsi_conn *conn)
598 {
599 	struct spdk_iscsi_tgt_node *target;
600 
601 	if (conn->state == ISCSI_CONN_STATE_EXITED && conn->sess != NULL &&
602 	    conn->sess->session_type == SESSION_TYPE_NORMAL &&
603 	    conn->full_feature) {
604 		target = conn->sess->target;
605 		pthread_mutex_lock(&target->mutex);
606 		target->num_active_conns--;
607 		pthread_mutex_unlock(&target->mutex);
608 
609 		assert(conn->dev != NULL);
610 		spdk_scsi_dev_free_io_channels(conn->dev);
611 	}
612 
613 	__sync_fetch_and_sub(&g_num_connections[spdk_env_get_current_core()], 1);
614 	spdk_iscsi_poll_group_remove_conn(conn);
615 }
616 
617 void spdk_shutdown_iscsi_conns(void)
618 {
619 	struct spdk_iscsi_conn	*conn;
620 	int			i;
621 
622 	pthread_mutex_lock(&g_conns_mutex);
623 
624 	for (i = 0; i < MAX_ISCSI_CONNECTIONS; i++) {
625 		conn = spdk_find_iscsi_connection_by_id(i);
626 		if (conn == NULL) {
627 			continue;
628 		}
629 		conn->state = ISCSI_CONN_STATE_EXITING;
630 	}
631 
632 	pthread_mutex_unlock(&g_conns_mutex);
633 	g_shutdown_timer = spdk_poller_register(spdk_iscsi_conn_check_shutdown, NULL,
634 						1000);
635 }
636 
637 int
638 spdk_iscsi_drop_conns(struct spdk_iscsi_conn *conn, const char *conn_match,
639 		      int drop_all)
640 {
641 	struct spdk_iscsi_conn	*xconn;
642 	const char			*xconn_match;
643 	int				i, num;
644 
645 	SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "spdk_iscsi_drop_conns\n");
646 
647 	num = 0;
648 	pthread_mutex_lock(&g_conns_mutex);
649 	for (i = 0; i < MAX_ISCSI_CONNECTIONS; i++) {
650 		xconn = spdk_find_iscsi_connection_by_id(i);
651 
652 		if (xconn == NULL) {
653 			continue;
654 		}
655 
656 		if (xconn == conn) {
657 			continue;
658 		}
659 
660 		if (!drop_all && xconn->initiator_port == NULL) {
661 			continue;
662 		}
663 
664 		xconn_match =
665 			drop_all ? xconn->initiator_name : spdk_scsi_port_get_name(xconn->initiator_port);
666 
667 		if (!strcasecmp(conn_match, xconn_match) &&
668 		    conn->target == xconn->target) {
669 
670 			if (num == 0) {
671 				/*
672 				 * Only print this message before we report the
673 				 *  first dropped connection.
674 				 */
675 				SPDK_ERRLOG("drop old connections %s by %s\n",
676 					    conn->target->name, conn_match);
677 			}
678 
679 			SPDK_ERRLOG("exiting conn by %s (%s)\n",
680 				    xconn_match, xconn->initiator_addr);
681 			if (xconn->sess != NULL) {
682 				SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "TSIH=%u\n", xconn->sess->tsih);
683 			} else {
684 				SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "TSIH=xx\n");
685 			}
686 
687 			SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "CID=%u\n", xconn->cid);
688 			xconn->state = ISCSI_CONN_STATE_EXITING;
689 			num++;
690 		}
691 	}
692 
693 	pthread_mutex_unlock(&g_conns_mutex);
694 
695 	if (num != 0) {
696 		SPDK_ERRLOG("exiting %d conns\n", num);
697 	}
698 
699 	return 0;
700 }
701 
702 /**
703  * \brief Reads data for the specified iSCSI connection from its TCP socket.
704  *
705  * The TCP socket is marked as non-blocking, so this function may not read
706  * all data requested.
707  *
708  * Returns SPDK_ISCSI_CONNECTION_FATAL if the recv() operation indicates a fatal
709  * error with the TCP connection (including if the TCP connection was closed
710  * unexpectedly.
711  *
712  * Otherwise returns the number of bytes successfully read.
713  */
714 int
715 spdk_iscsi_conn_read_data(struct spdk_iscsi_conn *conn, int bytes,
716 			  void *buf)
717 {
718 	int ret;
719 
720 	if (bytes == 0) {
721 		return 0;
722 	}
723 
724 	ret = spdk_sock_recv(conn->sock, buf, bytes);
725 
726 	if (ret > 0) {
727 		spdk_trace_record(TRACE_READ_FROM_SOCKET_DONE, conn->id, ret, 0, 0);
728 	}
729 
730 	if (ret < 0) {
731 		if (errno == EAGAIN || errno == EWOULDBLOCK) {
732 			return 0;
733 		} else {
734 			SPDK_ERRLOG("spdk_sock_recv() failed, errno %d: %s\n",
735 				    errno, spdk_strerror(errno));
736 		}
737 		return SPDK_ISCSI_CONNECTION_FATAL;
738 	}
739 
740 	/* connection closed */
741 	if (ret == 0) {
742 		return SPDK_ISCSI_CONNECTION_FATAL;
743 	}
744 
745 	return ret;
746 }
747 
748 void
749 spdk_iscsi_task_mgmt_cpl(struct spdk_scsi_task *scsi_task)
750 {
751 	struct spdk_iscsi_task *task = spdk_iscsi_task_from_scsi_task(scsi_task);
752 
753 	spdk_iscsi_task_mgmt_response(task->conn, task);
754 	spdk_iscsi_task_put(task);
755 }
756 
757 static void
758 process_completed_read_subtask_list(struct spdk_iscsi_conn *conn,
759 				    struct spdk_iscsi_task *primary)
760 {
761 	struct spdk_iscsi_task *tmp;
762 
763 	while (!TAILQ_EMPTY(&primary->subtask_list)) {
764 		tmp = TAILQ_FIRST(&primary->subtask_list);
765 		if (tmp->scsi.offset == primary->bytes_completed) {
766 			TAILQ_REMOVE(&primary->subtask_list, tmp, subtask_link);
767 			primary->bytes_completed += tmp->scsi.length;
768 			spdk_iscsi_task_response(conn, tmp);
769 			spdk_iscsi_task_put(tmp);
770 		} else {
771 			break;
772 		}
773 	}
774 }
775 
776 static void
777 process_read_task_completion(struct spdk_iscsi_conn *conn,
778 			     struct spdk_iscsi_task *task,
779 			     struct spdk_iscsi_task *primary)
780 {
781 	struct spdk_iscsi_task *tmp;
782 	bool flag = false;
783 
784 	if (task->scsi.status != SPDK_SCSI_STATUS_GOOD) {
785 		TAILQ_FOREACH(tmp, &primary->subtask_list, subtask_link) {
786 			memcpy(tmp->scsi.sense_data, task->scsi.sense_data,
787 			       task->scsi.sense_data_len);
788 			tmp->scsi.sense_data_len = task->scsi.sense_data_len;
789 			tmp->scsi.status = task->scsi.status;
790 		}
791 	}
792 
793 	if ((task != primary) &&
794 	    (task->scsi.offset != primary->bytes_completed)) {
795 		TAILQ_FOREACH(tmp, &primary->subtask_list, subtask_link) {
796 			if (task->scsi.offset < tmp->scsi.offset) {
797 				TAILQ_INSERT_BEFORE(tmp, task, subtask_link);
798 				flag = true;
799 				break;
800 			}
801 		}
802 		if (!flag) {
803 			TAILQ_INSERT_TAIL(&primary->subtask_list, task, subtask_link);
804 		}
805 		return;
806 	}
807 
808 	primary->bytes_completed += task->scsi.length;
809 	spdk_iscsi_task_response(conn, task);
810 
811 	if ((task != primary) ||
812 	    (task->scsi.transfer_len == task->scsi.length)) {
813 		spdk_iscsi_task_put(task);
814 	}
815 	process_completed_read_subtask_list(conn, primary);
816 }
817 
818 void
819 spdk_iscsi_task_cpl(struct spdk_scsi_task *scsi_task)
820 {
821 	struct spdk_iscsi_task *primary;
822 	struct spdk_iscsi_task *task = spdk_iscsi_task_from_scsi_task(scsi_task);
823 	struct spdk_iscsi_conn *conn = task->conn;
824 
825 	spdk_trace_record(TRACE_ISCSI_TASK_DONE, conn->id, 0, (uintptr_t)task, 0);
826 
827 	primary = spdk_iscsi_task_get_primary(task);
828 
829 	if (spdk_iscsi_task_is_read(primary)) {
830 		process_read_task_completion(conn, task, primary);
831 	} else {
832 		primary->bytes_completed += task->scsi.length;
833 		if ((task != primary) &&
834 		    (task->scsi.status != SPDK_SCSI_STATUS_GOOD)) {
835 			memcpy(primary->scsi.sense_data, task->scsi.sense_data,
836 			       task->scsi.sense_data_len);
837 			primary->scsi.sense_data_len = task->scsi.sense_data_len;
838 			primary->scsi.status = task->scsi.status;
839 		}
840 
841 		if (primary->bytes_completed == primary->scsi.transfer_len) {
842 			spdk_del_transfer_task(conn, primary->tag);
843 			spdk_iscsi_task_response(conn, primary);
844 			/*
845 			 * Check if this is the last task completed for an iSCSI write
846 			 *  that required child subtasks.  If task != primary, we know
847 			 *  for sure that it was part of an iSCSI write with child subtasks.
848 			 *  The trickier case is when the last task completed was the initial
849 			 *  task - in this case the task will have a smaller length than
850 			 *  the overall transfer length.
851 			 */
852 			if (task != primary || task->scsi.length != task->scsi.transfer_len) {
853 				TAILQ_REMOVE(&conn->active_r2t_tasks, primary, link);
854 				spdk_iscsi_task_put(primary);
855 			}
856 		}
857 		spdk_iscsi_task_put(task);
858 	}
859 }
860 
861 static int
862 spdk_iscsi_get_pdu_length(struct spdk_iscsi_pdu *pdu, int header_digest,
863 			  int data_digest)
864 {
865 	int data_len, enable_digest, total;
866 
867 	enable_digest = 1;
868 	if (pdu->bhs.opcode == ISCSI_OP_LOGIN_RSP) {
869 		enable_digest = 0;
870 	}
871 
872 	total = ISCSI_BHS_LEN;
873 
874 	total += (4 * pdu->bhs.total_ahs_len);
875 
876 	if (enable_digest && header_digest) {
877 		total += ISCSI_DIGEST_LEN;
878 	}
879 
880 	data_len = DGET24(pdu->bhs.data_segment_len);
881 	if (data_len > 0) {
882 		total += ISCSI_ALIGN(data_len);
883 		if (enable_digest && data_digest) {
884 			total += ISCSI_DIGEST_LEN;
885 		}
886 	}
887 
888 	return total;
889 }
890 
891 static int
892 spdk_iscsi_conn_handle_nop(struct spdk_iscsi_conn *conn)
893 {
894 	uint64_t	tsc;
895 
896 	/* Check for nop interval expiration */
897 	tsc = spdk_get_ticks();
898 	if (conn->nop_outstanding) {
899 		if ((tsc - conn->last_nopin) > (conn->timeout  * spdk_get_ticks_hz())) {
900 			SPDK_ERRLOG("Timed out waiting for NOP-Out response from initiator\n");
901 			SPDK_ERRLOG("  tsc=0x%lx, last_nopin=0x%lx\n", tsc, conn->last_nopin);
902 			return -1;
903 		}
904 	} else if (tsc - conn->last_nopin > conn->nopininterval) {
905 		conn->last_nopin = tsc;
906 		spdk_iscsi_send_nopin(conn);
907 	}
908 
909 	return 0;
910 }
911 
912 /**
913  * \brief Makes one attempt to flush response PDUs back to the initiator.
914  *
915  * Builds a list of iovecs for response PDUs that must be sent back to the
916  * initiator and passes it to writev().
917  *
918  * Since the socket is non-blocking, writev() may not be able to flush all
919  * of the iovecs, and may even partially flush one of the iovecs.  In this
920  * case, the partially flushed PDU will remain on the write_pdu_list with
921  * an offset pointing to the next byte to be flushed.
922  *
923  * Returns 0 if all PDUs were flushed.
924  *
925  * Returns 1 if some PDUs could not be flushed due to lack of send buffer
926  * space.
927  *
928  * Returns -1 if an exception error occurred indicating the TCP connection
929  * should be closed.
930  */
931 static int
932 spdk_iscsi_conn_flush_pdus_internal(struct spdk_iscsi_conn *conn)
933 {
934 	const int array_size = 32;
935 	struct iovec	iovec_array[array_size];
936 	struct iovec	*iov = iovec_array;
937 	int iovec_cnt = 0;
938 	int bytes = 0;
939 	int total_length = 0;
940 	uint32_t writev_offset;
941 	struct spdk_iscsi_pdu *pdu;
942 	int pdu_length;
943 
944 	pdu = TAILQ_FIRST(&conn->write_pdu_list);
945 
946 	if (pdu == NULL) {
947 		return 0;
948 	}
949 
950 	/*
951 	 * Build up a list of iovecs for the first few PDUs in the
952 	 *  connection's write_pdu_list.
953 	 */
954 	while (pdu != NULL && ((array_size - iovec_cnt) >= 5)) {
955 		pdu_length = spdk_iscsi_get_pdu_length(pdu,
956 						       conn->header_digest,
957 						       conn->data_digest);
958 		iovec_cnt += spdk_iscsi_build_iovecs(conn,
959 						     &iovec_array[iovec_cnt],
960 						     pdu);
961 		total_length += pdu_length;
962 		pdu = TAILQ_NEXT(pdu, tailq);
963 	}
964 
965 	/*
966 	 * Check if the first PDU was partially written out the last time
967 	 *  this function was called, and if so adjust the iovec array
968 	 *  accordingly.
969 	 */
970 	writev_offset = TAILQ_FIRST(&conn->write_pdu_list)->writev_offset;
971 	total_length -= writev_offset;
972 	while (writev_offset > 0) {
973 		if (writev_offset >= iov->iov_len) {
974 			writev_offset -= iov->iov_len;
975 			iov++;
976 			iovec_cnt--;
977 		} else {
978 			iov->iov_len -= writev_offset;
979 			iov->iov_base = (char *)iov->iov_base + writev_offset;
980 			writev_offset = 0;
981 		}
982 	}
983 
984 	spdk_trace_record(TRACE_FLUSH_WRITEBUF_START, conn->id, total_length, 0, iovec_cnt);
985 
986 	bytes = spdk_sock_writev(conn->sock, iov, iovec_cnt);
987 	if (bytes == -1) {
988 		if (errno == EWOULDBLOCK || errno == EAGAIN) {
989 			return 1;
990 		} else {
991 			SPDK_ERRLOG("spdk_sock_writev() failed, errno %d: %s\n",
992 				    errno, spdk_strerror(errno));
993 			return -1;
994 		}
995 	}
996 
997 	spdk_trace_record(TRACE_FLUSH_WRITEBUF_DONE, conn->id, bytes, 0, 0);
998 
999 	pdu = TAILQ_FIRST(&conn->write_pdu_list);
1000 
1001 	/*
1002 	 * Free any PDUs that were fully written.  If a PDU was only
1003 	 *  partially written, update its writev_offset so that next
1004 	 *  time only the unwritten portion will be sent to writev().
1005 	 */
1006 	while (bytes > 0) {
1007 		pdu_length = spdk_iscsi_get_pdu_length(pdu,
1008 						       conn->header_digest,
1009 						       conn->data_digest);
1010 		pdu_length -= pdu->writev_offset;
1011 
1012 		if (bytes >= pdu_length) {
1013 			bytes -= pdu_length;
1014 			TAILQ_REMOVE(&conn->write_pdu_list, pdu, tailq);
1015 
1016 			if ((conn->full_feature) &&
1017 			    (conn->sess->ErrorRecoveryLevel >= 1) &&
1018 			    spdk_iscsi_is_deferred_free_pdu(pdu)) {
1019 				SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "stat_sn=%d\n",
1020 					      from_be32(&pdu->bhs.stat_sn));
1021 				TAILQ_INSERT_TAIL(&conn->snack_pdu_list, pdu,
1022 						  tailq);
1023 			} else {
1024 				spdk_iscsi_conn_free_pdu(conn, pdu);
1025 			}
1026 
1027 			pdu = TAILQ_FIRST(&conn->write_pdu_list);
1028 		} else {
1029 			pdu->writev_offset += bytes;
1030 			bytes = 0;
1031 		}
1032 	}
1033 
1034 	return TAILQ_EMPTY(&conn->write_pdu_list) ? 0 : 1;
1035 }
1036 
1037 /**
1038  * \brief Flushes response PDUs back to the initiator.
1039  *
1040  * This function may return without all PDUs having flushed to the
1041  * underlying TCP socket buffer - for example, in the case where the
1042  * socket buffer is already full.
1043  *
1044  * During normal RUNNING connection state, if not all PDUs are flushed,
1045  * then subsequent calls to this routine will eventually flush
1046  * remaining PDUs.
1047  *
1048  * During other connection states (EXITING or LOGGED_OUT), this
1049  * function will spin until all PDUs have successfully been flushed.
1050  *
1051  * Returns 0 for success and when all PDUs were able to be flushed.
1052  *
1053  * Returns 1 for success but when some PDUs could not be flushed due
1054  * to lack of TCP buffer space.
1055  *
1056  * Returns -1 for an exceptional error indicating the TCP connection
1057  * should be closed.
1058  */
1059 static void
1060 spdk_iscsi_conn_flush_pdus(void *_conn)
1061 {
1062 	struct spdk_iscsi_conn *conn = _conn;
1063 	int rc;
1064 
1065 	if (conn->state == ISCSI_CONN_STATE_RUNNING) {
1066 		rc = spdk_iscsi_conn_flush_pdus_internal(conn);
1067 		if (rc == 0 && conn->flush_poller != NULL) {
1068 			spdk_poller_unregister(&conn->flush_poller);
1069 		} else if (rc == 1 && conn->flush_poller == NULL) {
1070 			conn->flush_poller = spdk_poller_register(spdk_iscsi_conn_flush_pdus, conn, 50);
1071 		}
1072 	} else {
1073 		/*
1074 		 * If the connection state is not RUNNING, then
1075 		 * keep trying to flush PDUs until our list is
1076 		 * empty - to make sure all data is sent before
1077 		 * closing the connection.
1078 		 */
1079 		do {
1080 			rc = spdk_iscsi_conn_flush_pdus_internal(conn);
1081 		} while (rc == 1);
1082 	}
1083 
1084 	if (rc < 0 && conn->state < ISCSI_CONN_STATE_EXITING) {
1085 		/*
1086 		 * If the poller has already started destruction of the connection,
1087 		 *  i.e. the socket read failed, then the connection state may already
1088 		 *  be EXITED.  We don't want to set it back to EXITING in that case.
1089 		 */
1090 		conn->state = ISCSI_CONN_STATE_EXITING;
1091 	}
1092 }
1093 
1094 void
1095 spdk_iscsi_conn_write_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
1096 {
1097 	TAILQ_INSERT_TAIL(&conn->write_pdu_list, pdu, tailq);
1098 	spdk_iscsi_conn_flush_pdus(conn);
1099 }
1100 
1101 #define GET_PDU_LOOP_COUNT	16
1102 
1103 static int
1104 spdk_iscsi_conn_handle_incoming_pdus(struct spdk_iscsi_conn *conn)
1105 {
1106 	struct spdk_iscsi_pdu *pdu;
1107 	int i, rc;
1108 
1109 	/* Read new PDUs from network */
1110 	for (i = 0; i < GET_PDU_LOOP_COUNT; i++) {
1111 		rc = spdk_iscsi_read_pdu(conn, &pdu);
1112 		if (rc == 0) {
1113 			break;
1114 		} else if (rc == SPDK_ISCSI_CONNECTION_FATAL) {
1115 			return rc;
1116 		}
1117 
1118 		if (conn->state == ISCSI_CONN_STATE_LOGGED_OUT) {
1119 			SPDK_ERRLOG("pdu received after logout\n");
1120 			spdk_put_pdu(pdu);
1121 			return SPDK_ISCSI_CONNECTION_FATAL;
1122 		}
1123 
1124 		rc = spdk_iscsi_execute(conn, pdu);
1125 		spdk_put_pdu(pdu);
1126 		if (rc != 0) {
1127 			SPDK_ERRLOG("spdk_iscsi_execute() fatal error on %s(%s)\n",
1128 				    conn->target_port != NULL ? spdk_scsi_port_get_name(conn->target_port) : "NULL",
1129 				    conn->initiator_port != NULL ? spdk_scsi_port_get_name(conn->initiator_port) : "NULL");
1130 			return rc;
1131 		}
1132 	}
1133 
1134 	return i;
1135 }
1136 
1137 static void
1138 spdk_iscsi_conn_sock_cb(void *arg, struct spdk_sock_group *group, struct spdk_sock *sock)
1139 {
1140 	struct spdk_iscsi_conn *conn = arg;
1141 	int rc;
1142 
1143 	assert(conn != NULL);
1144 
1145 	/* Handle incoming PDUs */
1146 	rc = spdk_iscsi_conn_handle_incoming_pdus(conn);
1147 	if (rc < 0) {
1148 		conn->state = ISCSI_CONN_STATE_EXITING;
1149 		spdk_iscsi_conn_flush_pdus(conn);
1150 	}
1151 }
1152 
1153 static int
1154 spdk_iscsi_conn_execute(struct spdk_iscsi_conn *conn)
1155 {
1156 	int				rc = 0;
1157 
1158 	if (conn->state == ISCSI_CONN_STATE_EXITED) {
1159 		return -1;
1160 	}
1161 
1162 	if (conn->state == ISCSI_CONN_STATE_EXITING) {
1163 		goto conn_exit;
1164 	}
1165 	/* Check for nop interval expiration */
1166 	rc = spdk_iscsi_conn_handle_nop(conn);
1167 	if (rc < 0) {
1168 		conn->state = ISCSI_CONN_STATE_EXITING;
1169 		goto conn_exit;
1170 	}
1171 
1172 	spdk_iscsi_conn_handle_queued_datain_tasks(conn);
1173 
1174 conn_exit:
1175 	if (conn->state == ISCSI_CONN_STATE_EXITING) {
1176 		spdk_iscsi_conn_destruct(conn);
1177 		return -1;
1178 	}
1179 
1180 	return 0;
1181 }
1182 
1183 static void
1184 spdk_iscsi_conn_full_feature_migrate(void *arg1, void *arg2)
1185 {
1186 	struct spdk_iscsi_conn *conn = arg1;
1187 
1188 	if (conn->sess->session_type == SESSION_TYPE_NORMAL) {
1189 		assert(conn->dev != NULL);
1190 		spdk_scsi_dev_allocate_io_channels(conn->dev);
1191 	}
1192 
1193 	/* The poller has been unregistered, so now we can re-register it on the new core. */
1194 	conn->lcore = spdk_env_get_current_core();
1195 	spdk_iscsi_poll_group_add_conn(conn, spdk_iscsi_conn_full_feature_do_work);
1196 }
1197 
1198 void
1199 spdk_iscsi_conn_login_do_work(void *arg)
1200 {
1201 	struct spdk_iscsi_conn	*conn = arg;
1202 	int				lcore;
1203 	int				rc;
1204 	struct spdk_event		*event;
1205 
1206 	/* General connection processing */
1207 	rc = spdk_iscsi_conn_execute(conn);
1208 	if (rc < 0) {
1209 		return;
1210 	}
1211 
1212 	/* Check if this connection transitioned to full feature phase. If it
1213 	 * did, migrate it to a dedicated reactor for the target node.
1214 	 */
1215 	if (conn->login_phase == ISCSI_FULL_FEATURE_PHASE) {
1216 		struct spdk_iscsi_tgt_node *target;
1217 
1218 		lcore = spdk_iscsi_conn_allocate_reactor(conn->portal->cpumask);
1219 		if (conn->sess->session_type == SESSION_TYPE_NORMAL) {
1220 			target = conn->sess->target;
1221 			pthread_mutex_lock(&target->mutex);
1222 			target->num_active_conns++;
1223 			if (target->num_active_conns == 1) {
1224 				/**
1225 				 * This is the only active connection for this target node.
1226 				 *  Save the lcore in the target node so it can be used for
1227 				 *  any other connections to this target node.
1228 				 */
1229 				target->lcore = lcore;
1230 			} else {
1231 				/**
1232 				 * There are other active connections for this target node.
1233 				 *  Ignore the lcore specified by the allocator and use the
1234 				 *  the target node's lcore to ensure this connection runs on
1235 				 *  the same lcore as other connections for this target node.
1236 				 */
1237 				lcore = target->lcore;
1238 			}
1239 			pthread_mutex_unlock(&target->mutex);
1240 		}
1241 
1242 		spdk_iscsi_poll_group_remove_conn_sock(conn);
1243 		spdk_iscsi_conn_stop(conn);
1244 
1245 		__sync_fetch_and_add(&g_num_connections[lcore], 1);
1246 		event = spdk_event_allocate(lcore, spdk_iscsi_conn_full_feature_migrate,
1247 					    conn, NULL);
1248 		spdk_event_call(event);
1249 	}
1250 }
1251 
1252 void
1253 spdk_iscsi_conn_full_feature_do_work(void *arg)
1254 {
1255 	struct spdk_iscsi_conn	*conn = arg;
1256 
1257 	spdk_iscsi_conn_execute(conn);
1258 }
1259 
1260 void
1261 spdk_iscsi_conn_set_min_per_core(int count)
1262 {
1263 	g_connections_per_lcore = count;
1264 }
1265 
1266 int
1267 spdk_iscsi_conn_get_min_per_core(void)
1268 {
1269 	return g_connections_per_lcore;
1270 }
1271 
1272 static uint32_t
1273 spdk_iscsi_conn_allocate_reactor(const struct spdk_cpuset *cpumask)
1274 {
1275 	uint32_t i, selected_core;
1276 	int32_t num_pollers, min_pollers;
1277 
1278 	min_pollers = INT_MAX;
1279 	selected_core = spdk_env_get_first_core();
1280 
1281 	SPDK_ENV_FOREACH_CORE(i) {
1282 		if (!spdk_cpuset_get_cpu(cpumask, i)) {
1283 			continue;
1284 		}
1285 
1286 		/* This core is running. Check how many pollers it already has. */
1287 		num_pollers = g_num_connections[i];
1288 
1289 		if ((num_pollers > 0) && (num_pollers < g_connections_per_lcore)) {
1290 			/* Fewer than the maximum connections per core,
1291 			 * but at least 1. Use this core.
1292 			 */
1293 			return i;
1294 		} else if (num_pollers < min_pollers) {
1295 			/* Track the core that has the minimum number of pollers
1296 			 * to be used if no cores meet our criteria
1297 			 */
1298 			selected_core = i;
1299 			min_pollers = num_pollers;
1300 		}
1301 	}
1302 
1303 	return selected_core;
1304 }
1305 
1306 static void
1307 logout_timeout(void *arg)
1308 {
1309 	struct spdk_iscsi_conn *conn = arg;
1310 
1311 	spdk_iscsi_conn_destruct(conn);
1312 }
1313 
1314 void
1315 spdk_iscsi_conn_logout(struct spdk_iscsi_conn *conn)
1316 {
1317 	conn->state = ISCSI_CONN_STATE_LOGGED_OUT;
1318 	conn->logout_timer = spdk_poller_register(logout_timeout, conn, ISCSI_LOGOUT_TIMEOUT * 1000000);
1319 }
1320 
1321 SPDK_TRACE_REGISTER_FN(iscsi_conn_trace)
1322 {
1323 	spdk_trace_register_owner(OWNER_ISCSI_CONN, 'c');
1324 	spdk_trace_register_object(OBJECT_ISCSI_PDU, 'p');
1325 	spdk_trace_register_description("READ FROM SOCKET DONE", "", TRACE_READ_FROM_SOCKET_DONE,
1326 					OWNER_ISCSI_CONN, OBJECT_NONE, 0, 0, 0, "");
1327 	spdk_trace_register_description("FLUSH WRITEBUF START", "", TRACE_FLUSH_WRITEBUF_START,
1328 					OWNER_ISCSI_CONN, OBJECT_NONE, 0, 0, 0, "iovec: ");
1329 	spdk_trace_register_description("FLUSH WRITEBUF DONE", "", TRACE_FLUSH_WRITEBUF_DONE,
1330 					OWNER_ISCSI_CONN, OBJECT_NONE, 0, 0, 0, "");
1331 	spdk_trace_register_description("READ PDU", "", TRACE_READ_PDU,
1332 					OWNER_ISCSI_CONN, OBJECT_ISCSI_PDU, 1, 0, 0, "opc:   ");
1333 	spdk_trace_register_description("ISCSI TASK DONE", "", TRACE_ISCSI_TASK_DONE,
1334 					OWNER_ISCSI_CONN, OBJECT_SCSI_TASK, 0, 0, 0, "");
1335 	spdk_trace_register_description("ISCSI TASK QUEUE", "", TRACE_ISCSI_TASK_QUEUE,
1336 					OWNER_ISCSI_CONN, OBJECT_SCSI_TASK, 1, 1, 0, "pdu:   ");
1337 	spdk_trace_register_description("ISCSI CONN ACTIVE", "", TRACE_ISCSI_CONN_ACTIVE,
1338 					OWNER_ISCSI_CONN, OBJECT_NONE, 0, 0, 0, "");
1339 	spdk_trace_register_description("ISCSI CONN IDLE", "", TRACE_ISCSI_CONN_IDLE,
1340 					OWNER_ISCSI_CONN, OBJECT_NONE, 0, 0, 0, "");
1341 }
1342