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