xref: /netbsd-src/sys/dev/iscsi/iscsi_ioctl.c (revision ef4e7bc3c5055802d89ff0e7d9f113ce923b0602)
1 /*	$NetBSD: iscsi_ioctl.c,v 1.37 2024/11/03 10:53:02 mlelstv Exp $	*/
2 
3 /*-
4  * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Wasabi Systems, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "iscsi_globals.h"
33 
34 #include <sys/file.h>
35 #include <sys/filedesc.h>
36 #include <sys/proc.h>
37 #include <sys/kmem.h>
38 
39 static kmutex_t iscsi_cleanup_mtx;
40 static kcondvar_t iscsi_cleanup_cv;
41 static kcondvar_t iscsi_event_cv;
42 static struct lwp *iscsi_cleanproc = NULL;
43 
44 static uint16_t current_id = 0;	/* Global session ID counter */
45 
46 /* list of event handlers */
47 static event_handler_list_t event_handlers =
48 	TAILQ_HEAD_INITIALIZER(event_handlers);
49 
50 static connection_list_t iscsi_timeout_conn_list =
51 	TAILQ_HEAD_INITIALIZER(iscsi_timeout_conn_list);
52 
53 static ccb_list_t iscsi_timeout_ccb_list =
54 	TAILQ_HEAD_INITIALIZER(iscsi_timeout_ccb_list);
55 
56 static session_list_t iscsi_cleanups_list =
57 	TAILQ_HEAD_INITIALIZER(iscsi_cleanups_list);
58 
59 static connection_list_t iscsi_cleanupc_list =
60 	TAILQ_HEAD_INITIALIZER(iscsi_cleanupc_list);
61 
62 static uint32_t handler_id = 0;	/* Handler ID counter */
63 
64 /* -------------------------------------------------------------------------- */
65 
66 /* Event management functions */
67 
68 /*
69  * find_handler:
70  *    Search the event handler list for the given ID.
71  *
72  *    Parameter:
73  *          id    The handler ID.
74  *
75  *    Returns:
76  *          Pointer to handler if found, else NULL.
77  */
78 
79 
80 static event_handler_t *
81 find_handler(uint32_t id)
82 {
83 	event_handler_t *curr;
84 
85 	KASSERT(mutex_owned(&iscsi_cleanup_mtx));
86 
87 	TAILQ_FOREACH(curr, &event_handlers, evh_link)
88 		if (curr->evh_id == id)
89 			break;
90 
91 	return curr;
92 }
93 
94 
95 /*
96  * register_event:
97  *    Create event handler entry, return ID.
98  *
99  *    Parameter:
100  *          par   The parameter.
101  */
102 
103 static void
104 register_event(iscsi_register_event_parameters_t *par)
105 {
106 	event_handler_t *handler;
107 	int was_empty;
108 
109 	handler = malloc(sizeof(event_handler_t), M_DEVBUF, M_WAITOK | M_ZERO);
110 	if (handler == NULL) {
111 		DEBOUT(("No mem for event handler\n"));
112 		par->status = ISCSI_STATUS_NO_RESOURCES;
113 		return;
114 	}
115 
116 	TAILQ_INIT(&handler->evh_events);
117 
118 	mutex_enter(&iscsi_cleanup_mtx);
119 	/* create a unique ID */
120 	do {
121 		++handler_id;
122 	} while (!handler_id || find_handler(handler_id) != NULL);
123 	par->event_id = handler->evh_id = handler_id;
124 
125 	was_empty = TAILQ_FIRST(&event_handlers) == NULL;
126 	TAILQ_INSERT_TAIL(&event_handlers, handler, evh_link);
127 	if (was_empty)
128 		iscsi_notify_cleanup();
129 	mutex_exit(&iscsi_cleanup_mtx);
130 
131 	par->status = ISCSI_STATUS_SUCCESS;
132 	DEB(5, ("Register Event OK, ID %d\n", par->event_id));
133 }
134 
135 
136 /*
137  * deregister_event:
138  *    Destroy handler entry and any waiting events, wake up waiter.
139  *
140  *    Parameter:
141  *          par   The parameter.
142  */
143 
144 static void
145 deregister_event(iscsi_register_event_parameters_t *par)
146 {
147 	event_handler_t *handler;
148 	event_t *evt;
149 
150 	mutex_enter(&iscsi_cleanup_mtx);
151 	handler = find_handler(par->event_id);
152 	if (handler == NULL) {
153 		mutex_exit(&iscsi_cleanup_mtx);
154 		DEB(1, ("Deregister Event ID %d not found\n", par->event_id));
155 		par->status = ISCSI_STATUS_INVALID_EVENT_ID;
156 		return;
157 	}
158 
159 	TAILQ_REMOVE(&event_handlers, handler, evh_link);
160 	if (handler->evh_waiter != NULL) {
161 		handler->evh_waiter->status = ISCSI_STATUS_EVENT_DEREGISTERED;
162 		cv_broadcast(&iscsi_event_cv);
163 	}
164 
165 	while ((evt = TAILQ_FIRST(&handler->evh_events)) != NULL) {
166 		TAILQ_REMOVE(&handler->evh_events, evt, ev_link);
167 		free(evt, M_TEMP);
168 	}
169 	mutex_exit(&iscsi_cleanup_mtx);
170 
171 	free(handler, M_DEVBUF);
172 	par->status = ISCSI_STATUS_SUCCESS;
173 	DEB(5, ("Deregister Event ID %d complete\n", par->event_id));
174 }
175 
176 
177 /*
178  * check_event:
179  *    Return first queued event. Optionally wait for arrival of event.
180  *
181  *    Parameter:
182  *          par   The parameter.
183  *          wait  Wait for event if true
184  */
185 
186 static void
187 check_event(iscsi_wait_event_parameters_t *par, bool wait)
188 {
189 	event_handler_t *handler;
190 	event_t *evt;
191 	int rc;
192 
193 	mutex_enter(&iscsi_cleanup_mtx);
194 	handler = find_handler(par->event_id);
195 	if (handler == NULL) {
196 		mutex_exit(&iscsi_cleanup_mtx);
197 		DEBOUT(("Wait Event ID %d not found\n", par->event_id));
198 		par->status = ISCSI_STATUS_INVALID_EVENT_ID;
199 		return;
200 	}
201 	if (handler->evh_waiter != NULL) {
202 		mutex_exit(&iscsi_cleanup_mtx);
203 		DEBOUT(("Wait Event ID %d already waiting\n", par->event_id));
204 		par->status = ISCSI_STATUS_EVENT_WAITING;
205 		return;
206 	}
207 	par->status = ISCSI_STATUS_SUCCESS;
208 	DEB(99, ("Wait Event ID %d\n", par->event_id));
209 
210 	do {
211 		evt = TAILQ_FIRST(&handler->evh_events);
212 		if (evt != NULL) {
213 			TAILQ_REMOVE(&handler->evh_events, evt, ev_link);
214 		} else {
215 			if (!wait) {
216 				par->status = ISCSI_STATUS_LIST_EMPTY;
217 				return;
218 			}
219 			if (par->status != ISCSI_STATUS_SUCCESS) {
220 				return;
221 			}
222 			handler->evh_waiter = par;
223 			rc = cv_wait_sig(&iscsi_event_cv, &iscsi_cleanup_mtx);
224 			if (rc) {
225 				mutex_exit(&iscsi_cleanup_mtx);
226 				par->status = ISCSI_STATUS_LIST_EMPTY;
227 				return;
228 			}
229 		}
230 	} while (evt == NULL);
231 	mutex_exit(&iscsi_cleanup_mtx);
232 
233 	par->connection_id = evt->ev_connection_id;
234 	par->session_id = evt->ev_session_id;
235 	par->event_kind = evt->ev_event_kind;
236 	par->reason = evt->ev_reason;
237 
238 	free(evt, M_TEMP);
239 }
240 
241 /*
242  * add_event
243  *    Adds an event entry to each registered handler queue.
244  *    Note that events are simply duplicated because we expect the number of
245  *    handlers to be very small, usually 1 (the daemon).
246  *
247  *    Parameters:
248  *       kind     The event kind
249  *       sid      The ID of the affected session
250  *       cid      The ID of the affected connection
251  *       reason   The reason code
252  */
253 
254 void
255 add_event(iscsi_event_t kind, uint32_t sid, uint32_t cid, uint32_t reason)
256 {
257 	event_handler_t *curr;
258 	event_t *evt;
259 
260 	DEB(9, ("Add_event kind %d, sid %d, cid %d, reason %d\n",
261 		kind, sid, cid, reason));
262 
263 	mutex_enter(&iscsi_cleanup_mtx);
264 	TAILQ_FOREACH(curr, &event_handlers, evh_link) {
265 		evt = malloc(sizeof(*evt), M_TEMP, M_NOWAIT);
266 		if (evt == NULL) {
267 			DEBOUT(("Cannot allocate event\n"));
268 			break;
269 		}
270 		evt->ev_event_kind = kind;
271 		evt->ev_session_id = sid;
272 		evt->ev_connection_id = cid;
273 		evt->ev_reason = reason;
274 
275 		TAILQ_INSERT_TAIL(&curr->evh_events, evt, ev_link);
276 		if (curr->evh_waiter != NULL) {
277 			curr->evh_waiter = NULL;
278 			cv_broadcast(&iscsi_event_cv);
279 		}
280 	}
281 	mutex_exit(&iscsi_cleanup_mtx);
282 }
283 
284 
285 /*
286  * check_event_handlers
287  *    Checks for dead event handlers. A dead event handler would deplete
288  *    memory over time, so we have to make sure someone at the other
289  *    end is actively monitoring events.
290  *    This function is called every 30 seconds or so (less frequent if there
291  *    is other activity for the cleanup thread to deal with) to go through
292  *    the list of handlers and check whether the first element in the event
293  *    list has changed at all. If not, the event is deregistered.
294  *    Note that this will not detect dead handlers if no events are pending,
295  *    but we don't care as long as events don't accumulate in the list.
296  *
297  */
298 
299 static void
300 check_event_handlers(void)
301 {
302 	event_handler_t *curr, *next;
303 	event_t *evt;
304 
305 	KASSERT(mutex_owned(&iscsi_cleanup_mtx));
306 
307 	for (curr = TAILQ_FIRST(&event_handlers); curr != NULL; curr = next) {
308 		next = TAILQ_NEXT(curr, evh_link);
309 		evt = TAILQ_FIRST(&curr->evh_events);
310 
311 		if (evt != NULL && evt == curr->evh_first_in_list) {
312 			DEBOUT(("Found Dead Event Handler %d, removing\n", curr->evh_id));
313 
314 			TAILQ_REMOVE(&event_handlers, curr, evh_link);
315 			while ((evt = TAILQ_FIRST(&curr->evh_events)) != NULL) {
316 				TAILQ_REMOVE(&curr->evh_events, evt, ev_link);
317 				free(evt, M_TEMP);
318 			}
319 			free(curr, M_DEVBUF);
320 		} else
321 			curr->evh_first_in_list = evt;
322 	}
323 }
324 
325 
326 /* -------------------------------------------------------------------------- */
327 
328 /*
329  * get_socket:
330  *    Get the file pointer from the socket handle passed into login.
331  *
332  *    Parameter:
333  *          fdes     IN: The socket handle
334  *          fpp      OUT: The pointer to the resulting file pointer
335  *
336  *    Returns:    0 on success, else an error code.
337  *
338  */
339 
340 static int
341 get_socket(int fdes, struct file **fpp)
342 {
343 	struct file *fp;
344 
345 	if ((fp = fd_getfile(fdes)) == NULL) {
346 		return EBADF;
347 	}
348 	if (fp->f_type != DTYPE_SOCKET) {
349 		return ENOTSOCK;
350 	}
351 
352 	/* Add the reference */
353 	mutex_enter(&fp->f_lock);
354 	fp->f_count++;
355 	mutex_exit(&fp->f_lock);
356 
357 	*fpp = fp;
358 	return 0;
359 }
360 
361 /*
362  * release_socket:
363  *    Release the file pointer from the socket handle passed into login.
364  *
365  *    Parameter:
366  *          fp       IN: The pointer to the resulting file pointer
367  *
368  */
369 
370 static void
371 release_socket(struct file *fp)
372 {
373 	/* Add the reference */
374 	mutex_enter(&fp->f_lock);
375 	fp->f_count--;
376 	mutex_exit(&fp->f_lock);
377 }
378 
379 
380 /*
381  * find_session:
382  *    Find a session by ID.
383  *
384  *    Parameter:  the session ID
385  *
386  *    Returns:    The pointer to the session (or NULL if not found)
387  */
388 
389 session_t *
390 find_session(uint32_t id)
391 {
392 	session_t *sess;
393 
394 	KASSERT(mutex_owned(&iscsi_cleanup_mtx));
395 
396 	TAILQ_FOREACH(sess, &iscsi_sessions, s_sessions)
397 		if (sess->s_id == id) {
398 			break;
399 		}
400 	return sess;
401 }
402 
403 
404 /*
405  * find_connection:
406  *    Find a connection by ID.
407  *
408  *    Parameter:  the session pointer and the connection ID
409  *
410  *    Returns:    The pointer to the connection (or NULL if not found)
411  */
412 
413 connection_t *
414 find_connection(session_t *sess, uint32_t id)
415 {
416 	connection_t *conn;
417 
418 	KASSERT(mutex_owned(&iscsi_cleanup_mtx));
419 
420 	TAILQ_FOREACH(conn, &sess->s_conn_list, c_connections)
421 		if (conn->c_id == id) {
422 			break;
423 		}
424 	return conn;
425 }
426 
427 /*
428  * ref_session:
429  *    Reference a session
430  *
431  *    Session cannot be release until reference count reaches zero
432  *
433  *    Returns: 1 if reference counter would overflow
434  */
435 
436 int
437 ref_session(session_t *sess)
438 {
439 	int rc = 1;
440 
441 	mutex_enter(&iscsi_cleanup_mtx);
442 	KASSERT(sess != NULL);
443 	if (sess->s_refcount <= CCBS_PER_SESSION) {
444 		sess->s_refcount++;
445 		rc = 0;
446 	}
447 	mutex_exit(&iscsi_cleanup_mtx);
448 
449 	return rc;
450 }
451 
452 /*
453  * unref_session:
454  *    Unreference a session
455  *
456  *    Release session reference, trigger cleanup
457  */
458 
459 void
460 unref_session(session_t *session)
461 {
462 
463 	mutex_enter(&iscsi_cleanup_mtx);
464 	KASSERT(session != NULL);
465 	KASSERT(session->s_refcount > 0);
466 	if (--session->s_refcount == 0)
467 		cv_broadcast(&session->s_sess_cv);
468 	mutex_exit(&iscsi_cleanup_mtx);
469 }
470 
471 
472 /*
473  * kill_connection:
474  *    Terminate the connection as gracefully as possible.
475  *
476  *    Parameter:
477  *		conn		The connection to terminate
478  *		status		The status code for the connection's "terminating" field
479  *		logout		The logout reason code
480  *		recover	Attempt to recover connection
481  */
482 
483 void
484 kill_connection(connection_t *conn, uint32_t status, int logout, bool recover)
485 {
486 	session_t *sess = conn->c_session;
487 	int terminating;
488 
489 	DEBC(conn, 1, ("Kill_connection: terminating=%d, status=%d, logout=%d, "
490 			   "state=%d\n",
491 			   conn->c_terminating, status, logout, conn->c_state));
492 
493 	mutex_enter(&iscsi_cleanup_mtx);
494 	if (recover &&
495 	    !conn->c_destroy &&
496 	    conn->c_recover > MAX_RECOVERY_ATTEMPTS) {
497 		DEBC(conn, 1, ("Kill_connection: Too many recovery attempts, "
498 		               "destroying\n"));
499 		conn->c_destroy = TRUE;
500 	}
501 
502 	if (!recover || conn->c_destroy) {
503 
504 		if (conn->c_in_session) {
505 			conn->c_in_session = FALSE;
506 			TAILQ_REMOVE(&sess->s_conn_list, conn, c_connections);
507 			sess->s_mru_connection = TAILQ_FIRST(&sess->s_conn_list);
508 		}
509 
510 		if (!conn->c_destroy) {
511 			DEBC(conn, 1, ("Kill_connection setting destroy flag\n"));
512 			conn->c_destroy = TRUE;
513 		}
514 	}
515 
516 	mutex_enter(&conn->c_lock);
517 	terminating = conn->c_terminating;
518 	if (!terminating)
519 		conn->c_terminating = status;
520 	mutex_exit(&conn->c_lock);
521 
522 	/* Don't recurse */
523 	if (terminating) {
524 		mutex_exit(&iscsi_cleanup_mtx);
525 
526 		KASSERT(conn->c_state != ST_FULL_FEATURE);
527 		DEBC(conn, 1, ("Kill_connection exiting (already terminating)\n"));
528 		goto done;
529 	}
530 
531 	if (conn->c_state == ST_FULL_FEATURE) {
532 		sess->s_active_connections--;
533 		conn->c_state = ST_WINDING_DOWN;
534 
535 		/* If this is the last connection and ERL < 2, reset TSIH */
536 		if (!sess->s_active_connections && sess->s_ErrorRecoveryLevel < 2)
537 			sess->s_TSIH = 0;
538 
539 		/* Don't try to log out if the socket is broken or we're in the middle */
540 		/* of logging in */
541 		if (logout >= 0) {
542 			if (sess->s_ErrorRecoveryLevel < 2 &&
543 			    logout == RECOVER_CONNECTION) {
544 				logout = LOGOUT_CONNECTION;
545 			}
546 			if (!sess->s_active_connections &&
547 			    logout == LOGOUT_CONNECTION) {
548 				logout = LOGOUT_SESSION;
549 			}
550 
551 			/* connection is terminating, prevent cleanup */
552 			mutex_enter(&conn->c_lock);
553 			conn->c_usecount++;
554 			mutex_exit(&conn->c_lock);
555 
556 			mutex_exit(&iscsi_cleanup_mtx);
557 
558 			DEBC(conn, 1, ("Send_logout for reason %d\n", logout));
559 
560 			connection_timeout_start(conn, CONNECTION_TIMEOUT);
561 
562 			if (!send_logout(conn, conn, logout, FALSE)) {
563 				mutex_enter(&conn->c_lock);
564 				conn->c_usecount--;
565 				conn->c_terminating = ISCSI_STATUS_SUCCESS;
566 				mutex_exit(&conn->c_lock);
567 				return;
568 			}
569 			/*
570 			 * if the logout request was successfully sent,
571 			 * the logout response handler will do the rest
572 			 * of the termination processing. If the logout
573 			 * doesn't get a response, we'll get back in here
574 			 * once the timeout hits.
575 			 */
576 
577 			mutex_enter(&iscsi_cleanup_mtx);
578 
579 			/* release connection */
580 			mutex_enter(&conn->c_lock);
581 			conn->c_usecount--;
582 			mutex_exit(&conn->c_lock);
583 		}
584 
585 	}
586 
587 	conn->c_state = ST_SETTLING;
588 	mutex_exit(&iscsi_cleanup_mtx);
589 
590 done:
591 	/* let send thread take over next step of cleanup */
592 	mutex_enter(&conn->c_lock);
593 	cv_broadcast(&conn->c_conn_cv);
594 	mutex_exit(&conn->c_lock);
595 
596 	DEBC(conn, 5, ("kill_connection returns\n"));
597 }
598 
599 
600 /*
601  * kill_session:
602  *    Terminate the session as gracefully as possible.
603  *
604  *    Parameter:
605  *		session		Session to terminate
606  *		status		The status code for the termination
607  *		logout		The logout reason code
608 
609  */
610 
611 void
612 kill_session(uint32_t sid, uint32_t status, int logout, bool recover)
613 {
614 	session_t *sess;
615 	connection_t *conn;
616 
617 	DEB(1, ("ISCSI: kill_session %d, status %d, logout %d, recover %d\n",
618 			sid, status, logout, recover));
619 
620 	mutex_enter(&iscsi_cleanup_mtx);
621 
622 	sess = find_session(sid);
623 	if (sess == NULL) {
624 		mutex_exit(&iscsi_cleanup_mtx);
625 
626 		DEB(5, ("Session %u already gone\n", sid));
627 		return;
628 	}
629 
630 	if (sess->s_terminating) {
631 		mutex_exit(&iscsi_cleanup_mtx);
632 
633 		DEB(5, ("Session is being killed with status %d\n",sess->s_terminating));
634 		return;
635 	}
636 
637 	/*
638 	 * don't do anything if session isn't established yet, termination will be
639 	 * handled elsewhere
640 	 */
641 	if (sess->s_sessions.tqe_next == NULL && sess->s_sessions.tqe_prev == NULL) {
642 		mutex_exit(&iscsi_cleanup_mtx);
643 
644 		DEB(5, ("Session is being killed which is not yet established\n"));
645 		return;
646 	}
647 
648 	if (recover) {
649 		/*
650 		 * Only recover when there's just one active connection left.
651 		 * Otherwise we get in all sorts of timing problems, and it doesn't
652 		 * make much sense anyway to recover when the other side has
653 		 * requested that we kill a multipathed session.
654 		 */
655 		conn = NULL;
656 		if (sess->s_active_connections == 1)
657 			conn = assign_connection(sess, FALSE);
658 
659 		mutex_exit(&iscsi_cleanup_mtx);
660 
661 		if (conn != NULL)
662 			kill_connection(conn, status, logout, TRUE);
663 		return;
664 	}
665 
666 	if (sess->s_refcount > 0) {
667 		mutex_exit(&iscsi_cleanup_mtx);
668 
669 		DEB(5, ("Session is being killed while in use (refcnt = %d)\n",
670 			sess->s_refcount));
671 		return;
672 	}
673 
674 	/* Remove session from global list */
675 	sess->s_terminating = status;
676 	TAILQ_REMOVE(&iscsi_sessions, sess, s_sessions);
677 	sess->s_sessions.tqe_next = NULL;
678 	sess->s_sessions.tqe_prev = NULL;
679 
680 	/*
681 	 * If all connections are already gone, trigger cleanup
682 	 * otherwise, the last connection will do this
683 	 */
684 	if (sess->s_active_connections == 0)
685 		iscsi_notify_cleanup();
686 
687 	mutex_exit(&iscsi_cleanup_mtx);
688 
689 	/* kill all connections */
690 	while ((conn = TAILQ_FIRST(&sess->s_conn_list)) != NULL) {
691 		kill_connection(conn, status, logout, FALSE);
692 		logout = NO_LOGOUT;
693 	}
694 }
695 
696 
697 /*
698  * create_connection:
699  *    Create and init the necessary framework for a connection:
700  *       Take over userland socket
701  *       Alloc the connection structure itself
702  *       Copy connection parameters
703  *       Create the send and receive threads
704  *       And finally, log in.
705  *
706  *    Parameter:
707  *          par      IN/OUT: The login parameters
708  *          session  IN: The owning session
709  *          l        IN: The lwp pointer of the caller
710  *
711  *    Returns:    0 on success
712  *                >0 on failure, connection structure deleted
713  *                <0 on failure, connection is still terminating
714  */
715 
716 static int
717 create_connection(iscsi_login_parameters_t *par, session_t *sess,
718 				  struct lwp *l)
719 {
720 	connection_t *conn;
721 	int rc;
722 
723 	DEB(1, ("Create Connection for Session %d\n", sess->s_id));
724 
725 	if (sess->s_MaxConnections &&
726 	    sess->s_active_connections >= sess->s_MaxConnections) {
727 		DEBOUT(("Too many connections (max = %d, curr = %d)\n",
728 				sess->s_MaxConnections, sess->s_active_connections));
729 		/* Always close descriptor */
730 		fd_close(par->socket);
731 
732 		par->status = ISCSI_STATUS_MAXED_CONNECTIONS;
733 		return EIO;
734 	}
735 
736 	conn = malloc(sizeof(*conn), M_DEVBUF, M_WAITOK | M_ZERO);
737 	if (conn == NULL) {
738 		DEBOUT(("No mem for connection\n"));
739 
740 		/* Always close descriptor */
741 		fd_close(par->socket);
742 
743 		par->status = ISCSI_STATUS_NO_RESOURCES;
744 		return EIO;
745 	}
746 
747 	rc = get_socket(par->socket, &conn->c_sock);
748 	if (rc != EBADF)
749 		fd_close(par->socket);
750 
751 	if (rc) {
752 		DEBOUT(("Invalid socket %d\n", par->socket));
753 		free(conn, M_DEVBUF);
754 		par->status = ISCSI_STATUS_INVALID_SOCKET;
755 		return rc;
756 	}
757 
758 	DEBC(conn, 1, ("get_socket: par_sock=%d, fdesc=%p\n",
759 			par->socket, conn->c_sock));
760 
761 	mutex_enter(&iscsi_cleanup_mtx);
762 	/* create a unique ID */
763 	do {
764 		++sess->s_conn_id;
765 	} while (!sess->s_conn_id ||
766 		 find_connection(sess, sess->s_conn_id) != NULL);
767 	par->connection_id = conn->c_id = sess->s_conn_id;
768 	mutex_exit(&iscsi_cleanup_mtx);
769 	DEB(99, ("Connection ID = %d\n", conn->c_id));
770 
771 	conn->c_session = sess;
772 
773 	TAILQ_INIT(&conn->c_ccbs_waiting);
774 	TAILQ_INIT(&conn->c_pdus_to_send);
775 	TAILQ_INIT(&conn->c_pdu_pool);
776 
777 	mutex_init(&conn->c_lock, MUTEX_DEFAULT, IPL_BIO);
778 	cv_init(&conn->c_conn_cv, "conn");
779 	cv_init(&conn->c_pdu_cv, "pdupool");
780 	cv_init(&conn->c_ccb_cv, "ccbwait");
781 	cv_init(&conn->c_idle_cv, "idle");
782 	rw_init(&conn->c_sock_rw);
783 
784 	callout_init(&conn->c_timeout, CALLOUT_MPSAFE);
785 	callout_setfunc(&conn->c_timeout, connection_timeout_co, conn);
786 	conn->c_idle_timeout_val = CONNECTION_IDLE_TIMEOUT;
787 
788 	init_sernum(&conn->c_StatSN_buf);
789 	create_pdus(conn);
790 
791 	conn->c_threadobj = l;
792 	conn->c_login_par = par;
793 
794 	DEB(5, ("Creating receive thread\n"));
795 	if ((rc = kthread_create(PRI_BIO, KTHREAD_MPSAFE, NULL, iscsi_rcv_thread,
796 				conn, &conn->c_rcvproc,
797 				"ConnRcv")) != 0) {
798 		DEBOUT(("Can't create rcv thread (rc %d)\n", rc));
799 
800 		release_socket(conn->c_sock);
801 		rw_destroy(&conn->c_sock_rw);
802 		callout_destroy(&conn->c_timeout);
803 		cv_destroy(&conn->c_idle_cv);
804 		cv_destroy(&conn->c_ccb_cv);
805 		cv_destroy(&conn->c_pdu_cv);
806 		cv_destroy(&conn->c_conn_cv);
807 		mutex_destroy(&conn->c_lock);
808 		free(conn, M_DEVBUF);
809 		par->status = ISCSI_STATUS_NO_RESOURCES;
810 		return rc;
811 	}
812 	DEB(5, ("Creating send thread\n"));
813 	if ((rc = kthread_create(PRI_BIO, KTHREAD_MPSAFE, NULL, iscsi_send_thread,
814 				conn, &conn->c_sendproc,
815 				"ConnSend")) != 0) {
816 		DEBOUT(("Can't create send thread (rc %d)\n", rc));
817 
818 		conn->c_terminating = ISCSI_STATUS_NO_RESOURCES;
819 
820 		/*
821 		 * We must close the socket here to force the receive
822 		 * thread to wake up
823 		 */
824 		DEBC(conn, 1, ("Closing Socket %p\n", conn->c_sock));
825 		mutex_enter(&conn->c_sock->f_lock);
826 		conn->c_sock->f_count += 1;
827 		mutex_exit(&conn->c_sock->f_lock);
828 		closef(conn->c_sock);
829 
830 		/* give receive thread time to exit */
831 		kpause("settle", false, 2 * hz, NULL);
832 
833 		release_socket(conn->c_sock);
834 		callout_destroy(&conn->c_timeout);
835 		rw_destroy(&conn->c_sock_rw);
836 		cv_destroy(&conn->c_idle_cv);
837 		cv_destroy(&conn->c_ccb_cv);
838 		cv_destroy(&conn->c_pdu_cv);
839 		cv_destroy(&conn->c_conn_cv);
840 		mutex_destroy(&conn->c_lock);
841 		free(conn, M_DEVBUF);
842 		par->status = ISCSI_STATUS_NO_RESOURCES;
843 		return rc;
844 	}
845 
846 	/*
847 	 * At this point, each thread will tie 'sock' into its own file descriptor
848 	 * tables w/o increasing the use count - they will inherit the use
849 	 * increments performed in get_socket().
850 	 */
851 
852 	if ((rc = send_login(conn)) != 0) {
853 		DEBC(conn, 0, ("Login failed (rc %d)\n", rc));
854 		/* Don't attempt to recover, there seems to be something amiss */
855 		kill_connection(conn, rc, NO_LOGOUT, FALSE);
856 		par->status = rc;
857 		return -1;
858 	}
859 
860 	mutex_enter(&iscsi_cleanup_mtx);
861 	if (sess->s_terminating) {
862 		mutex_exit(&iscsi_cleanup_mtx);
863 		DEBC(conn, 0, ("Session terminating\n"));
864 		kill_connection(conn, rc, NO_LOGOUT, FALSE);
865 		par->status = sess->s_terminating;
866 		return -1;
867 	}
868 	conn->c_state = ST_FULL_FEATURE;
869 	TAILQ_INSERT_TAIL(&sess->s_conn_list, conn, c_connections);
870 	conn->c_in_session = TRUE;
871 	sess->s_total_connections++;
872 	sess->s_active_connections++;
873 	sess->s_mru_connection = conn;
874 	mutex_exit(&iscsi_cleanup_mtx);
875 
876 	DEBC(conn, 5, ("Connection created successfully!\n"));
877 	return 0;
878 }
879 
880 
881 /*
882  * recreate_connection:
883  *    Revive dead connection
884  *
885  *    Parameter:
886  *          par      IN/OUT: The login parameters
887  *          conn     IN: The connection
888  *          l        IN: The lwp pointer of the caller
889  *
890  *    Returns:    0 on success
891  *                >0 on failure, connection structure deleted
892  *                <0 on failure, connection is still terminating
893  */
894 
895 static int
896 recreate_connection(iscsi_login_parameters_t *par, session_t *sess,
897 					connection_t *conn, struct lwp *l)
898 {
899 	int rc;
900 	ccb_t *ccb;
901 	ccb_list_t old_waiting;
902 	pdu_t *pdu;
903 	uint32_t sn;
904 
905 	DEB(1, ("ReCreate Connection %d for Session %d, ERL=%d\n",
906 		conn->c_id, conn->c_session->s_id,
907 		conn->c_session->s_ErrorRecoveryLevel));
908 
909 	if (sess->s_MaxConnections &&
910 	    sess->s_active_connections >= sess->s_MaxConnections) {
911 		DEBOUT(("Too many connections (max = %d, curr = %d)\n",
912 			sess->s_MaxConnections, sess->s_active_connections));
913 
914 		/* Close the desecriptor */
915 		rc = EIO;
916 		if (fd_getfile(par->socket) != NULL)
917 			rc = fd_close(par->socket);
918 
919 		par->status = ISCSI_STATUS_MAXED_CONNECTIONS;
920 		return rc;
921 	}
922 
923 	rw_enter(&conn->c_sock_rw, RW_WRITER);
924 	if (conn->c_sock != NULL) {
925 		closef(conn->c_sock);
926 		conn->c_sock = NULL;
927 	}
928 	rc = get_socket(par->socket, &conn->c_sock);
929 	rw_exit(&conn->c_sock_rw);
930 	if (rc != EBADF)
931 		fd_close(par->socket);
932 
933 	if (rc) {
934 		DEBOUT(("Invalid socket %d\n", par->socket));
935 		par->status = ISCSI_STATUS_INVALID_SOCKET;
936 		return rc;
937 	}
938 
939 	DEBC(conn, 1, ("get_socket: par_sock=%d, fdesc=%p\n",
940 			par->socket, conn->c_sock));
941 
942 	conn->c_threadobj = l;
943 	conn->c_login_par = par;
944 	conn->c_terminating = ISCSI_STATUS_SUCCESS;
945 	conn->c_recover++;
946 	conn->c_num_timeouts = 0;
947 	conn->c_state = ST_SEC_NEG;
948 	conn->c_HeaderDigest = 0;
949 	conn->c_DataDigest = 0;
950 
951 	sess->s_active_connections++;
952 
953 	TAILQ_INIT(&old_waiting);
954 
955 	mutex_enter(&conn->c_lock);
956 	while ((ccb = TAILQ_FIRST(&conn->c_ccbs_waiting)) != NULL) {
957 		suspend_ccb(ccb, FALSE);
958 		TAILQ_INSERT_TAIL(&old_waiting, ccb, ccb_chain);
959 	}
960 	init_sernum(&conn->c_StatSN_buf);
961 	cv_broadcast(&conn->c_idle_cv);
962 	mutex_exit(&conn->c_lock);
963 
964 	if ((rc = send_login(conn)) != 0) {
965 		DEBC(conn, 0, ("Re-Login failed (rc %d)\n", rc));
966 		while ((ccb = TAILQ_FIRST(&old_waiting)) != NULL) {
967 			TAILQ_REMOVE(&old_waiting, ccb, ccb_chain);
968 			wake_ccb(ccb, rc);
969 		}
970 		/* Don't attempt to recover, there seems to be something amiss */
971 		kill_connection(conn, rc, NO_LOGOUT, FALSE);
972 		par->status = rc;
973 		return -1;
974 	}
975 
976 	DEBC(conn, 9, ("Re-Login successful\n"));
977 	par->status = ISCSI_STATUS_SUCCESS;
978 
979 	conn->c_state = ST_FULL_FEATURE;
980 	sess->s_mru_connection = conn;
981 
982 	while ((ccb = TAILQ_FIRST(&old_waiting)) != NULL) {
983 		TAILQ_REMOVE(&old_waiting, ccb, ccb_chain);
984 		mutex_enter(&conn->c_lock);
985 		suspend_ccb(ccb, TRUE);
986 		mutex_exit(&conn->c_lock);
987 
988 		rc = send_task_management(conn, ccb, NULL, TASK_REASSIGN);
989 		/* if we get an error on reassign, restart the original request */
990 		if (rc && ccb->ccb_pdu_waiting != NULL) {
991 			mutex_enter(&sess->s_lock);
992 			if (sn_a_lt_b(ccb->ccb_CmdSN, sess->s_ExpCmdSN)) {
993 				pdu = ccb->ccb_pdu_waiting;
994 				sn = get_sernum(sess, pdu);
995 
996 				/* update CmdSN */
997 				DEBC(conn, 0, ("Resend ccb %p (%d) - updating CmdSN old %u, new %u\n",
998 					   ccb, rc, ccb->ccb_CmdSN, sn));
999 				ccb->ccb_CmdSN = sn;
1000 				pdu->pdu_hdr.pduh_p.command.CmdSN = htonl(ccb->ccb_CmdSN);
1001 			} else {
1002 				DEBC(conn, 0, ("Resend ccb %p (%d) - CmdSN %u\n",
1003 					   ccb, rc, ccb->ccb_CmdSN));
1004 			}
1005 			mutex_exit(&sess->s_lock);
1006 			resend_pdu(ccb);
1007 		} else {
1008 			DEBC(conn, 0, ("Resend ccb %p (%d) CmdSN %u - reassigned\n",
1009 				ccb, rc, ccb->ccb_CmdSN));
1010 			ccb_timeout_start(ccb, COMMAND_TIMEOUT);
1011 		}
1012 	}
1013 
1014 	mutex_enter(&sess->s_lock);
1015 	cv_broadcast(&sess->s_sess_cv);
1016 	mutex_exit(&sess->s_lock);
1017 
1018 	DEBC(conn, 0, ("Connection ReCreated successfully - status %d\n",
1019 						 par->status));
1020 
1021 	return 0;
1022 }
1023 
1024 /* -------------------------------------------------------------------------- */
1025 
1026 /*
1027  * check_login_pars:
1028  *    Check the parameters passed into login/add_connection
1029  *    for validity and consistency.
1030  *
1031  *    Parameter:
1032  *          par      The login parameters
1033  *
1034  *    Returns:    0 on success, else an error code.
1035  */
1036 
1037 static int
1038 check_login_pars(iscsi_login_parameters_t *par)
1039 {
1040 	int i, n;
1041 
1042 	if (par->is_present.auth_info) {
1043 		/* check consistency of authentication parameters */
1044 
1045 		if (par->auth_info.auth_number > ISCSI_AUTH_OPTIONS) {
1046 			DEBOUT(("Auth number invalid: %d\n", par->auth_info.auth_number));
1047 			return ISCSI_STATUS_PARAMETER_INVALID;
1048 		}
1049 
1050 		if (par->auth_info.auth_number > 2) {
1051 			DEBOUT(("Auth number invalid: %d\n", par->auth_info.auth_number));
1052 			return ISCSI_STATUS_NOTIMPL;
1053 		}
1054 
1055 		for (i = 0, n = 0; i < par->auth_info.auth_number; i++) {
1056 #if 0
1057 			if (par->auth_info.auth_type[i] < ISCSI_AUTH_None) {
1058 				DEBOUT(("Auth type invalid: %d\n",
1059 						par->auth_info.auth_type[i]));
1060 				return ISCSI_STATUS_PARAMETER_INVALID;
1061 			}
1062 #endif
1063 			if (par->auth_info.auth_type[i] > ISCSI_AUTH_CHAP) {
1064 				DEBOUT(("Auth type invalid: %d\n",
1065 						par->auth_info.auth_type[i]));
1066 				return ISCSI_STATUS_NOTIMPL;
1067 			}
1068 			n = max(n, par->auth_info.auth_type[i]);
1069 		}
1070 		if (n) {
1071 			if (!par->is_present.password ||
1072 				(par->auth_info.mutual_auth &&
1073 				 !par->is_present.target_password)) {
1074 				DEBOUT(("Password missing\n"));
1075 				return ISCSI_STATUS_PARAMETER_MISSING;
1076 			}
1077 			/* Note: Default for user-name is initiator name */
1078 		}
1079 	}
1080 	if (par->login_type != ISCSI_LOGINTYPE_DISCOVERY &&
1081 	    !par->is_present.TargetName) {
1082 		DEBOUT(("Target name missing, login type %d\n", par->login_type));
1083 		return ISCSI_STATUS_PARAMETER_MISSING;
1084 	}
1085 	if (par->is_present.MaxRecvDataSegmentLength) {
1086 		if (par->MaxRecvDataSegmentLength < 512 ||
1087 			par->MaxRecvDataSegmentLength > 0xffffff) {
1088 			DEBOUT(("MaxRecvDataSegmentLength invalid: %d\n",
1089 					par->MaxRecvDataSegmentLength));
1090 			return ISCSI_STATUS_PARAMETER_INVALID;
1091 		}
1092 	}
1093 	return 0;
1094 }
1095 
1096 
1097 /*
1098  * login:
1099  *    Handle the login ioctl - Create a session:
1100  *       Alloc the session structure
1101  *       Copy session parameters
1102  *       And call create_connection to establish the connection.
1103  *
1104  *    Parameter:
1105  *          par      IN/OUT: The login parameters
1106  *          l        IN: The lwp pointer of the caller
1107  */
1108 
1109 static void
1110 login(iscsi_login_parameters_t *par, struct lwp *l, device_t dev)
1111 {
1112 	session_t *sess;
1113 	int rc;
1114 
1115 	DEB(99, ("ISCSI: login\n"));
1116 
1117 	if (!iscsi_InitiatorName[0]) {
1118 		DEB(1, ("No Initiator Name\n"));
1119 		par->status = ISCSI_STATUS_NO_INITIATOR_NAME;
1120 		return;
1121 	}
1122 
1123 	if ((par->status = check_login_pars(par)) != 0)
1124 		return;
1125 
1126 	/* alloc the session */
1127 	sess = malloc(sizeof(*sess), M_DEVBUF, M_WAITOK | M_ZERO);
1128 	if (sess == NULL) {
1129 		DEBOUT(("No mem for session\n"));
1130 		par->status = ISCSI_STATUS_NO_RESOURCES;
1131 		return;
1132 	}
1133 	TAILQ_INIT(&sess->s_conn_list);
1134 	TAILQ_INIT(&sess->s_ccb_pool);
1135 
1136 	mutex_init(&sess->s_lock, MUTEX_DEFAULT, IPL_BIO);
1137 	cv_init(&sess->s_sess_cv, "session");
1138 	cv_init(&sess->s_ccb_cv, "ccb");
1139 
1140 	mutex_enter(&iscsi_cleanup_mtx);
1141 	/* create a unique ID */
1142 	do {
1143 		++current_id;
1144 	} while (!current_id || find_session(current_id) != NULL);
1145 	par->session_id = sess->s_id = current_id;
1146 	mutex_exit(&iscsi_cleanup_mtx);
1147 
1148 	create_ccbs(sess);
1149 	sess->s_login_type = par->login_type;
1150 	sess->s_CmdSN = 1;
1151 
1152 	if ((rc = create_connection(par, sess, l)) != 0) {
1153 		if (rc > 0) {
1154 			destroy_ccbs(sess);
1155 			cv_destroy(&sess->s_ccb_cv);
1156 			cv_destroy(&sess->s_sess_cv);
1157 			mutex_destroy(&sess->s_lock);
1158 			free(sess, M_DEVBUF);
1159 		}
1160 		return;
1161 	}
1162 
1163 	mutex_enter(&iscsi_cleanup_mtx);
1164 	TAILQ_INSERT_HEAD(&iscsi_sessions, sess, s_sessions);
1165 	mutex_exit(&iscsi_cleanup_mtx);
1166 
1167 	/* Session established, map LUNs? */
1168 	if (par->login_type == ISCSI_LOGINTYPE_MAP) {
1169 		copyinstr(par->TargetName, sess->s_tgtname,
1170 		    sizeof(sess->s_tgtname), NULL);
1171 		DEB(1, ("Login: map session %d\n", sess->s_id));
1172 		if (!map_session(sess, dev)) {
1173 			DEB(1, ("Login: map session %d failed\n", sess->s_id));
1174 			kill_session(par->session_id, ISCSI_STATUS_MAP_FAILED,
1175 					LOGOUT_SESSION, FALSE);
1176 			par->status = ISCSI_STATUS_MAP_FAILED;
1177 			return;
1178 		}
1179 	}
1180 }
1181 
1182 
1183 /*
1184  * logout:
1185  *    Handle the logout ioctl - Kill a session.
1186  *
1187  *    Parameter:
1188  *          par      IN/OUT: The login parameters
1189  */
1190 
1191 static void
1192 logout(iscsi_logout_parameters_t *par)
1193 {
1194 	session_t *session;
1195 
1196 	DEB(5, ("ISCSI: logout session %d\n", par->session_id));
1197 
1198 	mutex_enter(&iscsi_cleanup_mtx);
1199 	if ((session = find_session(par->session_id)) == NULL) {
1200 		mutex_exit(&iscsi_cleanup_mtx);
1201 		DEBOUT(("Session %d not found\n", par->session_id));
1202 		par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1203 		return;
1204 	}
1205 	mutex_exit(&iscsi_cleanup_mtx);
1206 	/* If the session exists, this always succeeds */
1207 	par->status = ISCSI_STATUS_SUCCESS;
1208 
1209 	kill_session(par->session_id,
1210 	    ISCSI_STATUS_LOGOUT, LOGOUT_SESSION,
1211 	    FALSE);
1212 }
1213 
1214 
1215 /*
1216  * add_connection:
1217  *    Handle the add_connection ioctl.
1218  *
1219  *    Parameter:
1220  *          par      IN/OUT: The login parameters
1221  *          l        IN: The lwp pointer of the caller
1222  */
1223 
1224 static int
1225 add_connection(iscsi_login_parameters_t *par, struct lwp *l)
1226 {
1227 	session_t *session;
1228 
1229 	DEB(5, ("ISCSI: add_connection to session %d\n", par->session_id));
1230 
1231 	mutex_enter(&iscsi_cleanup_mtx);
1232 	if ((session = find_session(par->session_id)) == NULL) {
1233 		mutex_exit(&iscsi_cleanup_mtx);
1234 		DEBOUT(("Session %d not found\n", par->session_id));
1235 		par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1236 		return -1;
1237 	}
1238 	mutex_exit(&iscsi_cleanup_mtx);
1239 
1240 	par->status = check_login_pars(par);
1241 	if (par->status)
1242 		return -1;
1243 
1244 	return create_connection(par, session, l);
1245 }
1246 
1247 
1248 /*
1249  * remove_connection:
1250  *    Handle the remove_connection ioctl.
1251  *
1252  *    Parameter:
1253  *          par      IN/OUT: The remove parameters
1254  */
1255 
1256 static void
1257 remove_connection(iscsi_remove_parameters_t *par)
1258 {
1259 	connection_t *conn;
1260 	session_t *session;
1261 
1262 	DEB(5, ("ISCSI: remove_connection %d from session %d\n",
1263 			par->connection_id, par->session_id));
1264 
1265 	mutex_enter(&iscsi_cleanup_mtx);
1266 	if ((session = find_session(par->session_id)) == NULL) {
1267 		mutex_exit(&iscsi_cleanup_mtx);
1268 		DEBOUT(("Session %d not found\n", par->session_id));
1269 		par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1270 		return;
1271 	}
1272 
1273 	if ((conn = find_connection(session, par->connection_id)) == NULL) {
1274 		mutex_exit(&iscsi_cleanup_mtx);
1275 		DEBOUT(("Connection %d not found in session %d\n",
1276 				par->connection_id, par->session_id));
1277 
1278 		par->status = ISCSI_STATUS_INVALID_CONNECTION_ID;
1279 	} else {
1280 		mutex_exit(&iscsi_cleanup_mtx);
1281 		kill_connection(conn, ISCSI_STATUS_LOGOUT, LOGOUT_CONNECTION,
1282 					FALSE);
1283 		par->status = ISCSI_STATUS_SUCCESS;
1284 	}
1285 }
1286 
1287 
1288 /*
1289  * restore_connection:
1290  *    Handle the restore_connection ioctl.
1291  *
1292  *    Parameter:
1293  *          par      IN/OUT: The login parameters
1294  *          l        IN: The lwp pointer of the caller
1295  */
1296 
1297 static void
1298 restore_connection(iscsi_login_parameters_t *par, struct lwp *l)
1299 {
1300 	session_t *sess;
1301 	connection_t *conn;
1302 
1303 	DEB(1, ("ISCSI: restore_connection %d of session %d\n",
1304 			par->connection_id, par->session_id));
1305 
1306 	mutex_enter(&iscsi_cleanup_mtx);
1307 	if ((sess = find_session(par->session_id)) == NULL) {
1308 		mutex_exit(&iscsi_cleanup_mtx);
1309 		DEBOUT(("Session %d not found\n", par->session_id));
1310 		par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1311 		return;
1312 	}
1313 	if ((conn = find_connection(sess, par->connection_id)) == NULL) {
1314 		mutex_exit(&iscsi_cleanup_mtx);
1315 		DEBOUT(("Connection %d not found in session %d\n",
1316 				par->connection_id, par->session_id));
1317 		par->status = ISCSI_STATUS_INVALID_CONNECTION_ID;
1318 		return;
1319 	}
1320 	if (!conn->c_terminating) {
1321 		mutex_exit(&iscsi_cleanup_mtx);
1322 		DEBC(conn, 0, ("Connection is alive\n"));
1323 		par->status = ISCSI_STATUS_SUCCESS;
1324 		return;
1325 	}
1326 	mutex_exit(&iscsi_cleanup_mtx);
1327 
1328 	if ((par->status = check_login_pars(par)) == 0) {
1329 		recreate_connection(par, sess, conn, l);
1330 	}
1331 }
1332 
1333 
1334 #ifndef ISCSI_MINIMAL
1335 
1336 /*
1337  * io_command:
1338  *    Handle the io_command ioctl.
1339  *
1340  *    Parameter:
1341  *          par      IN/OUT: The iocommand parameters
1342  *          l        IN: The lwp pointer of the caller
1343  */
1344 
1345 static void
1346 io_command(iscsi_iocommand_parameters_t *par, struct lwp *l)
1347 {
1348 	uint32_t datalen = par->req.datalen;
1349 	session_t *session;
1350 	void *kbuf = NULL;
1351 	int error;
1352 
1353 	DEB(9, ("ISCSI: io_command, SID=%d, lun=%" PRIu64 "\n", par->session_id, par->lun));
1354 	mutex_enter(&iscsi_cleanup_mtx);
1355 	if ((session = find_session(par->session_id)) == NULL) {
1356 		mutex_exit(&iscsi_cleanup_mtx);
1357 		DEBOUT(("Session %d not found\n", par->session_id));
1358 		par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1359 		return;
1360 	}
1361 	mutex_exit(&iscsi_cleanup_mtx);
1362 
1363 	par->req.senselen_used = 0;
1364 	par->req.datalen_used = 0;
1365 	par->req.error = 0;
1366 	par->req.status = 0;
1367 	par->req.retsts = SCCMD_UNKNOWN;	/* init to failure code */
1368 
1369 	if (par->req.cmdlen > 16 || par->req.senselen > sizeof(par->req.sense)) {
1370 		par->status = ISCSI_STATUS_PARAMETER_INVALID;
1371 		return;
1372 	}
1373 
1374 	if (datalen) {
1375 		/* Arbitrarily limit datalen to 8k. */
1376 		if (datalen > 8192) {
1377 			par->status = ISCSI_STATUS_PARAMETER_INVALID;
1378 			return;
1379 		}
1380 		kbuf = kmem_zalloc(datalen, KM_SLEEP);
1381 		if ((par->req.flags & SCCMD_WRITE) != 0) {
1382 			error = copyin(par->req.databuf, kbuf, datalen);
1383 			if (error) {
1384 				kmem_free(kbuf, datalen);
1385 				par->status = ISCSI_STATUS_PARAMETER_INVALID;
1386 				return;
1387 			}
1388 		}
1389 	}
1390 	par->status = send_io_command(session, par->lun, &par->req,
1391 								  par->options.immediate, par->connection_id);
1392 
1393 	if (kbuf) {
1394 		if ((par->req.flags & SCCMD_READ) != 0) {
1395 			(void) copyout(kbuf, par->req.databuf, datalen);
1396 		}
1397 		kmem_free(kbuf, datalen);
1398 	}
1399 	switch (par->status) {
1400 	case ISCSI_STATUS_SUCCESS:
1401 		par->req.retsts = SCCMD_OK;
1402 		break;
1403 
1404 	case ISCSI_STATUS_TARGET_BUSY:
1405 		par->req.retsts = SCCMD_BUSY;
1406 		break;
1407 
1408 	case ISCSI_STATUS_TIMEOUT:
1409 	case ISCSI_STATUS_SOCKET_ERROR:
1410 		par->req.retsts = SCCMD_TIMEOUT;
1411 		break;
1412 
1413 	default:
1414 		par->req.retsts = (par->req.senselen_used) ? SCCMD_SENSE
1415 												   : SCCMD_UNKNOWN;
1416 		break;
1417 	}
1418 }
1419 #endif
1420 
1421 /*
1422  * send_targets:
1423  *    Handle the send_targets ioctl.
1424  *    Note: If the passed buffer is too small to hold the complete response,
1425  *    the response is kept in the session structure so it can be
1426  *    retrieved with the next call to this function without having to go to
1427  *    the target again. Once the complete response has been retrieved, it
1428  *    is discarded.
1429  *
1430  *    Parameter:
1431  *          par      IN/OUT: The send_targets parameters
1432  */
1433 
1434 static void
1435 send_targets(iscsi_send_targets_parameters_t *par)
1436 {
1437 	int rc;
1438 	uint32_t rlen, cplen;
1439 	session_t *sess;
1440 
1441 	mutex_enter(&iscsi_cleanup_mtx);
1442 	if ((sess = find_session(par->session_id)) == NULL) {
1443 		mutex_exit(&iscsi_cleanup_mtx);
1444 		DEBOUT(("Session %d not found\n", par->session_id));
1445 		par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1446 		return;
1447 	}
1448 	mutex_exit(&iscsi_cleanup_mtx);
1449 
1450 	DEB(9, ("ISCSI: send_targets, rsp_size=%d; Saved list: %p\n",
1451 			par->response_size, sess->s_target_list));
1452 
1453 	if (sess->s_target_list == NULL) {
1454 		rc = send_send_targets(sess, par->key);
1455 		if (rc) {
1456 			par->status = rc;
1457 			return;
1458 		}
1459 	}
1460 	rlen = sess->s_target_list_len;
1461 	par->response_total = rlen;
1462 	cplen = min(par->response_size, rlen);
1463 	if (cplen) {
1464 		copyout(sess->s_target_list, par->response_buffer, cplen);
1465 	}
1466 	par->response_used = cplen;
1467 
1468 	/* If all of the response was copied, don't keep it around */
1469 	if (rlen && par->response_used == rlen) {
1470 		free(sess->s_target_list, M_TEMP);
1471 		sess->s_target_list = NULL;
1472 	}
1473 
1474 	par->status = ISCSI_STATUS_SUCCESS;
1475 }
1476 
1477 
1478 /*
1479  * set_node_name:
1480  *    Handle the set_node_name ioctl.
1481  *
1482  *    Parameter:
1483  *          par      IN/OUT: The set_node_name parameters
1484  */
1485 
1486 static void
1487 set_node_name(iscsi_set_node_name_parameters_t *par)
1488 {
1489 
1490 	if (strlen(par->InitiatorName) >= ISCSI_STRING_LENGTH ||
1491 		strlen(par->InitiatorAlias) >= ISCSI_STRING_LENGTH) {
1492 		DEBOUT(("*** set_node_name string too long!\n"));
1493 		par->status = ISCSI_STATUS_PARAMETER_INVALID;
1494 		return;
1495 	}
1496 	strlcpy(iscsi_InitiatorName, par->InitiatorName, sizeof(iscsi_InitiatorName));
1497 	strlcpy(iscsi_InitiatorAlias, par->InitiatorAlias, sizeof(iscsi_InitiatorAlias));
1498 	memcpy(&iscsi_InitiatorISID, par->ISID, 6);
1499 	DEB(5, ("ISCSI: set_node_name, ISID A=%x, B=%x, C=%x, D=%x\n",
1500 			iscsi_InitiatorISID.ISID_A, iscsi_InitiatorISID.ISID_B,
1501 			iscsi_InitiatorISID.ISID_C, iscsi_InitiatorISID.ISID_D));
1502 
1503 	if (!iscsi_InitiatorISID.ISID_A && !iscsi_InitiatorISID.ISID_B &&
1504 		!iscsi_InitiatorISID.ISID_C && !iscsi_InitiatorISID.ISID_D) {
1505 		iscsi_InitiatorISID.ISID_A = T_FORMAT_EN;
1506 		iscsi_InitiatorISID.ISID_B = htons(0x1);
1507 		iscsi_InitiatorISID.ISID_C = 0x37;
1508 		iscsi_InitiatorISID.ISID_D = 0;
1509 	}
1510 
1511 	par->status = ISCSI_STATUS_SUCCESS;
1512 }
1513 
1514 
1515 /*
1516  * connection_status:
1517  *    Handle the connection_status ioctl.
1518  *
1519  *    Parameter:
1520  *          par      IN/OUT: The status parameters
1521  */
1522 
1523 static void
1524 connection_status(iscsi_conn_status_parameters_t *par)
1525 {
1526 	connection_t *conn;
1527 	session_t *sess;
1528 
1529 	mutex_enter(&iscsi_cleanup_mtx);
1530 	if ((sess = find_session(par->session_id)) == NULL) {
1531 		mutex_exit(&iscsi_cleanup_mtx);
1532 		par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1533 		return;
1534 	}
1535 
1536 	if (par->connection_id) {
1537 		conn = find_connection(sess, par->connection_id);
1538 	} else {
1539 		conn = TAILQ_FIRST(&sess->s_conn_list);
1540 	}
1541 	par->status = (conn == NULL) ? ISCSI_STATUS_INVALID_CONNECTION_ID :
1542 					ISCSI_STATUS_SUCCESS;
1543 	mutex_exit(&iscsi_cleanup_mtx);
1544 	DEB(9, ("ISCSI: connection_status, session %d connection %d --> %d\n",
1545 			par->session_id, par->connection_id, par->status));
1546 }
1547 
1548 
1549 /*
1550  * get_version:
1551  *    Handle the get_version ioctl.
1552  *
1553  *    Parameter:
1554  *          par      IN/OUT: The version parameters
1555  */
1556 
1557 static void
1558 get_version(iscsi_get_version_parameters_t *par)
1559 {
1560 	par->status = ISCSI_STATUS_SUCCESS;
1561 	par->interface_version = INTERFACE_VERSION;
1562 	par->major = VERSION_MAJOR;
1563 	par->minor = VERSION_MINOR;
1564 	strlcpy(par->version_string, VERSION_STRING,
1565 		sizeof(par->version_string));
1566 }
1567 
1568 
1569 /* -------------------------------------------------------------------- */
1570 
1571 /*
1572  * kill_all_sessions:
1573  *    Terminate all sessions (called when the driver unloads).
1574  */
1575 
1576 int
1577 kill_all_sessions(void)
1578 {
1579 	session_t *sess;
1580 	int rc = 0;
1581 	uint32_t sid;
1582 
1583 	mutex_enter(&iscsi_cleanup_mtx);
1584 	while ((sess = TAILQ_FIRST(&iscsi_sessions)) != NULL) {
1585 		sid = sess->s_id;
1586 		mutex_exit(&iscsi_cleanup_mtx);
1587 		kill_session(sid, ISCSI_STATUS_DRIVER_UNLOAD, LOGOUT_SESSION,
1588 				FALSE);
1589 		mutex_enter(&iscsi_cleanup_mtx);
1590 	}
1591 	if (TAILQ_FIRST(&iscsi_sessions) != NULL) {
1592 		DEBOUT(("Failed to kill all sessions\n"));
1593 		rc = EBUSY;
1594 	}
1595 	mutex_exit(&iscsi_cleanup_mtx);
1596 
1597 	return rc;
1598 }
1599 
1600 /*
1601  * handle_connection_error:
1602  *    Deal with a problem during send or receive.
1603  *
1604  *    Parameter:
1605  *       conn        The connection the problem is associated with
1606  *       status      The status code to insert into any unfinished CCBs
1607  *       dologout    Whether Logout should be attempted
1608  */
1609 
1610 void
1611 handle_connection_error(connection_t *conn, uint32_t status, int dologout)
1612 {
1613 	DEBC(conn, 0, ("*** Connection Error, status=%d, logout=%d, state=%d\n",
1614 				   status, dologout, conn->c_state));
1615 
1616 	if (!conn->c_terminating && conn->c_state <= ST_LOGOUT_SENT) {
1617 		/* if we get an error while winding down, escalate it */
1618 		if (dologout >= 0 && conn->c_state >= ST_WINDING_DOWN) {
1619 			dologout = NO_LOGOUT;
1620 		}
1621 		kill_connection(conn, status, dologout, TRUE);
1622 	}
1623 }
1624 
1625 /*
1626  * remove a connection from session and add to the cleanup list
1627  */
1628 void
1629 add_connection_cleanup(connection_t *conn)
1630 {
1631 	session_t *sess = NULL;
1632 
1633 	mutex_enter(&iscsi_cleanup_mtx);
1634 	if (conn->c_in_session) {
1635 		sess = conn->c_session;
1636 		conn->c_in_session = FALSE;
1637 		conn->c_session = NULL;
1638 		TAILQ_REMOVE(&sess->s_conn_list, conn, c_connections);
1639 		sess->s_mru_connection = TAILQ_FIRST(&sess->s_conn_list);
1640 	}
1641 	TAILQ_INSERT_TAIL(&iscsi_cleanupc_list, conn, c_connections);
1642 	iscsi_notify_cleanup();
1643 	mutex_exit(&iscsi_cleanup_mtx);
1644 }
1645 
1646 /*
1647  * callout wrappers for timeouts, the work is done by the cleanup thread
1648  */
1649 void
1650 connection_timeout_co(void *par)
1651 {
1652 	connection_t *conn = par;
1653 
1654 	mutex_enter(&iscsi_cleanup_mtx);
1655 	if (conn->c_timedout == TOUT_ARMED) {
1656 		conn->c_timedout = TOUT_QUEUED;
1657 		TAILQ_INSERT_TAIL(&iscsi_timeout_conn_list, conn, c_tchain);
1658 		iscsi_notify_cleanup();
1659 	}
1660 	mutex_exit(&iscsi_cleanup_mtx);
1661 }
1662 
1663 void
1664 connection_timeout_start(connection_t *conn, int ticks)
1665 {
1666 	mutex_enter(&iscsi_cleanup_mtx);
1667 	if (conn->c_timedout != TOUT_QUEUED) {
1668 		conn->c_timedout = TOUT_ARMED;
1669 		callout_schedule(&conn->c_timeout, ticks);
1670 	}
1671 	mutex_exit(&iscsi_cleanup_mtx);
1672 }
1673 
1674 void
1675 connection_timeout_stop(connection_t *conn)
1676 {
1677 	callout_stop(&conn->c_timeout);
1678 	mutex_enter(&iscsi_cleanup_mtx);
1679 	if (conn->c_timedout == TOUT_QUEUED)
1680 		TAILQ_REMOVE(&iscsi_timeout_conn_list, conn, c_tchain);
1681 	if (curlwp != iscsi_cleanproc) {
1682 		while (conn->c_timedout == TOUT_BUSY)
1683 			kpause("connbusy", false, 1, &iscsi_cleanup_mtx);
1684 	}
1685 	conn->c_timedout = TOUT_NONE;
1686 	mutex_exit(&iscsi_cleanup_mtx);
1687 }
1688 
1689 void
1690 ccb_timeout_co(void *par)
1691 {
1692 	ccb_t *ccb = par;
1693 
1694 	mutex_enter(&iscsi_cleanup_mtx);
1695 	if (ccb->ccb_timedout == TOUT_ARMED) {
1696 		ccb->ccb_timedout = TOUT_QUEUED;
1697 		TAILQ_INSERT_TAIL(&iscsi_timeout_ccb_list, ccb, ccb_tchain);
1698 		iscsi_notify_cleanup();
1699 	}
1700 	mutex_exit(&iscsi_cleanup_mtx);
1701 }
1702 
1703 void
1704 ccb_timeout_start(ccb_t *ccb, int ticks)
1705 {
1706 	mutex_enter(&iscsi_cleanup_mtx);
1707 	if (ccb->ccb_timedout != TOUT_QUEUED) {
1708 		ccb->ccb_timedout = TOUT_ARMED;
1709 		callout_schedule(&ccb->ccb_timeout, ticks);
1710 	}
1711 	mutex_exit(&iscsi_cleanup_mtx);
1712 }
1713 
1714 void
1715 ccb_timeout_stop(ccb_t *ccb)
1716 {
1717 	callout_stop(&ccb->ccb_timeout);
1718 	mutex_enter(&iscsi_cleanup_mtx);
1719 	if (ccb->ccb_timedout == TOUT_QUEUED)
1720 		TAILQ_REMOVE(&iscsi_timeout_ccb_list, ccb, ccb_tchain);
1721 	if (curlwp != iscsi_cleanproc) {
1722 		while (ccb->ccb_timedout == TOUT_BUSY)
1723 			kpause("ccbbusy", false, 1, &iscsi_cleanup_mtx);
1724 	}
1725 	ccb->ccb_timedout = TOUT_NONE;
1726 	mutex_exit(&iscsi_cleanup_mtx);
1727 }
1728 
1729 /*
1730  * iscsi_cleanup_thread
1731  *    Global thread to handle connection and session cleanup after termination.
1732  */
1733 
1734 static void
1735 iscsi_cleanup_thread(void *par)
1736 {
1737 	int s, rc;
1738 	session_t *sess, *nxts;
1739 	connection_t *conn, *nxtc;
1740 	ccb_t *ccb;
1741 
1742 	mutex_enter(&iscsi_cleanup_mtx);
1743 	while (iscsi_num_send_threads || !iscsi_detaching ||
1744 	       !TAILQ_EMPTY(&iscsi_cleanupc_list) || !TAILQ_EMPTY(&iscsi_cleanups_list)) {
1745 		TAILQ_FOREACH_SAFE(conn, &iscsi_cleanupc_list, c_connections, nxtc) {
1746 
1747 			TAILQ_REMOVE(&iscsi_cleanupc_list, conn, c_connections);
1748 			mutex_exit(&iscsi_cleanup_mtx);
1749 
1750 			sess = conn->c_session;
1751 
1752 			/*
1753 			 * This implies that connection cleanup only runs when
1754 			 * the send/recv threads have been killed
1755 			 */
1756 			DEBC(conn, 5, ("Cleanup: Waiting for threads to exit\n"));
1757 
1758 			mutex_enter(&conn->c_lock);
1759 			while (conn->c_sendproc || conn->c_rcvproc)
1760 				kpause("threads", false, hz, &conn->c_lock);
1761 
1762 			for (s=1; conn->c_usecount > 0 && s < 3; ++s)
1763 				kpause("usecount", false, hz, &conn->c_lock);
1764 
1765 			if (conn->c_usecount > 0) {
1766 				DEBC(conn, 5, ("Cleanup: %d CCBs busy\n", conn->c_usecount));
1767 				mutex_exit(&conn->c_lock);
1768 				/* retry later */
1769 				mutex_enter(&iscsi_cleanup_mtx);
1770 				TAILQ_INSERT_HEAD(&iscsi_cleanupc_list, conn, c_connections);
1771 				continue;
1772 			}
1773 			mutex_exit(&conn->c_lock);
1774 
1775 			KASSERT(!conn->c_in_session);
1776 
1777 			callout_halt(&conn->c_timeout, NULL);
1778 			closef(conn->c_sock);
1779 			callout_destroy(&conn->c_timeout);
1780 			rw_destroy(&conn->c_sock_rw);
1781 			cv_destroy(&conn->c_idle_cv);
1782 			cv_destroy(&conn->c_ccb_cv);
1783 			cv_destroy(&conn->c_pdu_cv);
1784 			cv_destroy(&conn->c_conn_cv);
1785 			mutex_destroy(&conn->c_lock);
1786 			free(conn, M_DEVBUF);
1787 
1788 			mutex_enter(&iscsi_cleanup_mtx);
1789 
1790 			if (--sess->s_total_connections == 0) {
1791 				DEB(1, ("Cleanup: session %d\n", sess->s_id));
1792 				if (!sess->s_terminating) {
1793 					sess->s_terminating = ISCSI_CONNECTION_TERMINATED;
1794 					KASSERT(sess->s_sessions.tqe_prev != NULL);
1795 					TAILQ_REMOVE(&iscsi_sessions, sess, s_sessions);
1796 					sess->s_sessions.tqe_next = NULL;
1797 					sess->s_sessions.tqe_prev = NULL;
1798 				}
1799 				KASSERT(sess->s_sessions.tqe_prev == NULL);
1800 				TAILQ_INSERT_HEAD(&iscsi_cleanups_list, sess, s_sessions);
1801 			}
1802 		}
1803 
1804 		TAILQ_FOREACH_SAFE(sess, &iscsi_cleanups_list, s_sessions, nxts) {
1805 			if (sess->s_refcount > 0)
1806 				continue;
1807 			TAILQ_REMOVE(&iscsi_cleanups_list, sess, s_sessions);
1808 			sess->s_sessions.tqe_next = NULL;
1809 			sess->s_sessions.tqe_prev = NULL;
1810 			mutex_exit(&iscsi_cleanup_mtx);
1811 
1812 			DEB(1, ("Cleanup: Unmap session %d\n", sess->s_id));
1813 			if (unmap_session(sess) == 0) {
1814 				DEB(1, ("Cleanup: Unmap session %d failed\n", sess->s_id));
1815 				mutex_enter(&iscsi_cleanup_mtx);
1816 				TAILQ_INSERT_HEAD(&iscsi_cleanups_list, sess, s_sessions);
1817 				continue;
1818 			}
1819 
1820 			if (sess->s_target_list != NULL)
1821 				free(sess->s_target_list, M_TEMP);
1822 
1823 			/* notify event handlers of session shutdown */
1824 			add_event(ISCSI_SESSION_TERMINATED, sess->s_id, 0, sess->s_terminating);
1825 			DEB(1, ("Cleanup: session ended %d\n", sess->s_id));
1826 
1827 			destroy_ccbs(sess);
1828 			cv_destroy(&sess->s_ccb_cv);
1829 			cv_destroy(&sess->s_sess_cv);
1830 			mutex_destroy(&sess->s_lock);
1831 			free(sess, M_DEVBUF);
1832 
1833 			mutex_enter(&iscsi_cleanup_mtx);
1834 		}
1835 
1836 		/* handle ccb timeouts */
1837 		while ((ccb = TAILQ_FIRST(&iscsi_timeout_ccb_list)) != NULL) {
1838 			TAILQ_REMOVE(&iscsi_timeout_ccb_list, ccb, ccb_tchain);
1839 			KASSERT(ccb->ccb_timedout == TOUT_QUEUED);
1840 			ccb->ccb_timedout = TOUT_BUSY;
1841 			mutex_exit(&iscsi_cleanup_mtx);
1842 			ccb_timeout(ccb);
1843 			mutex_enter(&iscsi_cleanup_mtx);
1844 			if (ccb->ccb_timedout == TOUT_BUSY)
1845 				ccb->ccb_timedout = TOUT_NONE;
1846 		}
1847 
1848 		/* handle connection timeouts */
1849 		while ((conn = TAILQ_FIRST(&iscsi_timeout_conn_list)) != NULL) {
1850 			TAILQ_REMOVE(&iscsi_timeout_conn_list, conn, c_tchain);
1851 			KASSERT(conn->c_timedout == TOUT_QUEUED);
1852 			conn->c_timedout = TOUT_BUSY;
1853 			mutex_exit(&iscsi_cleanup_mtx);
1854 			connection_timeout(conn);
1855 			mutex_enter(&iscsi_cleanup_mtx);
1856 			if (conn->c_timedout == TOUT_BUSY)
1857 				conn->c_timedout = TOUT_NONE;
1858 		}
1859 
1860 		/* Go to sleep, but wake up every 120 seconds to
1861 		 * check for dead event handlers */
1862 		rc = cv_timedwait(&iscsi_cleanup_cv, &iscsi_cleanup_mtx,
1863 			(TAILQ_FIRST(&event_handlers)) ? 120 * hz : 0);
1864 
1865 		/* if timed out, not woken up */
1866 		if (rc == EWOULDBLOCK)
1867 			check_event_handlers();
1868 	}
1869 	mutex_exit(&iscsi_cleanup_mtx);
1870 
1871 	add_event(ISCSI_DRIVER_TERMINATING, 0, 0, ISCSI_STATUS_DRIVER_UNLOAD);
1872 
1873 	/*
1874 	 * Wait for all event handlers to deregister, but don't wait more
1875 	 * than 1 minute (assume registering app has died if it takes longer).
1876 	 */
1877 	mutex_enter(&iscsi_cleanup_mtx);
1878 	for (s = 0; TAILQ_FIRST(&event_handlers) != NULL && s < 60; s++)
1879 		kpause("waiteventclr", true, hz, &iscsi_cleanup_mtx);
1880 	mutex_exit(&iscsi_cleanup_mtx);
1881 
1882 	iscsi_cleanproc = NULL;
1883 	DEB(5, ("Cleanup thread exits\n"));
1884 	kthread_exit(0);
1885 }
1886 
1887 void
1888 iscsi_init_cleanup(void)
1889 {
1890 
1891 	mutex_init(&iscsi_cleanup_mtx, MUTEX_DEFAULT, IPL_BIO);
1892 	cv_init(&iscsi_cleanup_cv, "cleanup");
1893 	cv_init(&iscsi_event_cv, "iscsievtwait");
1894 
1895 	if (kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, iscsi_cleanup_thread,
1896 	    NULL, &iscsi_cleanproc, "iscsi_cleanup") != 0) {
1897 		panic("Can't create cleanup thread!");
1898 	}
1899 }
1900 
1901 int
1902 iscsi_destroy_cleanup(void)
1903 {
1904 
1905 	iscsi_detaching = true;
1906 	mutex_enter(&iscsi_cleanup_mtx);
1907 	while (iscsi_cleanproc != NULL) {
1908 		iscsi_notify_cleanup();
1909 		kpause("detach_wait", false, hz, &iscsi_cleanup_mtx);
1910 	}
1911 	mutex_exit(&iscsi_cleanup_mtx);
1912 
1913 	cv_destroy(&iscsi_event_cv);
1914 	cv_destroy(&iscsi_cleanup_cv);
1915 	mutex_destroy(&iscsi_cleanup_mtx);
1916 
1917 	return 0;
1918 }
1919 
1920 void
1921 iscsi_notify_cleanup(void)
1922 {
1923 	KASSERT(mutex_owned(&iscsi_cleanup_mtx));
1924 
1925 	cv_signal(&iscsi_cleanup_cv);
1926 }
1927 
1928 
1929 /* -------------------------------------------------------------------- */
1930 
1931 /*
1932  * iscsi_ioctl:
1933  *    Driver ioctl entry.
1934  *
1935  *    Parameter:
1936  *       file     File structure
1937  *       cmd      The ioctl Command
1938  *       addr     IN/OUT: The command parameter
1939  *       flag     Flags (ignored)
1940  *       l        IN: The lwp object of the caller
1941  */
1942 
1943 int
1944 iscsiioctl(struct file *fp, u_long cmd, void *addr)
1945 {
1946 	struct lwp *l = curlwp;
1947 	struct iscsifd *d = fp->f_iscsi;
1948 
1949 	DEB(1, ("ISCSI Ioctl cmd = %x\n", (int) cmd));
1950 
1951 	switch (cmd) {
1952 	case ISCSI_GET_VERSION:
1953 		get_version((iscsi_get_version_parameters_t *) addr);
1954 		break;
1955 
1956 	case ISCSI_LOGIN:
1957 		login((iscsi_login_parameters_t *) addr, l, d->fd_dev);
1958 		break;
1959 
1960 	case ISCSI_ADD_CONNECTION:
1961 		add_connection((iscsi_login_parameters_t *) addr, l);
1962 		break;
1963 
1964 	case ISCSI_RESTORE_CONNECTION:
1965 		restore_connection((iscsi_login_parameters_t *) addr, l);
1966 		break;
1967 
1968 	case ISCSI_LOGOUT:
1969 		logout((iscsi_logout_parameters_t *) addr);
1970 		break;
1971 
1972 	case ISCSI_REMOVE_CONNECTION:
1973 		remove_connection((iscsi_remove_parameters_t *) addr);
1974 		break;
1975 
1976 #ifndef ISCSI_MINIMAL
1977 	case ISCSI_IO_COMMAND:
1978 		io_command((iscsi_iocommand_parameters_t *) addr, l);
1979 		break;
1980 #endif
1981 
1982 	case ISCSI_SEND_TARGETS:
1983 		send_targets((iscsi_send_targets_parameters_t *) addr);
1984 		break;
1985 
1986 	case ISCSI_SET_NODE_NAME:
1987 		set_node_name((iscsi_set_node_name_parameters_t *) addr);
1988 		break;
1989 
1990 	case ISCSI_CONNECTION_STATUS:
1991 		connection_status((iscsi_conn_status_parameters_t *) addr);
1992 		break;
1993 
1994 	case ISCSI_REGISTER_EVENT:
1995 		register_event((iscsi_register_event_parameters_t *) addr);
1996 		break;
1997 
1998 	case ISCSI_DEREGISTER_EVENT:
1999 		deregister_event((iscsi_register_event_parameters_t *) addr);
2000 		break;
2001 
2002 	case ISCSI_WAIT_EVENT:
2003 		check_event((iscsi_wait_event_parameters_t *) addr, TRUE);
2004 		break;
2005 
2006 	case ISCSI_POLL_EVENT:
2007 		check_event((iscsi_wait_event_parameters_t *) addr, FALSE);
2008 		break;
2009 
2010 	default:
2011 		DEBOUT(("Invalid IO-Control Code\n"));
2012 		return ENOTTY;
2013 	}
2014 
2015     /*
2016      * NOTE: We return 0 even if the function fails as long as the ioctl code
2017      * is good, so the status code is copied back to the caller.
2018 	 */
2019 	return 0;
2020 }
2021