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