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