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