1 /*        $NetBSD: iscsi_ioctl.c,v 1.37 2024/11/03 10:53:02 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 #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 *
find_handler(uint32_t id)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
register_event(iscsi_register_event_parameters_t * par)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
deregister_event(iscsi_register_event_parameters_t * par)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
check_event(iscsi_wait_event_parameters_t * par,bool wait)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
add_event(iscsi_event_t kind,uint32_t sid,uint32_t cid,uint32_t reason)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
check_event_handlers(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
get_socket(int fdes,struct file ** fpp)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
release_socket(struct file * fp)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 *
find_session(uint32_t id)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 *
find_connection(session_t * sess,uint32_t id)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
ref_session(session_t * sess)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
unref_session(session_t * session)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
kill_connection(connection_t * conn,uint32_t status,int logout,bool recover)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, ("Kill_connection: Too many recovery attempts, "
498                                    "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           mutex_enter(&conn->c_lock);
517           terminating = conn->c_terminating;
518           if (!terminating)
519                     conn->c_terminating = status;
520           mutex_exit(&conn->c_lock);
521 
522           /* Don't recurse */
523           if (terminating) {
524                     mutex_exit(&iscsi_cleanup_mtx);
525 
526                     KASSERT(conn->c_state != ST_FULL_FEATURE);
527                     DEBC(conn, 1, ("Kill_connection exiting (already terminating)\n"));
528                     goto done;
529           }
530 
531           if (conn->c_state == ST_FULL_FEATURE) {
532                     sess->s_active_connections--;
533                     conn->c_state = ST_WINDING_DOWN;
534 
535                     /* If this is the last connection and ERL < 2, reset TSIH */
536                     if (!sess->s_active_connections && sess->s_ErrorRecoveryLevel < 2)
537                               sess->s_TSIH = 0;
538 
539                     /* Don't try to log out if the socket is broken or we're in the middle */
540                     /* of logging in */
541                     if (logout >= 0) {
542                               if (sess->s_ErrorRecoveryLevel < 2 &&
543                                   logout == RECOVER_CONNECTION) {
544                                         logout = LOGOUT_CONNECTION;
545                               }
546                               if (!sess->s_active_connections &&
547                                   logout == LOGOUT_CONNECTION) {
548                                         logout = LOGOUT_SESSION;
549                               }
550 
551                               /* connection is terminating, prevent cleanup */
552                               mutex_enter(&conn->c_lock);
553                               conn->c_usecount++;
554                               mutex_exit(&conn->c_lock);
555 
556                               mutex_exit(&iscsi_cleanup_mtx);
557 
558                               DEBC(conn, 1, ("Send_logout for reason %d\n", logout));
559 
560                               connection_timeout_start(conn, CONNECTION_TIMEOUT);
561 
562                               if (!send_logout(conn, conn, logout, FALSE)) {
563                                         mutex_enter(&conn->c_lock);
564                                         conn->c_usecount--;
565                                         conn->c_terminating = ISCSI_STATUS_SUCCESS;
566                                         mutex_exit(&conn->c_lock);
567                                         return;
568                               }
569                               /*
570                                * if the logout request was successfully sent,
571                                * the logout response handler will do the rest
572                                * of the termination processing. If the logout
573                                * doesn't get a response, we'll get back in here
574                                * once the timeout hits.
575                                */
576 
577                               mutex_enter(&iscsi_cleanup_mtx);
578 
579                               /* release connection */
580                               mutex_enter(&conn->c_lock);
581                               conn->c_usecount--;
582                               mutex_exit(&conn->c_lock);
583                     }
584 
585           }
586 
587           conn->c_state = ST_SETTLING;
588           mutex_exit(&iscsi_cleanup_mtx);
589 
590 done:
591           /* let send thread take over next step of cleanup */
592           mutex_enter(&conn->c_lock);
593           cv_broadcast(&conn->c_conn_cv);
594           mutex_exit(&conn->c_lock);
595 
596           DEBC(conn, 5, ("kill_connection returns\n"));
597 }
598 
599 
600 /*
601  * kill_session:
602  *    Terminate the session as gracefully as possible.
603  *
604  *    Parameter:
605  *                  session             Session to terminate
606  *                  status              The status code for the termination
607  *                  logout              The logout reason code
608 
609  */
610 
611 void
kill_session(uint32_t sid,uint32_t status,int logout,bool recover)612 kill_session(uint32_t sid, uint32_t status, int logout, bool recover)
613 {
614           session_t *sess;
615           connection_t *conn;
616 
617           DEB(1, ("ISCSI: kill_session %d, status %d, logout %d, recover %d\n",
618                               sid, status, logout, recover));
619 
620           mutex_enter(&iscsi_cleanup_mtx);
621 
622           sess = find_session(sid);
623           if (sess == NULL) {
624                     mutex_exit(&iscsi_cleanup_mtx);
625 
626                     DEB(5, ("Session %u already gone\n", sid));
627                     return;
628           }
629 
630           if (sess->s_terminating) {
631                     mutex_exit(&iscsi_cleanup_mtx);
632 
633                     DEB(5, ("Session is being killed with status %d\n",sess->s_terminating));
634                     return;
635           }
636 
637           /*
638            * don't do anything if session isn't established yet, termination will be
639            * handled elsewhere
640            */
641           if (sess->s_sessions.tqe_next == NULL && sess->s_sessions.tqe_prev == NULL) {
642                     mutex_exit(&iscsi_cleanup_mtx);
643 
644                     DEB(5, ("Session is being killed which is not yet established\n"));
645                     return;
646           }
647 
648           if (recover) {
649                     /*
650                      * Only recover when there's just one active connection left.
651                      * Otherwise we get in all sorts of timing problems, and it doesn't
652                      * make much sense anyway to recover when the other side has
653                      * requested that we kill a multipathed session.
654                      */
655                     conn = NULL;
656                     if (sess->s_active_connections == 1)
657                               conn = assign_connection(sess, FALSE);
658 
659                     mutex_exit(&iscsi_cleanup_mtx);
660 
661                     if (conn != NULL)
662                               kill_connection(conn, status, logout, TRUE);
663                     return;
664           }
665 
666           if (sess->s_refcount > 0) {
667                     mutex_exit(&iscsi_cleanup_mtx);
668 
669                     DEB(5, ("Session is being killed while in use (refcnt = %d)\n",
670                               sess->s_refcount));
671                     return;
672           }
673 
674           /* Remove session from global list */
675           sess->s_terminating = status;
676           TAILQ_REMOVE(&iscsi_sessions, sess, s_sessions);
677           sess->s_sessions.tqe_next = NULL;
678           sess->s_sessions.tqe_prev = NULL;
679 
680           /*
681            * If all connections are already gone, trigger cleanup
682            * otherwise, the last connection will do this
683            */
684           if (sess->s_active_connections == 0)
685                     iscsi_notify_cleanup();
686 
687           mutex_exit(&iscsi_cleanup_mtx);
688 
689           /* kill all connections */
690           while ((conn = TAILQ_FIRST(&sess->s_conn_list)) != NULL) {
691                     kill_connection(conn, status, logout, FALSE);
692                     logout = NO_LOGOUT;
693           }
694 }
695 
696 
697 /*
698  * create_connection:
699  *    Create and init the necessary framework for a connection:
700  *       Take over userland socket
701  *       Alloc the connection structure itself
702  *       Copy connection parameters
703  *       Create the send and receive threads
704  *       And finally, log in.
705  *
706  *    Parameter:
707  *          par      IN/OUT: The login parameters
708  *          session  IN: The owning session
709  *          l        IN: The lwp pointer of the caller
710  *
711  *    Returns:    0 on success
712  *                >0 on failure, connection structure deleted
713  *                <0 on failure, connection is still terminating
714  */
715 
716 static int
create_connection(iscsi_login_parameters_t * par,session_t * sess,struct lwp * l)717 create_connection(iscsi_login_parameters_t *par, session_t *sess,
718                                           struct lwp *l)
719 {
720           connection_t *conn;
721           int rc;
722 
723           DEB(1, ("Create Connection for Session %d\n", sess->s_id));
724 
725           if (sess->s_MaxConnections &&
726               sess->s_active_connections >= sess->s_MaxConnections) {
727                     DEBOUT(("Too many connections (max = %d, curr = %d)\n",
728                                         sess->s_MaxConnections, sess->s_active_connections));
729                     /* Always close descriptor */
730                     fd_close(par->socket);
731 
732                     par->status = ISCSI_STATUS_MAXED_CONNECTIONS;
733                     return EIO;
734           }
735 
736           conn = malloc(sizeof(*conn), M_DEVBUF, M_WAITOK | M_ZERO);
737           if (conn == NULL) {
738                     DEBOUT(("No mem for connection\n"));
739 
740                     /* Always close descriptor */
741                     fd_close(par->socket);
742 
743                     par->status = ISCSI_STATUS_NO_RESOURCES;
744                     return EIO;
745           }
746 
747           rc = get_socket(par->socket, &conn->c_sock);
748           if (rc != EBADF)
749                     fd_close(par->socket);
750 
751           if (rc) {
752                     DEBOUT(("Invalid socket %d\n", par->socket));
753                     free(conn, M_DEVBUF);
754                     par->status = ISCSI_STATUS_INVALID_SOCKET;
755                     return rc;
756           }
757 
758           DEBC(conn, 1, ("get_socket: par_sock=%d, fdesc=%p\n",
759                               par->socket, conn->c_sock));
760 
761           mutex_enter(&iscsi_cleanup_mtx);
762           /* create a unique ID */
763           do {
764                     ++sess->s_conn_id;
765           } while (!sess->s_conn_id ||
766                      find_connection(sess, sess->s_conn_id) != NULL);
767           par->connection_id = conn->c_id = sess->s_conn_id;
768           mutex_exit(&iscsi_cleanup_mtx);
769           DEB(99, ("Connection ID = %d\n", conn->c_id));
770 
771           conn->c_session = sess;
772 
773           TAILQ_INIT(&conn->c_ccbs_waiting);
774           TAILQ_INIT(&conn->c_pdus_to_send);
775           TAILQ_INIT(&conn->c_pdu_pool);
776 
777           mutex_init(&conn->c_lock, MUTEX_DEFAULT, IPL_BIO);
778           cv_init(&conn->c_conn_cv, "conn");
779           cv_init(&conn->c_pdu_cv, "pdupool");
780           cv_init(&conn->c_ccb_cv, "ccbwait");
781           cv_init(&conn->c_idle_cv, "idle");
782           rw_init(&conn->c_sock_rw);
783 
784           callout_init(&conn->c_timeout, CALLOUT_MPSAFE);
785           callout_setfunc(&conn->c_timeout, connection_timeout_co, conn);
786           conn->c_idle_timeout_val = CONNECTION_IDLE_TIMEOUT;
787 
788           init_sernum(&conn->c_StatSN_buf);
789           create_pdus(conn);
790 
791           conn->c_threadobj = l;
792           conn->c_login_par = par;
793 
794           DEB(5, ("Creating receive thread\n"));
795           if ((rc = kthread_create(PRI_BIO, KTHREAD_MPSAFE, NULL, iscsi_rcv_thread,
796                                         conn, &conn->c_rcvproc,
797                                         "ConnRcv")) != 0) {
798                     DEBOUT(("Can't create rcv thread (rc %d)\n", rc));
799 
800                     release_socket(conn->c_sock);
801                     rw_destroy(&conn->c_sock_rw);
802                     callout_destroy(&conn->c_timeout);
803                     cv_destroy(&conn->c_idle_cv);
804                     cv_destroy(&conn->c_ccb_cv);
805                     cv_destroy(&conn->c_pdu_cv);
806                     cv_destroy(&conn->c_conn_cv);
807                     mutex_destroy(&conn->c_lock);
808                     free(conn, M_DEVBUF);
809                     par->status = ISCSI_STATUS_NO_RESOURCES;
810                     return rc;
811           }
812           DEB(5, ("Creating send thread\n"));
813           if ((rc = kthread_create(PRI_BIO, KTHREAD_MPSAFE, NULL, iscsi_send_thread,
814                                         conn, &conn->c_sendproc,
815                                         "ConnSend")) != 0) {
816                     DEBOUT(("Can't create send thread (rc %d)\n", rc));
817 
818                     conn->c_terminating = ISCSI_STATUS_NO_RESOURCES;
819 
820                     /*
821                      * We must close the socket here to force the receive
822                      * thread to wake up
823                      */
824                     DEBC(conn, 1, ("Closing Socket %p\n", conn->c_sock));
825                     mutex_enter(&conn->c_sock->f_lock);
826                     conn->c_sock->f_count += 1;
827                     mutex_exit(&conn->c_sock->f_lock);
828                     closef(conn->c_sock);
829 
830                     /* give receive thread time to exit */
831                     kpause("settle", false, 2 * hz, NULL);
832 
833                     release_socket(conn->c_sock);
834                     callout_destroy(&conn->c_timeout);
835                     rw_destroy(&conn->c_sock_rw);
836                     cv_destroy(&conn->c_idle_cv);
837                     cv_destroy(&conn->c_ccb_cv);
838                     cv_destroy(&conn->c_pdu_cv);
839                     cv_destroy(&conn->c_conn_cv);
840                     mutex_destroy(&conn->c_lock);
841                     free(conn, M_DEVBUF);
842                     par->status = ISCSI_STATUS_NO_RESOURCES;
843                     return rc;
844           }
845 
846           /*
847            * At this point, each thread will tie 'sock' into its own file descriptor
848            * tables w/o increasing the use count - they will inherit the use
849            * increments performed in get_socket().
850            */
851 
852           if ((rc = send_login(conn)) != 0) {
853                     DEBC(conn, 0, ("Login failed (rc %d)\n", rc));
854                     /* Don't attempt to recover, there seems to be something amiss */
855                     kill_connection(conn, rc, NO_LOGOUT, FALSE);
856                     par->status = rc;
857                     return -1;
858           }
859 
860           mutex_enter(&iscsi_cleanup_mtx);
861           if (sess->s_terminating) {
862                     mutex_exit(&iscsi_cleanup_mtx);
863                     DEBC(conn, 0, ("Session terminating\n"));
864                     kill_connection(conn, rc, NO_LOGOUT, FALSE);
865                     par->status = sess->s_terminating;
866                     return -1;
867           }
868           conn->c_state = ST_FULL_FEATURE;
869           TAILQ_INSERT_TAIL(&sess->s_conn_list, conn, c_connections);
870           conn->c_in_session = TRUE;
871           sess->s_total_connections++;
872           sess->s_active_connections++;
873           sess->s_mru_connection = conn;
874           mutex_exit(&iscsi_cleanup_mtx);
875 
876           DEBC(conn, 5, ("Connection created successfully!\n"));
877           return 0;
878 }
879 
880 
881 /*
882  * recreate_connection:
883  *    Revive dead connection
884  *
885  *    Parameter:
886  *          par      IN/OUT: The login parameters
887  *          conn     IN: The connection
888  *          l        IN: The lwp pointer of the caller
889  *
890  *    Returns:    0 on success
891  *                >0 on failure, connection structure deleted
892  *                <0 on failure, connection is still terminating
893  */
894 
895 static int
recreate_connection(iscsi_login_parameters_t * par,session_t * sess,connection_t * conn,struct lwp * l)896 recreate_connection(iscsi_login_parameters_t *par, session_t *sess,
897                                                   connection_t *conn, struct lwp *l)
898 {
899           int rc;
900           ccb_t *ccb;
901           ccb_list_t old_waiting;
902           pdu_t *pdu;
903           uint32_t sn;
904 
905           DEB(1, ("ReCreate Connection %d for Session %d, ERL=%d\n",
906                     conn->c_id, conn->c_session->s_id,
907                     conn->c_session->s_ErrorRecoveryLevel));
908 
909           if (sess->s_MaxConnections &&
910               sess->s_active_connections >= sess->s_MaxConnections) {
911                     DEBOUT(("Too many connections (max = %d, curr = %d)\n",
912                               sess->s_MaxConnections, sess->s_active_connections));
913 
914                     /* Close the desecriptor */
915                     rc = EIO;
916                     if (fd_getfile(par->socket) != NULL)
917                               rc = fd_close(par->socket);
918 
919                     par->status = ISCSI_STATUS_MAXED_CONNECTIONS;
920                     return rc;
921           }
922 
923           rw_enter(&conn->c_sock_rw, RW_WRITER);
924           if (conn->c_sock != NULL) {
925                     closef(conn->c_sock);
926                     conn->c_sock = NULL;
927           }
928           rc = get_socket(par->socket, &conn->c_sock);
929           rw_exit(&conn->c_sock_rw);
930           if (rc != EBADF)
931                     fd_close(par->socket);
932 
933           if (rc) {
934                     DEBOUT(("Invalid socket %d\n", par->socket));
935                     par->status = ISCSI_STATUS_INVALID_SOCKET;
936                     return rc;
937           }
938 
939           DEBC(conn, 1, ("get_socket: par_sock=%d, fdesc=%p\n",
940                               par->socket, conn->c_sock));
941 
942           conn->c_threadobj = l;
943           conn->c_login_par = par;
944           conn->c_terminating = ISCSI_STATUS_SUCCESS;
945           conn->c_recover++;
946           conn->c_num_timeouts = 0;
947           conn->c_state = ST_SEC_NEG;
948           conn->c_HeaderDigest = 0;
949           conn->c_DataDigest = 0;
950 
951           sess->s_active_connections++;
952 
953           TAILQ_INIT(&old_waiting);
954 
955           mutex_enter(&conn->c_lock);
956           while ((ccb = TAILQ_FIRST(&conn->c_ccbs_waiting)) != NULL) {
957                     suspend_ccb(ccb, FALSE);
958                     TAILQ_INSERT_TAIL(&old_waiting, ccb, ccb_chain);
959           }
960           init_sernum(&conn->c_StatSN_buf);
961           cv_broadcast(&conn->c_idle_cv);
962           mutex_exit(&conn->c_lock);
963 
964           if ((rc = send_login(conn)) != 0) {
965                     DEBC(conn, 0, ("Re-Login failed (rc %d)\n", rc));
966                     while ((ccb = TAILQ_FIRST(&old_waiting)) != NULL) {
967                               TAILQ_REMOVE(&old_waiting, ccb, ccb_chain);
968                               wake_ccb(ccb, rc);
969                     }
970                     /* Don't attempt to recover, there seems to be something amiss */
971                     kill_connection(conn, rc, NO_LOGOUT, FALSE);
972                     par->status = rc;
973                     return -1;
974           }
975 
976           DEBC(conn, 9, ("Re-Login successful\n"));
977           par->status = ISCSI_STATUS_SUCCESS;
978 
979           conn->c_state = ST_FULL_FEATURE;
980           sess->s_mru_connection = conn;
981 
982           while ((ccb = TAILQ_FIRST(&old_waiting)) != NULL) {
983                     TAILQ_REMOVE(&old_waiting, ccb, ccb_chain);
984                     mutex_enter(&conn->c_lock);
985                     suspend_ccb(ccb, TRUE);
986                     mutex_exit(&conn->c_lock);
987 
988                     rc = send_task_management(conn, ccb, NULL, TASK_REASSIGN);
989                     /* if we get an error on reassign, restart the original request */
990                     if (rc && ccb->ccb_pdu_waiting != NULL) {
991                               mutex_enter(&sess->s_lock);
992                               if (sn_a_lt_b(ccb->ccb_CmdSN, sess->s_ExpCmdSN)) {
993                                         pdu = ccb->ccb_pdu_waiting;
994                                         sn = get_sernum(sess, pdu);
995 
996                                         /* update CmdSN */
997                                         DEBC(conn, 0, ("Resend ccb %p (%d) - updating CmdSN old %u, new %u\n",
998                                                      ccb, rc, ccb->ccb_CmdSN, sn));
999                                         ccb->ccb_CmdSN = sn;
1000                                         pdu->pdu_hdr.pduh_p.command.CmdSN = htonl(ccb->ccb_CmdSN);
1001                               } else {
1002                                         DEBC(conn, 0, ("Resend ccb %p (%d) - CmdSN %u\n",
1003                                                      ccb, rc, ccb->ccb_CmdSN));
1004                               }
1005                               mutex_exit(&sess->s_lock);
1006                               resend_pdu(ccb);
1007                     } else {
1008                               DEBC(conn, 0, ("Resend ccb %p (%d) CmdSN %u - reassigned\n",
1009                                         ccb, rc, ccb->ccb_CmdSN));
1010                               ccb_timeout_start(ccb, COMMAND_TIMEOUT);
1011                     }
1012           }
1013 
1014           mutex_enter(&sess->s_lock);
1015           cv_broadcast(&sess->s_sess_cv);
1016           mutex_exit(&sess->s_lock);
1017 
1018           DEBC(conn, 0, ("Connection ReCreated successfully - status %d\n",
1019                                                              par->status));
1020 
1021           return 0;
1022 }
1023 
1024 /* -------------------------------------------------------------------------- */
1025 
1026 /*
1027  * check_login_pars:
1028  *    Check the parameters passed into login/add_connection
1029  *    for validity and consistency.
1030  *
1031  *    Parameter:
1032  *          par      The login parameters
1033  *
1034  *    Returns:    0 on success, else an error code.
1035  */
1036 
1037 static int
check_login_pars(iscsi_login_parameters_t * par)1038 check_login_pars(iscsi_login_parameters_t *par)
1039 {
1040           int i, n;
1041 
1042           if (par->is_present.auth_info) {
1043                     /* check consistency of authentication parameters */
1044 
1045                     if (par->auth_info.auth_number > ISCSI_AUTH_OPTIONS) {
1046                               DEBOUT(("Auth number invalid: %d\n", par->auth_info.auth_number));
1047                               return ISCSI_STATUS_PARAMETER_INVALID;
1048                     }
1049 
1050                     if (par->auth_info.auth_number > 2) {
1051                               DEBOUT(("Auth number invalid: %d\n", par->auth_info.auth_number));
1052                               return ISCSI_STATUS_NOTIMPL;
1053                     }
1054 
1055                     for (i = 0, n = 0; i < par->auth_info.auth_number; i++) {
1056 #if 0
1057                               if (par->auth_info.auth_type[i] < ISCSI_AUTH_None) {
1058                                         DEBOUT(("Auth type invalid: %d\n",
1059                                                             par->auth_info.auth_type[i]));
1060                                         return ISCSI_STATUS_PARAMETER_INVALID;
1061                               }
1062 #endif
1063                               if (par->auth_info.auth_type[i] > ISCSI_AUTH_CHAP) {
1064                                         DEBOUT(("Auth type invalid: %d\n",
1065                                                             par->auth_info.auth_type[i]));
1066                                         return ISCSI_STATUS_NOTIMPL;
1067                               }
1068                               n = max(n, par->auth_info.auth_type[i]);
1069                     }
1070                     if (n) {
1071                               if (!par->is_present.password ||
1072                                         (par->auth_info.mutual_auth &&
1073                                          !par->is_present.target_password)) {
1074                                         DEBOUT(("Password missing\n"));
1075                                         return ISCSI_STATUS_PARAMETER_MISSING;
1076                               }
1077                               /* Note: Default for user-name is initiator name */
1078                     }
1079           }
1080           if (par->login_type != ISCSI_LOGINTYPE_DISCOVERY &&
1081               !par->is_present.TargetName) {
1082                     DEBOUT(("Target name missing, login type %d\n", par->login_type));
1083                     return ISCSI_STATUS_PARAMETER_MISSING;
1084           }
1085           if (par->is_present.MaxRecvDataSegmentLength) {
1086                     if (par->MaxRecvDataSegmentLength < 512 ||
1087                               par->MaxRecvDataSegmentLength > 0xffffff) {
1088                               DEBOUT(("MaxRecvDataSegmentLength invalid: %d\n",
1089                                                   par->MaxRecvDataSegmentLength));
1090                               return ISCSI_STATUS_PARAMETER_INVALID;
1091                     }
1092           }
1093           return 0;
1094 }
1095 
1096 
1097 /*
1098  * login:
1099  *    Handle the login ioctl - Create a session:
1100  *       Alloc the session structure
1101  *       Copy session parameters
1102  *       And call create_connection to establish the connection.
1103  *
1104  *    Parameter:
1105  *          par      IN/OUT: The login parameters
1106  *          l        IN: The lwp pointer of the caller
1107  */
1108 
1109 static void
login(iscsi_login_parameters_t * par,struct lwp * l,device_t dev)1110 login(iscsi_login_parameters_t *par, struct lwp *l, device_t dev)
1111 {
1112           session_t *sess;
1113           int rc;
1114 
1115           DEB(99, ("ISCSI: login\n"));
1116 
1117           if (!iscsi_InitiatorName[0]) {
1118                     DEB(1, ("No Initiator Name\n"));
1119                     par->status = ISCSI_STATUS_NO_INITIATOR_NAME;
1120                     return;
1121           }
1122 
1123           if ((par->status = check_login_pars(par)) != 0)
1124                     return;
1125 
1126           /* alloc the session */
1127           sess = malloc(sizeof(*sess), M_DEVBUF, M_WAITOK | M_ZERO);
1128           if (sess == NULL) {
1129                     DEBOUT(("No mem for session\n"));
1130                     par->status = ISCSI_STATUS_NO_RESOURCES;
1131                     return;
1132           }
1133           TAILQ_INIT(&sess->s_conn_list);
1134           TAILQ_INIT(&sess->s_ccb_pool);
1135 
1136           mutex_init(&sess->s_lock, MUTEX_DEFAULT, IPL_BIO);
1137           cv_init(&sess->s_sess_cv, "session");
1138           cv_init(&sess->s_ccb_cv, "ccb");
1139 
1140           mutex_enter(&iscsi_cleanup_mtx);
1141           /* create a unique ID */
1142           do {
1143                     ++current_id;
1144           } while (!current_id || find_session(current_id) != NULL);
1145           par->session_id = sess->s_id = current_id;
1146           mutex_exit(&iscsi_cleanup_mtx);
1147 
1148           create_ccbs(sess);
1149           sess->s_login_type = par->login_type;
1150           sess->s_CmdSN = 1;
1151 
1152           if ((rc = create_connection(par, sess, l)) != 0) {
1153                     if (rc > 0) {
1154                               destroy_ccbs(sess);
1155                               cv_destroy(&sess->s_ccb_cv);
1156                               cv_destroy(&sess->s_sess_cv);
1157                               mutex_destroy(&sess->s_lock);
1158                               free(sess, M_DEVBUF);
1159                     }
1160                     return;
1161           }
1162 
1163           mutex_enter(&iscsi_cleanup_mtx);
1164           TAILQ_INSERT_HEAD(&iscsi_sessions, sess, s_sessions);
1165           mutex_exit(&iscsi_cleanup_mtx);
1166 
1167           /* Session established, map LUNs? */
1168           if (par->login_type == ISCSI_LOGINTYPE_MAP) {
1169                     copyinstr(par->TargetName, sess->s_tgtname,
1170                         sizeof(sess->s_tgtname), NULL);
1171                     DEB(1, ("Login: map session %d\n", sess->s_id));
1172                     if (!map_session(sess, dev)) {
1173                               DEB(1, ("Login: map session %d failed\n", sess->s_id));
1174                               kill_session(par->session_id, ISCSI_STATUS_MAP_FAILED,
1175                                                   LOGOUT_SESSION, FALSE);
1176                               par->status = ISCSI_STATUS_MAP_FAILED;
1177                               return;
1178                     }
1179           }
1180 }
1181 
1182 
1183 /*
1184  * logout:
1185  *    Handle the logout ioctl - Kill a session.
1186  *
1187  *    Parameter:
1188  *          par      IN/OUT: The login parameters
1189  */
1190 
1191 static void
logout(iscsi_logout_parameters_t * par)1192 logout(iscsi_logout_parameters_t *par)
1193 {
1194           session_t *session;
1195 
1196           DEB(5, ("ISCSI: logout session %d\n", par->session_id));
1197 
1198           mutex_enter(&iscsi_cleanup_mtx);
1199           if ((session = find_session(par->session_id)) == NULL) {
1200                     mutex_exit(&iscsi_cleanup_mtx);
1201                     DEBOUT(("Session %d not found\n", par->session_id));
1202                     par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1203                     return;
1204           }
1205           mutex_exit(&iscsi_cleanup_mtx);
1206           /* If the session exists, this always succeeds */
1207           par->status = ISCSI_STATUS_SUCCESS;
1208 
1209           kill_session(par->session_id,
1210               ISCSI_STATUS_LOGOUT, LOGOUT_SESSION,
1211               FALSE);
1212 }
1213 
1214 
1215 /*
1216  * add_connection:
1217  *    Handle the add_connection ioctl.
1218  *
1219  *    Parameter:
1220  *          par      IN/OUT: The login parameters
1221  *          l        IN: The lwp pointer of the caller
1222  */
1223 
1224 static int
add_connection(iscsi_login_parameters_t * par,struct lwp * l)1225 add_connection(iscsi_login_parameters_t *par, struct lwp *l)
1226 {
1227           session_t *session;
1228 
1229           DEB(5, ("ISCSI: add_connection to session %d\n", par->session_id));
1230 
1231           mutex_enter(&iscsi_cleanup_mtx);
1232           if ((session = find_session(par->session_id)) == NULL) {
1233                     mutex_exit(&iscsi_cleanup_mtx);
1234                     DEBOUT(("Session %d not found\n", par->session_id));
1235                     par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1236                     return -1;
1237           }
1238           mutex_exit(&iscsi_cleanup_mtx);
1239 
1240           par->status = check_login_pars(par);
1241           if (par->status)
1242                     return -1;
1243 
1244           return create_connection(par, session, l);
1245 }
1246 
1247 
1248 /*
1249  * remove_connection:
1250  *    Handle the remove_connection ioctl.
1251  *
1252  *    Parameter:
1253  *          par      IN/OUT: The remove parameters
1254  */
1255 
1256 static void
remove_connection(iscsi_remove_parameters_t * par)1257 remove_connection(iscsi_remove_parameters_t *par)
1258 {
1259           connection_t *conn;
1260           session_t *session;
1261 
1262           DEB(5, ("ISCSI: remove_connection %d from session %d\n",
1263                               par->connection_id, par->session_id));
1264 
1265           mutex_enter(&iscsi_cleanup_mtx);
1266           if ((session = find_session(par->session_id)) == NULL) {
1267                     mutex_exit(&iscsi_cleanup_mtx);
1268                     DEBOUT(("Session %d not found\n", par->session_id));
1269                     par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1270                     return;
1271           }
1272 
1273           if ((conn = find_connection(session, par->connection_id)) == NULL) {
1274                     mutex_exit(&iscsi_cleanup_mtx);
1275                     DEBOUT(("Connection %d not found in session %d\n",
1276                                         par->connection_id, par->session_id));
1277 
1278                     par->status = ISCSI_STATUS_INVALID_CONNECTION_ID;
1279           } else {
1280                     mutex_exit(&iscsi_cleanup_mtx);
1281                     kill_connection(conn, ISCSI_STATUS_LOGOUT, LOGOUT_CONNECTION,
1282                                                   FALSE);
1283                     par->status = ISCSI_STATUS_SUCCESS;
1284           }
1285 }
1286 
1287 
1288 /*
1289  * restore_connection:
1290  *    Handle the restore_connection ioctl.
1291  *
1292  *    Parameter:
1293  *          par      IN/OUT: The login parameters
1294  *          l        IN: The lwp pointer of the caller
1295  */
1296 
1297 static void
restore_connection(iscsi_login_parameters_t * par,struct lwp * l)1298 restore_connection(iscsi_login_parameters_t *par, struct lwp *l)
1299 {
1300           session_t *sess;
1301           connection_t *conn;
1302 
1303           DEB(1, ("ISCSI: restore_connection %d of session %d\n",
1304                               par->connection_id, par->session_id));
1305 
1306           mutex_enter(&iscsi_cleanup_mtx);
1307           if ((sess = find_session(par->session_id)) == NULL) {
1308                     mutex_exit(&iscsi_cleanup_mtx);
1309                     DEBOUT(("Session %d not found\n", par->session_id));
1310                     par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1311                     return;
1312           }
1313           if ((conn = find_connection(sess, par->connection_id)) == NULL) {
1314                     mutex_exit(&iscsi_cleanup_mtx);
1315                     DEBOUT(("Connection %d not found in session %d\n",
1316                                         par->connection_id, par->session_id));
1317                     par->status = ISCSI_STATUS_INVALID_CONNECTION_ID;
1318                     return;
1319           }
1320           if (!conn->c_terminating) {
1321                     mutex_exit(&iscsi_cleanup_mtx);
1322                     DEBC(conn, 0, ("Connection is alive\n"));
1323                     par->status = ISCSI_STATUS_SUCCESS;
1324                     return;
1325           }
1326           mutex_exit(&iscsi_cleanup_mtx);
1327 
1328           if ((par->status = check_login_pars(par)) == 0) {
1329                     recreate_connection(par, sess, conn, l);
1330           }
1331 }
1332 
1333 
1334 #ifndef ISCSI_MINIMAL
1335 
1336 /*
1337  * io_command:
1338  *    Handle the io_command ioctl.
1339  *
1340  *    Parameter:
1341  *          par      IN/OUT: The iocommand parameters
1342  *          l        IN: The lwp pointer of the caller
1343  */
1344 
1345 static void
io_command(iscsi_iocommand_parameters_t * par,struct lwp * l)1346 io_command(iscsi_iocommand_parameters_t *par, struct lwp *l)
1347 {
1348           uint32_t datalen = par->req.datalen;
1349           session_t *session;
1350           void *kbuf = NULL;
1351           int error;
1352 
1353           DEB(9, ("ISCSI: io_command, SID=%d, lun=%" PRIu64 "\n", par->session_id, par->lun));
1354           mutex_enter(&iscsi_cleanup_mtx);
1355           if ((session = find_session(par->session_id)) == NULL) {
1356                     mutex_exit(&iscsi_cleanup_mtx);
1357                     DEBOUT(("Session %d not found\n", par->session_id));
1358                     par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1359                     return;
1360           }
1361           mutex_exit(&iscsi_cleanup_mtx);
1362 
1363           par->req.senselen_used = 0;
1364           par->req.datalen_used = 0;
1365           par->req.error = 0;
1366           par->req.status = 0;
1367           par->req.retsts = SCCMD_UNKNOWN;        /* init to failure code */
1368 
1369           if (par->req.cmdlen > 16 || par->req.senselen > sizeof(par->req.sense)) {
1370                     par->status = ISCSI_STATUS_PARAMETER_INVALID;
1371                     return;
1372           }
1373 
1374           if (datalen) {
1375                     /* Arbitrarily limit datalen to 8k. */
1376                     if (datalen > 8192) {
1377                               par->status = ISCSI_STATUS_PARAMETER_INVALID;
1378                               return;
1379                     }
1380                     kbuf = kmem_zalloc(datalen, KM_SLEEP);
1381                     if ((par->req.flags & SCCMD_WRITE) != 0) {
1382                               error = copyin(par->req.databuf, kbuf, datalen);
1383                               if (error) {
1384                                         kmem_free(kbuf, datalen);
1385                                         par->status = ISCSI_STATUS_PARAMETER_INVALID;
1386                                         return;
1387                               }
1388                     }
1389           }
1390           par->status = send_io_command(session, par->lun, &par->req,
1391                                                                                   par->options.immediate, par->connection_id);
1392 
1393           if (kbuf) {
1394                     if ((par->req.flags & SCCMD_READ) != 0) {
1395                               (void) copyout(kbuf, par->req.databuf, datalen);
1396                     }
1397                     kmem_free(kbuf, datalen);
1398           }
1399           switch (par->status) {
1400           case ISCSI_STATUS_SUCCESS:
1401                     par->req.retsts = SCCMD_OK;
1402                     break;
1403 
1404           case ISCSI_STATUS_TARGET_BUSY:
1405                     par->req.retsts = SCCMD_BUSY;
1406                     break;
1407 
1408           case ISCSI_STATUS_TIMEOUT:
1409           case ISCSI_STATUS_SOCKET_ERROR:
1410                     par->req.retsts = SCCMD_TIMEOUT;
1411                     break;
1412 
1413           default:
1414                     par->req.retsts = (par->req.senselen_used) ? SCCMD_SENSE
1415                                                                                                                            : SCCMD_UNKNOWN;
1416                     break;
1417           }
1418 }
1419 #endif
1420 
1421 /*
1422  * send_targets:
1423  *    Handle the send_targets ioctl.
1424  *    Note: If the passed buffer is too small to hold the complete response,
1425  *    the response is kept in the session structure so it can be
1426  *    retrieved with the next call to this function without having to go to
1427  *    the target again. Once the complete response has been retrieved, it
1428  *    is discarded.
1429  *
1430  *    Parameter:
1431  *          par      IN/OUT: The send_targets parameters
1432  */
1433 
1434 static void
send_targets(iscsi_send_targets_parameters_t * par)1435 send_targets(iscsi_send_targets_parameters_t *par)
1436 {
1437           int rc;
1438           uint32_t rlen, cplen;
1439           session_t *sess;
1440 
1441           mutex_enter(&iscsi_cleanup_mtx);
1442           if ((sess = find_session(par->session_id)) == NULL) {
1443                     mutex_exit(&iscsi_cleanup_mtx);
1444                     DEBOUT(("Session %d not found\n", par->session_id));
1445                     par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1446                     return;
1447           }
1448           mutex_exit(&iscsi_cleanup_mtx);
1449 
1450           DEB(9, ("ISCSI: send_targets, rsp_size=%d; Saved list: %p\n",
1451                               par->response_size, sess->s_target_list));
1452 
1453           if (sess->s_target_list == NULL) {
1454                     rc = send_send_targets(sess, par->key);
1455                     if (rc) {
1456                               par->status = rc;
1457                               return;
1458                     }
1459           }
1460           rlen = sess->s_target_list_len;
1461           par->response_total = rlen;
1462           cplen = min(par->response_size, rlen);
1463           if (cplen) {
1464                     copyout(sess->s_target_list, par->response_buffer, cplen);
1465           }
1466           par->response_used = cplen;
1467 
1468           /* If all of the response was copied, don't keep it around */
1469           if (rlen && par->response_used == rlen) {
1470                     free(sess->s_target_list, M_TEMP);
1471                     sess->s_target_list = NULL;
1472           }
1473 
1474           par->status = ISCSI_STATUS_SUCCESS;
1475 }
1476 
1477 
1478 /*
1479  * set_node_name:
1480  *    Handle the set_node_name ioctl.
1481  *
1482  *    Parameter:
1483  *          par      IN/OUT: The set_node_name parameters
1484  */
1485 
1486 static void
set_node_name(iscsi_set_node_name_parameters_t * par)1487 set_node_name(iscsi_set_node_name_parameters_t *par)
1488 {
1489 
1490           if (strlen(par->InitiatorName) >= ISCSI_STRING_LENGTH ||
1491                     strlen(par->InitiatorAlias) >= ISCSI_STRING_LENGTH) {
1492                     DEBOUT(("*** set_node_name string too long!\n"));
1493                     par->status = ISCSI_STATUS_PARAMETER_INVALID;
1494                     return;
1495           }
1496           strlcpy(iscsi_InitiatorName, par->InitiatorName, sizeof(iscsi_InitiatorName));
1497           strlcpy(iscsi_InitiatorAlias, par->InitiatorAlias, sizeof(iscsi_InitiatorAlias));
1498           memcpy(&iscsi_InitiatorISID, par->ISID, 6);
1499           DEB(5, ("ISCSI: set_node_name, ISID A=%x, B=%x, C=%x, D=%x\n",
1500                               iscsi_InitiatorISID.ISID_A, iscsi_InitiatorISID.ISID_B,
1501                               iscsi_InitiatorISID.ISID_C, iscsi_InitiatorISID.ISID_D));
1502 
1503           if (!iscsi_InitiatorISID.ISID_A && !iscsi_InitiatorISID.ISID_B &&
1504                     !iscsi_InitiatorISID.ISID_C && !iscsi_InitiatorISID.ISID_D) {
1505                     iscsi_InitiatorISID.ISID_A = T_FORMAT_EN;
1506                     iscsi_InitiatorISID.ISID_B = htons(0x1);
1507                     iscsi_InitiatorISID.ISID_C = 0x37;
1508                     iscsi_InitiatorISID.ISID_D = 0;
1509           }
1510 
1511           par->status = ISCSI_STATUS_SUCCESS;
1512 }
1513 
1514 
1515 /*
1516  * connection_status:
1517  *    Handle the connection_status ioctl.
1518  *
1519  *    Parameter:
1520  *          par      IN/OUT: The status parameters
1521  */
1522 
1523 static void
connection_status(iscsi_conn_status_parameters_t * par)1524 connection_status(iscsi_conn_status_parameters_t *par)
1525 {
1526           connection_t *conn;
1527           session_t *sess;
1528 
1529           mutex_enter(&iscsi_cleanup_mtx);
1530           if ((sess = find_session(par->session_id)) == NULL) {
1531                     mutex_exit(&iscsi_cleanup_mtx);
1532                     par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1533                     return;
1534           }
1535 
1536           if (par->connection_id) {
1537                     conn = find_connection(sess, par->connection_id);
1538           } else {
1539                     conn = TAILQ_FIRST(&sess->s_conn_list);
1540           }
1541           par->status = (conn == NULL) ? ISCSI_STATUS_INVALID_CONNECTION_ID :
1542                                                   ISCSI_STATUS_SUCCESS;
1543           mutex_exit(&iscsi_cleanup_mtx);
1544           DEB(9, ("ISCSI: connection_status, session %d connection %d --> %d\n",
1545                               par->session_id, par->connection_id, par->status));
1546 }
1547 
1548 
1549 /*
1550  * get_version:
1551  *    Handle the get_version ioctl.
1552  *
1553  *    Parameter:
1554  *          par      IN/OUT: The version parameters
1555  */
1556 
1557 static void
get_version(iscsi_get_version_parameters_t * par)1558 get_version(iscsi_get_version_parameters_t *par)
1559 {
1560           par->status = ISCSI_STATUS_SUCCESS;
1561           par->interface_version = INTERFACE_VERSION;
1562           par->major = VERSION_MAJOR;
1563           par->minor = VERSION_MINOR;
1564           strlcpy(par->version_string, VERSION_STRING,
1565                     sizeof(par->version_string));
1566 }
1567 
1568 
1569 /* -------------------------------------------------------------------- */
1570 
1571 /*
1572  * kill_all_sessions:
1573  *    Terminate all sessions (called when the driver unloads).
1574  */
1575 
1576 int
kill_all_sessions(void)1577 kill_all_sessions(void)
1578 {
1579           session_t *sess;
1580           int rc = 0;
1581           uint32_t sid;
1582 
1583           mutex_enter(&iscsi_cleanup_mtx);
1584           while ((sess = TAILQ_FIRST(&iscsi_sessions)) != NULL) {
1585                     sid = sess->s_id;
1586                     mutex_exit(&iscsi_cleanup_mtx);
1587                     kill_session(sid, ISCSI_STATUS_DRIVER_UNLOAD, LOGOUT_SESSION,
1588                                         FALSE);
1589                     mutex_enter(&iscsi_cleanup_mtx);
1590           }
1591           if (TAILQ_FIRST(&iscsi_sessions) != NULL) {
1592                     DEBOUT(("Failed to kill all sessions\n"));
1593                     rc = EBUSY;
1594           }
1595           mutex_exit(&iscsi_cleanup_mtx);
1596 
1597           return rc;
1598 }
1599 
1600 /*
1601  * handle_connection_error:
1602  *    Deal with a problem during send or receive.
1603  *
1604  *    Parameter:
1605  *       conn        The connection the problem is associated with
1606  *       status      The status code to insert into any unfinished CCBs
1607  *       dologout    Whether Logout should be attempted
1608  */
1609 
1610 void
handle_connection_error(connection_t * conn,uint32_t status,int dologout)1611 handle_connection_error(connection_t *conn, uint32_t status, int dologout)
1612 {
1613           DEBC(conn, 0, ("*** Connection Error, status=%d, logout=%d, state=%d\n",
1614                                            status, dologout, conn->c_state));
1615 
1616           if (!conn->c_terminating && conn->c_state <= ST_LOGOUT_SENT) {
1617                     /* if we get an error while winding down, escalate it */
1618                     if (dologout >= 0 && conn->c_state >= ST_WINDING_DOWN) {
1619                               dologout = NO_LOGOUT;
1620                     }
1621                     kill_connection(conn, status, dologout, TRUE);
1622           }
1623 }
1624 
1625 /*
1626  * remove a connection from session and add to the cleanup list
1627  */
1628 void
add_connection_cleanup(connection_t * conn)1629 add_connection_cleanup(connection_t *conn)
1630 {
1631           session_t *sess = NULL;
1632 
1633           mutex_enter(&iscsi_cleanup_mtx);
1634           if (conn->c_in_session) {
1635                     sess = conn->c_session;
1636                     conn->c_in_session = FALSE;
1637                     conn->c_session = NULL;
1638                     TAILQ_REMOVE(&sess->s_conn_list, conn, c_connections);
1639                     sess->s_mru_connection = TAILQ_FIRST(&sess->s_conn_list);
1640           }
1641           TAILQ_INSERT_TAIL(&iscsi_cleanupc_list, conn, c_connections);
1642           iscsi_notify_cleanup();
1643           mutex_exit(&iscsi_cleanup_mtx);
1644 }
1645 
1646 /*
1647  * callout wrappers for timeouts, the work is done by the cleanup thread
1648  */
1649 void
connection_timeout_co(void * par)1650 connection_timeout_co(void *par)
1651 {
1652           connection_t *conn = par;
1653 
1654           mutex_enter(&iscsi_cleanup_mtx);
1655           if (conn->c_timedout == TOUT_ARMED) {
1656                     conn->c_timedout = TOUT_QUEUED;
1657                     TAILQ_INSERT_TAIL(&iscsi_timeout_conn_list, conn, c_tchain);
1658                     iscsi_notify_cleanup();
1659           }
1660           mutex_exit(&iscsi_cleanup_mtx);
1661 }
1662 
1663 void
connection_timeout_start(connection_t * conn,int ticks)1664 connection_timeout_start(connection_t *conn, int ticks)
1665 {
1666           mutex_enter(&iscsi_cleanup_mtx);
1667           if (conn->c_timedout != TOUT_QUEUED) {
1668                     conn->c_timedout = TOUT_ARMED;
1669                     callout_schedule(&conn->c_timeout, ticks);
1670           }
1671           mutex_exit(&iscsi_cleanup_mtx);
1672 }
1673 
1674 void
connection_timeout_stop(connection_t * conn)1675 connection_timeout_stop(connection_t *conn)
1676 {
1677           callout_stop(&conn->c_timeout);
1678           mutex_enter(&iscsi_cleanup_mtx);
1679           if (conn->c_timedout == TOUT_QUEUED)
1680                     TAILQ_REMOVE(&iscsi_timeout_conn_list, conn, c_tchain);
1681           if (curlwp != iscsi_cleanproc) {
1682                     while (conn->c_timedout == TOUT_BUSY)
1683                               kpause("connbusy", false, 1, &iscsi_cleanup_mtx);
1684           }
1685           conn->c_timedout = TOUT_NONE;
1686           mutex_exit(&iscsi_cleanup_mtx);
1687 }
1688 
1689 void
ccb_timeout_co(void * par)1690 ccb_timeout_co(void *par)
1691 {
1692           ccb_t *ccb = par;
1693 
1694           mutex_enter(&iscsi_cleanup_mtx);
1695           if (ccb->ccb_timedout == TOUT_ARMED) {
1696                     ccb->ccb_timedout = TOUT_QUEUED;
1697                     TAILQ_INSERT_TAIL(&iscsi_timeout_ccb_list, ccb, ccb_tchain);
1698                     iscsi_notify_cleanup();
1699           }
1700           mutex_exit(&iscsi_cleanup_mtx);
1701 }
1702 
1703 void
ccb_timeout_start(ccb_t * ccb,int ticks)1704 ccb_timeout_start(ccb_t *ccb, int ticks)
1705 {
1706           mutex_enter(&iscsi_cleanup_mtx);
1707           if (ccb->ccb_timedout != TOUT_QUEUED) {
1708                     ccb->ccb_timedout = TOUT_ARMED;
1709                     callout_schedule(&ccb->ccb_timeout, ticks);
1710           }
1711           mutex_exit(&iscsi_cleanup_mtx);
1712 }
1713 
1714 void
ccb_timeout_stop(ccb_t * ccb)1715 ccb_timeout_stop(ccb_t *ccb)
1716 {
1717           callout_stop(&ccb->ccb_timeout);
1718           mutex_enter(&iscsi_cleanup_mtx);
1719           if (ccb->ccb_timedout == TOUT_QUEUED)
1720                     TAILQ_REMOVE(&iscsi_timeout_ccb_list, ccb, ccb_tchain);
1721           if (curlwp != iscsi_cleanproc) {
1722                     while (ccb->ccb_timedout == TOUT_BUSY)
1723                               kpause("ccbbusy", false, 1, &iscsi_cleanup_mtx);
1724           }
1725           ccb->ccb_timedout = TOUT_NONE;
1726           mutex_exit(&iscsi_cleanup_mtx);
1727 }
1728 
1729 /*
1730  * iscsi_cleanup_thread
1731  *    Global thread to handle connection and session cleanup after termination.
1732  */
1733 
1734 static void
iscsi_cleanup_thread(void * par)1735 iscsi_cleanup_thread(void *par)
1736 {
1737           int s, rc;
1738           session_t *sess, *nxts;
1739           connection_t *conn, *nxtc;
1740           ccb_t *ccb;
1741 
1742           mutex_enter(&iscsi_cleanup_mtx);
1743           while (iscsi_num_send_threads || !iscsi_detaching ||
1744                  !TAILQ_EMPTY(&iscsi_cleanupc_list) || !TAILQ_EMPTY(&iscsi_cleanups_list)) {
1745                     TAILQ_FOREACH_SAFE(conn, &iscsi_cleanupc_list, c_connections, nxtc) {
1746 
1747                               TAILQ_REMOVE(&iscsi_cleanupc_list, conn, c_connections);
1748                               mutex_exit(&iscsi_cleanup_mtx);
1749 
1750                               sess = conn->c_session;
1751 
1752                               /*
1753                                * This implies that connection cleanup only runs when
1754                                * the send/recv threads have been killed
1755                                */
1756                               DEBC(conn, 5, ("Cleanup: Waiting for threads to exit\n"));
1757 
1758                               mutex_enter(&conn->c_lock);
1759                               while (conn->c_sendproc || conn->c_rcvproc)
1760                                         kpause("threads", false, hz, &conn->c_lock);
1761 
1762                               for (s=1; conn->c_usecount > 0 && s < 3; ++s)
1763                                         kpause("usecount", false, hz, &conn->c_lock);
1764 
1765                               if (conn->c_usecount > 0) {
1766                                         DEBC(conn, 5, ("Cleanup: %d CCBs busy\n", conn->c_usecount));
1767                                         mutex_exit(&conn->c_lock);
1768                                         /* retry later */
1769                                         mutex_enter(&iscsi_cleanup_mtx);
1770                                         TAILQ_INSERT_HEAD(&iscsi_cleanupc_list, conn, c_connections);
1771                                         continue;
1772                               }
1773                               mutex_exit(&conn->c_lock);
1774 
1775                               KASSERT(!conn->c_in_session);
1776 
1777                               callout_halt(&conn->c_timeout, NULL);
1778                               closef(conn->c_sock);
1779                               callout_destroy(&conn->c_timeout);
1780                               rw_destroy(&conn->c_sock_rw);
1781                               cv_destroy(&conn->c_idle_cv);
1782                               cv_destroy(&conn->c_ccb_cv);
1783                               cv_destroy(&conn->c_pdu_cv);
1784                               cv_destroy(&conn->c_conn_cv);
1785                               mutex_destroy(&conn->c_lock);
1786                               free(conn, M_DEVBUF);
1787 
1788                               mutex_enter(&iscsi_cleanup_mtx);
1789 
1790                               if (--sess->s_total_connections == 0) {
1791                                         DEB(1, ("Cleanup: session %d\n", sess->s_id));
1792                                         if (!sess->s_terminating) {
1793                                                   sess->s_terminating = ISCSI_CONNECTION_TERMINATED;
1794                                                   KASSERT(sess->s_sessions.tqe_prev != NULL);
1795                                                   TAILQ_REMOVE(&iscsi_sessions, sess, s_sessions);
1796                                                   sess->s_sessions.tqe_next = NULL;
1797                                                   sess->s_sessions.tqe_prev = NULL;
1798                                         }
1799                                         KASSERT(sess->s_sessions.tqe_prev == NULL);
1800                                         TAILQ_INSERT_HEAD(&iscsi_cleanups_list, sess, s_sessions);
1801                               }
1802                     }
1803 
1804                     TAILQ_FOREACH_SAFE(sess, &iscsi_cleanups_list, s_sessions, nxts) {
1805                               if (sess->s_refcount > 0)
1806                                         continue;
1807                               TAILQ_REMOVE(&iscsi_cleanups_list, sess, s_sessions);
1808                               sess->s_sessions.tqe_next = NULL;
1809                               sess->s_sessions.tqe_prev = NULL;
1810                               mutex_exit(&iscsi_cleanup_mtx);
1811 
1812                               DEB(1, ("Cleanup: Unmap session %d\n", sess->s_id));
1813                               if (unmap_session(sess) == 0) {
1814                                         DEB(1, ("Cleanup: Unmap session %d failed\n", sess->s_id));
1815                                         mutex_enter(&iscsi_cleanup_mtx);
1816                                         TAILQ_INSERT_HEAD(&iscsi_cleanups_list, sess, s_sessions);
1817                                         continue;
1818                               }
1819 
1820                               if (sess->s_target_list != NULL)
1821                                         free(sess->s_target_list, M_TEMP);
1822 
1823                               /* notify event handlers of session shutdown */
1824                               add_event(ISCSI_SESSION_TERMINATED, sess->s_id, 0, sess->s_terminating);
1825                               DEB(1, ("Cleanup: session ended %d\n", sess->s_id));
1826 
1827                               destroy_ccbs(sess);
1828                               cv_destroy(&sess->s_ccb_cv);
1829                               cv_destroy(&sess->s_sess_cv);
1830                               mutex_destroy(&sess->s_lock);
1831                               free(sess, M_DEVBUF);
1832 
1833                               mutex_enter(&iscsi_cleanup_mtx);
1834                     }
1835 
1836                     /* handle ccb timeouts */
1837                     while ((ccb = TAILQ_FIRST(&iscsi_timeout_ccb_list)) != NULL) {
1838                               TAILQ_REMOVE(&iscsi_timeout_ccb_list, ccb, ccb_tchain);
1839                               KASSERT(ccb->ccb_timedout == TOUT_QUEUED);
1840                               ccb->ccb_timedout = TOUT_BUSY;
1841                               mutex_exit(&iscsi_cleanup_mtx);
1842                               ccb_timeout(ccb);
1843                               mutex_enter(&iscsi_cleanup_mtx);
1844                               if (ccb->ccb_timedout == TOUT_BUSY)
1845                                         ccb->ccb_timedout = TOUT_NONE;
1846                     }
1847 
1848                     /* handle connection timeouts */
1849                     while ((conn = TAILQ_FIRST(&iscsi_timeout_conn_list)) != NULL) {
1850                               TAILQ_REMOVE(&iscsi_timeout_conn_list, conn, c_tchain);
1851                               KASSERT(conn->c_timedout == TOUT_QUEUED);
1852                               conn->c_timedout = TOUT_BUSY;
1853                               mutex_exit(&iscsi_cleanup_mtx);
1854                               connection_timeout(conn);
1855                               mutex_enter(&iscsi_cleanup_mtx);
1856                               if (conn->c_timedout == TOUT_BUSY)
1857                                         conn->c_timedout = TOUT_NONE;
1858                     }
1859 
1860                     /* Go to sleep, but wake up every 120 seconds to
1861                      * check for dead event handlers */
1862                     rc = cv_timedwait(&iscsi_cleanup_cv, &iscsi_cleanup_mtx,
1863                               (TAILQ_FIRST(&event_handlers)) ? 120 * hz : 0);
1864 
1865                     /* if timed out, not woken up */
1866                     if (rc == EWOULDBLOCK)
1867                               check_event_handlers();
1868           }
1869           mutex_exit(&iscsi_cleanup_mtx);
1870 
1871           add_event(ISCSI_DRIVER_TERMINATING, 0, 0, ISCSI_STATUS_DRIVER_UNLOAD);
1872 
1873           /*
1874            * Wait for all event handlers to deregister, but don't wait more
1875            * than 1 minute (assume registering app has died if it takes longer).
1876            */
1877           mutex_enter(&iscsi_cleanup_mtx);
1878           for (s = 0; TAILQ_FIRST(&event_handlers) != NULL && s < 60; s++)
1879                     kpause("waiteventclr", true, hz, &iscsi_cleanup_mtx);
1880           mutex_exit(&iscsi_cleanup_mtx);
1881 
1882           iscsi_cleanproc = NULL;
1883           DEB(5, ("Cleanup thread exits\n"));
1884           kthread_exit(0);
1885 }
1886 
1887 void
iscsi_init_cleanup(void)1888 iscsi_init_cleanup(void)
1889 {
1890 
1891           mutex_init(&iscsi_cleanup_mtx, MUTEX_DEFAULT, IPL_BIO);
1892           cv_init(&iscsi_cleanup_cv, "cleanup");
1893           cv_init(&iscsi_event_cv, "iscsievtwait");
1894 
1895           if (kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, iscsi_cleanup_thread,
1896               NULL, &iscsi_cleanproc, "iscsi_cleanup") != 0) {
1897                     panic("Can't create cleanup thread!");
1898           }
1899 }
1900 
1901 int
iscsi_destroy_cleanup(void)1902 iscsi_destroy_cleanup(void)
1903 {
1904 
1905           iscsi_detaching = true;
1906           mutex_enter(&iscsi_cleanup_mtx);
1907           while (iscsi_cleanproc != NULL) {
1908                     iscsi_notify_cleanup();
1909                     kpause("detach_wait", false, hz, &iscsi_cleanup_mtx);
1910           }
1911           mutex_exit(&iscsi_cleanup_mtx);
1912 
1913           cv_destroy(&iscsi_event_cv);
1914           cv_destroy(&iscsi_cleanup_cv);
1915           mutex_destroy(&iscsi_cleanup_mtx);
1916 
1917           return 0;
1918 }
1919 
1920 void
iscsi_notify_cleanup(void)1921 iscsi_notify_cleanup(void)
1922 {
1923           KASSERT(mutex_owned(&iscsi_cleanup_mtx));
1924 
1925           cv_signal(&iscsi_cleanup_cv);
1926 }
1927 
1928 
1929 /* -------------------------------------------------------------------- */
1930 
1931 /*
1932  * iscsi_ioctl:
1933  *    Driver ioctl entry.
1934  *
1935  *    Parameter:
1936  *       file     File structure
1937  *       cmd      The ioctl Command
1938  *       addr     IN/OUT: The command parameter
1939  *       flag     Flags (ignored)
1940  *       l        IN: The lwp object of the caller
1941  */
1942 
1943 int
iscsiioctl(struct file * fp,u_long cmd,void * addr)1944 iscsiioctl(struct file *fp, u_long cmd, void *addr)
1945 {
1946           struct lwp *l = curlwp;
1947           struct iscsifd *d = fp->f_iscsi;
1948 
1949           DEB(1, ("ISCSI Ioctl cmd = %x\n", (int) cmd));
1950 
1951           switch (cmd) {
1952           case ISCSI_GET_VERSION:
1953                     get_version((iscsi_get_version_parameters_t *) addr);
1954                     break;
1955 
1956           case ISCSI_LOGIN:
1957                     login((iscsi_login_parameters_t *) addr, l, d->fd_dev);
1958                     break;
1959 
1960           case ISCSI_ADD_CONNECTION:
1961                     add_connection((iscsi_login_parameters_t *) addr, l);
1962                     break;
1963 
1964           case ISCSI_RESTORE_CONNECTION:
1965                     restore_connection((iscsi_login_parameters_t *) addr, l);
1966                     break;
1967 
1968           case ISCSI_LOGOUT:
1969                     logout((iscsi_logout_parameters_t *) addr);
1970                     break;
1971 
1972           case ISCSI_REMOVE_CONNECTION:
1973                     remove_connection((iscsi_remove_parameters_t *) addr);
1974                     break;
1975 
1976 #ifndef ISCSI_MINIMAL
1977           case ISCSI_IO_COMMAND:
1978                     io_command((iscsi_iocommand_parameters_t *) addr, l);
1979                     break;
1980 #endif
1981 
1982           case ISCSI_SEND_TARGETS:
1983                     send_targets((iscsi_send_targets_parameters_t *) addr);
1984                     break;
1985 
1986           case ISCSI_SET_NODE_NAME:
1987                     set_node_name((iscsi_set_node_name_parameters_t *) addr);
1988                     break;
1989 
1990           case ISCSI_CONNECTION_STATUS:
1991                     connection_status((iscsi_conn_status_parameters_t *) addr);
1992                     break;
1993 
1994           case ISCSI_REGISTER_EVENT:
1995                     register_event((iscsi_register_event_parameters_t *) addr);
1996                     break;
1997 
1998           case ISCSI_DEREGISTER_EVENT:
1999                     deregister_event((iscsi_register_event_parameters_t *) addr);
2000                     break;
2001 
2002           case ISCSI_WAIT_EVENT:
2003                     check_event((iscsi_wait_event_parameters_t *) addr, TRUE);
2004                     break;
2005 
2006           case ISCSI_POLL_EVENT:
2007                     check_event((iscsi_wait_event_parameters_t *) addr, FALSE);
2008                     break;
2009 
2010           default:
2011                     DEBOUT(("Invalid IO-Control Code\n"));
2012                     return ENOTTY;
2013           }
2014 
2015     /*
2016      * NOTE: We return 0 even if the function fails as long as the ioctl code
2017      * is good, so the status code is copied back to the caller.
2018            */
2019           return 0;
2020 }
2021