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