xref: /netbsd-src/sys/dev/iscsi/iscsi_ioctl.c (revision ccd9df534e375a4366c5b55f23782053c7a98d82)
1 /*	$NetBSD: iscsi_ioctl.c,v 1.34 2023/11/25 10:08:27 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 	terminating = conn->c_terminating;
517 	if (!terminating)
518 		conn->c_terminating = status;
519 
520 	/* Don't recurse */
521 	if (terminating) {
522 		mutex_exit(&iscsi_cleanup_mtx);
523 
524 		KASSERT(conn->c_state != ST_FULL_FEATURE);
525 		DEBC(conn, 1, ("Kill_connection exiting (already terminating)\n"));
526 		goto done;
527 	}
528 
529 	if (conn->c_state == ST_FULL_FEATURE) {
530 		sess->s_active_connections--;
531 		conn->c_state = ST_WINDING_DOWN;
532 
533 		/* If this is the last connection and ERL < 2, reset TSIH */
534 		if (!sess->s_active_connections && sess->s_ErrorRecoveryLevel < 2)
535 			sess->s_TSIH = 0;
536 
537 		/* Don't try to log out if the socket is broken or we're in the middle */
538 		/* of logging in */
539 		if (logout >= 0) {
540 			if (sess->s_ErrorRecoveryLevel < 2 &&
541 			    logout == RECOVER_CONNECTION) {
542 				logout = LOGOUT_CONNECTION;
543 			}
544 			if (!sess->s_active_connections &&
545 			    logout == LOGOUT_CONNECTION) {
546 				logout = LOGOUT_SESSION;
547 			}
548 			mutex_exit(&iscsi_cleanup_mtx);
549 
550 			DEBC(conn, 1, ("Send_logout for reason %d\n", logout));
551 
552 			connection_timeout_start(conn, CONNECTION_TIMEOUT);
553 
554 			if (!send_logout(conn, conn, logout, FALSE)) {
555 				conn->c_terminating = ISCSI_STATUS_SUCCESS;
556 				return;
557 			}
558 			/*
559 			 * if the logout request was successfully sent,
560 			 * the logout response handler will do the rest
561 			 * of the termination processing. If the logout
562 			 * doesn't get a response, we'll get back in here
563 			 * once the timeout hits.
564 			 */
565 
566 			mutex_enter(&iscsi_cleanup_mtx);
567 		}
568 
569 	}
570 
571 	conn->c_state = ST_SETTLING;
572 	mutex_exit(&iscsi_cleanup_mtx);
573 
574 done:
575 	/* let send thread take over next step of cleanup */
576 	mutex_enter(&conn->c_lock);
577 	cv_broadcast(&conn->c_conn_cv);
578 	mutex_exit(&conn->c_lock);
579 
580 	DEBC(conn, 5, ("kill_connection returns\n"));
581 }
582 
583 
584 /*
585  * kill_session:
586  *    Terminate the session as gracefully as possible.
587  *
588  *    Parameter:
589  *		session		Session to terminate
590  *		status		The status code for the termination
591  *		logout		The logout reason code
592 
593  */
594 
595 void
596 kill_session(uint32_t sid, uint32_t status, int logout, bool recover)
597 {
598 	session_t *sess;
599 	connection_t *conn;
600 
601 	DEB(1, ("ISCSI: kill_session %d, status %d, logout %d, recover %d\n",
602 			sid, status, logout, recover));
603 
604 	mutex_enter(&iscsi_cleanup_mtx);
605 
606 	sess = find_session(sid);
607 	if (sess == NULL) {
608 		mutex_exit(&iscsi_cleanup_mtx);
609 
610 		DEB(5, ("Session %u already gone\n", sid));
611 		return;
612 	}
613 
614 	if (sess->s_terminating) {
615 		mutex_exit(&iscsi_cleanup_mtx);
616 
617 		DEB(5, ("Session is being killed with status %d\n",sess->s_terminating));
618 		return;
619 	}
620 
621 	/*
622 	 * don't do anything if session isn't established yet, termination will be
623 	 * handled elsewhere
624 	 */
625 	if (sess->s_sessions.tqe_next == NULL && sess->s_sessions.tqe_prev == NULL) {
626 		mutex_exit(&iscsi_cleanup_mtx);
627 
628 		DEB(5, ("Session is being killed which is not yet established\n"));
629 		return;
630 	}
631 
632 	if (recover) {
633 		mutex_exit(&iscsi_cleanup_mtx);
634 
635 		/*
636 		 * Only recover when there's just one active connection left.
637 		 * Otherwise we get in all sorts of timing problems, and it doesn't
638 		 * make much sense anyway to recover when the other side has
639 		 * requested that we kill a multipathed session.
640 		 */
641 		if (sess->s_active_connections == 1) {
642 			conn = assign_connection(sess, FALSE);
643 			if (conn != NULL)
644 				kill_connection(conn, status, logout, TRUE);
645 		}
646 		return;
647 	}
648 
649 	if (sess->s_refcount > 0) {
650 		mutex_exit(&iscsi_cleanup_mtx);
651 
652 		DEB(5, ("Session is being killed while in use (refcnt = %d)\n",
653 			sess->s_refcount));
654 		return;
655 	}
656 
657 	/* Remove session from global list */
658 	sess->s_terminating = status;
659 	TAILQ_REMOVE(&iscsi_sessions, sess, s_sessions);
660 	sess->s_sessions.tqe_next = NULL;
661 	sess->s_sessions.tqe_prev = NULL;
662 
663 	/*
664 	 * If all connections are already gone, trigger cleanup
665 	 * otherwise, the last connection will do this
666 	 */
667 	if (sess->s_active_connections == 0)
668 		iscsi_notify_cleanup();
669 
670 	mutex_exit(&iscsi_cleanup_mtx);
671 
672 	/* kill all connections */
673 	while ((conn = TAILQ_FIRST(&sess->s_conn_list)) != NULL) {
674 		kill_connection(conn, status, logout, FALSE);
675 		logout = NO_LOGOUT;
676 	}
677 }
678 
679 
680 /*
681  * create_connection:
682  *    Create and init the necessary framework for a connection:
683  *       Take over userland socket
684  *       Alloc the connection structure itself
685  *       Copy connection parameters
686  *       Create the send and receive threads
687  *       And finally, log in.
688  *
689  *    Parameter:
690  *          par      IN/OUT: The login parameters
691  *          session  IN: The owning session
692  *          l        IN: The lwp pointer of the caller
693  *
694  *    Returns:    0 on success
695  *                >0 on failure, connection structure deleted
696  *                <0 on failure, connection is still terminating
697  */
698 
699 static int
700 create_connection(iscsi_login_parameters_t *par, session_t *sess,
701 				  struct lwp *l)
702 {
703 	connection_t *conn;
704 	int rc;
705 
706 	DEB(1, ("Create Connection for Session %d\n", sess->s_id));
707 
708 	if (sess->s_MaxConnections &&
709 	    sess->s_active_connections >= sess->s_MaxConnections) {
710 		DEBOUT(("Too many connections (max = %d, curr = %d)\n",
711 				sess->s_MaxConnections, sess->s_active_connections));
712 		/* Always close descriptor */
713 		fd_close(par->socket);
714 
715 		par->status = ISCSI_STATUS_MAXED_CONNECTIONS;
716 		return EIO;
717 	}
718 
719 	conn = malloc(sizeof(*conn), M_DEVBUF, M_WAITOK | M_ZERO);
720 	if (conn == NULL) {
721 		DEBOUT(("No mem for connection\n"));
722 
723 		/* Always close descriptor */
724 		fd_close(par->socket);
725 
726 		par->status = ISCSI_STATUS_NO_RESOURCES;
727 		return EIO;
728 	}
729 
730 	rc = get_socket(par->socket, &conn->c_sock);
731 	if (rc != EBADF)
732 		fd_close(par->socket);
733 
734 	if (rc) {
735 		DEBOUT(("Invalid socket %d\n", par->socket));
736 		free(conn, M_DEVBUF);
737 		par->status = ISCSI_STATUS_INVALID_SOCKET;
738 		return rc;
739 	}
740 
741 	DEBC(conn, 1, ("get_socket: par_sock=%d, fdesc=%p\n",
742 			par->socket, conn->c_sock));
743 
744 	mutex_enter(&iscsi_cleanup_mtx);
745 	/* create a unique ID */
746 	do {
747 		++sess->s_conn_id;
748 	} while (!sess->s_conn_id ||
749 		 find_connection(sess, sess->s_conn_id) != NULL);
750 	par->connection_id = conn->c_id = sess->s_conn_id;
751 	mutex_exit(&iscsi_cleanup_mtx);
752 	DEB(99, ("Connection ID = %d\n", conn->c_id));
753 
754 	conn->c_session = sess;
755 
756 	TAILQ_INIT(&conn->c_ccbs_waiting);
757 	TAILQ_INIT(&conn->c_pdus_to_send);
758 	TAILQ_INIT(&conn->c_pdu_pool);
759 
760 	mutex_init(&conn->c_lock, MUTEX_DEFAULT, IPL_BIO);
761 	cv_init(&conn->c_conn_cv, "conn");
762 	cv_init(&conn->c_pdu_cv, "pdupool");
763 	cv_init(&conn->c_ccb_cv, "ccbwait");
764 	cv_init(&conn->c_idle_cv, "idle");
765 	rw_init(&conn->c_sock_rw);
766 
767 	callout_init(&conn->c_timeout, CALLOUT_MPSAFE);
768 	callout_setfunc(&conn->c_timeout, connection_timeout_co, conn);
769 	conn->c_idle_timeout_val = CONNECTION_IDLE_TIMEOUT;
770 
771 	init_sernum(&conn->c_StatSN_buf);
772 	create_pdus(conn);
773 
774 	conn->c_threadobj = l;
775 	conn->c_login_par = par;
776 
777 	DEB(5, ("Creating receive thread\n"));
778 	if ((rc = kthread_create(PRI_BIO, KTHREAD_MPSAFE, NULL, iscsi_rcv_thread,
779 				conn, &conn->c_rcvproc,
780 				"ConnRcv")) != 0) {
781 		DEBOUT(("Can't create rcv thread (rc %d)\n", rc));
782 
783 		release_socket(conn->c_sock);
784 		rw_destroy(&conn->c_sock_rw);
785 		callout_destroy(&conn->c_timeout);
786 		cv_destroy(&conn->c_idle_cv);
787 		cv_destroy(&conn->c_ccb_cv);
788 		cv_destroy(&conn->c_pdu_cv);
789 		cv_destroy(&conn->c_conn_cv);
790 		mutex_destroy(&conn->c_lock);
791 		free(conn, M_DEVBUF);
792 		par->status = ISCSI_STATUS_NO_RESOURCES;
793 		return rc;
794 	}
795 	DEB(5, ("Creating send thread\n"));
796 	if ((rc = kthread_create(PRI_BIO, KTHREAD_MPSAFE, NULL, iscsi_send_thread,
797 				conn, &conn->c_sendproc,
798 				"ConnSend")) != 0) {
799 		DEBOUT(("Can't create send thread (rc %d)\n", rc));
800 
801 		conn->c_terminating = ISCSI_STATUS_NO_RESOURCES;
802 
803 		/*
804 		 * We must close the socket here to force the receive
805 		 * thread to wake up
806 		 */
807 		DEBC(conn, 1, ("Closing Socket %p\n", conn->c_sock));
808 		mutex_enter(&conn->c_sock->f_lock);
809 		conn->c_sock->f_count += 1;
810 		mutex_exit(&conn->c_sock->f_lock);
811 		closef(conn->c_sock);
812 
813 		/* give receive thread time to exit */
814 		kpause("settle", false, 2 * hz, NULL);
815 
816 		release_socket(conn->c_sock);
817 		callout_destroy(&conn->c_timeout);
818 		rw_destroy(&conn->c_sock_rw);
819 		cv_destroy(&conn->c_idle_cv);
820 		cv_destroy(&conn->c_ccb_cv);
821 		cv_destroy(&conn->c_pdu_cv);
822 		cv_destroy(&conn->c_conn_cv);
823 		mutex_destroy(&conn->c_lock);
824 		free(conn, M_DEVBUF);
825 		par->status = ISCSI_STATUS_NO_RESOURCES;
826 		return rc;
827 	}
828 
829 	/*
830 	 * At this point, each thread will tie 'sock' into its own file descriptor
831 	 * tables w/o increasing the use count - they will inherit the use
832 	 * increments performed in get_socket().
833 	 */
834 
835 	if ((rc = send_login(conn)) != 0) {
836 		DEBC(conn, 0, ("Login failed (rc %d)\n", rc));
837 		/* Don't attempt to recover, there seems to be something amiss */
838 		kill_connection(conn, rc, NO_LOGOUT, FALSE);
839 		par->status = rc;
840 		return -1;
841 	}
842 
843 	mutex_enter(&iscsi_cleanup_mtx);
844 	if (sess->s_terminating) {
845 		mutex_exit(&iscsi_cleanup_mtx);
846 		DEBC(conn, 0, ("Session terminating\n"));
847 		kill_connection(conn, rc, NO_LOGOUT, FALSE);
848 		par->status = sess->s_terminating;
849 		return -1;
850 	}
851 	conn->c_state = ST_FULL_FEATURE;
852 	TAILQ_INSERT_TAIL(&sess->s_conn_list, conn, c_connections);
853 	conn->c_in_session = TRUE;
854 	sess->s_total_connections++;
855 	sess->s_active_connections++;
856 	sess->s_mru_connection = conn;
857 	mutex_exit(&iscsi_cleanup_mtx);
858 
859 	DEBC(conn, 5, ("Connection created successfully!\n"));
860 	return 0;
861 }
862 
863 
864 /*
865  * recreate_connection:
866  *    Revive dead connection
867  *
868  *    Parameter:
869  *          par      IN/OUT: The login parameters
870  *          conn     IN: The connection
871  *          l        IN: The lwp pointer of the caller
872  *
873  *    Returns:    0 on success
874  *                >0 on failure, connection structure deleted
875  *                <0 on failure, connection is still terminating
876  */
877 
878 static int
879 recreate_connection(iscsi_login_parameters_t *par, session_t *sess,
880 					connection_t *conn, struct lwp *l)
881 {
882 	int rc;
883 	ccb_t *ccb;
884 	ccb_list_t old_waiting;
885 	pdu_t *pdu;
886 	uint32_t sn;
887 
888 	DEB(1, ("ReCreate Connection %d for Session %d, ERL=%d\n",
889 		conn->c_id, conn->c_session->s_id,
890 		conn->c_session->s_ErrorRecoveryLevel));
891 
892 	if (sess->s_MaxConnections &&
893 	    sess->s_active_connections >= sess->s_MaxConnections) {
894 		DEBOUT(("Too many connections (max = %d, curr = %d)\n",
895 			sess->s_MaxConnections, sess->s_active_connections));
896 
897 		/* Close the desecriptor */
898 		rc = EIO;
899 		if (fd_getfile(par->socket) != NULL)
900 			rc = fd_close(par->socket);
901 
902 		par->status = ISCSI_STATUS_MAXED_CONNECTIONS;
903 		return rc;
904 	}
905 
906 	rw_enter(&conn->c_sock_rw, RW_WRITER);
907 	if (conn->c_sock != NULL) {
908 		closef(conn->c_sock);
909 		conn->c_sock = NULL;
910 	}
911 	rc = get_socket(par->socket, &conn->c_sock);
912 	rw_exit(&conn->c_sock_rw);
913 	if (rc != EBADF)
914 		fd_close(par->socket);
915 
916 	if (rc) {
917 		DEBOUT(("Invalid socket %d\n", par->socket));
918 		par->status = ISCSI_STATUS_INVALID_SOCKET;
919 		return rc;
920 	}
921 
922 	DEBC(conn, 1, ("get_socket: par_sock=%d, fdesc=%p\n",
923 			par->socket, conn->c_sock));
924 
925 	conn->c_threadobj = l;
926 	conn->c_login_par = par;
927 	conn->c_terminating = ISCSI_STATUS_SUCCESS;
928 	conn->c_recover++;
929 	conn->c_num_timeouts = 0;
930 	conn->c_state = ST_SEC_NEG;
931 	conn->c_HeaderDigest = 0;
932 	conn->c_DataDigest = 0;
933 
934 	sess->s_active_connections++;
935 
936 	TAILQ_INIT(&old_waiting);
937 
938 	mutex_enter(&conn->c_lock);
939 	while ((ccb = TAILQ_FIRST(&conn->c_ccbs_waiting)) != NULL) {
940 		suspend_ccb(ccb, FALSE);
941 		TAILQ_INSERT_TAIL(&old_waiting, ccb, ccb_chain);
942 	}
943 	init_sernum(&conn->c_StatSN_buf);
944 	cv_broadcast(&conn->c_idle_cv);
945 	mutex_exit(&conn->c_lock);
946 
947 	if ((rc = send_login(conn)) != 0) {
948 		DEBC(conn, 0, ("Re-Login failed (rc %d)\n", rc));
949 		while ((ccb = TAILQ_FIRST(&old_waiting)) != NULL) {
950 			TAILQ_REMOVE(&old_waiting, ccb, ccb_chain);
951 			wake_ccb(ccb, rc);
952 		}
953 		/* Don't attempt to recover, there seems to be something amiss */
954 		kill_connection(conn, rc, NO_LOGOUT, FALSE);
955 		par->status = rc;
956 		return -1;
957 	}
958 
959 	DEBC(conn, 9, ("Re-Login successful\n"));
960 	par->status = ISCSI_STATUS_SUCCESS;
961 
962 	conn->c_state = ST_FULL_FEATURE;
963 	sess->s_mru_connection = conn;
964 
965 	while ((ccb = TAILQ_FIRST(&old_waiting)) != NULL) {
966 		TAILQ_REMOVE(&old_waiting, ccb, ccb_chain);
967 		mutex_enter(&conn->c_lock);
968 		suspend_ccb(ccb, TRUE);
969 		mutex_exit(&conn->c_lock);
970 
971 		rc = send_task_management(conn, ccb, NULL, TASK_REASSIGN);
972 		/* if we get an error on reassign, restart the original request */
973 		if (rc && ccb->ccb_pdu_waiting != NULL) {
974 			mutex_enter(&sess->s_lock);
975 			if (sn_a_lt_b(ccb->ccb_CmdSN, sess->s_ExpCmdSN)) {
976 				pdu = ccb->ccb_pdu_waiting;
977 				sn = get_sernum(sess, pdu);
978 
979 				/* update CmdSN */
980 				DEBC(conn, 0, ("Resend ccb %p (%d) - updating CmdSN old %u, new %u\n",
981 					   ccb, rc, ccb->ccb_CmdSN, sn));
982 				ccb->ccb_CmdSN = sn;
983 				pdu->pdu_hdr.pduh_p.command.CmdSN = htonl(ccb->ccb_CmdSN);
984 			} else {
985 				DEBC(conn, 0, ("Resend ccb %p (%d) - CmdSN %u\n",
986 					   ccb, rc, ccb->ccb_CmdSN));
987 			}
988 			mutex_exit(&sess->s_lock);
989 			resend_pdu(ccb);
990 		} else {
991 			DEBC(conn, 0, ("Resend ccb %p (%d) CmdSN %u - reassigned\n",
992 				ccb, rc, ccb->ccb_CmdSN));
993 			ccb_timeout_start(ccb, COMMAND_TIMEOUT);
994 		}
995 	}
996 
997 	mutex_enter(&sess->s_lock);
998 	cv_broadcast(&sess->s_sess_cv);
999 	mutex_exit(&sess->s_lock);
1000 
1001 	DEBC(conn, 0, ("Connection ReCreated successfully - status %d\n",
1002 						 par->status));
1003 
1004 	return 0;
1005 }
1006 
1007 /* -------------------------------------------------------------------------- */
1008 
1009 /*
1010  * check_login_pars:
1011  *    Check the parameters passed into login/add_connection
1012  *    for validity and consistency.
1013  *
1014  *    Parameter:
1015  *          par      The login parameters
1016  *
1017  *    Returns:    0 on success, else an error code.
1018  */
1019 
1020 static int
1021 check_login_pars(iscsi_login_parameters_t *par)
1022 {
1023 	int i, n;
1024 
1025 	if (par->is_present.auth_info) {
1026 		/* check consistency of authentication parameters */
1027 
1028 		if (par->auth_info.auth_number > ISCSI_AUTH_OPTIONS) {
1029 			DEBOUT(("Auth number invalid: %d\n", par->auth_info.auth_number));
1030 			return ISCSI_STATUS_PARAMETER_INVALID;
1031 		}
1032 
1033 		if (par->auth_info.auth_number > 2) {
1034 			DEBOUT(("Auth number invalid: %d\n", par->auth_info.auth_number));
1035 			return ISCSI_STATUS_NOTIMPL;
1036 		}
1037 
1038 		for (i = 0, n = 0; i < par->auth_info.auth_number; i++) {
1039 #if 0
1040 			if (par->auth_info.auth_type[i] < ISCSI_AUTH_None) {
1041 				DEBOUT(("Auth type invalid: %d\n",
1042 						par->auth_info.auth_type[i]));
1043 				return ISCSI_STATUS_PARAMETER_INVALID;
1044 			}
1045 #endif
1046 			if (par->auth_info.auth_type[i] > ISCSI_AUTH_CHAP) {
1047 				DEBOUT(("Auth type invalid: %d\n",
1048 						par->auth_info.auth_type[i]));
1049 				return ISCSI_STATUS_NOTIMPL;
1050 			}
1051 			n = max(n, par->auth_info.auth_type[i]);
1052 		}
1053 		if (n) {
1054 			if (!par->is_present.password ||
1055 				(par->auth_info.mutual_auth &&
1056 				 !par->is_present.target_password)) {
1057 				DEBOUT(("Password missing\n"));
1058 				return ISCSI_STATUS_PARAMETER_MISSING;
1059 			}
1060 			/* Note: Default for user-name is initiator name */
1061 		}
1062 	}
1063 	if (par->login_type != ISCSI_LOGINTYPE_DISCOVERY &&
1064 	    !par->is_present.TargetName) {
1065 		DEBOUT(("Target name missing, login type %d\n", par->login_type));
1066 		return ISCSI_STATUS_PARAMETER_MISSING;
1067 	}
1068 	if (par->is_present.MaxRecvDataSegmentLength) {
1069 		if (par->MaxRecvDataSegmentLength < 512 ||
1070 			par->MaxRecvDataSegmentLength > 0xffffff) {
1071 			DEBOUT(("MaxRecvDataSegmentLength invalid: %d\n",
1072 					par->MaxRecvDataSegmentLength));
1073 			return ISCSI_STATUS_PARAMETER_INVALID;
1074 		}
1075 	}
1076 	return 0;
1077 }
1078 
1079 
1080 /*
1081  * login:
1082  *    Handle the login ioctl - Create a session:
1083  *       Alloc the session structure
1084  *       Copy session parameters
1085  *       And call create_connection to establish the connection.
1086  *
1087  *    Parameter:
1088  *          par      IN/OUT: The login parameters
1089  *          l        IN: The lwp pointer of the caller
1090  */
1091 
1092 static void
1093 login(iscsi_login_parameters_t *par, struct lwp *l, device_t dev)
1094 {
1095 	session_t *sess;
1096 	int rc;
1097 
1098 	DEB(99, ("ISCSI: login\n"));
1099 
1100 	if (!iscsi_InitiatorName[0]) {
1101 		DEB(1, ("No Initiator Name\n"));
1102 		par->status = ISCSI_STATUS_NO_INITIATOR_NAME;
1103 		return;
1104 	}
1105 
1106 	if ((par->status = check_login_pars(par)) != 0)
1107 		return;
1108 
1109 	/* alloc the session */
1110 	sess = malloc(sizeof(*sess), M_DEVBUF, M_WAITOK | M_ZERO);
1111 	if (sess == NULL) {
1112 		DEBOUT(("No mem for session\n"));
1113 		par->status = ISCSI_STATUS_NO_RESOURCES;
1114 		return;
1115 	}
1116 	TAILQ_INIT(&sess->s_conn_list);
1117 	TAILQ_INIT(&sess->s_ccb_pool);
1118 
1119 	mutex_init(&sess->s_lock, MUTEX_DEFAULT, IPL_BIO);
1120 	cv_init(&sess->s_sess_cv, "session");
1121 	cv_init(&sess->s_ccb_cv, "ccb");
1122 
1123 	mutex_enter(&iscsi_cleanup_mtx);
1124 	/* create a unique ID */
1125 	do {
1126 		++current_id;
1127 	} while (!current_id || find_session(current_id) != NULL);
1128 	par->session_id = sess->s_id = current_id;
1129 	mutex_exit(&iscsi_cleanup_mtx);
1130 
1131 	create_ccbs(sess);
1132 	sess->s_login_type = par->login_type;
1133 	sess->s_CmdSN = 1;
1134 
1135 	if ((rc = create_connection(par, sess, l)) != 0) {
1136 		if (rc > 0) {
1137 			destroy_ccbs(sess);
1138 			cv_destroy(&sess->s_ccb_cv);
1139 			cv_destroy(&sess->s_sess_cv);
1140 			mutex_destroy(&sess->s_lock);
1141 			free(sess, M_DEVBUF);
1142 		}
1143 		return;
1144 	}
1145 
1146 	mutex_enter(&iscsi_cleanup_mtx);
1147 	TAILQ_INSERT_HEAD(&iscsi_sessions, sess, s_sessions);
1148 	mutex_exit(&iscsi_cleanup_mtx);
1149 
1150 	/* Session established, map LUNs? */
1151 	if (par->login_type == ISCSI_LOGINTYPE_MAP) {
1152 		copyinstr(par->TargetName, sess->s_tgtname,
1153 		    sizeof(sess->s_tgtname), NULL);
1154 		DEB(1, ("Login: map session %d\n", sess->s_id));
1155 		if (!map_session(sess, dev)) {
1156 			DEB(1, ("Login: map session %d failed\n", sess->s_id));
1157 			kill_session(par->session_id, ISCSI_STATUS_MAP_FAILED,
1158 					LOGOUT_SESSION, FALSE);
1159 			par->status = ISCSI_STATUS_MAP_FAILED;
1160 			return;
1161 		}
1162 	}
1163 }
1164 
1165 
1166 /*
1167  * logout:
1168  *    Handle the logout ioctl - Kill a session.
1169  *
1170  *    Parameter:
1171  *          par      IN/OUT: The login parameters
1172  */
1173 
1174 static void
1175 logout(iscsi_logout_parameters_t *par)
1176 {
1177 	session_t *session;
1178 
1179 	DEB(5, ("ISCSI: logout session %d\n", par->session_id));
1180 
1181 	mutex_enter(&iscsi_cleanup_mtx);
1182 	if ((session = find_session(par->session_id)) == NULL) {
1183 		mutex_exit(&iscsi_cleanup_mtx);
1184 		DEBOUT(("Session %d not found\n", par->session_id));
1185 		par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1186 		return;
1187 	}
1188 	mutex_exit(&iscsi_cleanup_mtx);
1189 	/* If the session exists, this always succeeds */
1190 	par->status = ISCSI_STATUS_SUCCESS;
1191 
1192 	kill_session(par->session_id,
1193 	    ISCSI_STATUS_LOGOUT, LOGOUT_SESSION,
1194 	    FALSE);
1195 }
1196 
1197 
1198 /*
1199  * add_connection:
1200  *    Handle the add_connection ioctl.
1201  *
1202  *    Parameter:
1203  *          par      IN/OUT: The login parameters
1204  *          l        IN: The lwp pointer of the caller
1205  */
1206 
1207 static int
1208 add_connection(iscsi_login_parameters_t *par, struct lwp *l)
1209 {
1210 	session_t *session;
1211 
1212 	DEB(5, ("ISCSI: add_connection to session %d\n", par->session_id));
1213 
1214 	mutex_enter(&iscsi_cleanup_mtx);
1215 	if ((session = find_session(par->session_id)) == NULL) {
1216 		mutex_exit(&iscsi_cleanup_mtx);
1217 		DEBOUT(("Session %d not found\n", par->session_id));
1218 		par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1219 		return -1;
1220 	}
1221 	mutex_exit(&iscsi_cleanup_mtx);
1222 
1223 	par->status = check_login_pars(par);
1224 	if (par->status)
1225 		return -1;
1226 
1227 	return create_connection(par, session, l);
1228 }
1229 
1230 
1231 /*
1232  * remove_connection:
1233  *    Handle the remove_connection ioctl.
1234  *
1235  *    Parameter:
1236  *          par      IN/OUT: The remove parameters
1237  */
1238 
1239 static void
1240 remove_connection(iscsi_remove_parameters_t *par)
1241 {
1242 	connection_t *conn;
1243 	session_t *session;
1244 
1245 	DEB(5, ("ISCSI: remove_connection %d from session %d\n",
1246 			par->connection_id, par->session_id));
1247 
1248 	mutex_enter(&iscsi_cleanup_mtx);
1249 	if ((session = find_session(par->session_id)) == NULL) {
1250 		mutex_exit(&iscsi_cleanup_mtx);
1251 		DEBOUT(("Session %d not found\n", par->session_id));
1252 		par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1253 		return;
1254 	}
1255 
1256 	if ((conn = find_connection(session, par->connection_id)) == NULL) {
1257 		mutex_exit(&iscsi_cleanup_mtx);
1258 		DEBOUT(("Connection %d not found in session %d\n",
1259 				par->connection_id, par->session_id));
1260 
1261 		par->status = ISCSI_STATUS_INVALID_CONNECTION_ID;
1262 	} else {
1263 		mutex_exit(&iscsi_cleanup_mtx);
1264 		kill_connection(conn, ISCSI_STATUS_LOGOUT, LOGOUT_CONNECTION,
1265 					FALSE);
1266 		par->status = ISCSI_STATUS_SUCCESS;
1267 	}
1268 }
1269 
1270 
1271 /*
1272  * restore_connection:
1273  *    Handle the restore_connection ioctl.
1274  *
1275  *    Parameter:
1276  *          par      IN/OUT: The login parameters
1277  *          l        IN: The lwp pointer of the caller
1278  */
1279 
1280 static void
1281 restore_connection(iscsi_login_parameters_t *par, struct lwp *l)
1282 {
1283 	session_t *sess;
1284 	connection_t *conn;
1285 
1286 	DEB(1, ("ISCSI: restore_connection %d of session %d\n",
1287 			par->connection_id, par->session_id));
1288 
1289 	mutex_enter(&iscsi_cleanup_mtx);
1290 	if ((sess = find_session(par->session_id)) == NULL) {
1291 		mutex_exit(&iscsi_cleanup_mtx);
1292 		DEBOUT(("Session %d not found\n", par->session_id));
1293 		par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1294 		return;
1295 	}
1296 	if ((conn = find_connection(sess, par->connection_id)) == NULL) {
1297 		mutex_exit(&iscsi_cleanup_mtx);
1298 		DEBOUT(("Connection %d not found in session %d\n",
1299 				par->connection_id, par->session_id));
1300 		par->status = ISCSI_STATUS_INVALID_CONNECTION_ID;
1301 		return;
1302 	}
1303 	if (!conn->c_terminating) {
1304 		mutex_exit(&iscsi_cleanup_mtx);
1305 		DEBC(conn, 0, ("Connection is alive\n"));
1306 		par->status = ISCSI_STATUS_SUCCESS;
1307 		return;
1308 	}
1309 	mutex_exit(&iscsi_cleanup_mtx);
1310 
1311 	if ((par->status = check_login_pars(par)) == 0) {
1312 		recreate_connection(par, sess, conn, l);
1313 	}
1314 }
1315 
1316 
1317 #ifndef ISCSI_MINIMAL
1318 
1319 /*
1320  * io_command:
1321  *    Handle the io_command ioctl.
1322  *
1323  *    Parameter:
1324  *          par      IN/OUT: The iocommand parameters
1325  *          l        IN: The lwp pointer of the caller
1326  */
1327 
1328 static void
1329 io_command(iscsi_iocommand_parameters_t *par, struct lwp *l)
1330 {
1331 	uint32_t datalen = par->req.datalen;
1332 	session_t *session;
1333 	void *kbuf = NULL;
1334 	int error;
1335 
1336 	DEB(9, ("ISCSI: io_command, SID=%d, lun=%" PRIu64 "\n", par->session_id, par->lun));
1337 	mutex_enter(&iscsi_cleanup_mtx);
1338 	if ((session = find_session(par->session_id)) == NULL) {
1339 		mutex_exit(&iscsi_cleanup_mtx);
1340 		DEBOUT(("Session %d not found\n", par->session_id));
1341 		par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1342 		return;
1343 	}
1344 	mutex_exit(&iscsi_cleanup_mtx);
1345 
1346 	par->req.senselen_used = 0;
1347 	par->req.datalen_used = 0;
1348 	par->req.error = 0;
1349 	par->req.status = 0;
1350 	par->req.retsts = SCCMD_UNKNOWN;	/* init to failure code */
1351 
1352 	if (par->req.cmdlen > 16 || par->req.senselen > sizeof(par->req.sense)) {
1353 		par->status = ISCSI_STATUS_PARAMETER_INVALID;
1354 		return;
1355 	}
1356 
1357 	if (datalen) {
1358 		/* Arbitrarily limit datalen to 8k. */
1359 		if (datalen > 8192) {
1360 			par->status = ISCSI_STATUS_PARAMETER_INVALID;
1361 			return;
1362 		}
1363 		kbuf = kmem_zalloc(datalen, KM_SLEEP);
1364 		if ((par->req.flags & SCCMD_WRITE) != 0) {
1365 			error = copyin(par->req.databuf, kbuf, datalen);
1366 			if (error) {
1367 				kmem_free(kbuf, datalen);
1368 				par->status = ISCSI_STATUS_PARAMETER_INVALID;
1369 				return;
1370 			}
1371 		}
1372 	}
1373 	par->status = send_io_command(session, par->lun, &par->req,
1374 								  par->options.immediate, par->connection_id);
1375 
1376 	if (kbuf) {
1377 		if ((par->req.flags & SCCMD_READ) != 0) {
1378 			(void) copyout(kbuf, par->req.databuf, datalen);
1379 		}
1380 		kmem_free(kbuf, datalen);
1381 	}
1382 	switch (par->status) {
1383 	case ISCSI_STATUS_SUCCESS:
1384 		par->req.retsts = SCCMD_OK;
1385 		break;
1386 
1387 	case ISCSI_STATUS_TARGET_BUSY:
1388 		par->req.retsts = SCCMD_BUSY;
1389 		break;
1390 
1391 	case ISCSI_STATUS_TIMEOUT:
1392 	case ISCSI_STATUS_SOCKET_ERROR:
1393 		par->req.retsts = SCCMD_TIMEOUT;
1394 		break;
1395 
1396 	default:
1397 		par->req.retsts = (par->req.senselen_used) ? SCCMD_SENSE
1398 												   : SCCMD_UNKNOWN;
1399 		break;
1400 	}
1401 }
1402 #endif
1403 
1404 /*
1405  * send_targets:
1406  *    Handle the send_targets ioctl.
1407  *    Note: If the passed buffer is too small to hold the complete response,
1408  *    the response is kept in the session structure so it can be
1409  *    retrieved with the next call to this function without having to go to
1410  *    the target again. Once the complete response has been retrieved, it
1411  *    is discarded.
1412  *
1413  *    Parameter:
1414  *          par      IN/OUT: The send_targets parameters
1415  */
1416 
1417 static void
1418 send_targets(iscsi_send_targets_parameters_t *par)
1419 {
1420 	int rc;
1421 	uint32_t rlen, cplen;
1422 	session_t *sess;
1423 
1424 	mutex_enter(&iscsi_cleanup_mtx);
1425 	if ((sess = find_session(par->session_id)) == NULL) {
1426 		mutex_exit(&iscsi_cleanup_mtx);
1427 		DEBOUT(("Session %d not found\n", par->session_id));
1428 		par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1429 		return;
1430 	}
1431 	mutex_exit(&iscsi_cleanup_mtx);
1432 
1433 	DEB(9, ("ISCSI: send_targets, rsp_size=%d; Saved list: %p\n",
1434 			par->response_size, sess->s_target_list));
1435 
1436 	if (sess->s_target_list == NULL) {
1437 		rc = send_send_targets(sess, par->key);
1438 		if (rc) {
1439 			par->status = rc;
1440 			return;
1441 		}
1442 	}
1443 	rlen = sess->s_target_list_len;
1444 	par->response_total = rlen;
1445 	cplen = min(par->response_size, rlen);
1446 	if (cplen) {
1447 		copyout(sess->s_target_list, par->response_buffer, cplen);
1448 	}
1449 	par->response_used = cplen;
1450 
1451 	/* If all of the response was copied, don't keep it around */
1452 	if (rlen && par->response_used == rlen) {
1453 		free(sess->s_target_list, M_TEMP);
1454 		sess->s_target_list = NULL;
1455 	}
1456 
1457 	par->status = ISCSI_STATUS_SUCCESS;
1458 }
1459 
1460 
1461 /*
1462  * set_node_name:
1463  *    Handle the set_node_name ioctl.
1464  *
1465  *    Parameter:
1466  *          par      IN/OUT: The set_node_name parameters
1467  */
1468 
1469 static void
1470 set_node_name(iscsi_set_node_name_parameters_t *par)
1471 {
1472 
1473 	if (strlen(par->InitiatorName) >= ISCSI_STRING_LENGTH ||
1474 		strlen(par->InitiatorAlias) >= ISCSI_STRING_LENGTH) {
1475 		DEBOUT(("*** set_node_name string too long!\n"));
1476 		par->status = ISCSI_STATUS_PARAMETER_INVALID;
1477 		return;
1478 	}
1479 	strlcpy(iscsi_InitiatorName, par->InitiatorName, sizeof(iscsi_InitiatorName));
1480 	strlcpy(iscsi_InitiatorAlias, par->InitiatorAlias, sizeof(iscsi_InitiatorAlias));
1481 	memcpy(&iscsi_InitiatorISID, par->ISID, 6);
1482 	DEB(5, ("ISCSI: set_node_name, ISID A=%x, B=%x, C=%x, D=%x\n",
1483 			iscsi_InitiatorISID.ISID_A, iscsi_InitiatorISID.ISID_B,
1484 			iscsi_InitiatorISID.ISID_C, iscsi_InitiatorISID.ISID_D));
1485 
1486 	if (!iscsi_InitiatorISID.ISID_A && !iscsi_InitiatorISID.ISID_B &&
1487 		!iscsi_InitiatorISID.ISID_C && !iscsi_InitiatorISID.ISID_D) {
1488 		iscsi_InitiatorISID.ISID_A = T_FORMAT_EN;
1489 		iscsi_InitiatorISID.ISID_B = htons(0x1);
1490 		iscsi_InitiatorISID.ISID_C = 0x37;
1491 		iscsi_InitiatorISID.ISID_D = 0;
1492 	}
1493 
1494 	par->status = ISCSI_STATUS_SUCCESS;
1495 }
1496 
1497 
1498 /*
1499  * connection_status:
1500  *    Handle the connection_status ioctl.
1501  *
1502  *    Parameter:
1503  *          par      IN/OUT: The status parameters
1504  */
1505 
1506 static void
1507 connection_status(iscsi_conn_status_parameters_t *par)
1508 {
1509 	connection_t *conn;
1510 	session_t *sess;
1511 
1512 	mutex_enter(&iscsi_cleanup_mtx);
1513 	if ((sess = find_session(par->session_id)) == NULL) {
1514 		mutex_exit(&iscsi_cleanup_mtx);
1515 		par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1516 		return;
1517 	}
1518 
1519 	if (par->connection_id) {
1520 		conn = find_connection(sess, par->connection_id);
1521 	} else {
1522 		conn = TAILQ_FIRST(&sess->s_conn_list);
1523 	}
1524 	par->status = (conn == NULL) ? ISCSI_STATUS_INVALID_CONNECTION_ID :
1525 					ISCSI_STATUS_SUCCESS;
1526 	mutex_exit(&iscsi_cleanup_mtx);
1527 	DEB(9, ("ISCSI: connection_status, session %d connection %d --> %d\n",
1528 			par->session_id, par->connection_id, par->status));
1529 }
1530 
1531 
1532 /*
1533  * get_version:
1534  *    Handle the get_version ioctl.
1535  *
1536  *    Parameter:
1537  *          par      IN/OUT: The version parameters
1538  */
1539 
1540 static void
1541 get_version(iscsi_get_version_parameters_t *par)
1542 {
1543 	par->status = ISCSI_STATUS_SUCCESS;
1544 	par->interface_version = INTERFACE_VERSION;
1545 	par->major = VERSION_MAJOR;
1546 	par->minor = VERSION_MINOR;
1547 	strlcpy(par->version_string, VERSION_STRING,
1548 		sizeof(par->version_string));
1549 }
1550 
1551 
1552 /* -------------------------------------------------------------------- */
1553 
1554 /*
1555  * kill_all_sessions:
1556  *    Terminate all sessions (called when the driver unloads).
1557  */
1558 
1559 int
1560 kill_all_sessions(void)
1561 {
1562 	session_t *sess;
1563 	int rc = 0;
1564 	uint32_t sid;
1565 
1566 	mutex_enter(&iscsi_cleanup_mtx);
1567 	while ((sess = TAILQ_FIRST(&iscsi_sessions)) != NULL) {
1568 		sid = sess->s_id;
1569 		mutex_exit(&iscsi_cleanup_mtx);
1570 		kill_session(sid, ISCSI_STATUS_DRIVER_UNLOAD, LOGOUT_SESSION,
1571 				FALSE);
1572 		mutex_enter(&iscsi_cleanup_mtx);
1573 	}
1574 	if (TAILQ_FIRST(&iscsi_sessions) != NULL) {
1575 		DEBOUT(("Failed to kill all sessions\n"));
1576 		rc = EBUSY;
1577 	}
1578 	mutex_exit(&iscsi_cleanup_mtx);
1579 
1580 	return rc;
1581 }
1582 
1583 /*
1584  * handle_connection_error:
1585  *    Deal with a problem during send or receive.
1586  *
1587  *    Parameter:
1588  *       conn        The connection the problem is associated with
1589  *       status      The status code to insert into any unfinished CCBs
1590  *       dologout    Whether Logout should be attempted
1591  */
1592 
1593 void
1594 handle_connection_error(connection_t *conn, uint32_t status, int dologout)
1595 {
1596 	DEBC(conn, 0, ("*** Connection Error, status=%d, logout=%d, state=%d\n",
1597 				   status, dologout, conn->c_state));
1598 
1599 	if (!conn->c_terminating && conn->c_state <= ST_LOGOUT_SENT) {
1600 		/* if we get an error while winding down, escalate it */
1601 		if (dologout >= 0 && conn->c_state >= ST_WINDING_DOWN) {
1602 			dologout = NO_LOGOUT;
1603 		}
1604 		kill_connection(conn, status, dologout, TRUE);
1605 	}
1606 }
1607 
1608 /*
1609  * remove a connection from session and add to the cleanup list
1610  */
1611 void
1612 add_connection_cleanup(connection_t *conn)
1613 {
1614 	session_t *sess = NULL;
1615 
1616 	mutex_enter(&iscsi_cleanup_mtx);
1617 	if (conn->c_in_session) {
1618 		sess = conn->c_session;
1619 		conn->c_in_session = FALSE;
1620 		conn->c_session = NULL;
1621 		TAILQ_REMOVE(&sess->s_conn_list, conn, c_connections);
1622 		sess->s_mru_connection = TAILQ_FIRST(&sess->s_conn_list);
1623 	}
1624 	TAILQ_INSERT_TAIL(&iscsi_cleanupc_list, conn, c_connections);
1625 	iscsi_notify_cleanup();
1626 	mutex_exit(&iscsi_cleanup_mtx);
1627 }
1628 
1629 /*
1630  * callout wrappers for timeouts, the work is done by the cleanup thread
1631  */
1632 void
1633 connection_timeout_co(void *par)
1634 {
1635 	connection_t *conn = par;
1636 
1637 	mutex_enter(&iscsi_cleanup_mtx);
1638 	conn->c_timedout = TOUT_QUEUED;
1639 	TAILQ_INSERT_TAIL(&iscsi_timeout_conn_list, conn, c_tchain);
1640 	iscsi_notify_cleanup();
1641 	mutex_exit(&iscsi_cleanup_mtx);
1642 }
1643 
1644 void
1645 connection_timeout_start(connection_t *conn, int ticks)
1646 {
1647 	mutex_enter(&iscsi_cleanup_mtx);
1648 	if (conn->c_timedout != TOUT_QUEUED) {
1649 		conn->c_timedout = TOUT_ARMED;
1650 		callout_schedule(&conn->c_timeout, ticks);
1651 	}
1652 	mutex_exit(&iscsi_cleanup_mtx);
1653 }
1654 
1655 void
1656 connection_timeout_stop(connection_t *conn)
1657 {
1658 	callout_stop(&conn->c_timeout);
1659 	mutex_enter(&iscsi_cleanup_mtx);
1660 	if (conn->c_timedout == TOUT_QUEUED) {
1661 		TAILQ_REMOVE(&iscsi_timeout_conn_list, conn, c_tchain);
1662 		conn->c_timedout = TOUT_NONE;
1663 	}
1664 	if (curlwp != iscsi_cleanproc) {
1665 		while (conn->c_timedout == TOUT_BUSY)
1666 			kpause("connbusy", false, 1, &iscsi_cleanup_mtx);
1667 	}
1668 	mutex_exit(&iscsi_cleanup_mtx);
1669 }
1670 
1671 void
1672 ccb_timeout_co(void *par)
1673 {
1674 	ccb_t *ccb = par;
1675 
1676 	mutex_enter(&iscsi_cleanup_mtx);
1677 	ccb->ccb_timedout = TOUT_QUEUED;
1678 	TAILQ_INSERT_TAIL(&iscsi_timeout_ccb_list, ccb, ccb_tchain);
1679 	iscsi_notify_cleanup();
1680 	mutex_exit(&iscsi_cleanup_mtx);
1681 }
1682 
1683 void
1684 ccb_timeout_start(ccb_t *ccb, int ticks)
1685 {
1686 	mutex_enter(&iscsi_cleanup_mtx);
1687 	if (ccb->ccb_timedout != TOUT_QUEUED) {
1688 		ccb->ccb_timedout = TOUT_ARMED;
1689 		callout_schedule(&ccb->ccb_timeout, ticks);
1690 	}
1691 	mutex_exit(&iscsi_cleanup_mtx);
1692 }
1693 
1694 void
1695 ccb_timeout_stop(ccb_t *ccb)
1696 {
1697 	callout_stop(&ccb->ccb_timeout);
1698 	mutex_enter(&iscsi_cleanup_mtx);
1699 	if (ccb->ccb_timedout == TOUT_QUEUED) {
1700 		TAILQ_REMOVE(&iscsi_timeout_ccb_list, ccb, ccb_tchain);
1701 		ccb->ccb_timedout = TOUT_NONE;
1702 	}
1703 	if (curlwp != iscsi_cleanproc) {
1704 		while (ccb->ccb_timedout == TOUT_BUSY)
1705 			kpause("ccbbusy", false, 1, &iscsi_cleanup_mtx);
1706 	}
1707 	mutex_exit(&iscsi_cleanup_mtx);
1708 }
1709 
1710 /*
1711  * iscsi_cleanup_thread
1712  *    Global thread to handle connection and session cleanup after termination.
1713  */
1714 
1715 static void
1716 iscsi_cleanup_thread(void *par)
1717 {
1718 	int s, rc;
1719 	session_t *sess, *nxts;
1720 	connection_t *conn, *nxtc;
1721 	ccb_t *ccb;
1722 
1723 	mutex_enter(&iscsi_cleanup_mtx);
1724 	while (iscsi_num_send_threads || !iscsi_detaching ||
1725 	       !TAILQ_EMPTY(&iscsi_cleanupc_list) || !TAILQ_EMPTY(&iscsi_cleanups_list)) {
1726 		TAILQ_FOREACH_SAFE(conn, &iscsi_cleanupc_list, c_connections, nxtc) {
1727 
1728 			TAILQ_REMOVE(&iscsi_cleanupc_list, conn, c_connections);
1729 			mutex_exit(&iscsi_cleanup_mtx);
1730 
1731 			sess = conn->c_session;
1732 
1733 			/*
1734 			 * This implies that connection cleanup only runs when
1735 			 * the send/recv threads have been killed
1736 			 */
1737 			DEBC(conn, 5, ("Cleanup: Waiting for threads to exit\n"));
1738 
1739 			mutex_enter(&conn->c_lock);
1740 			while (conn->c_sendproc || conn->c_rcvproc)
1741 				kpause("threads", false, hz, &conn->c_lock);
1742 
1743 			for (s=1; conn->c_usecount > 0 && s < 3; ++s)
1744 				kpause("usecount", false, hz, &conn->c_lock);
1745 
1746 			if (conn->c_usecount > 0) {
1747 				DEBC(conn, 5, ("Cleanup: %d CCBs busy\n", conn->c_usecount));
1748 				mutex_exit(&conn->c_lock);
1749 				/* retry later */
1750 				mutex_enter(&iscsi_cleanup_mtx);
1751 				TAILQ_INSERT_HEAD(&iscsi_cleanupc_list, conn, c_connections);
1752 				continue;
1753 			}
1754 			mutex_exit(&conn->c_lock);
1755 
1756 			KASSERT(!conn->c_in_session);
1757 
1758 			callout_halt(&conn->c_timeout, NULL);
1759 			closef(conn->c_sock);
1760 			callout_destroy(&conn->c_timeout);
1761 			rw_destroy(&conn->c_sock_rw);
1762 			cv_destroy(&conn->c_idle_cv);
1763 			cv_destroy(&conn->c_ccb_cv);
1764 			cv_destroy(&conn->c_pdu_cv);
1765 			cv_destroy(&conn->c_conn_cv);
1766 			mutex_destroy(&conn->c_lock);
1767 			free(conn, M_DEVBUF);
1768 
1769 			mutex_enter(&iscsi_cleanup_mtx);
1770 
1771 			if (--sess->s_total_connections == 0) {
1772 				DEB(1, ("Cleanup: session %d\n", sess->s_id));
1773 				if (!sess->s_terminating) {
1774 					sess->s_terminating = ISCSI_CONNECTION_TERMINATED;
1775 					KASSERT(sess->s_sessions.tqe_prev != NULL);
1776 					TAILQ_REMOVE(&iscsi_sessions, sess, s_sessions);
1777 					sess->s_sessions.tqe_next = NULL;
1778 					sess->s_sessions.tqe_prev = NULL;
1779 				}
1780 				KASSERT(sess->s_sessions.tqe_prev == NULL);
1781 				TAILQ_INSERT_HEAD(&iscsi_cleanups_list, sess, s_sessions);
1782 			}
1783 		}
1784 
1785 		TAILQ_FOREACH_SAFE(sess, &iscsi_cleanups_list, s_sessions, nxts) {
1786 			if (sess->s_refcount > 0)
1787 				continue;
1788 			TAILQ_REMOVE(&iscsi_cleanups_list, sess, s_sessions);
1789 			sess->s_sessions.tqe_next = NULL;
1790 			sess->s_sessions.tqe_prev = NULL;
1791 			mutex_exit(&iscsi_cleanup_mtx);
1792 
1793 			DEB(1, ("Cleanup: Unmap session %d\n", sess->s_id));
1794 			if (unmap_session(sess) == 0) {
1795 				DEB(1, ("Cleanup: Unmap session %d failed\n", sess->s_id));
1796 				mutex_enter(&iscsi_cleanup_mtx);
1797 				TAILQ_INSERT_HEAD(&iscsi_cleanups_list, sess, s_sessions);
1798 				continue;
1799 			}
1800 
1801 			if (sess->s_target_list != NULL)
1802 				free(sess->s_target_list, M_TEMP);
1803 
1804 			/* notify event handlers of session shutdown */
1805 			add_event(ISCSI_SESSION_TERMINATED, sess->s_id, 0, sess->s_terminating);
1806 			DEB(1, ("Cleanup: session ended %d\n", sess->s_id));
1807 
1808 			destroy_ccbs(sess);
1809 			cv_destroy(&sess->s_ccb_cv);
1810 			cv_destroy(&sess->s_sess_cv);
1811 			mutex_destroy(&sess->s_lock);
1812 			free(sess, M_DEVBUF);
1813 
1814 			mutex_enter(&iscsi_cleanup_mtx);
1815 		}
1816 
1817 		/* handle ccb timeouts */
1818 		while ((ccb = TAILQ_FIRST(&iscsi_timeout_ccb_list)) != NULL) {
1819 			TAILQ_REMOVE(&iscsi_timeout_ccb_list, ccb, ccb_tchain);
1820 			KASSERT(ccb->ccb_timedout == TOUT_QUEUED);
1821 			ccb->ccb_timedout = TOUT_BUSY;
1822 			mutex_exit(&iscsi_cleanup_mtx);
1823 			ccb_timeout(ccb);
1824 			mutex_enter(&iscsi_cleanup_mtx);
1825 			if (ccb->ccb_timedout == TOUT_BUSY)
1826 				ccb->ccb_timedout = TOUT_NONE;
1827 		}
1828 
1829 		/* handle connection timeouts */
1830 		while ((conn = TAILQ_FIRST(&iscsi_timeout_conn_list)) != NULL) {
1831 			TAILQ_REMOVE(&iscsi_timeout_conn_list, conn, c_tchain);
1832 			KASSERT(conn->c_timedout == TOUT_QUEUED);
1833 			conn->c_timedout = TOUT_BUSY;
1834 			mutex_exit(&iscsi_cleanup_mtx);
1835 			connection_timeout(conn);
1836 			mutex_enter(&iscsi_cleanup_mtx);
1837 			if (conn->c_timedout == TOUT_BUSY)
1838 				conn->c_timedout = TOUT_NONE;
1839 		}
1840 
1841 		/* Go to sleep, but wake up every 120 seconds to
1842 		 * check for dead event handlers */
1843 		rc = cv_timedwait(&iscsi_cleanup_cv, &iscsi_cleanup_mtx,
1844 			(TAILQ_FIRST(&event_handlers)) ? 120 * hz : 0);
1845 
1846 		/* if timed out, not woken up */
1847 		if (rc == EWOULDBLOCK)
1848 			check_event_handlers();
1849 	}
1850 	mutex_exit(&iscsi_cleanup_mtx);
1851 
1852 	add_event(ISCSI_DRIVER_TERMINATING, 0, 0, ISCSI_STATUS_DRIVER_UNLOAD);
1853 
1854 	/*
1855 	 * Wait for all event handlers to deregister, but don't wait more
1856 	 * than 1 minute (assume registering app has died if it takes longer).
1857 	 */
1858 	mutex_enter(&iscsi_cleanup_mtx);
1859 	for (s = 0; TAILQ_FIRST(&event_handlers) != NULL && s < 60; s++)
1860 		kpause("waiteventclr", true, hz, &iscsi_cleanup_mtx);
1861 	mutex_exit(&iscsi_cleanup_mtx);
1862 
1863 	iscsi_cleanproc = NULL;
1864 	DEB(5, ("Cleanup thread exits\n"));
1865 	kthread_exit(0);
1866 }
1867 
1868 void
1869 iscsi_init_cleanup(void)
1870 {
1871 
1872 	mutex_init(&iscsi_cleanup_mtx, MUTEX_DEFAULT, IPL_BIO);
1873 	cv_init(&iscsi_cleanup_cv, "cleanup");
1874 	cv_init(&iscsi_event_cv, "iscsievtwait");
1875 
1876 	if (kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, iscsi_cleanup_thread,
1877 	    NULL, &iscsi_cleanproc, "iscsi_cleanup") != 0) {
1878 		panic("Can't create cleanup thread!");
1879 	}
1880 }
1881 
1882 int
1883 iscsi_destroy_cleanup(void)
1884 {
1885 
1886 	iscsi_detaching = true;
1887 	mutex_enter(&iscsi_cleanup_mtx);
1888 	while (iscsi_cleanproc != NULL) {
1889 		iscsi_notify_cleanup();
1890 		kpause("detach_wait", false, hz, &iscsi_cleanup_mtx);
1891 	}
1892 	mutex_exit(&iscsi_cleanup_mtx);
1893 
1894 	cv_destroy(&iscsi_event_cv);
1895 	cv_destroy(&iscsi_cleanup_cv);
1896 	mutex_destroy(&iscsi_cleanup_mtx);
1897 
1898 	return 0;
1899 }
1900 
1901 void
1902 iscsi_notify_cleanup(void)
1903 {
1904 	KASSERT(mutex_owned(&iscsi_cleanup_mtx));
1905 
1906 	cv_signal(&iscsi_cleanup_cv);
1907 }
1908 
1909 
1910 /* -------------------------------------------------------------------- */
1911 
1912 /*
1913  * iscsi_ioctl:
1914  *    Driver ioctl entry.
1915  *
1916  *    Parameter:
1917  *       file     File structure
1918  *       cmd      The ioctl Command
1919  *       addr     IN/OUT: The command parameter
1920  *       flag     Flags (ignored)
1921  *       l        IN: The lwp object of the caller
1922  */
1923 
1924 int
1925 iscsiioctl(struct file *fp, u_long cmd, void *addr)
1926 {
1927 	struct lwp *l = curlwp;
1928 	struct iscsifd *d = fp->f_iscsi;
1929 
1930 	DEB(1, ("ISCSI Ioctl cmd = %x\n", (int) cmd));
1931 
1932 	switch (cmd) {
1933 	case ISCSI_GET_VERSION:
1934 		get_version((iscsi_get_version_parameters_t *) addr);
1935 		break;
1936 
1937 	case ISCSI_LOGIN:
1938 		login((iscsi_login_parameters_t *) addr, l, d->fd_dev);
1939 		break;
1940 
1941 	case ISCSI_ADD_CONNECTION:
1942 		add_connection((iscsi_login_parameters_t *) addr, l);
1943 		break;
1944 
1945 	case ISCSI_RESTORE_CONNECTION:
1946 		restore_connection((iscsi_login_parameters_t *) addr, l);
1947 		break;
1948 
1949 	case ISCSI_LOGOUT:
1950 		logout((iscsi_logout_parameters_t *) addr);
1951 		break;
1952 
1953 	case ISCSI_REMOVE_CONNECTION:
1954 		remove_connection((iscsi_remove_parameters_t *) addr);
1955 		break;
1956 
1957 #ifndef ISCSI_MINIMAL
1958 	case ISCSI_IO_COMMAND:
1959 		io_command((iscsi_iocommand_parameters_t *) addr, l);
1960 		break;
1961 #endif
1962 
1963 	case ISCSI_SEND_TARGETS:
1964 		send_targets((iscsi_send_targets_parameters_t *) addr);
1965 		break;
1966 
1967 	case ISCSI_SET_NODE_NAME:
1968 		set_node_name((iscsi_set_node_name_parameters_t *) addr);
1969 		break;
1970 
1971 	case ISCSI_CONNECTION_STATUS:
1972 		connection_status((iscsi_conn_status_parameters_t *) addr);
1973 		break;
1974 
1975 	case ISCSI_REGISTER_EVENT:
1976 		register_event((iscsi_register_event_parameters_t *) addr);
1977 		break;
1978 
1979 	case ISCSI_DEREGISTER_EVENT:
1980 		deregister_event((iscsi_register_event_parameters_t *) addr);
1981 		break;
1982 
1983 	case ISCSI_WAIT_EVENT:
1984 		check_event((iscsi_wait_event_parameters_t *) addr, TRUE);
1985 		break;
1986 
1987 	case ISCSI_POLL_EVENT:
1988 		check_event((iscsi_wait_event_parameters_t *) addr, FALSE);
1989 		break;
1990 
1991 	default:
1992 		DEBOUT(("Invalid IO-Control Code\n"));
1993 		return ENOTTY;
1994 	}
1995 
1996     /*
1997      * NOTE: We return 0 even if the function fails as long as the ioctl code
1998      * is good, so the status code is copied back to the caller.
1999 	 */
2000 	return 0;
2001 }
2002