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