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