1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * iSCSI session interfaces 26 */ 27 28 #include <sys/bootprops.h> 29 #include "iscsi.h" 30 #include "persistent.h" 31 #include "iscsi_targetparam.h" 32 33 #define ISCSI_SESS_ENUM_TIMEOUT_DEFAULT 60 34 #define SCSI_INQUIRY_PQUAL_MASK 0xE0 35 36 /* 37 * used to store report lun information found 38 * 39 * lun_valid: if TRUE means the entry contains a valid entry 40 * lun_found: if TRUE means the lun has been found in the sess_lun_list 41 * lun_num: contains the lun_number 42 */ 43 typedef struct replun_data { 44 boolean_t lun_valid; 45 boolean_t lun_found; 46 uint16_t lun_num; 47 } replun_data_t; 48 49 int iscsi_sess_enum_timeout = ISCSI_SESS_ENUM_TIMEOUT_DEFAULT; 50 51 /* 52 * The following private tunable, settable via 53 * set iscsi:iscsi_sess_max_delay = 64 54 * in /etc/system, provides customer relief for configurations max interval in 55 * seconds of retry for a unreachable target during the login. 56 */ 57 int iscsi_sess_max_delay = ISCSI_DEFAULT_MAX_STORM_DELAY; 58 59 /* internal interfaces */ 60 /* LINTED E_STATIC_UNUSED */ 61 static iscsi_sess_t *iscsi_sess_alloc(iscsi_hba_t *ihp, iscsi_sess_type_t type); 62 static char *iscsi_sess_event_str(iscsi_sess_event_t event); 63 static iscsi_status_t iscsi_sess_threads_create(iscsi_sess_t *isp); 64 static void iscsi_sess_flush(iscsi_sess_t *isp); 65 static void iscsi_sess_offline_luns(iscsi_sess_t *isp); 66 static iscsi_status_t retrieve_lundata(uint32_t lun_count, unsigned char *buf, 67 iscsi_sess_t *isp, uint16_t *lun_data, uint8_t *lun_addr_type); 68 69 /* internal state machine interfaces */ 70 static void iscsi_sess_state_free(iscsi_sess_t *isp, 71 iscsi_sess_event_t event); 72 static void iscsi_sess_state_logged_in(iscsi_sess_t *isp, 73 iscsi_sess_event_t event); 74 static void iscsi_sess_state_failed(iscsi_sess_t *isp, 75 iscsi_sess_event_t event); 76 static void iscsi_sess_state_in_flush(iscsi_sess_t *isp, 77 iscsi_sess_event_t event); 78 static void iscsi_sess_state_flushed(iscsi_sess_t *isp, 79 iscsi_sess_event_t event); 80 81 /* internal enumeration interfaces */ 82 static void iscsi_sess_enumeration(void *arg); 83 static iscsi_status_t iscsi_sess_testunitready(iscsi_sess_t *isp); 84 static iscsi_status_t iscsi_sess_reportluns(iscsi_sess_t *isp); 85 static void iscsi_sess_inquiry(iscsi_sess_t *isp, uint16_t lun_num, 86 uint8_t lun_addr_type); 87 88 /* 89 * +--------------------------------------------------------------------+ 90 * | External Session Interfaces | 91 * +--------------------------------------------------------------------+ 92 */ 93 iscsi_sess_t * 94 iscsi_sess_create(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t method, 95 struct sockaddr *addr_dsc, char *target_name, int tpgt, uchar_t isid_lsb, 96 iscsi_sess_type_t type, uint32_t *oid) 97 { 98 iscsi_sess_t *isp = NULL; 99 int len = 0; 100 char *tq_name; 101 char *th_name; 102 103 len = strlen(target_name); 104 105 clean_failed_sess: 106 if (isp != NULL) { 107 (void) iscsi_sess_destroy(isp); 108 } 109 110 for (isp = ihp->hba_sess_list; isp; isp = isp->sess_next) { 111 /* Match target name and LSB ISID */ 112 if ((strcmp((char *)isp->sess_name, target_name) == 0) && 113 (isp->sess_isid[5] == isid_lsb)) { 114 115 /* Match TPGT */ 116 if (isp->sess_tpgt_conf == tpgt) { 117 /* Found mathing session, return oid/ptr */ 118 *oid = isp->sess_oid; 119 if (isp->sess_wd_thread) 120 return (isp); 121 /* 122 * Under rare cases wd thread is already 123 * freed, create it if so. 124 */ 125 th_name = kmem_zalloc(ISCSI_TH_MAX_NAME_LEN, 126 KM_SLEEP); 127 if (snprintf(th_name, (ISCSI_TH_MAX_NAME_LEN 128 - 1), ISCSI_SESS_WD_NAME_FORMAT, 129 ihp->hba_oid, isp->sess_oid) < 130 ISCSI_TH_MAX_NAME_LEN) { 131 isp->sess_wd_thread = 132 iscsi_thread_create(ihp->hba_dip, 133 th_name, iscsi_wd_thread, isp); 134 (void) iscsi_thread_start( 135 isp->sess_wd_thread); 136 } 137 kmem_free(th_name, ISCSI_TH_MAX_NAME_LEN); 138 if (isp->sess_wd_thread == NULL) { 139 /* No way to save it */ 140 goto clean_failed_sess; 141 } 142 return (isp); 143 } 144 145 /* 146 * Also protect against creating duplicate 147 * sessions with different configured tpgt 148 * values. default vs. defined. 149 */ 150 if ((((isp->sess_tpgt_conf == ISCSI_DEFAULT_TPGT) && 151 (tpgt != ISCSI_DEFAULT_TPGT)) || 152 ((isp->sess_tpgt_conf != ISCSI_DEFAULT_TPGT) && 153 (tpgt == ISCSI_DEFAULT_TPGT)))) { 154 /* Dangerous configuration. Fail Request */ 155 return (NULL); 156 } 157 } 158 } 159 160 isp = (iscsi_sess_t *)kmem_zalloc(sizeof (iscsi_sess_t), KM_SLEEP); 161 /* 162 * If this session is not a Send Targets session, set the target 163 * that this session is associated with. 164 */ 165 if (strncmp(target_name, SENDTARGETS_DISCOVERY, 166 strlen(SENDTARGETS_DISCOVERY))) { 167 isp->sess_target_oid = iscsi_targetparam_get_oid( 168 (uchar_t *)target_name); 169 } 170 171 if (method & iSCSIDiscoveryMethodBoot) { 172 /* This is boot session. */ 173 isp->sess_boot = B_TRUE; 174 } else { 175 isp->sess_boot = B_FALSE; 176 } 177 178 /* Associate session with this discovery method */ 179 method = method & ~(iSCSIDiscoveryMethodBoot); 180 181 isp->sess_discovered_by = method; 182 if (addr_dsc == NULL) { 183 bzero(&isp->sess_discovered_addr, 184 sizeof (isp->sess_discovered_addr)); 185 } else { 186 bcopy(addr_dsc, &isp->sess_discovered_addr, 187 SIZEOF_SOCKADDR(addr_dsc)); 188 } 189 190 /* assign unique key for the session */ 191 mutex_enter(&iscsi_oid_mutex); 192 isp->sess_oid = iscsi_oid++; 193 *oid = isp->sess_oid; 194 mutex_exit(&iscsi_oid_mutex); 195 196 /* setup session parameters */ 197 isp->sess_name_length = 0; 198 isp->sess_sig = ISCSI_SIG_SESS; 199 isp->sess_state = ISCSI_SESS_STATE_FREE; 200 mutex_init(&isp->sess_state_mutex, NULL, MUTEX_DRIVER, NULL); 201 isp->sess_hba = ihp; 202 isp->sess_enum_in_progress = B_FALSE; 203 204 isp->sess_isid[0] = ISCSI_SUN_ISID_0; 205 isp->sess_isid[1] = ISCSI_SUN_ISID_1; 206 isp->sess_isid[2] = ISCSI_SUN_ISID_2; 207 isp->sess_isid[3] = ISCSI_SUN_ISID_3; 208 isp->sess_isid[4] = 0; 209 isp->sess_isid[5] = isid_lsb; 210 211 isp->sess_cmdsn = 1; 212 isp->sess_expcmdsn = 1; 213 isp->sess_maxcmdsn = 1; 214 isp->sess_last_err = NoError; 215 isp->sess_tsid = 0; 216 isp->sess_type = type; 217 218 /* copy default driver login parameters */ 219 bcopy(&ihp->hba_params, &isp->sess_params, 220 sizeof (iscsi_login_params_t)); 221 222 /* copy target name into session */ 223 bcopy((char *)target_name, isp->sess_name, len); 224 isp->sess_name_length = len; 225 isp->sess_tpgt_conf = tpgt; 226 isp->sess_tpgt_nego = ISCSI_DEFAULT_TPGT; 227 228 /* initialize pending and completion queues */ 229 iscsi_init_queue(&isp->sess_queue_pending); 230 iscsi_init_queue(&isp->sess_queue_completion); 231 232 /* setup sessions lun list */ 233 isp->sess_lun_list = NULL; 234 rw_init(&isp->sess_lun_list_rwlock, NULL, RW_DRIVER, NULL); 235 236 /* setup sessions connection list */ 237 isp->sess_conn_act = NULL; 238 isp->sess_conn_list = NULL; 239 rw_init(&isp->sess_conn_list_rwlock, NULL, RW_DRIVER, NULL); 240 241 mutex_init(&isp->sess_cmdsn_mutex, NULL, MUTEX_DRIVER, NULL); 242 243 /* create the session task queue */ 244 tq_name = kmem_zalloc(ISCSI_TH_MAX_NAME_LEN, KM_SLEEP); 245 if (snprintf(tq_name, (ISCSI_TH_MAX_NAME_LEN - 1), 246 ISCSI_SESS_LOGIN_TASKQ_NAME_FORMAT, ihp->hba_oid, isp->sess_oid) < 247 ISCSI_TH_MAX_NAME_LEN) { 248 isp->sess_taskq = ddi_taskq_create(ihp->hba_dip, 249 tq_name, 1, TASKQ_DEFAULTPRI, 0); 250 } 251 kmem_free(tq_name, ISCSI_TH_MAX_NAME_LEN); 252 if (isp->sess_taskq == NULL) { 253 goto iscsi_sess_cleanup2; 254 } 255 256 /* startup watchdog */ 257 th_name = kmem_zalloc(ISCSI_TH_MAX_NAME_LEN, KM_SLEEP); 258 if (snprintf(th_name, (ISCSI_TH_MAX_NAME_LEN - 1), 259 ISCSI_SESS_WD_NAME_FORMAT, ihp->hba_oid, isp->sess_oid) < 260 ISCSI_TH_MAX_NAME_LEN) { 261 isp->sess_wd_thread = iscsi_thread_create(ihp->hba_dip, 262 th_name, iscsi_wd_thread, isp); 263 (void) iscsi_thread_start(isp->sess_wd_thread); 264 } 265 kmem_free(th_name, ISCSI_TH_MAX_NAME_LEN); 266 if (isp->sess_wd_thread == NULL) { 267 goto iscsi_sess_cleanup1; 268 } 269 270 /* Add new target to the hba target list */ 271 if (ihp->hba_sess_list == NULL) { 272 ihp->hba_sess_list = isp; 273 } else { 274 isp->sess_next = ihp->hba_sess_list; 275 ihp->hba_sess_list = isp; 276 } 277 KSTAT_INC_HBA_CNTR_SESS(ihp); 278 279 (void) iscsi_sess_kstat_init(isp); 280 281 return (isp); 282 283 iscsi_sess_cleanup1: 284 ddi_taskq_destroy(isp->sess_taskq); 285 iscsi_sess_cleanup2: 286 mutex_destroy(&isp->sess_cmdsn_mutex); 287 rw_destroy(&isp->sess_conn_list_rwlock); 288 rw_destroy(&isp->sess_lun_list_rwlock); 289 iscsi_destroy_queue(&isp->sess_queue_completion); 290 iscsi_destroy_queue(&isp->sess_queue_pending); 291 mutex_destroy(&isp->sess_state_mutex); 292 kmem_free(isp, sizeof (iscsi_sess_t)); 293 294 return (NULL); 295 } 296 297 /* 298 * iscsi_sess_get - return the session structure for based on a 299 * passed in oid and hba instance. 300 */ 301 int 302 iscsi_sess_get(uint32_t oid, iscsi_hba_t *ihp, iscsi_sess_t **ispp) 303 { 304 int rval = 0; 305 iscsi_sess_t *isp = NULL; 306 307 ASSERT(ihp != NULL); 308 ASSERT(ispp != NULL); 309 310 /* See if we already created this session */ 311 for (isp = ihp->hba_sess_list; isp; isp = isp->sess_next) { 312 /* compare target name as the unique identifier */ 313 if (isp->sess_oid == oid) { 314 /* Found matching session */ 315 break; 316 } 317 } 318 319 /* If not null this session is already available */ 320 if (isp != NULL) { 321 /* Existing session, return it */ 322 *ispp = isp; 323 } else { 324 rval = EFAULT; 325 } 326 return (rval); 327 } 328 329 /* 330 * iscsi_sess_online - initiate online of sessions connections 331 */ 332 void 333 iscsi_sess_online(void *arg) 334 { 335 iscsi_sess_t *isp; 336 iscsi_hba_t *ihp; 337 iscsi_conn_t *icp; 338 int idx; 339 340 isp = (iscsi_sess_t *)arg; 341 342 ASSERT(isp != NULL); 343 ihp = isp->sess_hba; 344 ASSERT(ihp != NULL); 345 346 /* 347 * Stale /dev links can cause us to get floods 348 * of config requests. To prevent these repeated 349 * requests from causing unneeded login to the 350 * unreachable target, we won't try it during 351 * the delay. 352 */ 353 if (ddi_get_lbolt() < isp->sess_failure_lbolt + 354 SEC_TO_TICK(isp->sess_storm_delay)) { 355 return; 356 } 357 358 /* 359 * Perform a crude version of round robin to 360 * determine which connection to use for 361 * this session. Since byte 5 in session ID 362 * is overridden for full feature session, 363 * the connection to be selected depends on 364 * the result of sess_isid[5] devided by the 365 * next connection ID. 366 * If MS/T is enabled and there are multiple 367 * IPs are available on the target, we can 368 * select different IPs to connect in this 369 * way. 370 */ 371 icp = isp->sess_conn_act; 372 if (icp == NULL) { 373 icp = isp->sess_conn_list; 374 for (idx = 0; idx < (isp->sess_isid[5] % 375 isp->sess_conn_next_cid); idx++) { 376 ASSERT(icp->conn_next != NULL); 377 icp = icp->conn_next; 378 } 379 isp->sess_conn_act = icp; 380 } 381 382 if (icp == NULL) { 383 cmn_err(CE_NOTE, "iscsi session(%d) - " 384 "no connection assigned", isp->sess_oid); 385 return; 386 } 387 388 /* 389 * If connection is in free state, start 390 * login. If already logged in, try to 391 * re-enumerate LUs on the session. 392 */ 393 mutex_enter(&icp->conn_state_mutex); 394 if (icp->conn_state == ISCSI_CONN_STATE_FREE) { 395 /* 396 * attempt to login into the first connection in our connection 397 * list. If this fails, we will try the next connection 398 * in our list until end of the list. 399 */ 400 while (icp != NULL) { 401 if (iscsi_conn_state_machine( 402 icp, ISCSI_CONN_EVENT_T1) == 403 ISCSI_STATUS_SUCCESS) { 404 mutex_exit(&icp->conn_state_mutex); 405 break; 406 } else { 407 mutex_exit(&icp->conn_state_mutex); 408 icp = icp->conn_next; 409 if (icp != NULL) { 410 mutex_enter(&icp->conn_state_mutex); 411 } 412 } 413 } 414 isp->sess_conn_act = icp; 415 if (icp == NULL) { 416 /* the target for this session is unreachable */ 417 isp->sess_failure_lbolt = ddi_get_lbolt(); 418 if (isp->sess_storm_delay == 0) { 419 isp->sess_storm_delay++; 420 } else { 421 422 if ((isp->sess_storm_delay * 2) < 423 iscsi_sess_max_delay) { 424 isp->sess_storm_delay = 425 isp->sess_storm_delay * 2; 426 } else { 427 isp->sess_storm_delay = 428 iscsi_sess_max_delay; 429 } 430 } 431 432 } else { 433 isp->sess_storm_delay = 0; 434 isp->sess_failure_lbolt = 0; 435 } 436 } else if (icp->conn_state == ISCSI_CONN_STATE_LOGGED_IN) { 437 mutex_exit(&icp->conn_state_mutex); 438 mutex_enter(&isp->sess_state_mutex); 439 iscsi_sess_state_machine(isp, 440 ISCSI_SESS_EVENT_N1); 441 mutex_exit(&isp->sess_state_mutex); 442 } else { 443 mutex_exit(&icp->conn_state_mutex); 444 } 445 } 446 447 /* 448 * iscsi_sess_destroy - Destroys a iscsi session structure 449 * and de-associates it from the hba. 450 */ 451 iscsi_status_t 452 iscsi_sess_destroy(iscsi_sess_t *isp) 453 { 454 iscsi_status_t rval = ISCSI_STATUS_SUCCESS; 455 iscsi_status_t tmprval = ISCSI_STATUS_SUCCESS; 456 iscsi_hba_t *ihp; 457 iscsi_sess_t *t_isp; 458 iscsi_lun_t *ilp; 459 iscsi_conn_t *icp; 460 461 ASSERT(isp != NULL); 462 ihp = isp->sess_hba; 463 ASSERT(ihp != NULL); 464 465 /* 466 * The first step in tearing down the session 467 * has to be offlining all the LUNs. This will 468 * ensure there is no outstanding IO by upper 469 * level drivers. If this fails then we are 470 * unable to destroy the session. 471 * 472 * Try all luns and continue upon failure 473 * to remove what is removable before returning 474 * the last error. 475 */ 476 rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER); 477 ilp = isp->sess_lun_list; 478 while (ilp != NULL) { 479 iscsi_lun_t *ilp_next = ilp->lun_next; 480 481 tmprval = iscsi_lun_destroy(ihp, ilp); 482 if (!ISCSI_SUCCESS(tmprval)) { 483 rval = tmprval; 484 } 485 ilp = ilp_next; 486 } 487 rw_exit(&isp->sess_lun_list_rwlock); 488 489 if (!ISCSI_SUCCESS(rval)) { 490 return (rval); 491 } 492 493 /* The next step is to logout of the connections. */ 494 icp = isp->sess_conn_list; 495 while (icp != NULL) { 496 rval = iscsi_conn_offline(icp); 497 if (ISCSI_SUCCESS(rval)) { 498 /* Succes, Continue processing... */ 499 icp = icp->conn_next; 500 } else { 501 /* Failure, Stop processing... */ 502 rw_exit(&isp->sess_conn_list_rwlock); 503 return (rval); 504 } 505 } 506 507 /* 508 * At this point all connections should be in 509 * a FREE state which will have pushed the session 510 * to a FREE state. 511 */ 512 ASSERT(isp->sess_state == ISCSI_SESS_STATE_FREE); 513 514 /* Stop watchdog before destroying connections */ 515 if (isp->sess_wd_thread) { 516 iscsi_thread_destroy(isp->sess_wd_thread); 517 isp->sess_wd_thread = NULL; 518 } 519 520 /* Destroy connections */ 521 rw_enter(&isp->sess_conn_list_rwlock, RW_WRITER); 522 icp = isp->sess_conn_list; 523 while (icp != NULL) { 524 rval = iscsi_conn_destroy(icp); 525 if (!ISCSI_SUCCESS(rval)) { 526 rw_exit(&isp->sess_conn_list_rwlock); 527 return (rval); 528 } 529 icp = isp->sess_conn_list; 530 } 531 rw_exit(&isp->sess_conn_list_rwlock); 532 533 /* Destroy session task queue */ 534 ddi_taskq_destroy(isp->sess_taskq); 535 536 /* destroy pending and completion queues */ 537 iscsi_destroy_queue(&isp->sess_queue_pending); 538 iscsi_destroy_queue(&isp->sess_queue_completion); 539 540 /* Remove session from ihp */ 541 if (ihp->hba_sess_list == isp) { 542 /* session first item in list */ 543 ihp->hba_sess_list = isp->sess_next; 544 } else { 545 /* 546 * search hba list for isp pointing 547 * to session being removed. Then 548 * update that sessions next pointer. 549 */ 550 t_isp = ihp->hba_sess_list; 551 while (t_isp->sess_next != NULL) { 552 if (t_isp->sess_next == isp) { 553 break; 554 } 555 t_isp = t_isp->sess_next; 556 } 557 if (t_isp->sess_next == isp) { 558 t_isp->sess_next = isp->sess_next; 559 } else { 560 /* couldn't find session */ 561 ASSERT(FALSE); 562 } 563 } 564 565 /* Destroy this Sessions Data */ 566 (void) iscsi_sess_kstat_term(isp); 567 rw_destroy(&isp->sess_lun_list_rwlock); 568 rw_destroy(&isp->sess_conn_list_rwlock); 569 mutex_destroy(&isp->sess_cmdsn_mutex); 570 mutex_destroy(&isp->sess_state_mutex); 571 kmem_free(isp, sizeof (iscsi_sess_t)); 572 573 return (rval); 574 } 575 576 extern ib_boot_prop_t *iscsiboot_prop; 577 /* 578 * static iscsi_sess_set_auth - 579 * 580 */ 581 boolean_t 582 iscsi_sess_set_auth(iscsi_sess_t *isp) 583 { 584 char *init_name; 585 iscsi_chap_props_t *chap = NULL; 586 iscsi_auth_props_t *auth = NULL; 587 uchar_t *tmp = NULL; 588 589 if (isp == (iscsi_sess_t *)NULL) { 590 return (B_FALSE); 591 } 592 593 /* Obtain initiator's name */ 594 if (isp->sess_hba == (iscsi_hba_t *)NULL) { 595 return (B_FALSE); 596 } 597 598 init_name = (char *)isp->sess_hba->hba_name; 599 600 /* Zero out the session authentication structure */ 601 bzero(&isp->sess_auth, sizeof (iscsi_auth_t)); 602 603 if (isp->sess_boot == B_FALSE) { 604 605 auth = (iscsi_auth_props_t *)kmem_zalloc 606 (sizeof (iscsi_auth_props_t), KM_SLEEP); 607 /* Obtain target's authentication settings. */ 608 if (persistent_auth_get((char *)isp->sess_name, auth) 609 != B_TRUE) { 610 /* 611 * If no target authentication settings found, 612 * try to obtain system wide configuration 613 * (from the initiator). 614 */ 615 bzero(auth, sizeof (*auth)); 616 if (persistent_auth_get(init_name, auth) != B_TRUE) { 617 bzero(auth, sizeof (*auth)); 618 auth->a_auth_method = authMethodNone; 619 } 620 621 /* 622 * We do not support system wide bi-directional 623 * auth flag. 624 */ 625 auth->a_bi_auth = B_FALSE; 626 } 627 628 chap = (iscsi_chap_props_t *)kmem_zalloc 629 (sizeof (iscsi_chap_props_t), KM_SLEEP); 630 631 /* 632 * Initialize the target-side chap name to the session name 633 * if no chap settings have been saved for the current session. 634 */ 635 if (persistent_chap_get((char *)isp->sess_name, chap) 636 == B_FALSE) { 637 int name_len = strlen((char *)isp->sess_name); 638 bcopy((char *)isp->sess_name, chap->c_user, name_len); 639 chap->c_user_len = name_len; 640 (void) (persistent_chap_set((char *)isp->sess_name, 641 chap)); 642 bzero(chap, sizeof (*chap)); 643 } 644 645 if (auth->a_auth_method & authMethodCHAP) { 646 /* Obtain initiator's CHAP settings. */ 647 if (persistent_chap_get(init_name, chap) == B_FALSE) { 648 /* No initiator secret defined. */ 649 kmem_free(chap, sizeof (iscsi_chap_props_t)); 650 /* Set authentication method to NONE */ 651 isp->sess_auth.password_length = 0; 652 kmem_free(auth, sizeof (iscsi_auth_props_t)); 653 return (B_FALSE); 654 } 655 656 bcopy(chap->c_user, isp->sess_auth.username, 657 sizeof (chap->c_user)); 658 bcopy(chap->c_secret, isp->sess_auth.password, 659 sizeof (chap->c_secret)); 660 isp->sess_auth.password_length = chap->c_secret_len; 661 } else { 662 /* Set authentication method to NONE */ 663 isp->sess_auth.password_length = 0; 664 } 665 666 /* 667 * Consider enabling bidirectional authentication only if 668 * authentication method is not NONE. 669 */ 670 if (auth->a_auth_method & authMethodCHAP && 671 auth->a_bi_auth == B_TRUE) { 672 /* Enable bi-directional authentication. */ 673 isp->sess_auth.bidirectional_auth = 1; 674 675 bzero(chap, sizeof (*chap)); 676 /* Obtain target's CHAP settings. */ 677 if (persistent_chap_get((char *)isp->sess_name, chap) 678 == B_TRUE) { 679 bcopy(chap->c_secret, 680 isp->sess_auth.password_in, 681 sizeof (chap->c_secret)); 682 bcopy(chap->c_user, isp->sess_auth.username_in, 683 strlen((char *)chap->c_user)); 684 isp->sess_auth.password_length_in = 685 chap->c_secret_len; 686 } else { 687 /* 688 * No target secret defined. 689 * RADIUS server should have been enabled. 690 */ 691 /* EMPTY */ 692 } 693 } else { 694 /* Disable bi-directional authentication */ 695 isp->sess_auth.bidirectional_auth = 0; 696 } 697 698 if (auth != NULL) { 699 kmem_free(auth, sizeof (iscsi_auth_props_t)); 700 } 701 if (chap != NULL) { 702 kmem_free(chap, sizeof (iscsi_chap_props_t)); 703 } 704 } else { 705 /* 706 * This session is boot session. We will use the CHAP and 707 * the user name got from the boot property structure instead 708 * of persistent sotre. 709 */ 710 if (iscsiboot_prop == NULL) { 711 return (B_FALSE); 712 } 713 714 if (iscsiboot_prop->boot_init.ini_chap_sec == NULL) { 715 return (B_FALSE); 716 } 717 718 /* CHAP secret */ 719 (void) bcopy(iscsiboot_prop->boot_init.ini_chap_sec, 720 isp->sess_auth.password, 721 strlen((char *)iscsiboot_prop->boot_init.ini_chap_sec)); 722 723 /* 724 * If chap name is not set, 725 * we will use initiator name instead. 726 */ 727 if (iscsiboot_prop->boot_init.ini_chap_name == NULL) { 728 (void) bcopy(init_name, isp->sess_auth.username, 729 strlen(init_name)); 730 } else { 731 tmp = iscsiboot_prop->boot_init.ini_chap_name; 732 (void) bcopy(tmp, 733 isp->sess_auth.username, strlen((char *)tmp)); 734 } 735 736 isp->sess_auth.password_length = 737 strlen((char *)iscsiboot_prop->boot_init.ini_chap_sec); 738 739 if (iscsiboot_prop->boot_tgt.tgt_chap_sec != NULL) { 740 /* 741 * Bidirectional authentication is required. 742 */ 743 tmp = iscsiboot_prop->boot_tgt.tgt_chap_sec; 744 (void) bcopy(tmp, 745 isp->sess_auth.password_in, strlen((char *)tmp)); 746 747 /* 748 * If the target's chap name is not set, we will use 749 * session name instead. 750 */ 751 if (iscsiboot_prop->boot_tgt.tgt_chap_name == NULL) { 752 (void) bcopy(isp->sess_name, 753 isp->sess_auth.username_in, 754 isp->sess_name_length); 755 } else { 756 tmp = iscsiboot_prop->boot_tgt.tgt_chap_name; 757 (void) bcopy(tmp, 758 isp->sess_auth.username_in, 759 strlen((char *)tmp)); 760 } 761 tmp = iscsiboot_prop->boot_tgt.tgt_chap_sec; 762 isp->sess_auth.password_length_in = 763 strlen((char *)tmp); 764 isp->sess_auth.bidirectional_auth = 1; 765 } 766 } 767 768 /* Set up authentication buffers only if configured */ 769 if ((isp->sess_auth.password_length != 0) || 770 (isp->sess_auth.password_length_in != 0)) { 771 isp->sess_auth.num_auth_buffers = 5; 772 isp->sess_auth.auth_buffers[0].address = 773 &(isp->sess_auth.auth_client_block); 774 isp->sess_auth.auth_buffers[0].length = 775 sizeof (isp->sess_auth.auth_client_block); 776 isp->sess_auth.auth_buffers[1].address = 777 &(isp->sess_auth.auth_recv_string_block); 778 isp->sess_auth.auth_buffers[1].length = 779 sizeof (isp->sess_auth.auth_recv_string_block); 780 isp->sess_auth.auth_buffers[2].address = 781 &(isp->sess_auth.auth_send_string_block); 782 isp->sess_auth.auth_buffers[2].length = 783 sizeof (isp->sess_auth.auth_send_string_block); 784 isp->sess_auth.auth_buffers[3].address = 785 &(isp->sess_auth.auth_recv_binary_block); 786 isp->sess_auth.auth_buffers[3].length = 787 sizeof (isp->sess_auth.auth_recv_binary_block); 788 isp->sess_auth.auth_buffers[4].address = 789 &(isp->sess_auth.auth_send_binary_block); 790 isp->sess_auth.auth_buffers[4].length = 791 sizeof (isp->sess_auth.auth_send_binary_block); 792 } 793 794 return (B_TRUE); 795 } 796 797 798 /* 799 * iscsi_sess_reserve_itt - Used to reserve an ITT hash slot 800 */ 801 iscsi_status_t 802 iscsi_sess_reserve_itt(iscsi_sess_t *isp, iscsi_cmd_t *icmdp) 803 { 804 /* If no more slots are open fail reservation */ 805 if (isp->sess_cmd_table_count >= ISCSI_CMD_TABLE_SIZE) { 806 return (ISCSI_STATUS_ITT_TABLE_FULL); 807 } 808 809 /* 810 * Find the next available slot. Normally its the 811 * slot pointed to by the session's sess_itt value. 812 * If this is not true the table has become fragmented. 813 * Fragmentation can occur during max loads and IOs 814 * are completed out of order. Defragmentation will 815 * occur when IO slows down and ITT slots are released. 816 */ 817 while (isp->sess_cmd_table[isp->sess_itt % 818 ISCSI_CMD_TABLE_SIZE] != NULL) { 819 isp->sess_itt++; 820 } 821 822 /* reserve slot and update counters */ 823 icmdp->cmd_itt = isp->sess_itt; 824 isp->sess_cmd_table[icmdp->cmd_itt % 825 ISCSI_CMD_TABLE_SIZE] = icmdp; 826 isp->sess_cmd_table_count++; 827 isp->sess_itt++; 828 829 return (ISCSI_STATUS_SUCCESS); 830 } 831 832 /* 833 * iscsi_sess_release_itt - Used to release ITT hash slot 834 */ 835 void 836 iscsi_sess_release_itt(iscsi_sess_t *isp, iscsi_cmd_t *icmdp) 837 { 838 int hash_index = (icmdp->cmd_itt % ISCSI_CMD_TABLE_SIZE); 839 840 ASSERT(isp->sess_cmd_table[hash_index] != NULL); 841 842 /* release slot and update counters */ 843 isp->sess_cmd_table[hash_index] = NULL; 844 isp->sess_cmd_table_count--; 845 } 846 847 /* 848 * iscsi_sess_redrive_io - Used to redrive IO on connections in 849 * a full feature state. 850 */ 851 void 852 iscsi_sess_redrive_io(iscsi_sess_t *isp) 853 { 854 iscsi_conn_t *icp; 855 856 ASSERT(isp != NULL); 857 858 icp = isp->sess_conn_list; 859 while (icp != NULL) { 860 if (ISCSI_CONN_STATE_FULL_FEATURE( 861 icp->conn_state)) { 862 iscsi_thread_send_wakeup( 863 icp->conn_tx_thread); 864 } 865 icp = icp->conn_next; 866 } 867 } 868 869 /* 870 * iscsi_sess_state_machine - 871 * 872 * 7.3.1 Session State Diagram for an Initiator 873 * 874 * Symbolic Names for States: 875 * Q1: FREE - State on instantiation of after cleanup 876 * Q3: LOGGED_IN - Waiting for all session events. 877 * Q4: FAILED - Waiting for session recovery or session cont. 878 * Q5: IN_FLUSH - A login parameter has changed. We are in the 879 * process of flushing active, aborting, and 880 * completed queues. Once flushed the iscsi_ic_thread() 881 * will drop of drop connections (T14) and reconnect 882 * to the target with new values. 883 * Q6: FLUSHED - Active, Aborting and Completed Queues flushed. 884 * Awaiting reconnect or failure. iscsi_tx/ic_threads 885 * are still running and might be timing-out IOs. 886 * State Q3/4 represent the Full Feature Phase operation of the session. 887 * 888 * The state diagram is as follows: 889 * 890 * ------ (N6/7 == NOOP) 891 * / Q1 \ 892 * +----------------------->\ /<-------------+ 893 * | ---+--- | 894 * | N5 |N1 | 895 * | +----+ +-------------+ | | 896 * | | V V | V | 897 * | | ----+-- -----+ | 898 * |N6|N6 / Q4 \ / Q3 \(N6 == NOOP) | 899 * +--+---\ /----+--->\ /-----+---------+ 900 * | ------- /N1 -+---- | N3| 901 * | (N7 == NOOP) / N7| ^ N1/3/5| | 902 * | / | +-------+ | 903 * | +-----+ / | | 904 * | | V / v | 905 * | | ------- -+---- | 906 * |N6|N6 / Q6 \ N5 / Q5 \ | 907 * +--+---\ /<--------\ /-----+---------+ 908 * ------- ------ | N3 909 * (N7 == NOOP) ^ N1/3/5| 910 * +-------+ 911 * 912 * The state transition table is as follows: 913 * 914 * +----+------+----+--------+----+ 915 * |Q1 |Q3 |Q4 |Q5 |Q6 | 916 * -----+----+------+----+--------+----+ 917 * Q1 |N6/7|N1 | - | | | 918 * -----+----+------+----+--------+----+ 919 * Q3 |N3 |N1/3/5|N5 |N7 | | 920 * -----+----+------+----+--------+----+ 921 * Q4 |N6 |N1 |N6/7| | | 922 * -----+----+------+----+--------+----+ 923 * Q5 |N3 | | |N1/3/5/7|N6 | 924 * -----+----+------+----+--------+----+ 925 * Q6 |N6 |N1 |N6/7| | | 926 * -----+----+------+----+--------+----+ 927 * 928 * Event definitions: 929 * 930 * -N1: A connection logged in 931 * -N3: A connection logged out 932 * -N5: A connection failed 933 * -N6: Session state timeout occurred, or a session 934 * reinstatement cleared this session instance. This results in 935 * the freeing of all associated resources and the session state 936 * is discarded. 937 * -N7: Login parameters for session have changed. 938 * Re-negeotation required. 939 */ 940 void 941 iscsi_sess_state_machine(iscsi_sess_t *isp, iscsi_sess_event_t event) 942 { 943 ASSERT(isp != NULL); 944 ASSERT(mutex_owned(&isp->sess_state_mutex)); 945 946 DTRACE_PROBE3(event, iscsi_sess_t *, isp, 947 char *, iscsi_sess_state_str(isp->sess_state), 948 char *, iscsi_sess_event_str(event)); 949 950 isp->sess_prev_state = isp->sess_state; 951 isp->sess_state_lbolt = ddi_get_lbolt(); 952 953 switch (isp->sess_state) { 954 case ISCSI_SESS_STATE_FREE: 955 iscsi_sess_state_free(isp, event); 956 break; 957 case ISCSI_SESS_STATE_LOGGED_IN: 958 iscsi_sess_state_logged_in(isp, event); 959 break; 960 case ISCSI_SESS_STATE_FAILED: 961 iscsi_sess_state_failed(isp, event); 962 break; 963 case ISCSI_SESS_STATE_IN_FLUSH: 964 iscsi_sess_state_in_flush(isp, event); 965 break; 966 case ISCSI_SESS_STATE_FLUSHED: 967 iscsi_sess_state_flushed(isp, event); 968 break; 969 default: 970 ASSERT(FALSE); 971 } 972 } 973 974 975 /* 976 * iscsi_sess_state_str - 977 * 978 */ 979 char * 980 iscsi_sess_state_str(iscsi_sess_state_t state) 981 { 982 switch (state) { 983 case ISCSI_SESS_STATE_FREE: 984 return ("free"); 985 case ISCSI_SESS_STATE_LOGGED_IN: 986 return ("logged_in"); 987 case ISCSI_SESS_STATE_FAILED: 988 return ("failed"); 989 case ISCSI_SESS_STATE_IN_FLUSH: 990 return ("in_flush"); 991 case ISCSI_SESS_STATE_FLUSHED: 992 return ("flushed"); 993 default: 994 return ("unknown"); 995 } 996 } 997 998 999 /* 1000 * +--------------------------------------------------------------------+ 1001 * | Internal Session Interfaces | 1002 * +--------------------------------------------------------------------+ 1003 */ 1004 1005 1006 /* 1007 * iscsi_sess_state_free - 1008 * 1009 */ 1010 static void 1011 iscsi_sess_state_free(iscsi_sess_t *isp, iscsi_sess_event_t event) 1012 { 1013 iscsi_status_t status; 1014 iscsi_hba_t *ihp; 1015 iscsi_task_t *itp; 1016 1017 ASSERT(isp != NULL); 1018 ihp = isp->sess_hba; 1019 ASSERT(ihp != NULL); 1020 ASSERT(isp->sess_state == ISCSI_SESS_STATE_FREE); 1021 1022 /* switch on event change */ 1023 switch (event) { 1024 /* 1025 * -N1: A connection logged in 1026 */ 1027 case ISCSI_SESS_EVENT_N1: 1028 status = iscsi_sess_threads_create(isp); 1029 if (ISCSI_SUCCESS(status)) { 1030 isp->sess_state = ISCSI_SESS_STATE_LOGGED_IN; 1031 if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) { 1032 cmn_err(CE_NOTE, 1033 "!iscsi session(%u) %s online\n", 1034 isp->sess_oid, isp->sess_name); 1035 1036 if (isp->sess_enum_in_progress == B_FALSE) { 1037 isp->sess_enum_in_progress = B_TRUE; 1038 mutex_exit(&isp->sess_state_mutex); 1039 1040 /* start enumeration */ 1041 itp = kmem_zalloc(sizeof (iscsi_task_t), 1042 KM_SLEEP); 1043 itp->t_arg = isp; 1044 itp->t_blocking = B_TRUE; 1045 iscsi_sess_enumeration(itp); 1046 kmem_free(itp, sizeof (iscsi_task_t)); 1047 1048 mutex_enter(&isp->sess_state_mutex); 1049 isp->sess_enum_in_progress = B_FALSE; 1050 } 1051 } 1052 } else { 1053 ASSERT(FALSE); 1054 } 1055 break; 1056 1057 /* 1058 * -N6: Session state timeout occurred, or a session 1059 * reinstatement cleared this session instance. This results in 1060 * the freeing of all associated resources and the session state 1061 * is discarded. 1062 */ 1063 case ISCSI_SESS_EVENT_N6: 1064 /* FALLTHRU */ 1065 1066 /* 1067 * -N7: Login parameters for session have changed. 1068 * Re-negeotation required. 1069 */ 1070 case ISCSI_SESS_EVENT_N7: 1071 /* NOOP - not connected */ 1072 break; 1073 1074 /* All other events are invalid for this state */ 1075 default: 1076 ASSERT(FALSE); 1077 } 1078 } 1079 1080 1081 /* 1082 * iscsi_sess_logged_in - 1083 * 1084 */ 1085 static void 1086 iscsi_sess_state_logged_in(iscsi_sess_t *isp, iscsi_sess_event_t event) 1087 { 1088 iscsi_task_t *itp; 1089 1090 ASSERT(isp != NULL); 1091 ASSERT(isp->sess_state == ISCSI_SESS_STATE_LOGGED_IN); 1092 1093 /* switch on event change */ 1094 switch (event) { 1095 /* 1096 * -N1: At least one transport connection reached the 1097 * LOGGED_IN state 1098 */ 1099 case ISCSI_SESS_EVENT_N1: 1100 /* 1101 * A different connection already logged in. If the 1102 * session is NORMAL, just re-enumerate the session. 1103 */ 1104 if ((isp->sess_type == ISCSI_SESS_TYPE_NORMAL) && 1105 (isp->sess_enum_in_progress == B_FALSE)) { 1106 isp->sess_enum_in_progress = B_TRUE; 1107 mutex_exit(&isp->sess_state_mutex); 1108 1109 /* start enumeration */ 1110 itp = kmem_zalloc(sizeof (iscsi_task_t), KM_SLEEP); 1111 itp->t_arg = isp; 1112 itp->t_blocking = B_TRUE; 1113 iscsi_sess_enumeration(itp); 1114 kmem_free(itp, sizeof (iscsi_task_t)); 1115 1116 mutex_enter(&isp->sess_state_mutex); 1117 isp->sess_enum_in_progress = B_FALSE; 1118 } 1119 break; 1120 1121 /* 1122 * -N3: A connection logged out. 1123 */ 1124 case ISCSI_SESS_EVENT_N3: 1125 /* FALLTHRU */ 1126 1127 /* 1128 * -N5: A connection failed 1129 */ 1130 case ISCSI_SESS_EVENT_N5: 1131 /* 1132 * MC/S: If this is the last connection to 1133 * fail then move the the failed state. 1134 */ 1135 if (event == ISCSI_SESS_EVENT_N3) { 1136 isp->sess_state = ISCSI_SESS_STATE_FREE; 1137 } else { 1138 isp->sess_state = ISCSI_SESS_STATE_FAILED; 1139 } 1140 1141 /* no longer connected reset nego tpgt */ 1142 isp->sess_tpgt_nego = ISCSI_DEFAULT_TPGT; 1143 1144 iscsi_sess_flush(isp); 1145 1146 if (event == ISCSI_SESS_EVENT_N3) { 1147 if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) { 1148 cmn_err(CE_NOTE, 1149 "!iscsi session(%u) %s offline\n", 1150 isp->sess_oid, isp->sess_name); 1151 } 1152 /* 1153 * An enumeration may also in progress 1154 * in the same session. Release the 1155 * sess_state_mutex to avoid deadlock 1156 * 1157 * During the process of offlining the LUNs 1158 * our ic thread might be calling back into 1159 * the driver via a target driver failure 1160 * path to do a reset or something 1161 * we need to release the sess_state_mutex 1162 * while we are killing these threads so 1163 * they don't get deadlocked. 1164 */ 1165 mutex_exit(&isp->sess_state_mutex); 1166 iscsi_sess_offline_luns(isp); 1167 iscsi_thread_destroy(isp->sess_ic_thread); 1168 } else { 1169 mutex_exit(&isp->sess_state_mutex); 1170 iscsi_thread_destroy(isp->sess_ic_thread); 1171 } 1172 1173 mutex_enter(&isp->sess_state_mutex); 1174 break; 1175 1176 /* 1177 * -N6: Session state timeout occurred, or a session 1178 * reinstatement cleared this session instance. This results in 1179 * the freeing of all associated resources and the session state 1180 * is discarded. 1181 */ 1182 case ISCSI_SESS_EVENT_N6: 1183 /* NOOP - Not last connection */ 1184 break; 1185 1186 /* 1187 * -N7: Login parameters for session have changed. 1188 * Re-negeotation required. 1189 */ 1190 case ISCSI_SESS_EVENT_N7: 1191 isp->sess_state = ISCSI_SESS_STATE_IN_FLUSH; 1192 break; 1193 1194 /* All other events are invalid for this state */ 1195 default: 1196 ASSERT(FALSE); 1197 } 1198 } 1199 1200 1201 /* 1202 * iscsi_sess_state_failed - 1203 * 1204 */ 1205 static void 1206 iscsi_sess_state_failed(iscsi_sess_t *isp, iscsi_sess_event_t event) 1207 { 1208 iscsi_status_t rval; 1209 iscsi_hba_t *ihp; 1210 iscsi_task_t *itp; 1211 1212 ASSERT(isp != NULL); 1213 ihp = isp->sess_hba; 1214 ASSERT(ihp != NULL); 1215 ASSERT(isp->sess_state == ISCSI_SESS_STATE_FAILED); 1216 1217 /* switch on event change */ 1218 switch (event) { 1219 /* -N1: A session continuation attempt succeeded */ 1220 case ISCSI_SESS_EVENT_N1: 1221 rval = iscsi_sess_threads_create(isp); 1222 if (ISCSI_SUCCESS(rval)) { 1223 isp->sess_state = ISCSI_SESS_STATE_LOGGED_IN; 1224 if ((isp->sess_type == ISCSI_SESS_TYPE_NORMAL) && 1225 (isp->sess_enum_in_progress == B_FALSE)) { 1226 isp->sess_enum_in_progress = B_TRUE; 1227 mutex_exit(&isp->sess_state_mutex); 1228 1229 /* start enumeration */ 1230 itp = kmem_zalloc(sizeof (iscsi_task_t), 1231 KM_SLEEP); 1232 itp->t_arg = isp; 1233 itp->t_blocking = B_FALSE; 1234 if (ddi_taskq_dispatch(isp->sess_taskq, 1235 iscsi_sess_enumeration, itp, DDI_SLEEP) != 1236 DDI_SUCCESS) { 1237 kmem_free(itp, sizeof (iscsi_task_t)); 1238 cmn_err(CE_WARN, 1239 "iscsi connection (%u) failure - " 1240 "unable to schedule enumeration", 1241 isp->sess_oid); 1242 } 1243 1244 mutex_enter(&isp->sess_state_mutex); 1245 isp->sess_enum_in_progress = B_FALSE; 1246 } 1247 } else { 1248 isp->sess_state = ISCSI_SESS_STATE_FREE; 1249 ASSERT(FALSE); 1250 } 1251 break; 1252 1253 /* 1254 * -N6: Session state timeout occurred, or a session 1255 * reinstatement cleared this session instance. This results in 1256 * the freeing of all associated resources and the session state 1257 * is discarded. 1258 */ 1259 case ISCSI_SESS_EVENT_N6: 1260 isp->sess_state = ISCSI_SESS_STATE_FREE; 1261 1262 if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) { 1263 cmn_err(CE_NOTE, "!iscsi session(%u) %s offline\n", 1264 isp->sess_oid, isp->sess_name); 1265 } 1266 1267 mutex_exit(&isp->sess_state_mutex); 1268 iscsi_sess_offline_luns(isp); 1269 mutex_enter(&isp->sess_state_mutex); 1270 break; 1271 1272 /* 1273 * -N7: Login parameters for session have changed. 1274 * Re-negeotation required. 1275 */ 1276 case ISCSI_SESS_EVENT_N7: 1277 /* NOOP - not connected */ 1278 break; 1279 1280 /* All other events are invalid for this state */ 1281 default: 1282 ASSERT(FALSE); 1283 } 1284 } 1285 1286 1287 /* 1288 * iscsi_sess_state_in_flush - 1289 * 1290 */ 1291 static void 1292 iscsi_sess_state_in_flush(iscsi_sess_t *isp, iscsi_sess_event_t event) 1293 { 1294 ASSERT(isp != NULL); 1295 ASSERT(isp->sess_state == ISCSI_SESS_STATE_IN_FLUSH); 1296 1297 /* switch on event change */ 1298 switch (event) { 1299 /* -N1: A session continuation attempt succeeded */ 1300 case ISCSI_SESS_EVENT_N1: 1301 /* NOOP - connections already online */ 1302 break; 1303 1304 /* 1305 * -N3: A connection logged out. 1306 */ 1307 case ISCSI_SESS_EVENT_N3: 1308 /* FALLTHRU */ 1309 1310 /* 1311 * -N5: A connection failed 1312 */ 1313 case ISCSI_SESS_EVENT_N5: 1314 /* 1315 * MC/S: If this is the last connection to 1316 * fail then move the the failed state. 1317 */ 1318 if (event == ISCSI_SESS_EVENT_N3) { 1319 isp->sess_state = ISCSI_SESS_STATE_FREE; 1320 } else { 1321 isp->sess_state = ISCSI_SESS_STATE_FLUSHED; 1322 } 1323 1324 /* no longer connected reset nego tpgt */ 1325 isp->sess_tpgt_nego = ISCSI_DEFAULT_TPGT; 1326 iscsi_sess_flush(isp); 1327 1328 if (event == ISCSI_SESS_EVENT_N3) { 1329 if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) { 1330 cmn_err(CE_NOTE, 1331 "!iscsi session(%u) %s offline\n", 1332 isp->sess_oid, isp->sess_name); 1333 } 1334 /* 1335 * An enumeration may also in progress 1336 * in the same session. Release the 1337 * sess_state_mutex to avoid deadlock 1338 * 1339 * During the process of offlining the LUNs 1340 * our ic thread might be calling back into 1341 * the driver via a target driver failure 1342 * path to do a reset or something 1343 * we need to release the sess_state_mutex 1344 * while we are killing these threads so 1345 * they don't get deadlocked. 1346 */ 1347 mutex_exit(&isp->sess_state_mutex); 1348 iscsi_sess_offline_luns(isp); 1349 iscsi_thread_destroy(isp->sess_ic_thread); 1350 } else { 1351 mutex_exit(&isp->sess_state_mutex); 1352 iscsi_thread_destroy(isp->sess_ic_thread); 1353 } 1354 1355 mutex_enter(&isp->sess_state_mutex); 1356 break; 1357 1358 /* 1359 * -N6: Session state timeout occurred, or a session 1360 * reinstatement cleared this session instance. This results in 1361 * the freeing of all associated resources and the session state 1362 * is discarded. 1363 */ 1364 case ISCSI_SESS_EVENT_N6: 1365 /* NOOP - Not last connection */ 1366 break; 1367 1368 /* 1369 * -N7: Login parameters for session have changed. 1370 * Re-negeotation required. 1371 */ 1372 case ISCSI_SESS_EVENT_N7: 1373 /* NOOP - Already attempting to update */ 1374 break; 1375 1376 /* All other events are invalid for this state */ 1377 default: 1378 ASSERT(FALSE); 1379 } 1380 } 1381 1382 1383 /* 1384 * iscsi_sess_state_flushed - 1385 * 1386 */ 1387 static void 1388 iscsi_sess_state_flushed(iscsi_sess_t *isp, iscsi_sess_event_t event) 1389 { 1390 iscsi_status_t rval; 1391 iscsi_hba_t *ihp; 1392 iscsi_task_t *itp; 1393 1394 ASSERT(isp != NULL); 1395 ASSERT(isp->sess_state == ISCSI_SESS_STATE_FLUSHED); 1396 ihp = isp->sess_hba; 1397 ASSERT(ihp != NULL); 1398 1399 /* switch on event change */ 1400 switch (event) { 1401 /* -N1: A session continuation attempt succeeded */ 1402 case ISCSI_SESS_EVENT_N1: 1403 rval = iscsi_sess_threads_create(isp); 1404 if (ISCSI_SUCCESS(rval)) { 1405 isp->sess_state = ISCSI_SESS_STATE_LOGGED_IN; 1406 if ((isp->sess_type == ISCSI_SESS_TYPE_NORMAL) && 1407 (isp->sess_enum_in_progress == B_FALSE)) { 1408 isp->sess_enum_in_progress = B_TRUE; 1409 mutex_exit(&isp->sess_state_mutex); 1410 1411 /* start enumeration */ 1412 itp = kmem_zalloc(sizeof (iscsi_task_t), 1413 KM_SLEEP); 1414 itp->t_arg = isp; 1415 itp->t_blocking = B_FALSE; 1416 if (ddi_taskq_dispatch(isp->sess_taskq, 1417 iscsi_sess_enumeration, itp, DDI_SLEEP) != 1418 DDI_SUCCESS) { 1419 kmem_free(itp, sizeof (iscsi_task_t)); 1420 cmn_err(CE_WARN, 1421 "iscsi connection (%u) failure - " 1422 "unable to schedule enumeration", 1423 isp->sess_oid); 1424 } 1425 1426 mutex_enter(&isp->sess_state_mutex); 1427 isp->sess_enum_in_progress = B_FALSE; 1428 } 1429 } else { 1430 isp->sess_state = ISCSI_SESS_STATE_FREE; 1431 ASSERT(FALSE); 1432 } 1433 break; 1434 1435 /* 1436 * -N6: Session state timeout occurred, or a session 1437 * reinstatement cleared this session instance. This results in 1438 * the freeing of all associated resources and the session state 1439 * is discarded. 1440 */ 1441 case ISCSI_SESS_EVENT_N6: 1442 isp->sess_state = ISCSI_SESS_STATE_FREE; 1443 1444 if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) { 1445 cmn_err(CE_NOTE, "!iscsi session(%u) %s offline\n", 1446 isp->sess_oid, isp->sess_name); 1447 } 1448 1449 mutex_exit(&isp->sess_state_mutex); 1450 iscsi_sess_offline_luns(isp); 1451 mutex_enter(&isp->sess_state_mutex); 1452 break; 1453 1454 /* 1455 * -N7: Login parameters for session have changed. 1456 * Re-negeotation required. 1457 */ 1458 case ISCSI_SESS_EVENT_N7: 1459 /* NOOP - not connected */ 1460 break; 1461 1462 /* All other events are invalid for this state */ 1463 default: 1464 ASSERT(FALSE); 1465 } 1466 } 1467 1468 /* 1469 * iscsi_sess_event_str - 1470 * 1471 */ 1472 static char * 1473 iscsi_sess_event_str(iscsi_sess_event_t event) 1474 { 1475 switch (event) { 1476 case ISCSI_SESS_EVENT_N1: 1477 return ("N1"); 1478 case ISCSI_SESS_EVENT_N3: 1479 return ("N3"); 1480 case ISCSI_SESS_EVENT_N5: 1481 return ("N5"); 1482 case ISCSI_SESS_EVENT_N6: 1483 return ("N6"); 1484 case ISCSI_SESS_EVENT_N7: 1485 return ("N7"); 1486 default: 1487 return ("unknown"); 1488 } 1489 } 1490 1491 /* 1492 * iscsi_sess_thread_create - 1493 * 1494 */ 1495 static iscsi_status_t 1496 iscsi_sess_threads_create(iscsi_sess_t *isp) 1497 { 1498 iscsi_hba_t *ihp; 1499 char th_name[ISCSI_TH_MAX_NAME_LEN]; 1500 1501 ASSERT(isp != NULL); 1502 ihp = isp->sess_hba; 1503 ASSERT(ihp != NULL); 1504 1505 /* Completion thread creation. */ 1506 if (snprintf(th_name, sizeof (th_name) - 1, 1507 ISCSI_SESS_IOTH_NAME_FORMAT, ihp->hba_oid, 1508 isp->sess_oid) >= sizeof (th_name)) { 1509 return (ISCSI_STATUS_INTERNAL_ERROR); 1510 } 1511 1512 isp->sess_ic_thread = iscsi_thread_create(ihp->hba_dip, 1513 th_name, iscsi_ic_thread, isp); 1514 1515 if (isp->sess_ic_thread == NULL) { 1516 return (ISCSI_STATUS_INTERNAL_ERROR); 1517 } 1518 1519 (void) iscsi_thread_start(isp->sess_ic_thread); 1520 1521 return (ISCSI_STATUS_SUCCESS); 1522 } 1523 1524 /* 1525 * iscsi_sess_enumeration - This function is used to drive the enumeration 1526 * of LUs on a session. It will first prepare the target by sending test 1527 * unit ready commands, then it will issue a report luns. If the report 1528 * luns is successful then it will process all the luns in the report. 1529 * If report luns is not successful we will do a stepping enumeration 1530 * of luns until no more luns are found. 1531 */ 1532 static void 1533 iscsi_sess_enumeration(void *arg) 1534 { 1535 iscsi_task_t *itp = (iscsi_task_t *)arg; 1536 iscsi_sess_t *isp; 1537 iscsi_status_t rval = ISCSI_STATUS_SUCCESS; 1538 1539 ASSERT(itp != NULL); 1540 isp = (iscsi_sess_t *)itp->t_arg; 1541 ASSERT(isp != NULL); 1542 1543 /* 1544 * Send initial TEST_UNIT_READY to target. If it fails this we 1545 * stop our enumeration as the target is not responding properly. 1546 */ 1547 rval = iscsi_sess_testunitready(isp); 1548 if (ISCSI_SUCCESS(rval)) { 1549 /* 1550 * Now we know the target is ready start our enumeration with 1551 * REPORT LUNs, If this fails we will have to fall back to 1552 * stepping 1553 */ 1554 rval = iscsi_sess_reportluns(isp); 1555 if (!ISCSI_SUCCESS(rval)) { 1556 /* 1557 * report luns failed so lets just check for LUN 0. 1558 * This will match fcp's enumeration support and 1559 * avoid issues with older devices like the A5K that 1560 * respond poorly. 1561 */ 1562 if (isp->sess_lun_list == NULL) { 1563 iscsi_sess_inquiry(isp, 0, 0); 1564 } 1565 } 1566 } else { 1567 cmn_err(CE_NOTE, "iscsi session(%u) unable to enumerate " 1568 "logical units - test unit ready failed", isp->sess_oid); 1569 } 1570 1571 if (itp->t_blocking == B_FALSE) { 1572 kmem_free(itp, sizeof (iscsi_task_t)); 1573 } 1574 } 1575 1576 /* 1577 * iscsi_sess_testunitready - This is used during enumeration to 1578 * ensure an array is ready to be enumerated. 1579 */ 1580 static iscsi_status_t 1581 iscsi_sess_testunitready(iscsi_sess_t *isp) 1582 { 1583 iscsi_status_t rval = ISCSI_STATUS_SUCCESS; 1584 int retries = 0; 1585 struct uscsi_cmd ucmd; 1586 char cdb[CDB_GROUP0]; 1587 1588 ASSERT(isp != NULL); 1589 1590 /* loop until successful sending test unit ready or retries out */ 1591 do { 1592 /* cdb is all zeros */ 1593 bzero(&cdb[0], CDB_GROUP0); 1594 1595 /* setup uscsi cmd */ 1596 bzero(&ucmd, sizeof (struct uscsi_cmd)); 1597 ucmd.uscsi_timeout = iscsi_sess_enum_timeout; 1598 ucmd.uscsi_cdb = &cdb[0]; 1599 ucmd.uscsi_cdblen = CDB_GROUP0; 1600 1601 /* send test unit ready to lun zero on this session */ 1602 rval = iscsi_handle_passthru(isp, 0, &ucmd); 1603 1604 /* 1605 * If passthru was successful then we were able to 1606 * communicate with the target, continue enumeration. 1607 */ 1608 if (ISCSI_SUCCESS(rval)) { 1609 break; 1610 } 1611 1612 } while (retries++ < 3); 1613 1614 return (rval); 1615 } 1616 1617 #define SCSI_REPORTLUNS_ADDRESS_SIZE 8 1618 #define SCSI_REPORTLUNS_ADDRESS_MASK 0xC0 1619 #define SCSI_REPORTLUNS_ADDRESS_PERIPHERAL 0x00 1620 #define SCSI_REPORTLUNS_ADDRESS_FLAT_SPACE 0x40 1621 #define SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT 0x80 1622 #define SCSI_REPORTLUNS_ADDRESS_EXTENDED_UNIT 0xC0 1623 #define SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT_2B 0x00 1624 #define SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT_4B 0x01 1625 #define SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT_6B 0x10 1626 #define SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT_8B 0x20 1627 #define SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT_SIZE 0x30 1628 1629 /* 1630 * iscsi_sess_reportluns - This is used during enumeration to 1631 * ensure an array is ready to be enumerated. 1632 */ 1633 static iscsi_status_t 1634 iscsi_sess_reportluns(iscsi_sess_t *isp) 1635 { 1636 iscsi_status_t rval = ISCSI_STATUS_SUCCESS; 1637 iscsi_hba_t *ihp; 1638 struct uscsi_cmd ucmd; 1639 unsigned char cdb[CDB_GROUP5]; 1640 unsigned char *buf = NULL; 1641 int buf_len = sizeof (struct scsi_inquiry); 1642 uint32_t lun_list_length = 0; 1643 uint16_t lun_num = 0; 1644 uint8_t lun_addr_type = 0; 1645 uint32_t lun_count = 0; 1646 uint32_t lun_start = 0; 1647 uint32_t lun_total = 0; 1648 int retries = 0; 1649 iscsi_lun_t *ilp = NULL; 1650 replun_data_t *saved_replun_ptr = NULL; 1651 1652 ASSERT(isp != NULL); 1653 ihp = isp->sess_hba; 1654 ASSERT(ihp != NULL); 1655 1656 /* 1657 * Attempt to send report luns until we successfully 1658 * get all the data or the retries run out. 1659 */ 1660 do { 1661 /* 1662 * Allocate our buffer based on current buf_len. 1663 * buf_len may change after we received a response 1664 * from the target. 1665 */ 1666 if (buf == NULL) { 1667 buf = kmem_zalloc(buf_len, KM_SLEEP); 1668 } 1669 1670 /* setup cdb */ 1671 bzero(&cdb, CDB_GROUP5); 1672 cdb[0] = SCMD_REPORT_LUNS; 1673 cdb[6] = (buf_len & 0xff000000) >> 24; 1674 cdb[7] = (buf_len & 0x00ff0000) >> 16; 1675 cdb[8] = (buf_len & 0x0000ff00) >> 8; 1676 cdb[9] = (buf_len & 0x000000ff); 1677 1678 /* setup uscsi cmd */ 1679 bzero(&ucmd, sizeof (struct uscsi_cmd)); 1680 ucmd.uscsi_flags = USCSI_READ; 1681 ucmd.uscsi_timeout = iscsi_sess_enum_timeout; 1682 ucmd.uscsi_cdb = (char *)&cdb[0]; 1683 ucmd.uscsi_cdblen = CDB_GROUP5; 1684 ucmd.uscsi_bufaddr = (char *)buf; 1685 ucmd.uscsi_buflen = buf_len; 1686 1687 /* send uscsi cmd to lun 0 on session */ 1688 rval = iscsi_handle_passthru(isp, 0, &ucmd); 1689 1690 /* If passthru successful but not scsi status update istatus */ 1691 if (ISCSI_SUCCESS(rval) && 1692 (ucmd.uscsi_status != STATUS_GOOD)) { 1693 rval = ISCSI_STATUS_USCSI_FAILED; 1694 } 1695 1696 /* If successful, check if we have all the data */ 1697 if (ISCSI_SUCCESS(rval)) { 1698 /* total data - header (SCSI_REPORTLUNS_ADDRESS_SIZE) */ 1699 lun_list_length = htonl(*(uint32_t *)buf); 1700 1701 if (buf_len >= lun_list_length + 1702 SCSI_REPORTLUNS_ADDRESS_SIZE) { 1703 /* we have all the data, were done */ 1704 break; 1705 } 1706 1707 /* 1708 * We don't have all the data. free up the 1709 * memory for the next pass and update the 1710 * buf_len 1711 */ 1712 kmem_free(buf, buf_len); 1713 buf = NULL; 1714 buf_len = lun_list_length + 1715 SCSI_REPORTLUNS_ADDRESS_SIZE; 1716 } else { 1717 retries++; 1718 } 1719 1720 } while (retries < 3); 1721 1722 /* If not successful go no farther */ 1723 if (!ISCSI_SUCCESS(rval)) { 1724 kmem_free(buf, buf_len); 1725 return (rval); 1726 } 1727 1728 /* 1729 * find out the number of luns returned by the SCSI ReportLun call 1730 * and allocate buffer space 1731 */ 1732 lun_total = lun_list_length / SCSI_REPORTLUNS_ADDRESS_SIZE; 1733 saved_replun_ptr = kmem_zalloc(lun_total * sizeof (replun_data_t), 1734 KM_SLEEP); 1735 1736 /* 1737 * walk the isp->sess_lun_list 1738 * for each lun in this list 1739 * look to see if this lun is in the SCSI ReportLun list we 1740 * just retrieved 1741 * if it is in the SCSI ReportLun list and it is already ONLINE 1742 * nothing needs to be done 1743 * if it is in the SCSI ReportLun list and it is OFFLINE, 1744 * issue the iscsi_lun_online() 1745 * if it isn't in the SCSI ReportLunlist then 1746 * issue the iscsi_sess_inquiry() 1747 * 1748 * as we walk the SCSI ReportLun list, we save this lun information 1749 * into the buffer we just allocated. This will save us from 1750 * having to figure out this information later 1751 */ 1752 lun_start = 0; 1753 rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER); 1754 for (ilp = isp->sess_lun_list; ilp; ilp = ilp->lun_next) { 1755 for (lun_count = lun_start; 1756 lun_count < lun_total; lun_count++) { 1757 /* 1758 * if the first lun in saved_replun_ptr buffer has already 1759 * been found we can move on and do not have to check this lun 1760 * in the future 1761 */ 1762 if (lun_count == lun_start && 1763 saved_replun_ptr[lun_start].lun_found) { 1764 lun_start++; 1765 continue; 1766 } 1767 /* 1768 * check to see if the lun we are looking for is in the 1769 * saved_replun_ptr buffer 1770 * if it is, process the lun 1771 * if it isn't, then we must go to SCSI 1772 * Report Lun buffer 1773 * we retrieved to get lun info 1774 */ 1775 if (saved_replun_ptr[lun_count].lun_valid == 1776 B_TRUE) { 1777 if (saved_replun_ptr[lun_count].lun_num == 1778 ilp->lun_num) { 1779 /* 1780 * the lun we are looking for is found 1781 * 1782 * if the state of the lun is currently OFFLINE 1783 * or with INVALID, try to turn it back online 1784 */ 1785 if ((ilp->lun_state & 1786 ISCSI_LUN_STATE_OFFLINE) || 1787 (ilp->lun_state & 1788 ISCSI_LUN_STATE_INVALID)) { 1789 DTRACE_PROBE2( 1790 sess_reportluns_lun_is_not_online, 1791 int, ilp->lun_num, int, 1792 ilp->lun_state); 1793 iscsi_lun_online(ihp, ilp); 1794 } 1795 saved_replun_ptr[lun_count].lun_found = B_TRUE; 1796 break; 1797 } 1798 } else { 1799 /* 1800 * lun information is not found in the saved_replun 1801 * buffer, retrieve lun information from the SCSI 1802 * Report Lun buffer and store this information in 1803 * the saved_replun buffer 1804 */ 1805 if (retrieve_lundata(lun_count, buf, isp, &lun_num, 1806 &lun_addr_type) != ISCSI_STATUS_SUCCESS) { 1807 continue; 1808 } 1809 saved_replun_ptr[lun_count].lun_valid = B_TRUE; 1810 saved_replun_ptr[lun_count].lun_num = lun_num; 1811 if (ilp->lun_num == lun_num) { 1812 /* 1813 * lun is found in the SCSI Report Lun buffer 1814 * make sure the lun is in the ONLINE state 1815 */ 1816 saved_replun_ptr[lun_count].lun_found = B_TRUE; 1817 if ((ilp->lun_state & 1818 ISCSI_LUN_STATE_OFFLINE) || 1819 (ilp->lun_state & 1820 ISCSI_LUN_STATE_INVALID)) { 1821 #define SRLINON sess_reportluns_lun_is_not_online 1822 DTRACE_PROBE2( 1823 SRLINON, 1824 int, ilp->lun_num, int, 1825 ilp->lun_state); 1826 1827 iscsi_lun_online( 1828 ihp, ilp); 1829 #undef SRLINON 1830 } 1831 break; 1832 } 1833 } 1834 } 1835 1836 if (lun_count == lun_total) { 1837 /* 1838 * this lun we found in the sess->lun_list does not exist 1839 * anymore, need to offline this lun 1840 */ 1841 1842 DTRACE_PROBE2(sess_reportluns_lun_no_longer_exists, 1843 int, ilp->lun_num, int, ilp->lun_state); 1844 1845 (void) iscsi_lun_destroy(ihp, ilp); 1846 } 1847 } 1848 rw_exit(&isp->sess_lun_list_rwlock); 1849 1850 /* 1851 * look for new luns that we found in the SCSI Report Lun buffer that 1852 * we did not have in the sess->lun_list and add them into the list 1853 */ 1854 for (lun_count = lun_start; lun_count < lun_total; lun_count++) { 1855 if (saved_replun_ptr[lun_count].lun_valid == B_FALSE) { 1856 /* 1857 * lun information is not in the 1858 * saved_replun buffer, retrieve 1859 * it from the SCSI Report Lun buffer 1860 */ 1861 if (retrieve_lundata(lun_count, buf, isp, 1862 &lun_num, &lun_addr_type) != ISCSI_STATUS_SUCCESS) { 1863 continue; 1864 } 1865 } else { 1866 /* 1867 * lun information is in the saved_replun buffer 1868 * if this lun has been found already, then we can move on 1869 */ 1870 if (saved_replun_ptr[lun_count].lun_found == B_TRUE) { 1871 continue; 1872 } 1873 lun_num = saved_replun_ptr[lun_count].lun_num; 1874 } 1875 1876 1877 /* New luns found should not conflict with existing luns */ 1878 rw_enter(&isp->sess_lun_list_rwlock, RW_READER); 1879 for (ilp = isp->sess_lun_list; ilp; ilp = ilp->lun_next) { 1880 if (ilp->lun_num == lun_num) { 1881 break; 1882 } 1883 } 1884 rw_exit(&isp->sess_lun_list_rwlock); 1885 1886 if (ilp == NULL) { 1887 /* new lun found, add this lun */ 1888 iscsi_sess_inquiry(isp, lun_num, lun_addr_type); 1889 } else { 1890 cmn_err(CE_NOTE, 1891 "!Duplicate Lun Number(%d) recieved from " 1892 "Target(%s)", lun_num, isp->sess_name); 1893 } 1894 } 1895 1896 kmem_free(buf, buf_len); 1897 kmem_free(saved_replun_ptr, lun_total * sizeof (replun_data_t)); 1898 return (rval); 1899 } 1900 1901 #define ISCSI_MAX_INQUIRY_BUF_SIZE 0xFF 1902 #define ISCSI_MAX_INQUIRY_RETRIES 3 1903 1904 /* 1905 * iscsi_sess_inquiry - Final processing of a LUN before we create a tgt 1906 * mapping. We need to collect the stardard inquiry page and the 1907 * vendor identification page for this LUN. If both of these are 1908 * successful and the identification page contains a NAA or EUI type 1909 * we will continue. Otherwise we fail the creation of a tgt for 1910 * this LUN. 1911 * 1912 * The GUID creation in this function will be removed 1913 * we are pushing to have all this GUID code somewhere else. 1914 */ 1915 static void 1916 iscsi_sess_inquiry(iscsi_sess_t *isp, uint16_t lun_num, uint8_t lun_addr_type) 1917 { 1918 iscsi_status_t rval; 1919 struct uscsi_cmd ucmd; 1920 uchar_t cdb[CDB_GROUP0]; 1921 uchar_t *inq; 1922 size_t inq_len; 1923 uchar_t *inq83; 1924 size_t inq83_len; 1925 int retries; 1926 ddi_devid_t devid; 1927 char *guid = NULL; 1928 1929 ASSERT(isp != NULL); 1930 1931 inq = kmem_zalloc(ISCSI_MAX_INQUIRY_BUF_SIZE, KM_SLEEP); 1932 inq83 = kmem_zalloc(ISCSI_MAX_INQUIRY_BUF_SIZE, KM_SLEEP); 1933 1934 /* 1935 * STANDARD INQUIRY - We need the standard inquiry information 1936 * to feed into the scsi_hba_nodename_compatible_get function. 1937 * This function is used to detemine which driver will bind 1938 * on top of us, via the compatible id. 1939 */ 1940 bzero(&cdb, CDB_GROUP0); 1941 cdb[0] = SCMD_INQUIRY; 1942 cdb[4] = ISCSI_MAX_INQUIRY_BUF_SIZE; 1943 1944 bzero(&ucmd, sizeof (struct uscsi_cmd)); 1945 ucmd.uscsi_flags = USCSI_READ; 1946 ucmd.uscsi_timeout = iscsi_sess_enum_timeout; 1947 ucmd.uscsi_cdb = (char *)&cdb[0]; 1948 ucmd.uscsi_cdblen = CDB_GROUP0; 1949 ucmd.uscsi_bufaddr = (char *)inq; 1950 ucmd.uscsi_buflen = ISCSI_MAX_INQUIRY_BUF_SIZE; 1951 1952 /* Attempt to get inquiry information until successful or retries */ 1953 retries = 0; 1954 do { 1955 /* issue passthru */ 1956 rval = iscsi_handle_passthru(isp, lun_num, &ucmd); 1957 1958 /* If we were successful but scsi stat failed update istatus */ 1959 if (ISCSI_SUCCESS(rval) && 1960 (ucmd.uscsi_status != STATUS_GOOD)) { 1961 rval = ISCSI_STATUS_USCSI_FAILED; 1962 } 1963 1964 /* If successful break */ 1965 if (ISCSI_SUCCESS(rval)) { 1966 inq_len = ISCSI_MAX_INQUIRY_BUF_SIZE - ucmd.uscsi_resid; 1967 break; 1968 } 1969 1970 /* loop until we are successful or retries run out */ 1971 } while (retries++ < ISCSI_MAX_INQUIRY_RETRIES); 1972 1973 /* If failed don't continue */ 1974 if (!ISCSI_SUCCESS(rval)) { 1975 cmn_err(CE_NOTE, "iscsi session(%u) unable to enumerate " 1976 "logical unit - inquiry failed lun %d", 1977 isp->sess_oid, lun_num); 1978 1979 goto inq_done; 1980 } 1981 1982 /* 1983 * T-10 SPC Section 6.4.2. Standard INQUIRY Peripheral 1984 * qualifier of 000b is the only type we should attempt 1985 * to plumb under the IO stack. 1986 */ 1987 if ((inq[0] & SCSI_INQUIRY_PQUAL_MASK) != 0x00) { 1988 goto inq_done; 1989 } 1990 1991 /* 1992 * VENDOR IDENTIFICATION INQUIRY - This will be used to identify 1993 * a unique lunId. This Id is passed to the mdi alloc calls so 1994 * we can properly plumb into scsi_vhci/mpxio. 1995 */ 1996 1997 bzero(&cdb, CDB_GROUP0); 1998 cdb[0] = SCMD_INQUIRY; 1999 cdb[1] = 0x01; /* EVP bit */ 2000 cdb[2] = 0x83; 2001 cdb[4] = ISCSI_MAX_INQUIRY_BUF_SIZE; 2002 2003 ucmd.uscsi_flags = USCSI_READ; 2004 ucmd.uscsi_timeout = iscsi_sess_enum_timeout; 2005 ucmd.uscsi_cdb = (char *)&cdb[0]; 2006 ucmd.uscsi_cdblen = CDB_GROUP0; 2007 ucmd.uscsi_bufaddr = (char *)inq83; 2008 ucmd.uscsi_buflen = ISCSI_MAX_INQUIRY_BUF_SIZE; 2009 2010 /* Attempt to get inquiry information until successful or retries */ 2011 retries = 0; 2012 do { 2013 /* issue passthru command */ 2014 rval = iscsi_handle_passthru(isp, lun_num, &ucmd); 2015 2016 /* If we were successful but scsi stat failed update istatus */ 2017 if (ISCSI_SUCCESS(rval) && 2018 (ucmd.uscsi_status != STATUS_GOOD)) { 2019 rval = ISCSI_STATUS_USCSI_FAILED; 2020 } 2021 2022 /* Break if successful */ 2023 if (ISCSI_SUCCESS(rval)) { 2024 inq83_len = ISCSI_MAX_INQUIRY_BUF_SIZE - 2025 ucmd.uscsi_resid; 2026 break; 2027 } 2028 2029 } while (retries++ < ISCSI_MAX_INQUIRY_RETRIES); 2030 2031 /* 2032 * If we were successful collecting page 83 data attempt 2033 * to generate a GUID. If no GUID can be generated then 2034 * the logical unit will skip attempt to plumb under 2035 * scsi_vhci/mpxio. 2036 */ 2037 if (ISCSI_SUCCESS(rval)) { 2038 /* create DEVID from inquiry data */ 2039 if (ddi_devid_scsi_encode( 2040 DEVID_SCSI_ENCODE_VERSION_LATEST, NULL, 2041 inq, inq_len, NULL, 0, inq83, inq83_len, &devid) == 2042 DDI_SUCCESS) { 2043 2044 /* extract GUID from DEVID */ 2045 guid = ddi_devid_to_guid(devid); 2046 2047 /* devid no longer needed */ 2048 ddi_devid_free(devid); 2049 } 2050 } 2051 2052 rval = iscsi_lun_create(isp, lun_num, lun_addr_type, 2053 (struct scsi_inquiry *)inq, guid); 2054 2055 if (guid != NULL) { 2056 /* guid no longer needed */ 2057 ddi_devid_free_guid(guid); 2058 } 2059 2060 inq_done: 2061 /* free up memory now that we are done */ 2062 kmem_free(inq, ISCSI_MAX_INQUIRY_BUF_SIZE); 2063 kmem_free(inq83, ISCSI_MAX_INQUIRY_BUF_SIZE); 2064 } 2065 2066 static iscsi_status_t 2067 retrieve_lundata(uint32_t lun_count, unsigned char *buf, iscsi_sess_t *isp, 2068 uint16_t *lun_num, uint8_t *lun_addr_type) 2069 { 2070 uint32_t lun_idx = 0; 2071 2072 ASSERT(lun_num != NULL); 2073 ASSERT(lun_addr_type != NULL); 2074 2075 lun_idx = (lun_count + 1) * SCSI_REPORTLUNS_ADDRESS_SIZE; 2076 /* determine report luns addressing type */ 2077 switch (buf[lun_idx] & SCSI_REPORTLUNS_ADDRESS_MASK) { 2078 /* 2079 * Vendors in the field have been found to be concatenating 2080 * bus/target/lun to equal the complete lun value instead 2081 * of switching to flat space addressing 2082 */ 2083 /* 00b - peripheral device addressing method */ 2084 case SCSI_REPORTLUNS_ADDRESS_PERIPHERAL: 2085 /* FALLTHRU */ 2086 /* 10b - logical unit addressing method */ 2087 case SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT: 2088 /* FALLTHRU */ 2089 /* 01b - flat space addressing method */ 2090 case SCSI_REPORTLUNS_ADDRESS_FLAT_SPACE: 2091 /* byte0 bit0-5=msb lun byte1 bit0-7=lsb lun */ 2092 *lun_addr_type = (buf[lun_idx] & 2093 SCSI_REPORTLUNS_ADDRESS_MASK) >> 6; 2094 *lun_num = (buf[lun_idx] & 0x3F) << 8; 2095 *lun_num |= buf[lun_idx + 1]; 2096 return (ISCSI_STATUS_SUCCESS); 2097 default: /* protocol error */ 2098 cmn_err(CE_NOTE, "iscsi session(%u) unable " 2099 "to enumerate logical units - report " 2100 "luns returned an unsupported format", 2101 isp->sess_oid); 2102 break; 2103 } 2104 return (ISCSI_STATUS_INTERNAL_ERROR); 2105 } 2106 2107 /* 2108 * iscsi_sess_flush - flushes remaining pending io on the session 2109 */ 2110 static void 2111 iscsi_sess_flush(iscsi_sess_t *isp) 2112 { 2113 iscsi_cmd_t *icmdp; 2114 2115 ASSERT(isp != NULL); 2116 ASSERT(isp->sess_state != ISCSI_SESS_STATE_LOGGED_IN); 2117 2118 /* 2119 * Flush out any remaining commands in the pending 2120 * queue. 2121 */ 2122 mutex_enter(&isp->sess_queue_pending.mutex); 2123 icmdp = isp->sess_queue_pending.head; 2124 while (icmdp != NULL) { 2125 iscsi_cmd_state_machine(icmdp, 2126 ISCSI_CMD_EVENT_E7, isp); 2127 icmdp = isp->sess_queue_pending.head; 2128 } 2129 mutex_exit(&isp->sess_queue_pending.mutex); 2130 } 2131 2132 /* 2133 * iscsi_sess_offline_luns - offline all this sessions luns 2134 */ 2135 static void 2136 iscsi_sess_offline_luns(iscsi_sess_t *isp) 2137 { 2138 iscsi_lun_t *ilp; 2139 iscsi_hba_t *ihp; 2140 2141 ASSERT(isp != NULL); 2142 ASSERT(isp->sess_state != ISCSI_SESS_STATE_LOGGED_IN); 2143 ihp = isp->sess_hba; 2144 ASSERT(ihp != NULL); 2145 2146 rw_enter(&isp->sess_lun_list_rwlock, RW_READER); 2147 ilp = isp->sess_lun_list; 2148 while (ilp != NULL) { 2149 (void) iscsi_lun_offline(ihp, ilp, B_FALSE); 2150 ilp = ilp->lun_next; 2151 } 2152 rw_exit(&isp->sess_lun_list_rwlock); 2153 } 2154 2155 /* 2156 * iscsi_sess_get_by_target - return the session structure for based on a 2157 * passed in target oid and hba instance. NOTE: There may be 2158 * multiple sessions associated with any given target. In this case, 2159 * we will return the first matching session. This function 2160 * is intended to be used in retrieving target info that is constant 2161 * across sessions (target name, alias, etc.). 2162 */ 2163 int 2164 iscsi_sess_get_by_target(uint32_t target_oid, iscsi_hba_t *ihp, 2165 iscsi_sess_t **ispp) 2166 { 2167 int rval = 0; 2168 iscsi_sess_t *isp = NULL; 2169 2170 ASSERT(ihp != NULL); 2171 ASSERT(ispp != NULL); 2172 2173 /* See if we already created this session */ 2174 for (isp = ihp->hba_sess_list; isp; isp = isp->sess_next) { 2175 /* 2176 * Look for a session associated to the given target. 2177 * Return the first one found. 2178 */ 2179 if (isp->sess_target_oid == target_oid) { 2180 /* Found matching session */ 2181 break; 2182 } 2183 } 2184 2185 /* If not null this session is already available */ 2186 if (isp != NULL) { 2187 /* Existing session, return it */ 2188 *ispp = isp; 2189 } else { 2190 rval = EFAULT; 2191 } 2192 return (rval); 2193 } 2194