iscsi_ioctl.c revision 1.32 1 /* $NetBSD: iscsi_ioctl.c,v 1.32 2020/06/21 23:08:16 chs 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 #include <sys/kmem.h>
38
39 static kmutex_t iscsi_cleanup_mtx;
40 static kcondvar_t iscsi_cleanup_cv;
41 static kcondvar_t iscsi_event_cv;
42 static struct lwp *iscsi_cleanproc = NULL;
43
44 static uint16_t current_id = 0; /* Global session ID counter */
45
46 /* list of event handlers */
47 static event_handler_list_t event_handlers =
48 TAILQ_HEAD_INITIALIZER(event_handlers);
49
50 static connection_list_t iscsi_timeout_conn_list =
51 TAILQ_HEAD_INITIALIZER(iscsi_timeout_conn_list);
52
53 static ccb_list_t iscsi_timeout_ccb_list =
54 TAILQ_HEAD_INITIALIZER(iscsi_timeout_ccb_list);
55
56 static session_list_t iscsi_cleanups_list =
57 TAILQ_HEAD_INITIALIZER(iscsi_cleanups_list);
58
59 static connection_list_t iscsi_cleanupc_list =
60 TAILQ_HEAD_INITIALIZER(iscsi_cleanupc_list);
61
62 static uint32_t handler_id = 0; /* Handler ID counter */
63
64 /* -------------------------------------------------------------------------- */
65
66 /* Event management functions */
67
68 /*
69 * find_handler:
70 * Search the event handler list for the given ID.
71 *
72 * Parameter:
73 * id The handler ID.
74 *
75 * Returns:
76 * Pointer to handler if found, else NULL.
77 */
78
79
80 static event_handler_t *
81 find_handler(uint32_t id)
82 {
83 event_handler_t *curr;
84
85 KASSERT(mutex_owned(&iscsi_cleanup_mtx));
86
87 TAILQ_FOREACH(curr, &event_handlers, evh_link)
88 if (curr->evh_id == id)
89 break;
90
91 return curr;
92 }
93
94
95 /*
96 * register_event:
97 * Create event handler entry, return ID.
98 *
99 * Parameter:
100 * par The parameter.
101 */
102
103 static void
104 register_event(iscsi_register_event_parameters_t *par)
105 {
106 event_handler_t *handler;
107 int was_empty;
108
109 handler = malloc(sizeof(event_handler_t), M_DEVBUF, M_WAITOK | M_ZERO);
110 if (handler == NULL) {
111 DEBOUT(("No mem for event handler\n"));
112 par->status = ISCSI_STATUS_NO_RESOURCES;
113 return;
114 }
115
116 TAILQ_INIT(&handler->evh_events);
117
118 mutex_enter(&iscsi_cleanup_mtx);
119 /* create a unique ID */
120 do {
121 ++handler_id;
122 } while (!handler_id || find_handler(handler_id) != NULL);
123 par->event_id = handler->evh_id = handler_id;
124
125 was_empty = TAILQ_FIRST(&event_handlers) == NULL;
126 TAILQ_INSERT_TAIL(&event_handlers, handler, evh_link);
127 if (was_empty)
128 iscsi_notify_cleanup();
129 mutex_exit(&iscsi_cleanup_mtx);
130
131 par->status = ISCSI_STATUS_SUCCESS;
132 DEB(5, ("Register Event OK, ID %d\n", par->event_id));
133 }
134
135
136 /*
137 * deregister_event:
138 * Destroy handler entry and any waiting events, wake up waiter.
139 *
140 * Parameter:
141 * par The parameter.
142 */
143
144 static void
145 deregister_event(iscsi_register_event_parameters_t *par)
146 {
147 event_handler_t *handler;
148 event_t *evt;
149
150 mutex_enter(&iscsi_cleanup_mtx);
151 handler = find_handler(par->event_id);
152 if (handler == NULL) {
153 mutex_exit(&iscsi_cleanup_mtx);
154 DEB(1, ("Deregister Event ID %d not found\n", par->event_id));
155 par->status = ISCSI_STATUS_INVALID_EVENT_ID;
156 return;
157 }
158
159 TAILQ_REMOVE(&event_handlers, handler, evh_link);
160 if (handler->evh_waiter != NULL) {
161 handler->evh_waiter->status = ISCSI_STATUS_EVENT_DEREGISTERED;
162 cv_broadcast(&iscsi_event_cv);
163 }
164
165 while ((evt = TAILQ_FIRST(&handler->evh_events)) != NULL) {
166 TAILQ_REMOVE(&handler->evh_events, evt, ev_link);
167 free(evt, M_TEMP);
168 }
169 mutex_exit(&iscsi_cleanup_mtx);
170
171 free(handler, M_DEVBUF);
172 par->status = ISCSI_STATUS_SUCCESS;
173 DEB(5, ("Deregister Event ID %d complete\n", par->event_id));
174 }
175
176
177 /*
178 * check_event:
179 * Return first queued event. Optionally wait for arrival of event.
180 *
181 * Parameter:
182 * par The parameter.
183 * wait Wait for event if true
184 */
185
186 static void
187 check_event(iscsi_wait_event_parameters_t *par, bool wait)
188 {
189 event_handler_t *handler;
190 event_t *evt;
191 int rc;
192
193 mutex_enter(&iscsi_cleanup_mtx);
194 handler = find_handler(par->event_id);
195 if (handler == NULL) {
196 mutex_exit(&iscsi_cleanup_mtx);
197 DEBOUT(("Wait Event ID %d not found\n", par->event_id));
198 par->status = ISCSI_STATUS_INVALID_EVENT_ID;
199 return;
200 }
201 if (handler->evh_waiter != NULL) {
202 mutex_exit(&iscsi_cleanup_mtx);
203 DEBOUT(("Wait Event ID %d already waiting\n", par->event_id));
204 par->status = ISCSI_STATUS_EVENT_WAITING;
205 return;
206 }
207 par->status = ISCSI_STATUS_SUCCESS;
208 DEB(99, ("Wait Event ID %d\n", par->event_id));
209
210 do {
211 evt = TAILQ_FIRST(&handler->evh_events);
212 if (evt != NULL) {
213 TAILQ_REMOVE(&handler->evh_events, evt, ev_link);
214 } else {
215 if (!wait) {
216 par->status = ISCSI_STATUS_LIST_EMPTY;
217 return;
218 }
219 if (par->status != ISCSI_STATUS_SUCCESS) {
220 return;
221 }
222 handler->evh_waiter = par;
223 rc = cv_wait_sig(&iscsi_event_cv, &iscsi_cleanup_mtx);
224 if (rc) {
225 mutex_exit(&iscsi_cleanup_mtx);
226 par->status = ISCSI_STATUS_LIST_EMPTY;
227 return;
228 }
229 }
230 } while (evt == NULL);
231 mutex_exit(&iscsi_cleanup_mtx);
232
233 par->connection_id = evt->ev_connection_id;
234 par->session_id = evt->ev_session_id;
235 par->event_kind = evt->ev_event_kind;
236 par->reason = evt->ev_reason;
237
238 free(evt, M_TEMP);
239 }
240
241 /*
242 * add_event
243 * Adds an event entry to each registered handler queue.
244 * Note that events are simply duplicated because we expect the number of
245 * handlers to be very small, usually 1 (the daemon).
246 *
247 * Parameters:
248 * kind The event kind
249 * sid The ID of the affected session
250 * cid The ID of the affected connection
251 * reason The reason code
252 */
253
254 void
255 add_event(iscsi_event_t kind, uint32_t sid, uint32_t cid, uint32_t reason)
256 {
257 event_handler_t *curr;
258 event_t *evt;
259
260 DEB(9, ("Add_event kind %d, sid %d, cid %d, reason %d\n",
261 kind, sid, cid, reason));
262
263 mutex_enter(&iscsi_cleanup_mtx);
264 TAILQ_FOREACH(curr, &event_handlers, evh_link) {
265 evt = malloc(sizeof(*evt), M_TEMP, M_NOWAIT);
266 if (evt == NULL) {
267 DEBOUT(("Cannot allocate event\n"));
268 break;
269 }
270 evt->ev_event_kind = kind;
271 evt->ev_session_id = sid;
272 evt->ev_connection_id = cid;
273 evt->ev_reason = reason;
274
275 TAILQ_INSERT_TAIL(&curr->evh_events, evt, ev_link);
276 if (curr->evh_waiter != NULL) {
277 curr->evh_waiter = NULL;
278 cv_broadcast(&iscsi_event_cv);
279 }
280 }
281 mutex_exit(&iscsi_cleanup_mtx);
282 }
283
284
285 /*
286 * check_event_handlers
287 * Checks for dead event handlers. A dead event handler would deplete
288 * memory over time, so we have to make sure someone at the other
289 * end is actively monitoring events.
290 * This function is called every 30 seconds or so (less frequent if there
291 * is other activity for the cleanup thread to deal with) to go through
292 * the list of handlers and check whether the first element in the event
293 * list has changed at all. If not, the event is deregistered.
294 * Note that this will not detect dead handlers if no events are pending,
295 * but we don't care as long as events don't accumulate in the list.
296 *
297 */
298
299 static void
300 check_event_handlers(void)
301 {
302 event_handler_t *curr, *next;
303 event_t *evt;
304
305 KASSERT(mutex_owned(&iscsi_cleanup_mtx));
306
307 for (curr = TAILQ_FIRST(&event_handlers); curr != NULL; curr = next) {
308 next = TAILQ_NEXT(curr, evh_link);
309 evt = TAILQ_FIRST(&curr->evh_events);
310
311 if (evt != NULL && evt == curr->evh_first_in_list) {
312 DEBOUT(("Found Dead Event Handler %d, removing\n", curr->evh_id));
313
314 TAILQ_REMOVE(&event_handlers, curr, evh_link);
315 while ((evt = TAILQ_FIRST(&curr->evh_events)) != NULL) {
316 TAILQ_REMOVE(&curr->evh_events, evt, ev_link);
317 free(evt, M_TEMP);
318 }
319 free(curr, M_DEVBUF);
320 } else
321 curr->evh_first_in_list = evt;
322 }
323 }
324
325
326 /* -------------------------------------------------------------------------- */
327
328 /*
329 * get_socket:
330 * Get the file pointer from the socket handle passed into login.
331 *
332 * Parameter:
333 * fdes IN: The socket handle
334 * fpp OUT: The pointer to the resulting file pointer
335 *
336 * Returns: 0 on success, else an error code.
337 *
338 */
339
340 static int
341 get_socket(int fdes, struct file **fpp)
342 {
343 struct file *fp;
344
345 if ((fp = fd_getfile(fdes)) == NULL) {
346 return EBADF;
347 }
348 if (fp->f_type != DTYPE_SOCKET) {
349 return ENOTSOCK;
350 }
351
352 /* Add the reference */
353 mutex_enter(&fp->f_lock);
354 fp->f_count++;
355 mutex_exit(&fp->f_lock);
356
357 *fpp = fp;
358 return 0;
359 }
360
361 /*
362 * release_socket:
363 * Release the file pointer from the socket handle passed into login.
364 *
365 * Parameter:
366 * fp IN: The pointer to the resulting file pointer
367 *
368 */
369
370 static void
371 release_socket(struct file *fp)
372 {
373 /* Add the reference */
374 mutex_enter(&fp->f_lock);
375 fp->f_count--;
376 mutex_exit(&fp->f_lock);
377 }
378
379
380 /*
381 * find_session:
382 * Find a session by ID.
383 *
384 * Parameter: the session ID
385 *
386 * Returns: The pointer to the session (or NULL if not found)
387 */
388
389 session_t *
390 find_session(uint32_t id)
391 {
392 session_t *sess;
393
394 KASSERT(mutex_owned(&iscsi_cleanup_mtx));
395
396 TAILQ_FOREACH(sess, &iscsi_sessions, s_sessions)
397 if (sess->s_id == id) {
398 break;
399 }
400 return sess;
401 }
402
403
404 /*
405 * find_connection:
406 * Find a connection by ID.
407 *
408 * Parameter: the session pointer and the connection ID
409 *
410 * Returns: The pointer to the connection (or NULL if not found)
411 */
412
413 connection_t *
414 find_connection(session_t *sess, uint32_t id)
415 {
416 connection_t *conn;
417
418 KASSERT(mutex_owned(&iscsi_cleanup_mtx));
419
420 TAILQ_FOREACH(conn, &sess->s_conn_list, c_connections)
421 if (conn->c_id == id) {
422 break;
423 }
424 return conn;
425 }
426
427 /*
428 * ref_session:
429 * Reference a session
430 *
431 * Session cannot be release until reference count reaches zero
432 *
433 * Returns: 1 if reference counter would overflow
434 */
435
436 int
437 ref_session(session_t *sess)
438 {
439 int rc = 1;
440
441 mutex_enter(&iscsi_cleanup_mtx);
442 KASSERT(sess != NULL);
443 if (sess->s_refcount <= CCBS_PER_SESSION) {
444 sess->s_refcount++;
445 rc = 0;
446 }
447 mutex_exit(&iscsi_cleanup_mtx);
448
449 return rc;
450 }
451
452 /*
453 * unref_session:
454 * Unreference a session
455 *
456 * Release session reference, trigger cleanup
457 */
458
459 void
460 unref_session(session_t *session)
461 {
462
463 mutex_enter(&iscsi_cleanup_mtx);
464 KASSERT(session != NULL);
465 KASSERT(session->s_refcount > 0);
466 if (--session->s_refcount == 0)
467 cv_broadcast(&session->s_sess_cv);
468 mutex_exit(&iscsi_cleanup_mtx);
469 }
470
471
472 /*
473 * kill_connection:
474 * Terminate the connection as gracefully as possible.
475 *
476 * Parameter:
477 * conn The connection to terminate
478 * status The status code for the connection's "terminating" field
479 * logout The logout reason code
480 * recover Attempt to recover connection
481 */
482
483 void
484 kill_connection(connection_t *conn, uint32_t status, int logout, bool recover)
485 {
486 session_t *sess = conn->c_session;
487 int terminating;
488
489 DEBC(conn, 1, ("Kill_connection: terminating=%d, status=%d, logout=%d, "
490 "state=%d\n",
491 conn->c_terminating, status, logout, conn->c_state));
492
493 mutex_enter(&iscsi_cleanup_mtx);
494 if (recover &&
495 !conn->c_destroy &&
496 conn->c_recover > MAX_RECOVERY_ATTEMPTS) {
497 DEBC(conn, 1,
498 ("Kill_connection: Too many recovery attempts, destroying\n"));
499 conn->c_destroy = TRUE;
500 }
501
502 if (!recover || conn->c_destroy) {
503
504 if (conn->c_in_session) {
505 conn->c_in_session = FALSE;
506 TAILQ_REMOVE(&sess->s_conn_list, conn, c_connections);
507 sess->s_mru_connection = TAILQ_FIRST(&sess->s_conn_list);
508 }
509
510 if (!conn->c_destroy) {
511 DEBC(conn, 1, ("Kill_connection setting destroy flag\n"));
512 conn->c_destroy = TRUE;
513 }
514 }
515
516 terminating = conn->c_terminating;
517 if (!terminating)
518 conn->c_terminating = status;
519
520 /* Don't recurse */
521 if (terminating) {
522 mutex_exit(&iscsi_cleanup_mtx);
523
524 KASSERT(conn->c_state != ST_FULL_FEATURE);
525 DEBC(conn, 1, ("Kill_connection exiting (already terminating)\n"));
526 goto done;
527 }
528
529 if (conn->c_state == ST_FULL_FEATURE) {
530 sess->s_active_connections--;
531 conn->c_state = ST_WINDING_DOWN;
532
533 /* If this is the last connection and ERL < 2, reset TSIH */
534 if (!sess->s_active_connections && sess->s_ErrorRecoveryLevel < 2)
535 sess->s_TSIH = 0;
536
537 /* Don't try to log out if the socket is broken or we're in the middle */
538 /* of logging in */
539 if (logout >= 0) {
540 if (sess->s_ErrorRecoveryLevel < 2 &&
541 logout == RECOVER_CONNECTION) {
542 logout = LOGOUT_CONNECTION;
543 }
544 if (!sess->s_active_connections &&
545 logout == LOGOUT_CONNECTION) {
546 logout = LOGOUT_SESSION;
547 }
548 mutex_exit(&iscsi_cleanup_mtx);
549
550 connection_timeout_start(conn, CONNECTION_TIMEOUT);
551
552 if (!send_logout(conn, conn, logout, FALSE)) {
553 conn->c_terminating = ISCSI_STATUS_SUCCESS;
554 return;
555 }
556 /*
557 * if the logout request was successfully sent,
558 * the logout response handler will do the rest
559 * of the termination processing. If the logout
560 * doesn't get a response, we'll get back in here
561 * once the timeout hits.
562 */
563
564 mutex_enter(&iscsi_cleanup_mtx);
565 }
566
567 }
568
569 conn->c_state = ST_SETTLING;
570 mutex_exit(&iscsi_cleanup_mtx);
571
572 done:
573 /* let send thread take over next step of cleanup */
574 mutex_enter(&conn->c_lock);
575 cv_broadcast(&conn->c_conn_cv);
576 mutex_exit(&conn->c_lock);
577
578 DEBC(conn, 5, ("kill_connection returns\n"));
579 }
580
581
582 /*
583 * kill_session:
584 * Terminate the session as gracefully as possible.
585 *
586 * Parameter:
587 * session Session to terminate
588 * status The status code for the termination
589 * logout The logout reason code
590
591 */
592
593 void
594 kill_session(session_t *sess, uint32_t status, int logout, bool recover)
595 {
596 connection_t *conn;
597
598 DEB(1, ("ISCSI: kill_session %d, status %d, logout %d, recover %d\n",
599 sess->s_id, status, logout, recover));
600
601 mutex_enter(&iscsi_cleanup_mtx);
602 if (sess->s_terminating) {
603 mutex_exit(&iscsi_cleanup_mtx);
604
605 DEB(5, ("Session is being killed with status %d\n",sess->s_terminating));
606 return;
607 }
608
609 /*
610 * don't do anything if session isn't established yet, termination will be
611 * handled elsewhere
612 */
613 if (sess->s_sessions.tqe_next == NULL && sess->s_sessions.tqe_prev == NULL) {
614 mutex_exit(&iscsi_cleanup_mtx);
615
616 DEB(5, ("Session is being killed which is not yet established\n"));
617 return;
618 }
619
620 if (recover) {
621 mutex_exit(&iscsi_cleanup_mtx);
622
623 /*
624 * Only recover when there's just one active connection left.
625 * Otherwise we get in all sorts of timing problems, and it doesn't
626 * make much sense anyway to recover when the other side has
627 * requested that we kill a multipathed session.
628 */
629 if (sess->s_active_connections == 1) {
630 conn = assign_connection(sess, FALSE);
631 if (conn != NULL)
632 kill_connection(conn, status, logout, TRUE);
633 }
634 return;
635 }
636
637 if (sess->s_refcount > 0) {
638 mutex_exit(&iscsi_cleanup_mtx);
639
640 DEB(5, ("Session is being killed while in use (refcnt = %d)\n",
641 sess->s_refcount));
642 return;
643 }
644
645 /* Remove session from global list */
646 sess->s_terminating = status;
647 TAILQ_REMOVE(&iscsi_sessions, sess, s_sessions);
648 sess->s_sessions.tqe_next = NULL;
649 sess->s_sessions.tqe_prev = NULL;
650
651 mutex_exit(&iscsi_cleanup_mtx);
652
653 /* kill all connections */
654 while ((conn = TAILQ_FIRST(&sess->s_conn_list)) != NULL) {
655 kill_connection(conn, status, logout, FALSE);
656 logout = NO_LOGOUT;
657 }
658 }
659
660
661 /*
662 * create_connection:
663 * Create and init the necessary framework for a connection:
664 * Alloc the connection structure itself
665 * Copy connection parameters
666 * Create the send and receive threads
667 * And finally, log in.
668 *
669 * Parameter:
670 * par IN/OUT: The login parameters
671 * session IN: The owning session
672 * l IN: The lwp pointer of the caller
673 *
674 * Returns: 0 on success
675 * >0 on failure, connection structure deleted
676 * <0 on failure, connection is still terminating
677 */
678
679 static int
680 create_connection(iscsi_login_parameters_t *par, session_t *sess,
681 struct lwp *l)
682 {
683 connection_t *conn;
684 int rc;
685
686 DEB(1, ("Create Connection for Session %d\n", sess->s_id));
687
688 if (sess->s_MaxConnections &&
689 sess->s_active_connections >= sess->s_MaxConnections) {
690 DEBOUT(("Too many connections (max = %d, curr = %d)\n",
691 sess->s_MaxConnections, sess->s_active_connections));
692 par->status = ISCSI_STATUS_MAXED_CONNECTIONS;
693 return EIO;
694 }
695
696 conn = malloc(sizeof(*conn), M_DEVBUF, M_WAITOK | M_ZERO);
697 if (conn == NULL) {
698 DEBOUT(("No mem for connection\n"));
699 par->status = ISCSI_STATUS_NO_RESOURCES;
700 return EIO;
701 }
702
703 mutex_enter(&iscsi_cleanup_mtx);
704 /* create a unique ID */
705 do {
706 ++sess->s_conn_id;
707 } while (!sess->s_conn_id ||
708 find_connection(sess, sess->s_conn_id) != NULL);
709 par->connection_id = conn->c_id = sess->s_conn_id;
710 mutex_exit(&iscsi_cleanup_mtx);
711 DEB(99, ("Connection ID = %d\n", conn->c_id));
712
713 conn->c_session = sess;
714
715 TAILQ_INIT(&conn->c_ccbs_waiting);
716 TAILQ_INIT(&conn->c_pdus_to_send);
717 TAILQ_INIT(&conn->c_pdu_pool);
718
719 mutex_init(&conn->c_lock, MUTEX_DEFAULT, IPL_BIO);
720 cv_init(&conn->c_conn_cv, "conn");
721 cv_init(&conn->c_pdu_cv, "pdupool");
722 cv_init(&conn->c_ccb_cv, "ccbwait");
723 cv_init(&conn->c_idle_cv, "idle");
724
725 callout_init(&conn->c_timeout, CALLOUT_MPSAFE);
726 callout_setfunc(&conn->c_timeout, connection_timeout_co, conn);
727 conn->c_idle_timeout_val = CONNECTION_IDLE_TIMEOUT;
728
729 init_sernum(&conn->c_StatSN_buf);
730 create_pdus(conn);
731
732 if ((rc = get_socket(par->socket, &conn->c_sock)) != 0) {
733 DEBOUT(("Invalid socket %d\n", par->socket));
734
735 callout_destroy(&conn->c_timeout);
736 cv_destroy(&conn->c_idle_cv);
737 cv_destroy(&conn->c_ccb_cv);
738 cv_destroy(&conn->c_pdu_cv);
739 cv_destroy(&conn->c_conn_cv);
740 mutex_destroy(&conn->c_lock);
741 free(conn, M_DEVBUF);
742 par->status = ISCSI_STATUS_INVALID_SOCKET;
743 return rc;
744 }
745 DEBC(conn, 1, ("get_socket: par_sock=%d, fdesc=%p\n",
746 par->socket, conn->c_sock));
747
748 /* close the file descriptor */
749 fd_close(par->socket);
750
751 conn->c_threadobj = l;
752 conn->c_login_par = par;
753
754 DEB(5, ("Creating receive thread\n"));
755 if ((rc = kthread_create(PRI_BIO, KTHREAD_MPSAFE, NULL, iscsi_rcv_thread,
756 conn, &conn->c_rcvproc,
757 "ConnRcv")) != 0) {
758 DEBOUT(("Can't create rcv thread (rc %d)\n", rc));
759
760 release_socket(conn->c_sock);
761 callout_destroy(&conn->c_timeout);
762 cv_destroy(&conn->c_idle_cv);
763 cv_destroy(&conn->c_ccb_cv);
764 cv_destroy(&conn->c_pdu_cv);
765 cv_destroy(&conn->c_conn_cv);
766 mutex_destroy(&conn->c_lock);
767 free(conn, M_DEVBUF);
768 par->status = ISCSI_STATUS_NO_RESOURCES;
769 return rc;
770 }
771 DEB(5, ("Creating send thread\n"));
772 if ((rc = kthread_create(PRI_BIO, KTHREAD_MPSAFE, NULL, iscsi_send_thread,
773 conn, &conn->c_sendproc,
774 "ConnSend")) != 0) {
775 DEBOUT(("Can't create send thread (rc %d)\n", rc));
776
777 conn->c_terminating = ISCSI_STATUS_NO_RESOURCES;
778
779 /*
780 * We must close the socket here to force the receive
781 * thread to wake up
782 */
783 DEBC(conn, 1, ("Closing Socket %p\n", conn->c_sock));
784 mutex_enter(&conn->c_sock->f_lock);
785 conn->c_sock->f_count += 1;
786 mutex_exit(&conn->c_sock->f_lock);
787 closef(conn->c_sock);
788
789 /* give receive thread time to exit */
790 kpause("settle", false, 2 * hz, NULL);
791
792 release_socket(conn->c_sock);
793 callout_destroy(&conn->c_timeout);
794 cv_destroy(&conn->c_idle_cv);
795 cv_destroy(&conn->c_ccb_cv);
796 cv_destroy(&conn->c_pdu_cv);
797 cv_destroy(&conn->c_conn_cv);
798 mutex_destroy(&conn->c_lock);
799 free(conn, M_DEVBUF);
800 par->status = ISCSI_STATUS_NO_RESOURCES;
801 return rc;
802 }
803
804 /*
805 * At this point, each thread will tie 'sock' into its own file descriptor
806 * tables w/o increasing the use count - they will inherit the use
807 * increments performed in get_socket().
808 */
809
810 if ((rc = send_login(conn)) != 0) {
811 DEBC(conn, 0, ("Login failed (rc %d)\n", rc));
812 /* Don't attempt to recover, there seems to be something amiss */
813 kill_connection(conn, rc, NO_LOGOUT, FALSE);
814 par->status = rc;
815 return -1;
816 }
817
818 mutex_enter(&iscsi_cleanup_mtx);
819 if (sess->s_terminating) {
820 mutex_exit(&iscsi_cleanup_mtx);
821 DEBC(conn, 0, ("Session terminating\n"));
822 kill_connection(conn, rc, NO_LOGOUT, FALSE);
823 par->status = sess->s_terminating;
824 return -1;
825 }
826 conn->c_state = ST_FULL_FEATURE;
827 TAILQ_INSERT_TAIL(&sess->s_conn_list, conn, c_connections);
828 conn->c_in_session = TRUE;
829 sess->s_total_connections++;
830 sess->s_active_connections++;
831 sess->s_mru_connection = conn;
832 mutex_exit(&iscsi_cleanup_mtx);
833
834 DEBC(conn, 5, ("Connection created successfully!\n"));
835 return 0;
836 }
837
838
839 /*
840 * recreate_connection:
841 * Revive dead connection
842 *
843 * Parameter:
844 * par IN/OUT: The login parameters
845 * conn IN: The connection
846 * l IN: The lwp pointer of the caller
847 *
848 * Returns: 0 on success
849 * >0 on failure, connection structure deleted
850 * <0 on failure, connection is still terminating
851 */
852
853 static int
854 recreate_connection(iscsi_login_parameters_t *par, session_t *sess,
855 connection_t *conn, struct lwp *l)
856 {
857 int rc;
858 ccb_t *ccb;
859 ccb_list_t old_waiting;
860 pdu_t *pdu;
861 uint32_t sn;
862
863 DEB(1, ("ReCreate Connection %d for Session %d, ERL=%d\n",
864 conn->c_id, conn->c_session->s_id,
865 conn->c_session->s_ErrorRecoveryLevel));
866
867 if (sess->s_MaxConnections &&
868 sess->s_active_connections >= sess->s_MaxConnections) {
869 DEBOUT(("Too many connections (max = %d, curr = %d)\n",
870 sess->s_MaxConnections, sess->s_active_connections));
871 par->status = ISCSI_STATUS_MAXED_CONNECTIONS;
872 return EIO;
873 }
874
875 /* close old socket */
876 if (conn->c_sock != NULL) {
877 closef(conn->c_sock);
878 conn->c_sock = NULL;
879 }
880
881 if ((rc = get_socket(par->socket, &conn->c_sock)) != 0) {
882 DEBOUT(("Invalid socket %d\n", par->socket));
883 par->status = ISCSI_STATUS_INVALID_SOCKET;
884 return rc;
885 }
886 DEBC(conn, 1, ("get_socket: par_sock=%d, fdesc=%p\n",
887 par->socket, conn->c_sock));
888
889 /* close the file descriptor */
890 fd_close(par->socket);
891
892 conn->c_threadobj = l;
893 conn->c_login_par = par;
894 conn->c_terminating = ISCSI_STATUS_SUCCESS;
895 conn->c_recover++;
896 conn->c_num_timeouts = 0;
897 conn->c_state = ST_SEC_NEG;
898 conn->c_HeaderDigest = 0;
899 conn->c_DataDigest = 0;
900
901 sess->s_active_connections++;
902
903 TAILQ_INIT(&old_waiting);
904
905 mutex_enter(&conn->c_lock);
906 while ((ccb = TAILQ_FIRST(&conn->c_ccbs_waiting)) != NULL) {
907 suspend_ccb(ccb, FALSE);
908 TAILQ_INSERT_TAIL(&old_waiting, ccb, ccb_chain);
909 }
910 init_sernum(&conn->c_StatSN_buf);
911 cv_broadcast(&conn->c_idle_cv);
912 mutex_exit(&conn->c_lock);
913
914 if ((rc = send_login(conn)) != 0) {
915 DEBOUT(("Login failed (rc %d)\n", rc));
916 while ((ccb = TAILQ_FIRST(&old_waiting)) != NULL) {
917 TAILQ_REMOVE(&old_waiting, ccb, ccb_chain);
918 wake_ccb(ccb, rc);
919 }
920 /* Don't attempt to recover, there seems to be something amiss */
921 kill_connection(conn, rc, NO_LOGOUT, FALSE);
922 par->status = rc;
923 return -1;
924 }
925
926 DEBC(conn, 9, ("Re-Login successful\n"));
927 par->status = ISCSI_STATUS_SUCCESS;
928
929 conn->c_state = ST_FULL_FEATURE;
930 sess->s_mru_connection = conn;
931
932 while ((ccb = TAILQ_FIRST(&old_waiting)) != NULL) {
933 TAILQ_REMOVE(&old_waiting, ccb, ccb_chain);
934 mutex_enter(&conn->c_lock);
935 suspend_ccb(ccb, TRUE);
936 mutex_exit(&conn->c_lock);
937
938 rc = send_task_management(conn, ccb, NULL, TASK_REASSIGN);
939 /* if we get an error on reassign, restart the original request */
940 if (rc && ccb->ccb_pdu_waiting != NULL) {
941 mutex_enter(&sess->s_lock);
942 if (sn_a_lt_b(ccb->ccb_CmdSN, sess->s_ExpCmdSN)) {
943 pdu = ccb->ccb_pdu_waiting;
944 sn = get_sernum(sess, pdu);
945
946 /* update CmdSN */
947 DEBC(conn, 0, ("Resend ccb %p (%d) - updating CmdSN old %u, new %u\n",
948 ccb, rc, ccb->ccb_CmdSN, sn));
949 ccb->ccb_CmdSN = sn;
950 pdu->pdu_hdr.pduh_p.command.CmdSN = htonl(ccb->ccb_CmdSN);
951 } else {
952 DEBC(conn, 0, ("Resend ccb %p (%d) - CmdSN %u\n",
953 ccb, rc, ccb->ccb_CmdSN));
954 }
955 mutex_exit(&sess->s_lock);
956 resend_pdu(ccb);
957 } else {
958 DEBC(conn, 0, ("Resend ccb %p (%d) CmdSN %u - reassigned\n",
959 ccb, rc, ccb->ccb_CmdSN));
960 ccb_timeout_start(ccb, COMMAND_TIMEOUT);
961 }
962 }
963
964 mutex_enter(&sess->s_lock);
965 cv_broadcast(&sess->s_sess_cv);
966 mutex_exit(&sess->s_lock);
967
968 DEBC(conn, 0, ("Connection ReCreated successfully - status %d\n",
969 par->status));
970
971 return 0;
972 }
973
974 /* -------------------------------------------------------------------------- */
975
976 /*
977 * check_login_pars:
978 * Check the parameters passed into login/add_connection
979 * for validity and consistency.
980 *
981 * Parameter:
982 * par The login parameters
983 *
984 * Returns: 0 on success, else an error code.
985 */
986
987 static int
988 check_login_pars(iscsi_login_parameters_t *par)
989 {
990 int i, n;
991
992 if (par->is_present.auth_info) {
993 /* check consistency of authentication parameters */
994
995 if (par->auth_info.auth_number > ISCSI_AUTH_OPTIONS) {
996 DEBOUT(("Auth number invalid: %d\n", par->auth_info.auth_number));
997 return ISCSI_STATUS_PARAMETER_INVALID;
998 }
999
1000 if (par->auth_info.auth_number > 2) {
1001 DEBOUT(("Auth number invalid: %d\n", par->auth_info.auth_number));
1002 return ISCSI_STATUS_NOTIMPL;
1003 }
1004
1005 for (i = 0, n = 0; i < par->auth_info.auth_number; i++) {
1006 #if 0
1007 if (par->auth_info.auth_type[i] < ISCSI_AUTH_None) {
1008 DEBOUT(("Auth type invalid: %d\n",
1009 par->auth_info.auth_type[i]));
1010 return ISCSI_STATUS_PARAMETER_INVALID;
1011 }
1012 #endif
1013 if (par->auth_info.auth_type[i] > ISCSI_AUTH_CHAP) {
1014 DEBOUT(("Auth type invalid: %d\n",
1015 par->auth_info.auth_type[i]));
1016 return ISCSI_STATUS_NOTIMPL;
1017 }
1018 n = max(n, par->auth_info.auth_type[i]);
1019 }
1020 if (n) {
1021 if (!par->is_present.password ||
1022 (par->auth_info.mutual_auth &&
1023 !par->is_present.target_password)) {
1024 DEBOUT(("Password missing\n"));
1025 return ISCSI_STATUS_PARAMETER_MISSING;
1026 }
1027 /* Note: Default for user-name is initiator name */
1028 }
1029 }
1030 if (par->login_type != ISCSI_LOGINTYPE_DISCOVERY &&
1031 !par->is_present.TargetName) {
1032 DEBOUT(("Target name missing, login type %d\n", par->login_type));
1033 return ISCSI_STATUS_PARAMETER_MISSING;
1034 }
1035 if (par->is_present.MaxRecvDataSegmentLength) {
1036 if (par->MaxRecvDataSegmentLength < 512 ||
1037 par->MaxRecvDataSegmentLength > 0xffffff) {
1038 DEBOUT(("MaxRecvDataSegmentLength invalid: %d\n",
1039 par->MaxRecvDataSegmentLength));
1040 return ISCSI_STATUS_PARAMETER_INVALID;
1041 }
1042 }
1043 return 0;
1044 }
1045
1046
1047 /*
1048 * login:
1049 * Handle the login ioctl - Create a session:
1050 * Alloc the session structure
1051 * Copy session parameters
1052 * And call create_connection to establish the connection.
1053 *
1054 * Parameter:
1055 * par IN/OUT: The login parameters
1056 * l IN: The lwp pointer of the caller
1057 */
1058
1059 static void
1060 login(iscsi_login_parameters_t *par, struct lwp *l, device_t dev)
1061 {
1062 session_t *sess;
1063 int rc;
1064
1065 DEB(99, ("ISCSI: login\n"));
1066
1067 if (!iscsi_InitiatorName[0]) {
1068 DEB(1, ("No Initiator Name\n"));
1069 par->status = ISCSI_STATUS_NO_INITIATOR_NAME;
1070 return;
1071 }
1072
1073 if ((par->status = check_login_pars(par)) != 0)
1074 return;
1075
1076 /* alloc the session */
1077 sess = malloc(sizeof(*sess), M_DEVBUF, M_WAITOK | M_ZERO);
1078 if (sess == NULL) {
1079 DEBOUT(("No mem for session\n"));
1080 par->status = ISCSI_STATUS_NO_RESOURCES;
1081 return;
1082 }
1083 TAILQ_INIT(&sess->s_conn_list);
1084 TAILQ_INIT(&sess->s_ccb_pool);
1085
1086 mutex_init(&sess->s_lock, MUTEX_DEFAULT, IPL_BIO);
1087 cv_init(&sess->s_sess_cv, "session");
1088 cv_init(&sess->s_ccb_cv, "ccb");
1089
1090 mutex_enter(&iscsi_cleanup_mtx);
1091 /* create a unique ID */
1092 do {
1093 ++current_id;
1094 } while (!current_id || find_session(current_id) != NULL);
1095 par->session_id = sess->s_id = current_id;
1096 mutex_exit(&iscsi_cleanup_mtx);
1097
1098 create_ccbs(sess);
1099 sess->s_login_type = par->login_type;
1100 sess->s_CmdSN = 1;
1101
1102 if ((rc = create_connection(par, sess, l)) != 0) {
1103 if (rc > 0) {
1104 destroy_ccbs(sess);
1105 cv_destroy(&sess->s_ccb_cv);
1106 cv_destroy(&sess->s_sess_cv);
1107 mutex_destroy(&sess->s_lock);
1108 free(sess, M_DEVBUF);
1109 }
1110 return;
1111 }
1112
1113 mutex_enter(&iscsi_cleanup_mtx);
1114 TAILQ_INSERT_HEAD(&iscsi_sessions, sess, s_sessions);
1115 mutex_exit(&iscsi_cleanup_mtx);
1116
1117 /* Session established, map LUNs? */
1118 if (par->login_type == ISCSI_LOGINTYPE_MAP) {
1119 copyinstr(par->TargetName, sess->s_tgtname,
1120 sizeof(sess->s_tgtname), NULL);
1121 DEB(1, ("Login: map session %d\n", sess->s_id));
1122 if (!map_session(sess, dev)) {
1123 DEB(1, ("Login: map session %d failed\n", sess->s_id));
1124 kill_session(sess, ISCSI_STATUS_MAP_FAILED,
1125 LOGOUT_SESSION, FALSE);
1126 par->status = ISCSI_STATUS_MAP_FAILED;
1127 return;
1128 }
1129 }
1130 }
1131
1132
1133 /*
1134 * logout:
1135 * Handle the logout ioctl - Kill a session.
1136 *
1137 * Parameter:
1138 * par IN/OUT: The login parameters
1139 */
1140
1141 static void
1142 logout(iscsi_logout_parameters_t *par)
1143 {
1144 session_t *session;
1145
1146 DEB(5, ("ISCSI: logout session %d\n", par->session_id));
1147
1148 mutex_enter(&iscsi_cleanup_mtx);
1149 if ((session = find_session(par->session_id)) == NULL) {
1150 mutex_exit(&iscsi_cleanup_mtx);
1151 DEBOUT(("Session %d not found\n", par->session_id));
1152 par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1153 return;
1154 }
1155 mutex_exit(&iscsi_cleanup_mtx);
1156 /* If the session exists, this always succeeds */
1157 par->status = ISCSI_STATUS_SUCCESS;
1158
1159 kill_session(session, ISCSI_STATUS_LOGOUT, LOGOUT_SESSION, FALSE);
1160 }
1161
1162
1163 /*
1164 * add_connection:
1165 * Handle the add_connection ioctl.
1166 *
1167 * Parameter:
1168 * par IN/OUT: The login parameters
1169 * l IN: The lwp pointer of the caller
1170 */
1171
1172 static void
1173 add_connection(iscsi_login_parameters_t *par, struct lwp *l)
1174 {
1175 session_t *session;
1176
1177 DEB(5, ("ISCSI: add_connection to session %d\n", par->session_id));
1178
1179 mutex_enter(&iscsi_cleanup_mtx);
1180 if ((session = find_session(par->session_id)) == NULL) {
1181 mutex_exit(&iscsi_cleanup_mtx);
1182 DEBOUT(("Session %d not found\n", par->session_id));
1183 par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1184 return;
1185 }
1186 mutex_exit(&iscsi_cleanup_mtx);
1187 if ((par->status = check_login_pars(par)) == 0) {
1188 create_connection(par, session, l);
1189 }
1190 }
1191
1192
1193 /*
1194 * remove_connection:
1195 * Handle the remove_connection ioctl.
1196 *
1197 * Parameter:
1198 * par IN/OUT: The remove parameters
1199 */
1200
1201 static void
1202 remove_connection(iscsi_remove_parameters_t *par)
1203 {
1204 connection_t *conn;
1205 session_t *session;
1206
1207 DEB(5, ("ISCSI: remove_connection %d from session %d\n",
1208 par->connection_id, par->session_id));
1209
1210 mutex_enter(&iscsi_cleanup_mtx);
1211 if ((session = find_session(par->session_id)) == NULL) {
1212 mutex_exit(&iscsi_cleanup_mtx);
1213 DEBOUT(("Session %d not found\n", par->session_id));
1214 par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1215 return;
1216 }
1217
1218 if ((conn = find_connection(session, par->connection_id)) == NULL) {
1219 mutex_exit(&iscsi_cleanup_mtx);
1220 DEBOUT(("Connection %d not found in session %d\n",
1221 par->connection_id, par->session_id));
1222
1223 par->status = ISCSI_STATUS_INVALID_CONNECTION_ID;
1224 } else {
1225 mutex_exit(&iscsi_cleanup_mtx);
1226 kill_connection(conn, ISCSI_STATUS_LOGOUT, LOGOUT_CONNECTION,
1227 FALSE);
1228 par->status = ISCSI_STATUS_SUCCESS;
1229 }
1230 }
1231
1232
1233 /*
1234 * restore_connection:
1235 * Handle the restore_connection ioctl.
1236 *
1237 * Parameter:
1238 * par IN/OUT: The login parameters
1239 * l IN: The lwp pointer of the caller
1240 */
1241
1242 static void
1243 restore_connection(iscsi_login_parameters_t *par, struct lwp *l)
1244 {
1245 session_t *sess;
1246 connection_t *conn;
1247
1248 DEB(1, ("ISCSI: restore_connection %d of session %d\n",
1249 par->connection_id, par->session_id));
1250
1251 mutex_enter(&iscsi_cleanup_mtx);
1252 if ((sess = find_session(par->session_id)) == NULL) {
1253 mutex_exit(&iscsi_cleanup_mtx);
1254 DEBOUT(("Session %d not found\n", par->session_id));
1255 par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1256 return;
1257 }
1258
1259 if ((conn = find_connection(sess, par->connection_id)) == NULL) {
1260 mutex_exit(&iscsi_cleanup_mtx);
1261 DEBOUT(("Connection %d not found in session %d\n",
1262 par->connection_id, par->session_id));
1263 par->status = ISCSI_STATUS_INVALID_CONNECTION_ID;
1264 return;
1265 }
1266 mutex_exit(&iscsi_cleanup_mtx);
1267
1268 if ((par->status = check_login_pars(par)) == 0) {
1269 recreate_connection(par, sess, conn, l);
1270 }
1271 }
1272
1273
1274 #ifndef ISCSI_MINIMAL
1275
1276 /*
1277 * io_command:
1278 * Handle the io_command ioctl.
1279 *
1280 * Parameter:
1281 * par IN/OUT: The iocommand parameters
1282 * l IN: The lwp pointer of the caller
1283 */
1284
1285 static void
1286 io_command(iscsi_iocommand_parameters_t *par, struct lwp *l)
1287 {
1288 uint32_t datalen = par->req.datalen;
1289 session_t *session;
1290 void *kbuf = NULL;
1291 int error;
1292
1293 DEB(9, ("ISCSI: io_command, SID=%d, lun=%" PRIu64 "\n", par->session_id, par->lun));
1294 mutex_enter(&iscsi_cleanup_mtx);
1295 if ((session = find_session(par->session_id)) == NULL) {
1296 mutex_exit(&iscsi_cleanup_mtx);
1297 DEBOUT(("Session %d not found\n", par->session_id));
1298 par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1299 return;
1300 }
1301 mutex_exit(&iscsi_cleanup_mtx);
1302
1303 par->req.senselen_used = 0;
1304 par->req.datalen_used = 0;
1305 par->req.error = 0;
1306 par->req.status = 0;
1307 par->req.retsts = SCCMD_UNKNOWN; /* init to failure code */
1308
1309 if (par->req.cmdlen > 16 || par->req.senselen > sizeof(par->req.sense)) {
1310 par->status = ISCSI_STATUS_PARAMETER_INVALID;
1311 return;
1312 }
1313
1314 if (datalen) {
1315 /* Arbitrarily limit datalen to 8k. */
1316 if (datalen > 8192) {
1317 par->status = ISCSI_STATUS_PARAMETER_INVALID;
1318 return;
1319 }
1320 kbuf = kmem_zalloc(datalen, KM_SLEEP);
1321 if ((par->req.flags & SCCMD_WRITE) != 0) {
1322 error = copyin(par->req.databuf, kbuf, datalen);
1323 if (error) {
1324 kmem_free(kbuf, datalen);
1325 par->status = ISCSI_STATUS_PARAMETER_INVALID;
1326 return;
1327 }
1328 }
1329 }
1330 par->status = send_io_command(session, par->lun, &par->req,
1331 par->options.immediate, par->connection_id);
1332
1333 if (kbuf) {
1334 if ((par->req.flags & SCCMD_READ) != 0) {
1335 (void) copyout(kbuf, par->req.databuf, datalen);
1336 }
1337 kmem_free(kbuf, datalen);
1338 }
1339 switch (par->status) {
1340 case ISCSI_STATUS_SUCCESS:
1341 par->req.retsts = SCCMD_OK;
1342 break;
1343
1344 case ISCSI_STATUS_TARGET_BUSY:
1345 par->req.retsts = SCCMD_BUSY;
1346 break;
1347
1348 case ISCSI_STATUS_TIMEOUT:
1349 case ISCSI_STATUS_SOCKET_ERROR:
1350 par->req.retsts = SCCMD_TIMEOUT;
1351 break;
1352
1353 default:
1354 par->req.retsts = (par->req.senselen_used) ? SCCMD_SENSE
1355 : SCCMD_UNKNOWN;
1356 break;
1357 }
1358 }
1359 #endif
1360
1361 /*
1362 * send_targets:
1363 * Handle the send_targets ioctl.
1364 * Note: If the passed buffer is too small to hold the complete response,
1365 * the response is kept in the session structure so it can be
1366 * retrieved with the next call to this function without having to go to
1367 * the target again. Once the complete response has been retrieved, it
1368 * is discarded.
1369 *
1370 * Parameter:
1371 * par IN/OUT: The send_targets parameters
1372 */
1373
1374 static void
1375 send_targets(iscsi_send_targets_parameters_t *par)
1376 {
1377 int rc;
1378 uint32_t rlen, cplen;
1379 session_t *sess;
1380
1381 mutex_enter(&iscsi_cleanup_mtx);
1382 if ((sess = find_session(par->session_id)) == NULL) {
1383 mutex_exit(&iscsi_cleanup_mtx);
1384 DEBOUT(("Session %d not found\n", par->session_id));
1385 par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1386 return;
1387 }
1388 mutex_exit(&iscsi_cleanup_mtx);
1389
1390 DEB(9, ("ISCSI: send_targets, rsp_size=%d; Saved list: %p\n",
1391 par->response_size, sess->s_target_list));
1392
1393 if (sess->s_target_list == NULL) {
1394 rc = send_send_targets(sess, par->key);
1395 if (rc) {
1396 par->status = rc;
1397 return;
1398 }
1399 }
1400 rlen = sess->s_target_list_len;
1401 par->response_total = rlen;
1402 cplen = min(par->response_size, rlen);
1403 if (cplen) {
1404 copyout(sess->s_target_list, par->response_buffer, cplen);
1405 }
1406 par->response_used = cplen;
1407
1408 /* If all of the response was copied, don't keep it around */
1409 if (rlen && par->response_used == rlen) {
1410 free(sess->s_target_list, M_TEMP);
1411 sess->s_target_list = NULL;
1412 }
1413
1414 par->status = ISCSI_STATUS_SUCCESS;
1415 }
1416
1417
1418 /*
1419 * set_node_name:
1420 * Handle the set_node_name ioctl.
1421 *
1422 * Parameter:
1423 * par IN/OUT: The set_node_name parameters
1424 */
1425
1426 static void
1427 set_node_name(iscsi_set_node_name_parameters_t *par)
1428 {
1429
1430 if (strlen(par->InitiatorName) >= ISCSI_STRING_LENGTH ||
1431 strlen(par->InitiatorAlias) >= ISCSI_STRING_LENGTH) {
1432 DEBOUT(("*** set_node_name string too long!\n"));
1433 par->status = ISCSI_STATUS_PARAMETER_INVALID;
1434 return;
1435 }
1436 strlcpy(iscsi_InitiatorName, par->InitiatorName, sizeof(iscsi_InitiatorName));
1437 strlcpy(iscsi_InitiatorAlias, par->InitiatorAlias, sizeof(iscsi_InitiatorAlias));
1438 memcpy(&iscsi_InitiatorISID, par->ISID, 6);
1439 DEB(5, ("ISCSI: set_node_name, ISID A=%x, B=%x, C=%x, D=%x\n",
1440 iscsi_InitiatorISID.ISID_A, iscsi_InitiatorISID.ISID_B,
1441 iscsi_InitiatorISID.ISID_C, iscsi_InitiatorISID.ISID_D));
1442
1443 if (!iscsi_InitiatorISID.ISID_A && !iscsi_InitiatorISID.ISID_B &&
1444 !iscsi_InitiatorISID.ISID_C && !iscsi_InitiatorISID.ISID_D) {
1445 iscsi_InitiatorISID.ISID_A = T_FORMAT_EN;
1446 iscsi_InitiatorISID.ISID_B = htons(0x1);
1447 iscsi_InitiatorISID.ISID_C = 0x37;
1448 iscsi_InitiatorISID.ISID_D = 0;
1449 }
1450
1451 par->status = ISCSI_STATUS_SUCCESS;
1452 }
1453
1454
1455 /*
1456 * connection_status:
1457 * Handle the connection_status ioctl.
1458 *
1459 * Parameter:
1460 * par IN/OUT: The status parameters
1461 */
1462
1463 static void
1464 connection_status(iscsi_conn_status_parameters_t *par)
1465 {
1466 connection_t *conn;
1467 session_t *sess;
1468
1469 mutex_enter(&iscsi_cleanup_mtx);
1470 if ((sess = find_session(par->session_id)) == NULL) {
1471 mutex_exit(&iscsi_cleanup_mtx);
1472 par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1473 return;
1474 }
1475
1476 if (par->connection_id) {
1477 conn = find_connection(sess, par->connection_id);
1478 } else {
1479 conn = TAILQ_FIRST(&sess->s_conn_list);
1480 }
1481 par->status = (conn == NULL) ? ISCSI_STATUS_INVALID_CONNECTION_ID :
1482 ISCSI_STATUS_SUCCESS;
1483 mutex_exit(&iscsi_cleanup_mtx);
1484 DEB(9, ("ISCSI: connection_status, session %d connection %d --> %d\n",
1485 par->session_id, par->connection_id, par->status));
1486 }
1487
1488
1489 /*
1490 * get_version:
1491 * Handle the get_version ioctl.
1492 *
1493 * Parameter:
1494 * par IN/OUT: The version parameters
1495 */
1496
1497 static void
1498 get_version(iscsi_get_version_parameters_t *par)
1499 {
1500 par->status = ISCSI_STATUS_SUCCESS;
1501 par->interface_version = INTERFACE_VERSION;
1502 par->major = VERSION_MAJOR;
1503 par->minor = VERSION_MINOR;
1504 strlcpy(par->version_string, VERSION_STRING,
1505 sizeof(par->version_string));
1506 }
1507
1508
1509 /* -------------------------------------------------------------------- */
1510
1511 /*
1512 * kill_all_sessions:
1513 * Terminate all sessions (called when the driver unloads).
1514 */
1515
1516 int
1517 kill_all_sessions(void)
1518 {
1519 session_t *sess;
1520 int rc = 0;
1521
1522 mutex_enter(&iscsi_cleanup_mtx);
1523 while ((sess = TAILQ_FIRST(&iscsi_sessions)) != NULL) {
1524 mutex_exit(&iscsi_cleanup_mtx);
1525 kill_session(sess, ISCSI_STATUS_DRIVER_UNLOAD, LOGOUT_SESSION,
1526 FALSE);
1527 mutex_enter(&iscsi_cleanup_mtx);
1528 }
1529 if (TAILQ_FIRST(&iscsi_sessions) != NULL) {
1530 DEBOUT(("Failed to kill all sessions\n"));
1531 rc = EBUSY;
1532 }
1533 mutex_exit(&iscsi_cleanup_mtx);
1534
1535 return rc;
1536 }
1537
1538 /*
1539 * handle_connection_error:
1540 * Deal with a problem during send or receive.
1541 *
1542 * Parameter:
1543 * conn The connection the problem is associated with
1544 * status The status code to insert into any unfinished CCBs
1545 * dologout Whether Logout should be attempted
1546 */
1547
1548 void
1549 handle_connection_error(connection_t *conn, uint32_t status, int dologout)
1550 {
1551
1552 DEBC(conn, 0, ("*** Connection Error, status=%d, logout=%d, state=%d\n",
1553 status, dologout, conn->c_state));
1554
1555 if (!conn->c_terminating && conn->c_state <= ST_LOGOUT_SENT) {
1556 /* if we get an error while winding down, escalate it */
1557 if (dologout >= 0 && conn->c_state >= ST_WINDING_DOWN) {
1558 dologout = NO_LOGOUT;
1559 }
1560 kill_connection(conn, status, dologout, TRUE);
1561 }
1562 }
1563
1564 /*
1565 * remove a connection from session and add to the cleanup list
1566 */
1567 void
1568 add_connection_cleanup(connection_t *conn)
1569 {
1570 session_t *sess;
1571
1572 mutex_enter(&iscsi_cleanup_mtx);
1573 if (conn->c_in_session) {
1574 sess = conn->c_session;
1575 conn->c_in_session = FALSE;
1576 conn->c_session = NULL;
1577 TAILQ_REMOVE(&sess->s_conn_list, conn, c_connections);
1578 sess->s_mru_connection = TAILQ_FIRST(&sess->s_conn_list);
1579 }
1580 TAILQ_INSERT_TAIL(&iscsi_cleanupc_list, conn, c_connections);
1581 iscsi_notify_cleanup();
1582 mutex_exit(&iscsi_cleanup_mtx);
1583 }
1584
1585 /*
1586 * callout wrappers for timeouts, the work is done by the cleanup thread
1587 */
1588 void
1589 connection_timeout_co(void *par)
1590 {
1591 connection_t *conn = par;
1592
1593 mutex_enter(&iscsi_cleanup_mtx);
1594 conn->c_timedout = TOUT_QUEUED;
1595 TAILQ_INSERT_TAIL(&iscsi_timeout_conn_list, conn, c_tchain);
1596 iscsi_notify_cleanup();
1597 mutex_exit(&iscsi_cleanup_mtx);
1598 }
1599
1600 void
1601 connection_timeout_start(connection_t *conn, int ticks)
1602 {
1603 mutex_enter(&iscsi_cleanup_mtx);
1604 if (conn->c_timedout != TOUT_QUEUED) {
1605 conn->c_timedout = TOUT_ARMED;
1606 callout_schedule(&conn->c_timeout, ticks);
1607 }
1608 mutex_exit(&iscsi_cleanup_mtx);
1609 }
1610
1611 void
1612 connection_timeout_stop(connection_t *conn)
1613 {
1614 callout_stop(&conn->c_timeout);
1615 mutex_enter(&iscsi_cleanup_mtx);
1616 if (conn->c_timedout == TOUT_QUEUED) {
1617 TAILQ_REMOVE(&iscsi_timeout_conn_list, conn, c_tchain);
1618 conn->c_timedout = TOUT_NONE;
1619 }
1620 if (curlwp != iscsi_cleanproc) {
1621 while (conn->c_timedout == TOUT_BUSY)
1622 kpause("connbusy", false, 1, &iscsi_cleanup_mtx);
1623 }
1624 mutex_exit(&iscsi_cleanup_mtx);
1625 }
1626
1627 void
1628 ccb_timeout_co(void *par)
1629 {
1630 ccb_t *ccb = par;
1631
1632 mutex_enter(&iscsi_cleanup_mtx);
1633 ccb->ccb_timedout = TOUT_QUEUED;
1634 TAILQ_INSERT_TAIL(&iscsi_timeout_ccb_list, ccb, ccb_tchain);
1635 iscsi_notify_cleanup();
1636 mutex_exit(&iscsi_cleanup_mtx);
1637 }
1638
1639 void
1640 ccb_timeout_start(ccb_t *ccb, int ticks)
1641 {
1642 mutex_enter(&iscsi_cleanup_mtx);
1643 if (ccb->ccb_timedout != TOUT_QUEUED) {
1644 ccb->ccb_timedout = TOUT_ARMED;
1645 callout_schedule(&ccb->ccb_timeout, ticks);
1646 }
1647 mutex_exit(&iscsi_cleanup_mtx);
1648 }
1649
1650 void
1651 ccb_timeout_stop(ccb_t *ccb)
1652 {
1653 callout_stop(&ccb->ccb_timeout);
1654 mutex_enter(&iscsi_cleanup_mtx);
1655 if (ccb->ccb_timedout == TOUT_QUEUED) {
1656 TAILQ_REMOVE(&iscsi_timeout_ccb_list, ccb, ccb_tchain);
1657 ccb->ccb_timedout = TOUT_NONE;
1658 }
1659 if (curlwp != iscsi_cleanproc) {
1660 while (ccb->ccb_timedout == TOUT_BUSY)
1661 kpause("ccbbusy", false, 1, &iscsi_cleanup_mtx);
1662 }
1663 mutex_exit(&iscsi_cleanup_mtx);
1664 }
1665
1666 /*
1667 * iscsi_cleanup_thread
1668 * Global thread to handle connection and session cleanup after termination.
1669 */
1670
1671 static void
1672 iscsi_cleanup_thread(void *par)
1673 {
1674 int s, rc;
1675 session_t *sess, *nxts;
1676 connection_t *conn, *nxtc;
1677 ccb_t *ccb;
1678
1679 mutex_enter(&iscsi_cleanup_mtx);
1680 while (iscsi_num_send_threads || !iscsi_detaching ||
1681 !TAILQ_EMPTY(&iscsi_cleanupc_list) || !TAILQ_EMPTY(&iscsi_cleanups_list)) {
1682 TAILQ_FOREACH_SAFE(conn, &iscsi_cleanupc_list, c_connections, nxtc) {
1683
1684 TAILQ_REMOVE(&iscsi_cleanupc_list, conn, c_connections);
1685 mutex_exit(&iscsi_cleanup_mtx);
1686
1687 sess = conn->c_session;
1688
1689 /*
1690 * This implies that connection cleanup only runs when
1691 * the send/recv threads have been killed
1692 */
1693 DEBC(conn, 5, ("Cleanup: Waiting for threads to exit\n"));
1694 while (conn->c_sendproc || conn->c_rcvproc)
1695 kpause("threads", false, hz, NULL);
1696
1697 for (s=1; conn->c_usecount > 0 && s < 3; ++s)
1698 kpause("usecount", false, hz, NULL);
1699
1700 if (conn->c_usecount > 0) {
1701 DEBC(conn, 5, ("Cleanup: %d CCBs busy\n", conn->c_usecount));
1702 /* retry later */
1703 mutex_enter(&iscsi_cleanup_mtx);
1704 TAILQ_INSERT_HEAD(&iscsi_cleanupc_list, conn, c_connections);
1705 continue;
1706 }
1707
1708 KASSERT(!conn->c_in_session);
1709
1710 callout_halt(&conn->c_timeout, NULL);
1711 closef(conn->c_sock);
1712 callout_destroy(&conn->c_timeout);
1713 cv_destroy(&conn->c_idle_cv);
1714 cv_destroy(&conn->c_ccb_cv);
1715 cv_destroy(&conn->c_pdu_cv);
1716 cv_destroy(&conn->c_conn_cv);
1717 mutex_destroy(&conn->c_lock);
1718 free(conn, M_DEVBUF);
1719
1720 mutex_enter(&iscsi_cleanup_mtx);
1721
1722 if (--sess->s_total_connections == 0) {
1723 DEB(1, ("Cleanup: session %d\n", sess->s_id));
1724 if (!sess->s_terminating) {
1725 sess->s_terminating = ISCSI_CONNECTION_TERMINATED;
1726 KASSERT(sess->s_sessions.tqe_prev != NULL);
1727 TAILQ_REMOVE(&iscsi_sessions, sess, s_sessions);
1728 sess->s_sessions.tqe_next = NULL;
1729 sess->s_sessions.tqe_prev = NULL;
1730 }
1731 KASSERT(sess->s_sessions.tqe_prev == NULL);
1732 TAILQ_INSERT_HEAD(&iscsi_cleanups_list, sess, s_sessions);
1733 }
1734 }
1735
1736 TAILQ_FOREACH_SAFE(sess, &iscsi_cleanups_list, s_sessions, nxts) {
1737 if (sess->s_refcount > 0)
1738 continue;
1739 TAILQ_REMOVE(&iscsi_cleanups_list, sess, s_sessions);
1740 sess->s_sessions.tqe_next = NULL;
1741 sess->s_sessions.tqe_prev = NULL;
1742 mutex_exit(&iscsi_cleanup_mtx);
1743
1744 DEB(1, ("Cleanup: Unmap session %d\n", sess->s_id));
1745 if (unmap_session(sess) == 0) {
1746 DEB(1, ("Cleanup: Unmap session %d failed\n", sess->s_id));
1747 mutex_enter(&iscsi_cleanup_mtx);
1748 TAILQ_INSERT_HEAD(&iscsi_cleanups_list, sess, s_sessions);
1749 continue;
1750 }
1751
1752 if (sess->s_target_list != NULL)
1753 free(sess->s_target_list, M_TEMP);
1754
1755 /* notify event handlers of session shutdown */
1756 add_event(ISCSI_SESSION_TERMINATED, sess->s_id, 0, sess->s_terminating);
1757 DEB(1, ("Cleanup: session ended %d\n", sess->s_id));
1758
1759 destroy_ccbs(sess);
1760 cv_destroy(&sess->s_ccb_cv);
1761 cv_destroy(&sess->s_sess_cv);
1762 mutex_destroy(&sess->s_lock);
1763 free(sess, M_DEVBUF);
1764
1765 mutex_enter(&iscsi_cleanup_mtx);
1766 }
1767
1768 /* handle ccb timeouts */
1769 while ((ccb = TAILQ_FIRST(&iscsi_timeout_ccb_list)) != NULL) {
1770 TAILQ_REMOVE(&iscsi_timeout_ccb_list, ccb, ccb_tchain);
1771 KASSERT(ccb->ccb_timedout == TOUT_QUEUED);
1772 ccb->ccb_timedout = TOUT_BUSY;
1773 mutex_exit(&iscsi_cleanup_mtx);
1774 ccb_timeout(ccb);
1775 mutex_enter(&iscsi_cleanup_mtx);
1776 if (ccb->ccb_timedout == TOUT_BUSY)
1777 ccb->ccb_timedout = TOUT_NONE;
1778 }
1779
1780 /* handle connection timeouts */
1781 while ((conn = TAILQ_FIRST(&iscsi_timeout_conn_list)) != NULL) {
1782 TAILQ_REMOVE(&iscsi_timeout_conn_list, conn, c_tchain);
1783 KASSERT(conn->c_timedout == TOUT_QUEUED);
1784 conn->c_timedout = TOUT_BUSY;
1785 mutex_exit(&iscsi_cleanup_mtx);
1786 connection_timeout(conn);
1787 mutex_enter(&iscsi_cleanup_mtx);
1788 if (conn->c_timedout == TOUT_BUSY)
1789 conn->c_timedout = TOUT_NONE;
1790 }
1791
1792 /* Go to sleep, but wake up every 30 seconds to
1793 * check for dead event handlers */
1794 rc = cv_timedwait(&iscsi_cleanup_cv, &iscsi_cleanup_mtx,
1795 (TAILQ_FIRST(&event_handlers)) ? 120 * hz : 0);
1796
1797 /* if timed out, not woken up */
1798 if (rc == EWOULDBLOCK)
1799 check_event_handlers();
1800 }
1801 mutex_exit(&iscsi_cleanup_mtx);
1802
1803 add_event(ISCSI_DRIVER_TERMINATING, 0, 0, ISCSI_STATUS_DRIVER_UNLOAD);
1804
1805 /*
1806 * Wait for all event handlers to deregister, but don't wait more
1807 * than 1 minute (assume registering app has died if it takes longer).
1808 */
1809 mutex_enter(&iscsi_cleanup_mtx);
1810 for (s = 0; TAILQ_FIRST(&event_handlers) != NULL && s < 60; s++)
1811 kpause("waiteventclr", true, hz, &iscsi_cleanup_mtx);
1812 mutex_exit(&iscsi_cleanup_mtx);
1813
1814 iscsi_cleanproc = NULL;
1815 DEB(5, ("Cleanup thread exits\n"));
1816 kthread_exit(0);
1817 }
1818
1819 void
1820 iscsi_init_cleanup(void)
1821 {
1822
1823 mutex_init(&iscsi_cleanup_mtx, MUTEX_DEFAULT, IPL_BIO);
1824 cv_init(&iscsi_cleanup_cv, "cleanup");
1825 cv_init(&iscsi_event_cv, "iscsievtwait");
1826
1827 if (kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, iscsi_cleanup_thread,
1828 NULL, &iscsi_cleanproc, "iscsi_cleanup") != 0) {
1829 panic("Can't create cleanup thread!");
1830 }
1831 }
1832
1833 int
1834 iscsi_destroy_cleanup(void)
1835 {
1836
1837 iscsi_detaching = true;
1838 mutex_enter(&iscsi_cleanup_mtx);
1839 while (iscsi_cleanproc != NULL) {
1840 iscsi_notify_cleanup();
1841 kpause("detach_wait", false, hz, &iscsi_cleanup_mtx);
1842 }
1843 mutex_exit(&iscsi_cleanup_mtx);
1844
1845 cv_destroy(&iscsi_event_cv);
1846 cv_destroy(&iscsi_cleanup_cv);
1847 mutex_destroy(&iscsi_cleanup_mtx);
1848
1849 return 0;
1850 }
1851
1852 void
1853 iscsi_notify_cleanup(void)
1854 {
1855 KASSERT(mutex_owned(&iscsi_cleanup_mtx));
1856
1857 cv_signal(&iscsi_cleanup_cv);
1858 }
1859
1860
1861 /* -------------------------------------------------------------------- */
1862
1863 /*
1864 * iscsi_ioctl:
1865 * Driver ioctl entry.
1866 *
1867 * Parameter:
1868 * file File structure
1869 * cmd The ioctl Command
1870 * addr IN/OUT: The command parameter
1871 * flag Flags (ignored)
1872 * l IN: The lwp object of the caller
1873 */
1874
1875 int
1876 iscsiioctl(struct file *fp, u_long cmd, void *addr)
1877 {
1878 struct lwp *l = curlwp;
1879 struct iscsifd *d = fp->f_iscsi;
1880
1881 DEB(1, ("ISCSI Ioctl cmd = %x\n", (int) cmd));
1882
1883 switch (cmd) {
1884 case ISCSI_GET_VERSION:
1885 get_version((iscsi_get_version_parameters_t *) addr);
1886 break;
1887
1888 case ISCSI_LOGIN:
1889 login((iscsi_login_parameters_t *) addr, l, d->fd_dev);
1890 break;
1891
1892 case ISCSI_ADD_CONNECTION:
1893 add_connection((iscsi_login_parameters_t *) addr, l);
1894 break;
1895
1896 case ISCSI_RESTORE_CONNECTION:
1897 restore_connection((iscsi_login_parameters_t *) addr, l);
1898 break;
1899
1900 case ISCSI_LOGOUT:
1901 logout((iscsi_logout_parameters_t *) addr);
1902 break;
1903
1904 case ISCSI_REMOVE_CONNECTION:
1905 remove_connection((iscsi_remove_parameters_t *) addr);
1906 break;
1907
1908 #ifndef ISCSI_MINIMAL
1909 case ISCSI_IO_COMMAND:
1910 io_command((iscsi_iocommand_parameters_t *) addr, l);
1911 break;
1912 #endif
1913
1914 case ISCSI_SEND_TARGETS:
1915 send_targets((iscsi_send_targets_parameters_t *) addr);
1916 break;
1917
1918 case ISCSI_SET_NODE_NAME:
1919 set_node_name((iscsi_set_node_name_parameters_t *) addr);
1920 break;
1921
1922 case ISCSI_CONNECTION_STATUS:
1923 connection_status((iscsi_conn_status_parameters_t *) addr);
1924 break;
1925
1926 case ISCSI_REGISTER_EVENT:
1927 register_event((iscsi_register_event_parameters_t *) addr);
1928 break;
1929
1930 case ISCSI_DEREGISTER_EVENT:
1931 deregister_event((iscsi_register_event_parameters_t *) addr);
1932 break;
1933
1934 case ISCSI_WAIT_EVENT:
1935 check_event((iscsi_wait_event_parameters_t *) addr, TRUE);
1936 break;
1937
1938 case ISCSI_POLL_EVENT:
1939 check_event((iscsi_wait_event_parameters_t *) addr, FALSE);
1940 break;
1941
1942 default:
1943 DEBOUT(("Invalid IO-Control Code\n"));
1944 return ENOTTY;
1945 }
1946
1947 /*
1948 * NOTE: We return 0 even if the function fails as long as the ioctl code
1949 * is good, so the status code is copied back to the caller.
1950 */
1951 return 0;
1952 }
1953