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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * iSCSI command interfaces 26 */ 27 28 #include "iscsi.h" 29 30 /* internal interfaces */ 31 static void iscsi_cmd_state_free(iscsi_cmd_t *icmdp, 32 iscsi_cmd_event_t event, void *arg); 33 static void iscsi_cmd_state_pending(iscsi_cmd_t *icmdp, 34 iscsi_cmd_event_t event, void *arg); 35 static void iscsi_cmd_state_active(iscsi_cmd_t *icmdp, 36 iscsi_cmd_event_t event, void *arg); 37 static void iscsi_cmd_state_aborting(iscsi_cmd_t *icmdp, 38 iscsi_cmd_event_t event, void *arg); 39 static void iscsi_cmd_state_completed(iscsi_cmd_t *icmdp, 40 iscsi_cmd_event_t event, void *arg); 41 static char *iscsi_cmd_state_str(iscsi_cmd_state_t state); 42 static char *iscsi_cmd_event_str(iscsi_cmd_event_t event); 43 /* LINTED E_STATIC_UNUSED */ 44 static char *iscsi_cmd_type_str(iscsi_cmd_type_t type); 45 46 #define ISCSI_INTERNAL_CMD_TIMEOUT 60 47 48 #define ISCSI_CMD_ISSUE_CALLBACK(icmdp, status) \ 49 icmdp->cmd_completed = B_TRUE; \ 50 icmdp->cmd_result = status; \ 51 cv_broadcast(&icmdp->cmd_completion); 52 53 #define ISCSI_CMD_SET_REASON_STAT(icmdp, reason, stat) \ 54 icmdp->cmd_un.scsi.pkt->pkt_reason = reason; \ 55 icmdp->cmd_un.scsi.pkt->pkt_statistics = stat; 56 57 /* 58 * The following private tunable, settable via 59 * set iscsi:iscsi_cmd_timeout_factor = 2 60 * in /etc/system, provides customer relief for configurations experiencing 61 * SCSI command timeouts due to high-latency/high-loss network connections 62 * or slow target response (possibly due to backing store issues). If frequent 63 * use of this tunable is necessary, a beter mechanism must be provided. 64 */ 65 int iscsi_cmd_timeout_factor = 1; 66 67 /* 68 * +--------------------------------------------------------------------+ 69 * | External Command Interfaces | 70 * +--------------------------------------------------------------------+ 71 */ 72 73 /* 74 * iscsi_cmd_state_machine - This function is used to drive the 75 * state machine of the internal iscsi commands. It takes in a command 76 * and the associated event affecting the command. 77 * 78 * 7.1.3 Command State Diagram for an Initiator 79 * Symbolic Names for States: 80 * C1: FREE - State on instantiation, or after successful 81 * completion. 82 * C2: PENDING - Command is in the session's pending queue awaiting 83 * its turn to be sent on the wire. 84 * C3: ACTIVE - Command has been sent on the wire and is 85 * awaiting completion. 86 * C4: ABORTING - Command which was sent on the wire has not timed 87 * out or been requested to abort by an upper layer 88 * driver. At this point there is a task management 89 * command in the active queue trying to abort the task. 90 * C5: COMPLETED - Command which is ready to complete via pkt callback. 91 * 92 * The state diagram is as follows: 93 * ------- 94 * / C1 \ 95 * I-------->\ /<------------ 96 * N| ---+--- | 97 * T| |E1 | 98 * E| V | 99 * R| ------- | 100 * N+--------/ C2 \ | 101 * A| E4/6/7\ /-------- | 102 * L| ---+--- E4/6/7| | 103 * | |E2 | | 104 * C| V | S | 105 * M| _______ | C | 106 * D+--------/ C3 \ | S | 107 * S E3/4/6/7\ /-------+ I | 108 * ---+---E3/4/6/7| | 109 * E4/6| | C | 110 * V | M | 111 * ------- | D | 112 * - >/ C4 \ | S | 113 * / \ /-------+ | 114 * | ---+---E3/6/7 | | 115 * | E4| V /E8 116 * ------ ------- 117 * / C5 \ 118 * \ / 119 * ---+--- 120 * 121 * The state transition table is as follows: 122 * 123 * +---------+---+---+-----+---------+ 124 * |C1 |C2 |C3 |C4 |C5 | 125 * ---+---------+---+---+-----+---------+ 126 * C1| - |E1 | - | - | | 127 * ---+---------+---+---+-----+---------+ 128 * C2|E4/6/7 |- |E2 | - |E4/6/7 | 129 * ---+---------+---+---+-----+---------+ 130 * C3|E3/4/6/7 |- |- |E4/6 |E3/4/6/7 | 131 * ---+---------+---+---+-----+---------+ 132 * C4| |- |- |E4 |E3/6/7 | 133 * ---+---------+---+---+-----+---------+ 134 * C5|E8 | | | | | 135 * ---+---------+---+---+-----+---------+ 136 * 137 * Event definitions: 138 * 139 * -E1: Command was requested to be sent on wire 140 * -E2: Command was submitted and now active on wire 141 * -E3: Command was successfully completed 142 * - SCSI command is move to completion queue 143 * - ABORT/RESET/etc are completed. 144 * -E4: Command has been requested to abort 145 * - SCSI command in pending queue will be returned 146 * to caller with aborted status. 147 * - SCSI command state updated and iscsi_handle_abort() 148 * will be called. 149 * - SCSI command with ABORTING state has already 150 * been requested to abort ignore request. 151 * - ABORT/RESET commands will be destroyed and the 152 * caller will be notify of the failure. 153 * - All other commands will just be destroyed. 154 * -E6: Command has timed out 155 * - SCSI commands in pending queue will be returned up the 156 * stack with TIMEOUT errors. 157 * - SCSI commands in the active queue and timed out 158 * will be moved to the aborting queue. 159 * - SCSI commands in ABORTING state will be returned up 160 * up the stack with TIMEOUT errors. 161 * - ABORT/RESET commands will be destroyed and the caller 162 * notified of the failure. 163 * - All other commands will just be detroyed. 164 * -E7: Connection has encountered a problem 165 * -E8: Command has completed 166 * - Only SCSI cmds should receive these events 167 * and reach the command state. 168 */ 169 void 170 iscsi_cmd_state_machine(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg) 171 { 172 boolean_t release_lock = B_TRUE; 173 174 ASSERT(icmdp != NULL); 175 ASSERT(arg != NULL); 176 177 DTRACE_PROBE3(event, iscsi_cmd_t *, icmdp, char *, 178 iscsi_cmd_state_str(icmdp->cmd_state), 179 char *, iscsi_cmd_event_str(event)); 180 181 mutex_enter(&icmdp->cmd_mutex); 182 icmdp->cmd_prev_state = icmdp->cmd_state; 183 switch (icmdp->cmd_state) { 184 case ISCSI_CMD_STATE_FREE: 185 iscsi_cmd_state_free(icmdp, event, arg); 186 break; 187 188 case ISCSI_CMD_STATE_PENDING: 189 iscsi_cmd_state_pending(icmdp, event, arg); 190 break; 191 192 case ISCSI_CMD_STATE_ACTIVE: 193 iscsi_cmd_state_active(icmdp, event, arg); 194 break; 195 196 case ISCSI_CMD_STATE_ABORTING: 197 iscsi_cmd_state_aborting(icmdp, event, arg); 198 break; 199 200 case ISCSI_CMD_STATE_COMPLETED: 201 iscsi_cmd_state_completed(icmdp, event, arg); 202 203 /* 204 * Once completed event is processed we DO NOT 205 * want to touch it again because the caller 206 * (sd, st, etc) may have freed the command. 207 */ 208 release_lock = B_FALSE; 209 break; 210 211 default: 212 ASSERT(FALSE); 213 } 214 215 if (release_lock == B_TRUE) { 216 if ((icmdp->cmd_free == B_FALSE) || 217 (icmdp->cmd_internal == B_FALSE)) { 218 mutex_exit(&icmdp->cmd_mutex); 219 return; 220 } 221 mutex_exit(&icmdp->cmd_mutex); 222 iscsi_cmd_free(icmdp); 223 } 224 } 225 226 /* 227 * iscsi_cmd_alloc - 228 * 229 */ 230 iscsi_cmd_t * 231 iscsi_cmd_alloc(iscsi_conn_t *icp, int km_flags) 232 { 233 iscsi_cmd_t *icmdp; 234 235 icmdp = kmem_zalloc(sizeof (iscsi_cmd_t), km_flags); 236 if (icmdp) { 237 icmdp->cmd_sig = ISCSI_SIG_CMD; 238 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 239 icmdp->cmd_conn = icp; 240 icmdp->cmd_internal = B_TRUE; 241 mutex_init(&icmdp->cmd_mutex, NULL, MUTEX_DRIVER, NULL); 242 cv_init(&icmdp->cmd_completion, NULL, CV_DRIVER, NULL); 243 } 244 return (icmdp); 245 } 246 247 /* 248 * iscsi_cmd_free - 249 * 250 */ 251 void 252 iscsi_cmd_free(iscsi_cmd_t *icmdp) 253 { 254 ASSERT(icmdp != NULL); 255 ASSERT(icmdp->cmd_sig == ISCSI_SIG_CMD); 256 ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_FREE); 257 ASSERT(icmdp->cmd_next == NULL); 258 ASSERT(icmdp->cmd_prev == NULL); 259 ASSERT(icmdp->cmd_internal); 260 261 if (icmdp->cmd_type == ISCSI_CMD_TYPE_R2T) 262 ASSERT(icmdp->cmd_un.r2t.icmdp == NULL); 263 else if (icmdp->cmd_type == ISCSI_CMD_TYPE_ABORT) 264 ASSERT(icmdp->cmd_un.abort.icmdp == NULL); 265 else if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) { 266 ASSERT(icmdp->cmd_un.scsi.r2t_icmdp == NULL); 267 ASSERT(icmdp->cmd_un.scsi.abort_icmdp == NULL); 268 } 269 mutex_destroy(&icmdp->cmd_mutex); 270 cv_destroy(&icmdp->cmd_completion); 271 kmem_free(icmdp, sizeof (iscsi_cmd_t)); 272 } 273 274 /* 275 * +--------------------------------------------------------------------+ 276 * | Internal Command Interfaces | 277 * +--------------------------------------------------------------------+ 278 */ 279 280 281 /* 282 * iscsi_cmd_state_free - 283 * 284 */ 285 static void 286 iscsi_cmd_state_free(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg) 287 { 288 iscsi_sess_t *isp = (iscsi_sess_t *)arg; 289 290 ASSERT(icmdp != NULL); 291 ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_FREE); 292 ASSERT(isp != NULL); 293 294 /* switch on event change */ 295 switch (event) { 296 /* -E1: Command was requested to be sent on wire */ 297 case ISCSI_CMD_EVENT_E1: 298 299 /* setup timestamps and timeouts for this command */ 300 icmdp->cmd_lbolt_pending = ddi_get_lbolt(); 301 if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) { 302 /* 303 * Establish absolute time when command should timeout. 304 * For commands the depend on cmdsn window to go 305 * active, the timeout will be ignored while on 306 * the pending queue and a new timeout will be 307 * established when the command goes active. 308 */ 309 if (icmdp->cmd_un.scsi.pkt && 310 icmdp->cmd_un.scsi.pkt->pkt_time) 311 icmdp->cmd_lbolt_timeout = 312 icmdp->cmd_lbolt_pending + SEC_TO_TICK( 313 icmdp->cmd_un.scsi.pkt->pkt_time * 314 iscsi_cmd_timeout_factor); 315 else 316 icmdp->cmd_lbolt_timeout = 0; 317 } else { 318 icmdp->cmd_lbolt_timeout = icmdp->cmd_lbolt_pending + 319 SEC_TO_TICK(ISCSI_INTERNAL_CMD_TIMEOUT * 320 iscsi_cmd_timeout_factor); 321 } 322 323 /* place into pending queue */ 324 iscsi_enqueue_pending_cmd(isp, icmdp); 325 326 break; 327 328 /* All other events are invalid for this state */ 329 default: 330 ASSERT(FALSE); 331 } 332 } 333 334 /* 335 * iscsi_cmd_state_pending - 336 * 337 */ 338 static void 339 iscsi_cmd_state_pending(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg) 340 { 341 iscsi_status_t status; 342 iscsi_sess_t *isp = (iscsi_sess_t *)arg; 343 boolean_t free_icmdp = B_FALSE; 344 int rval; 345 346 ASSERT(icmdp != NULL); 347 ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_PENDING); 348 ASSERT(isp != NULL); 349 ASSERT(mutex_owned(&isp->sess_queue_pending.mutex)); 350 351 /* switch on event change */ 352 switch (event) { 353 /* -E2: Command was submitted and now active on wire */ 354 case ISCSI_CMD_EVENT_E2: 355 356 /* A connection should have already been assigned */ 357 ASSERT(icmdp->cmd_conn != NULL); 358 359 /* 360 * RESERVE RESOURSES 361 */ 362 switch (icmdp->cmd_type) { 363 case ISCSI_CMD_TYPE_SCSI: 364 /* check cmdsn window */ 365 mutex_enter(&isp->sess_cmdsn_mutex); 366 if (!iscsi_sna_lte(isp->sess_cmdsn, 367 isp->sess_maxcmdsn)) { 368 /* cmdsn window closed */ 369 mutex_exit(&isp->sess_cmdsn_mutex); 370 mutex_exit(&isp->sess_queue_pending.mutex); 371 isp->sess_window_open = B_FALSE; 372 return; 373 } 374 375 /* assign itt */ 376 status = iscsi_sess_reserve_itt(isp, icmdp); 377 if (!ISCSI_SUCCESS(status)) { 378 /* no available itt slots */ 379 mutex_exit(&isp->sess_cmdsn_mutex); 380 mutex_exit(&isp->sess_queue_pending.mutex); 381 isp->sess_window_open = B_FALSE; 382 return; 383 } 384 mutex_exit(&isp->sess_cmdsn_mutex); 385 break; 386 387 case ISCSI_CMD_TYPE_ABORT: 388 /* 389 * Verify ABORT's parent SCSI command is still 390 * there. If parent SCSI command is completed 391 * then there is no longer any reason to abort 392 * the parent command. This could occur due 393 * to a connection or target reset. 394 */ 395 ASSERT(icmdp->cmd_un.abort.icmdp != NULL); 396 if (icmdp->cmd_un.abort.icmdp->cmd_state == 397 ISCSI_CMD_STATE_COMPLETED) { 398 iscsi_dequeue_pending_cmd(isp, icmdp); 399 mutex_exit(&isp->sess_queue_pending.mutex); 400 401 mutex_enter(&icmdp->cmd_un.abort.icmdp-> 402 cmd_mutex); 403 icmdp->cmd_un.abort.icmdp-> 404 cmd_un.scsi.abort_icmdp = NULL; 405 cv_broadcast(&icmdp->cmd_un.abort.icmdp-> 406 cmd_completion); 407 mutex_exit(&icmdp->cmd_un.abort.icmdp-> 408 cmd_mutex); 409 icmdp->cmd_un.abort.icmdp = NULL; 410 411 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 412 icmdp->cmd_free = B_TRUE; 413 return; 414 } 415 /* FALLTHRU */ 416 case ISCSI_CMD_TYPE_RESET: 417 /* FALLTHRU */ 418 case ISCSI_CMD_TYPE_LOGOUT: 419 mutex_enter(&isp->sess_cmdsn_mutex); 420 /* assign itt */ 421 status = iscsi_sess_reserve_itt(isp, icmdp); 422 if (!ISCSI_SUCCESS(status)) { 423 /* no available itt slots */ 424 mutex_exit(&isp->sess_cmdsn_mutex); 425 mutex_exit(&isp->sess_queue_pending.mutex); 426 isp->sess_window_open = B_FALSE; 427 return; 428 } 429 mutex_exit(&isp->sess_cmdsn_mutex); 430 break; 431 case ISCSI_CMD_TYPE_R2T: 432 /* no additional resources required */ 433 free_icmdp = B_TRUE; 434 break; 435 case ISCSI_CMD_TYPE_NOP: 436 /* assign itt, if needed */ 437 if (icmdp->cmd_itt == ISCSI_RSVD_TASK_TAG) { 438 /* not expecting a response */ 439 free_icmdp = B_TRUE; 440 } else { 441 /* expecting response, assign an itt */ 442 mutex_enter(&isp->sess_cmdsn_mutex); 443 /* assign itt */ 444 status = iscsi_sess_reserve_itt(isp, icmdp); 445 if (!ISCSI_SUCCESS(status)) { 446 /* no available itt slots */ 447 mutex_exit(&isp->sess_cmdsn_mutex); 448 mutex_exit(&isp->sess_queue_pending. 449 mutex); 450 isp->sess_window_open = B_FALSE; 451 return; 452 } 453 mutex_exit(&isp->sess_cmdsn_mutex); 454 } 455 break; 456 457 case ISCSI_CMD_TYPE_TEXT: 458 mutex_enter(&isp->sess_cmdsn_mutex); 459 /* check cmdsn window */ 460 if (!iscsi_sna_lte(isp->sess_cmdsn, 461 isp->sess_maxcmdsn)) { 462 /* cmdsn window closed */ 463 isp->sess_window_open = B_FALSE; 464 mutex_exit(&isp->sess_cmdsn_mutex); 465 mutex_exit(&isp->sess_queue_pending.mutex); 466 return; 467 } 468 if (icmdp->cmd_un.text.stage == 469 ISCSI_CMD_TEXT_INITIAL_REQ) { 470 /* assign itt */ 471 status = iscsi_sess_reserve_itt(isp, icmdp); 472 if (!ISCSI_SUCCESS(status)) { 473 /* no available itt slots */ 474 mutex_exit(&isp->sess_cmdsn_mutex); 475 mutex_exit(&isp->sess_queue_pending. 476 mutex); 477 isp->sess_window_open = B_FALSE; 478 return; 479 } 480 } 481 mutex_exit(&isp->sess_cmdsn_mutex); 482 break; 483 484 default: 485 ASSERT(FALSE); 486 } 487 488 /* 489 * RESOURCES RESERVED 490 * 491 * Now that we have the resources reserved, establish timeout 492 * for cmd_type values that depend on having an open cmdsn 493 * window (i.e. cmd_type that called iscsi_sna_lte() above). 494 */ 495 if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) { 496 if (icmdp->cmd_un.scsi.pkt && 497 icmdp->cmd_un.scsi.pkt->pkt_time) 498 icmdp->cmd_lbolt_timeout = 499 ddi_get_lbolt() + SEC_TO_TICK( 500 icmdp->cmd_un.scsi.pkt->pkt_time * 501 iscsi_cmd_timeout_factor); 502 else 503 icmdp->cmd_lbolt_timeout = 0; 504 } else if (icmdp->cmd_type == ISCSI_CMD_TYPE_TEXT) { 505 icmdp->cmd_lbolt_timeout = ddi_get_lbolt() + 506 SEC_TO_TICK(ISCSI_INTERNAL_CMD_TIMEOUT * 507 iscsi_cmd_timeout_factor); 508 } 509 510 /* remove command from pending queue */ 511 iscsi_dequeue_pending_cmd(isp, icmdp); 512 513 /* check if expecting a response */ 514 if (free_icmdp == B_FALSE) { 515 /* response expected, move to active queue */ 516 mutex_enter(&icmdp->cmd_conn->conn_queue_active.mutex); 517 iscsi_enqueue_active_cmd(icmdp->cmd_conn, icmdp); 518 mutex_exit(&icmdp->cmd_conn->conn_queue_active.mutex); 519 } 520 521 /* 522 * TRANSFER COMMAND 523 */ 524 rval = iscsi_tx_cmd(isp, icmdp); 525 526 ASSERT(!mutex_owned(&isp->sess_queue_pending.mutex)); 527 528 /* 529 * CHECK SUCCESS/FAILURE 530 */ 531 if (!ISCSI_SUCCESS(rval)) { 532 /* 533 * iscsi_tx_cmd failed. No cleanup is required 534 * of commands that were put in the active queue. 535 * If the tx failed then rx will also fail and cleanup 536 * all items in the active/aborted queue in a common. 537 */ 538 539 /* EMPTY */ 540 } 541 542 /* free temporary commands */ 543 if (free_icmdp == B_TRUE) { 544 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 545 icmdp->cmd_free = B_TRUE; 546 } 547 break; 548 549 /* -E4: Command has been requested to abort */ 550 case ISCSI_CMD_EVENT_E4: 551 552 icmdp->cmd_lbolt_aborting = ddi_get_lbolt(); 553 ISCSI_CMD_SET_REASON_STAT(icmdp, 554 CMD_ABORTED, STAT_ABORTED); 555 556 iscsi_dequeue_pending_cmd(isp, icmdp); 557 iscsi_enqueue_completed_cmd(isp, icmdp); 558 559 icmdp->cmd_lbolt_aborting = ddi_get_lbolt(); 560 561 break; 562 563 /* -E7: Command has been reset */ 564 case ISCSI_CMD_EVENT_E7: 565 566 /* FALLTHRU */ 567 568 /* -E6: Command has timed out */ 569 case ISCSI_CMD_EVENT_E6: 570 iscsi_dequeue_pending_cmd(isp, icmdp); 571 572 switch (icmdp->cmd_type) { 573 case ISCSI_CMD_TYPE_SCSI: 574 /* Complete to caller as TIMEOUT */ 575 if (event == ISCSI_CMD_EVENT_E6) { 576 ISCSI_CMD_SET_REASON_STAT(icmdp, 577 CMD_TIMEOUT, STAT_TIMEOUT); 578 } else { 579 ISCSI_CMD_SET_REASON_STAT(icmdp, 580 CMD_TRAN_ERR, 0); 581 } 582 iscsi_enqueue_completed_cmd(isp, icmdp); 583 break; 584 585 case ISCSI_CMD_TYPE_R2T: 586 mutex_enter(&icmdp->cmd_un.r2t.icmdp->cmd_mutex); 587 icmdp->cmd_un.r2t.icmdp-> 588 cmd_un.scsi.r2t_icmdp = NULL; 589 cv_broadcast(&icmdp->cmd_un.r2t.icmdp-> 590 cmd_completion); 591 mutex_exit(&icmdp->cmd_un.r2t.icmdp->cmd_mutex); 592 icmdp->cmd_un.r2t.icmdp = NULL; 593 594 /* 595 * If this command is timing out then 596 * the SCSI command will be timing out 597 * also. Just free the memory. 598 */ 599 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 600 icmdp->cmd_free = B_TRUE; 601 break; 602 603 case ISCSI_CMD_TYPE_NOP: 604 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 605 /* 606 * Timeout occured. Just free NOP. Another 607 * NOP request will be spawned to replace 608 * this one. 609 */ 610 icmdp->cmd_free = B_TRUE; 611 break; 612 613 case ISCSI_CMD_TYPE_ABORT: 614 mutex_enter(&icmdp->cmd_un.abort.icmdp->cmd_mutex); 615 icmdp->cmd_un.abort.icmdp-> 616 cmd_un.scsi.abort_icmdp = NULL; 617 cv_broadcast(&icmdp->cmd_un.abort.icmdp-> 618 cmd_completion); 619 mutex_exit(&icmdp->cmd_un.abort.icmdp->cmd_mutex); 620 icmdp->cmd_un.abort.icmdp = NULL; 621 622 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 623 icmdp->cmd_free = B_TRUE; 624 break; 625 626 case ISCSI_CMD_TYPE_RESET: 627 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 628 /* 629 * If we are failing a RESET we need 630 * to notify the tran_reset caller. 631 * with the cmd and notify caller. 632 */ 633 ISCSI_CMD_ISSUE_CALLBACK(icmdp, 634 ISCSI_STATUS_CMD_FAILED); 635 break; 636 637 case ISCSI_CMD_TYPE_LOGOUT: 638 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 639 /* notify requester of failure */ 640 ISCSI_CMD_ISSUE_CALLBACK(icmdp, 641 ISCSI_STATUS_CMD_FAILED); 642 break; 643 644 case ISCSI_CMD_TYPE_TEXT: 645 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 646 icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP; 647 /* 648 * If a TEXT command fails, notify the owner. 649 */ 650 ISCSI_CMD_ISSUE_CALLBACK(icmdp, 651 ISCSI_STATUS_CMD_FAILED); 652 break; 653 654 default: 655 ASSERT(FALSE); 656 break; 657 } 658 break; 659 660 /* All other events are invalid for this state */ 661 default: 662 ASSERT(FALSE); 663 } 664 } 665 666 667 /* 668 * iscsi_cmd_state_active - 669 * 670 */ 671 static void 672 iscsi_cmd_state_active(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg) 673 { 674 iscsi_sess_t *isp = (iscsi_sess_t *)arg; 675 iscsi_hba_t *ihp; 676 iscsi_cmd_t *t_icmdp = NULL; 677 iscsi_conn_t *icp = NULL; 678 679 ASSERT(icmdp != NULL); 680 ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_ACTIVE); 681 ASSERT(isp != NULL); 682 683 ihp = isp->sess_hba; 684 ASSERT(ihp != NULL); 685 686 icp = icmdp->cmd_conn; 687 ASSERT(icp != NULL); 688 ASSERT(mutex_owned(&icp->conn_queue_active.mutex)); 689 690 /* switch on event change */ 691 switch (event) { 692 /* -E3: Command was successfully completed */ 693 case ISCSI_CMD_EVENT_E3: 694 /* 695 * Remove command from the active list. We need to protect 696 * someone from looking up this command ITT until it's 697 * freed of the command is moved to a new queue location. 698 */ 699 mutex_enter(&isp->sess_cmdsn_mutex); 700 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp); 701 702 switch (icmdp->cmd_type) { 703 case ISCSI_CMD_TYPE_SCSI: 704 iscsi_sess_release_itt(isp, icmdp); 705 mutex_exit(&isp->sess_cmdsn_mutex); 706 iscsi_enqueue_completed_cmd(isp, icmdp); 707 break; 708 709 case ISCSI_CMD_TYPE_R2T: 710 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 711 mutex_exit(&isp->sess_cmdsn_mutex); 712 /* 713 * R2T commands do not have responses 714 * so these command should never be 715 * placed in the active queue. 716 */ 717 ASSERT(FALSE); 718 break; 719 720 case ISCSI_CMD_TYPE_NOP: 721 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 722 iscsi_sess_release_itt(isp, icmdp); 723 mutex_exit(&isp->sess_cmdsn_mutex); 724 725 /* free alloc */ 726 icmdp->cmd_free = B_TRUE; 727 break; 728 729 case ISCSI_CMD_TYPE_ABORT: 730 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 731 iscsi_sess_release_itt(isp, icmdp); 732 mutex_exit(&isp->sess_cmdsn_mutex); 733 734 /* 735 * Abort was completed successfully. We should 736 * complete the parent scsi command if it still 737 * exists as timed out, and the state is not 738 * COMPLETED 739 */ 740 t_icmdp = icmdp->cmd_un.abort.icmdp; 741 ASSERT(t_icmdp != NULL); 742 mutex_enter(&t_icmdp->cmd_mutex); 743 if (t_icmdp->cmd_state != ISCSI_CMD_STATE_COMPLETED) { 744 mutex_enter(&isp->sess_cmdsn_mutex); 745 iscsi_dequeue_active_cmd( 746 t_icmdp->cmd_conn, t_icmdp); 747 iscsi_sess_release_itt(isp, t_icmdp); 748 mutex_exit(&isp->sess_cmdsn_mutex); 749 750 ISCSI_CMD_SET_REASON_STAT( 751 t_icmdp, CMD_TIMEOUT, STAT_TIMEOUT); 752 iscsi_enqueue_completed_cmd(isp, t_icmdp); 753 } 754 755 t_icmdp->cmd_un.scsi.abort_icmdp = NULL; 756 cv_broadcast(&t_icmdp->cmd_completion); 757 mutex_exit(&t_icmdp->cmd_mutex); 758 icmdp->cmd_un.abort.icmdp = NULL; 759 760 icmdp->cmd_free = B_TRUE; 761 break; 762 case ISCSI_CMD_TYPE_RESET: 763 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 764 iscsi_sess_release_itt(isp, icmdp); 765 mutex_exit(&isp->sess_cmdsn_mutex); 766 767 /* 768 * Complete the abort/reset successfully. 769 */ 770 ISCSI_CMD_ISSUE_CALLBACK(icmdp, ISCSI_STATUS_SUCCESS); 771 break; 772 773 case ISCSI_CMD_TYPE_LOGOUT: 774 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 775 iscsi_sess_release_itt(isp, icmdp); 776 mutex_exit(&isp->sess_cmdsn_mutex); 777 778 /* 779 * Complete the logout successfully. 780 */ 781 ISCSI_CMD_ISSUE_CALLBACK(icmdp, ISCSI_STATUS_SUCCESS); 782 break; 783 784 case ISCSI_CMD_TYPE_TEXT: 785 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 786 if (icmdp->cmd_un.text.stage == 787 ISCSI_CMD_TEXT_FINAL_RSP) { 788 iscsi_sess_release_itt(isp, icmdp); 789 } 790 mutex_exit(&isp->sess_cmdsn_mutex); 791 792 /* 793 * Complete the text command successfully. 794 */ 795 ISCSI_CMD_ISSUE_CALLBACK(icmdp, icmdp->cmd_result); 796 break; 797 798 default: 799 mutex_exit(&isp->sess_cmdsn_mutex); 800 ASSERT(FALSE); 801 } 802 803 ASSERT(!mutex_owned(&isp->sess_cmdsn_mutex)); 804 break; 805 806 /* -E4: Command has been requested to abort */ 807 case ISCSI_CMD_EVENT_E4: 808 809 /* E4 is only for resets and aborts */ 810 ASSERT((icmdp->cmd_type == ISCSI_CMD_TYPE_ABORT) || 811 (icmdp->cmd_type == ISCSI_CMD_TYPE_RESET)); 812 /* FALLTHRU */ 813 814 /* -E6: Command has timed out */ 815 case ISCSI_CMD_EVENT_E6: 816 817 switch (icmdp->cmd_type) { 818 case ISCSI_CMD_TYPE_SCSI: 819 icmdp->cmd_state = ISCSI_CMD_STATE_ABORTING; 820 iscsi_handle_abort(icmdp); 821 break; 822 823 case ISCSI_CMD_TYPE_R2T: 824 mutex_enter(&isp->sess_cmdsn_mutex); 825 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp); 826 mutex_exit(&isp->sess_cmdsn_mutex); 827 828 /* should never get in active queue */ 829 ASSERT(FALSE); 830 break; 831 832 case ISCSI_CMD_TYPE_NOP: 833 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 834 835 mutex_enter(&isp->sess_cmdsn_mutex); 836 iscsi_sess_release_itt(isp, icmdp); 837 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp); 838 mutex_exit(&isp->sess_cmdsn_mutex); 839 840 icmdp->cmd_free = B_TRUE; 841 break; 842 843 case ISCSI_CMD_TYPE_ABORT: 844 icmdp->cmd_state = 845 ISCSI_CMD_STATE_FREE; 846 847 mutex_enter(&isp->sess_cmdsn_mutex); 848 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp); 849 iscsi_sess_release_itt(isp, icmdp); 850 mutex_exit(&isp->sess_cmdsn_mutex); 851 852 t_icmdp = icmdp->cmd_un.abort.icmdp; 853 ASSERT(t_icmdp != NULL); 854 mutex_enter(&t_icmdp->cmd_mutex); 855 856 /* 857 * If abort command is aborted then we should 858 * not act on the parent scsi command. If the 859 * abort command timed out then we need to 860 * complete the parent command if it still 861 * exists with a timeout failure. 862 */ 863 if ((event == ISCSI_CMD_EVENT_E6) && 864 (t_icmdp->cmd_state != ISCSI_CMD_STATE_COMPLETED)) { 865 866 mutex_enter(&isp->sess_cmdsn_mutex); 867 iscsi_dequeue_active_cmd( 868 t_icmdp->cmd_conn, 869 t_icmdp); 870 iscsi_sess_release_itt(isp, 871 t_icmdp); 872 mutex_exit(&isp->sess_cmdsn_mutex); 873 874 ISCSI_CMD_SET_REASON_STAT(t_icmdp, 875 CMD_TIMEOUT, STAT_TIMEOUT); 876 iscsi_enqueue_completed_cmd(isp, 877 t_icmdp); 878 } 879 880 t_icmdp->cmd_un.scsi.abort_icmdp = NULL; 881 cv_broadcast(&t_icmdp->cmd_completion); 882 mutex_exit(&t_icmdp->cmd_mutex); 883 icmdp->cmd_un.abort.icmdp = NULL; 884 885 icmdp->cmd_free = B_TRUE; 886 break; 887 888 case ISCSI_CMD_TYPE_RESET: 889 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 890 891 mutex_enter(&isp->sess_cmdsn_mutex); 892 iscsi_sess_release_itt(isp, icmdp); 893 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp); 894 mutex_exit(&isp->sess_cmdsn_mutex); 895 896 /* 897 * If we are failing a RESET we need 898 * to notify the tran_reset caller. 899 * It will free the memory associated 900 * with the cmd and notify caller. 901 */ 902 903 ISCSI_CMD_ISSUE_CALLBACK(icmdp, 904 ISCSI_STATUS_CMD_FAILED); 905 break; 906 907 case ISCSI_CMD_TYPE_LOGOUT: 908 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 909 910 mutex_enter(&isp->sess_cmdsn_mutex); 911 iscsi_sess_release_itt(isp, icmdp); 912 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp); 913 mutex_exit(&isp->sess_cmdsn_mutex); 914 915 /* 916 * Notify caller of failure. 917 */ 918 ISCSI_CMD_ISSUE_CALLBACK(icmdp, 919 ISCSI_STATUS_CMD_FAILED); 920 break; 921 922 case ISCSI_CMD_TYPE_TEXT: 923 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 924 icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP; 925 mutex_enter(&isp->sess_cmdsn_mutex); 926 iscsi_sess_release_itt(isp, icmdp); 927 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp); 928 mutex_exit(&isp->sess_cmdsn_mutex); 929 930 /* 931 * If a TEXT command fails, notify caller so 932 * it can free assocated command 933 */ 934 ISCSI_CMD_ISSUE_CALLBACK(icmdp, 935 ISCSI_STATUS_CMD_FAILED); 936 break; 937 938 default: 939 mutex_enter(&isp->sess_cmdsn_mutex); 940 ASSERT(FALSE); 941 } 942 943 ASSERT(!mutex_owned(&isp->sess_cmdsn_mutex)); 944 break; 945 946 /* -E7: Connection has encountered a problem */ 947 case ISCSI_CMD_EVENT_E7: 948 949 mutex_enter(&isp->sess_cmdsn_mutex); 950 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp); 951 952 switch (icmdp->cmd_type) { 953 case ISCSI_CMD_TYPE_SCSI: 954 iscsi_sess_release_itt(isp, icmdp); 955 mutex_exit(&isp->sess_cmdsn_mutex); 956 957 /* notify caller of error */ 958 ISCSI_CMD_SET_REASON_STAT(icmdp, 959 CMD_TRAN_ERR, 0); 960 iscsi_enqueue_completed_cmd(isp, icmdp); 961 break; 962 963 case ISCSI_CMD_TYPE_R2T: 964 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 965 mutex_exit(&isp->sess_cmdsn_mutex); 966 /* should never get in active queue */ 967 ASSERT(FALSE); 968 break; 969 970 case ISCSI_CMD_TYPE_NOP: 971 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 972 iscsi_sess_release_itt(isp, icmdp); 973 mutex_exit(&isp->sess_cmdsn_mutex); 974 975 icmdp->cmd_free = B_TRUE; 976 break; 977 978 case ISCSI_CMD_TYPE_ABORT: 979 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 980 iscsi_sess_release_itt(isp, icmdp); 981 mutex_exit(&isp->sess_cmdsn_mutex); 982 983 mutex_enter(&icmdp->cmd_un.abort.icmdp->cmd_mutex); 984 icmdp->cmd_un.abort.icmdp-> 985 cmd_un.scsi.abort_icmdp = NULL; 986 cv_broadcast(&icmdp->cmd_un.abort.icmdp-> 987 cmd_completion); 988 mutex_exit(&icmdp->cmd_un.abort.icmdp->cmd_mutex); 989 /* 990 * Nullify the abort command's pointer to its 991 * parent command. It does not have to complete its 992 * parent command because the parent command will 993 * also get an E7. 994 */ 995 icmdp->cmd_un.abort.icmdp = NULL; 996 997 icmdp->cmd_free = B_TRUE; 998 break; 999 1000 case ISCSI_CMD_TYPE_RESET: 1001 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 1002 iscsi_sess_release_itt(isp, icmdp); 1003 mutex_exit(&isp->sess_cmdsn_mutex); 1004 /* 1005 * If we are failing a ABORT we need 1006 * to notify the tran_abort caller. 1007 * It will free the memory associated 1008 * with the cmd and notify caller. 1009 */ 1010 1011 ISCSI_CMD_ISSUE_CALLBACK(icmdp, 1012 ISCSI_STATUS_CMD_FAILED); 1013 break; 1014 1015 case ISCSI_CMD_TYPE_LOGOUT: 1016 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 1017 /* 1018 * A connection problem and we attempted to 1019 * logout? I guess we can just free the 1020 * request. Someone has already pushed the 1021 * connection state. 1022 */ 1023 iscsi_sess_release_itt(isp, icmdp); 1024 mutex_exit(&isp->sess_cmdsn_mutex); 1025 1026 ISCSI_CMD_ISSUE_CALLBACK(icmdp, ISCSI_STATUS_SUCCESS); 1027 break; 1028 1029 case ISCSI_CMD_TYPE_TEXT: 1030 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 1031 icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP; 1032 iscsi_sess_release_itt(isp, icmdp); 1033 mutex_exit(&isp->sess_cmdsn_mutex); 1034 1035 /* 1036 * If a TEXT command fails, notify caller so 1037 * it can free assocated command 1038 */ 1039 ISCSI_CMD_ISSUE_CALLBACK(icmdp, 1040 ISCSI_STATUS_CMD_FAILED); 1041 break; 1042 1043 default: 1044 mutex_exit(&isp->sess_cmdsn_mutex); 1045 ASSERT(FALSE); 1046 break; 1047 } 1048 1049 ASSERT(!mutex_owned(&isp->sess_cmdsn_mutex)); 1050 break; 1051 1052 /* All other events are invalid for this state */ 1053 default: 1054 ASSERT(FALSE); 1055 } 1056 } 1057 1058 1059 /* 1060 * iscsi_cmd_state_aborting - 1061 * 1062 */ 1063 static void 1064 iscsi_cmd_state_aborting(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg) 1065 { 1066 iscsi_sess_t *isp = (iscsi_sess_t *)arg; 1067 1068 ASSERT(icmdp != NULL); 1069 ASSERT(icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI); 1070 ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_ABORTING); 1071 ASSERT(isp != NULL); 1072 ASSERT(mutex_owned(&icmdp->cmd_conn->conn_queue_active.mutex)); 1073 1074 /* switch on event change */ 1075 switch (event) { 1076 /* -E3: Command was successfully completed */ 1077 case ISCSI_CMD_EVENT_E3: 1078 /* 1079 * Remove command from the aborting list 1080 */ 1081 mutex_enter(&isp->sess_cmdsn_mutex); 1082 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp); 1083 iscsi_sess_release_itt(isp, icmdp); 1084 mutex_exit(&isp->sess_cmdsn_mutex); 1085 1086 iscsi_enqueue_completed_cmd(isp, icmdp); 1087 break; 1088 1089 /* -E4: Command has been requested to abort */ 1090 case ISCSI_CMD_EVENT_E4: 1091 /* 1092 * An upper level driver might attempt to 1093 * abort a command that we are already 1094 * aborting due to a nop. Since we are 1095 * already in the process of aborting 1096 * ignore the request. 1097 */ 1098 break; 1099 1100 /* -E6: Command has timed out */ 1101 case ISCSI_CMD_EVENT_E6: 1102 ASSERT(FALSE); 1103 /* 1104 * Timeouts should not occur on command in abort queue 1105 * they are already be processed due to a timeout. 1106 */ 1107 break; 1108 1109 /* -E7: Connection has encountered a problem */ 1110 case ISCSI_CMD_EVENT_E7: 1111 mutex_enter(&isp->sess_cmdsn_mutex); 1112 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp); 1113 iscsi_sess_release_itt(isp, icmdp); 1114 mutex_exit(&isp->sess_cmdsn_mutex); 1115 1116 /* complete io with error */ 1117 ISCSI_CMD_SET_REASON_STAT(icmdp, 1118 CMD_TRAN_ERR, 0); 1119 iscsi_enqueue_completed_cmd(isp, icmdp); 1120 break; 1121 1122 /* All other events are invalid for this state */ 1123 default: 1124 ASSERT(FALSE); 1125 } 1126 } 1127 1128 1129 /* 1130 * iscsi_cmd_state_completed - 1131 * 1132 */ 1133 static void 1134 iscsi_cmd_state_completed(iscsi_cmd_t *icmdp, 1135 iscsi_cmd_event_t event, void *arg) 1136 { 1137 iscsi_sess_t *isp = (iscsi_sess_t *)arg; 1138 1139 ASSERT(icmdp != NULL); 1140 ASSERT(icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI); 1141 ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_COMPLETED); 1142 ASSERT(isp != NULL); 1143 1144 /* switch on event change */ 1145 switch (event) { 1146 /* -E8: */ 1147 case ISCSI_CMD_EVENT_E8: 1148 icmdp->cmd_state = ISCSI_CMD_STATE_FREE; 1149 1150 /* the caller has already remove cmd from queue */ 1151 1152 icmdp->cmd_next = NULL; 1153 icmdp->cmd_prev = NULL; 1154 iscsi_iodone(isp, icmdp); 1155 break; 1156 /* All other events are invalid for this state */ 1157 default: 1158 ASSERT(FALSE); 1159 } 1160 } 1161 1162 1163 /* 1164 * iscsi_cmd_state_str - 1165 * 1166 */ 1167 static char * 1168 iscsi_cmd_state_str(iscsi_cmd_state_t state) 1169 { 1170 switch (state) { 1171 case ISCSI_CMD_STATE_FREE: 1172 return ("free"); 1173 case ISCSI_CMD_STATE_PENDING: 1174 return ("pending"); 1175 case ISCSI_CMD_STATE_ACTIVE: 1176 return ("active"); 1177 case ISCSI_CMD_STATE_ABORTING: 1178 return ("aborting"); 1179 case ISCSI_CMD_STATE_COMPLETED: 1180 return ("completed"); 1181 default: 1182 return ("unknown"); 1183 } 1184 } 1185 1186 1187 /* 1188 * iscsi_cmd_event_str - 1189 * 1190 */ 1191 static char * 1192 iscsi_cmd_event_str(iscsi_cmd_event_t event) 1193 { 1194 switch (event) { 1195 case ISCSI_CMD_EVENT_E1: 1196 return ("E1"); 1197 case ISCSI_CMD_EVENT_E2: 1198 return ("E2"); 1199 case ISCSI_CMD_EVENT_E3: 1200 return ("E3"); 1201 case ISCSI_CMD_EVENT_E4: 1202 return ("E4"); 1203 case ISCSI_CMD_EVENT_E6: 1204 return ("E6"); 1205 case ISCSI_CMD_EVENT_E7: 1206 return ("E7"); 1207 case ISCSI_CMD_EVENT_E8: 1208 return ("E8"); 1209 default: 1210 return ("unknown"); 1211 } 1212 } 1213 1214 1215 /* 1216 * iscsi_cmd_event_str - 1217 * 1218 */ 1219 static char * 1220 iscsi_cmd_type_str(iscsi_cmd_type_t type) 1221 { 1222 switch (type) { 1223 case ISCSI_CMD_TYPE_SCSI: 1224 return ("scsi"); 1225 case ISCSI_CMD_TYPE_R2T: 1226 return ("r2t"); 1227 case ISCSI_CMD_TYPE_NOP: 1228 return ("nop"); 1229 case ISCSI_CMD_TYPE_ABORT: 1230 return ("abort"); 1231 case ISCSI_CMD_TYPE_RESET: 1232 return ("reset"); 1233 case ISCSI_CMD_TYPE_LOGOUT: 1234 return ("logout"); 1235 default: 1236 return ("unknown"); 1237 } 1238 } 1239