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