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