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