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