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 26 #include <sys/cpuvar.h> 27 #include <sys/types.h> 28 #include <sys/conf.h> 29 #include <sys/stat.h> 30 #include <sys/file.h> 31 #include <sys/ddi.h> 32 #include <sys/sunddi.h> 33 #include <sys/modctl.h> 34 #include <sys/sysmacros.h> 35 #include <sys/socket.h> 36 #include <sys/strsubr.h> 37 #include <sys/nvpair.h> 38 39 #include <sys/stmf.h> 40 #include <sys/stmf_ioctl.h> 41 #include <sys/portif.h> 42 #include <sys/idm/idm.h> 43 #include <sys/idm/idm_conn_sm.h> 44 #include <iscsit_isns.h> 45 #include <iscsit.h> 46 47 #define ISCSIT_VERSION BUILD_DATE "-1.18dev" 48 #define ISCSIT_NAME_VERSION "COMSTAR ISCSIT v" ISCSIT_VERSION 49 50 /* 51 * DDI entry points. 52 */ 53 static int iscsit_drv_attach(dev_info_t *, ddi_attach_cmd_t); 54 static int iscsit_drv_detach(dev_info_t *, ddi_detach_cmd_t); 55 static int iscsit_drv_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 56 static int iscsit_drv_open(dev_t *, int, int, cred_t *); 57 static int iscsit_drv_close(dev_t, int, int, cred_t *); 58 static boolean_t iscsit_drv_busy(void); 59 static int iscsit_drv_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 60 static boolean_t iscsit_cmdsn_in_window(iscsit_conn_t *ict, uint32_t cmdsn); 61 static void iscsit_send_direct_scsi_resp(iscsit_conn_t *ict, idm_pdu_t *rx_pdu, 62 uint8_t response, uint8_t cmd_status); 63 static void iscsit_send_task_mgmt_resp(idm_pdu_t *tm_resp_pdu, 64 uint8_t tm_status); 65 66 extern struct mod_ops mod_miscops; 67 68 69 static struct cb_ops iscsit_cb_ops = { 70 iscsit_drv_open, /* cb_open */ 71 iscsit_drv_close, /* cb_close */ 72 nodev, /* cb_strategy */ 73 nodev, /* cb_print */ 74 nodev, /* cb_dump */ 75 nodev, /* cb_read */ 76 nodev, /* cb_write */ 77 iscsit_drv_ioctl, /* cb_ioctl */ 78 nodev, /* cb_devmap */ 79 nodev, /* cb_mmap */ 80 nodev, /* cb_segmap */ 81 nochpoll, /* cb_chpoll */ 82 ddi_prop_op, /* cb_prop_op */ 83 NULL, /* cb_streamtab */ 84 D_MP, /* cb_flag */ 85 CB_REV, /* cb_rev */ 86 nodev, /* cb_aread */ 87 nodev, /* cb_awrite */ 88 }; 89 90 static struct dev_ops iscsit_dev_ops = { 91 DEVO_REV, /* devo_rev */ 92 0, /* devo_refcnt */ 93 iscsit_drv_getinfo, /* devo_getinfo */ 94 nulldev, /* devo_identify */ 95 nulldev, /* devo_probe */ 96 iscsit_drv_attach, /* devo_attach */ 97 iscsit_drv_detach, /* devo_detach */ 98 nodev, /* devo_reset */ 99 &iscsit_cb_ops, /* devo_cb_ops */ 100 NULL, /* devo_bus_ops */ 101 NULL, /* devo_power */ 102 ddi_quiesce_not_needed, /* quiesce */ 103 }; 104 105 static struct modldrv modldrv = { 106 &mod_driverops, 107 "iSCSI Target", 108 &iscsit_dev_ops, 109 }; 110 111 static struct modlinkage modlinkage = { 112 MODREV_1, 113 &modldrv, 114 NULL, 115 }; 116 117 118 iscsit_global_t iscsit_global; 119 120 kmem_cache_t *iscsit_status_pdu_cache; 121 122 boolean_t iscsit_sm_logging = B_FALSE; 123 124 static idm_status_t iscsit_init(dev_info_t *dip); 125 static idm_status_t iscsit_enable_svc(iscsit_hostinfo_t *hostinfo); 126 static void iscsit_disable_svc(void); 127 128 static void 129 iscsit_op_scsi_task_mgmt(iscsit_conn_t *ict, idm_pdu_t *rx_pdu); 130 131 static void 132 iscsit_pdu_op_noop(iscsit_conn_t *ict, idm_pdu_t *rx_pdu); 133 134 static void 135 iscsit_pdu_op_login_cmd(iscsit_conn_t *ict, idm_pdu_t *rx_pdu); 136 137 void 138 iscsit_pdu_op_text_cmd(iscsit_conn_t *ict, idm_pdu_t *rx_pdu); 139 140 static void 141 iscsit_pdu_op_logout_cmd(iscsit_conn_t *ict, idm_pdu_t *rx_pdu); 142 143 int iscsit_cmd_window(); 144 145 void 146 iscsit_set_cmdsn(iscsit_conn_t *ict, idm_pdu_t *rx_pdu); 147 148 static void 149 iscsit_calc_rspsn(iscsit_conn_t *ict, idm_pdu_t *resp); 150 151 static void 152 iscsit_deferred_dispatch(idm_pdu_t *rx_pdu); 153 154 static void 155 iscsit_deferred(void *rx_pdu_void); 156 157 static idm_status_t 158 iscsit_conn_accept(idm_conn_t *ic); 159 160 static idm_status_t 161 iscsit_ffp_enabled(idm_conn_t *ic); 162 163 static idm_status_t 164 iscsit_ffp_disabled(idm_conn_t *ic, idm_ffp_disable_t disable_class); 165 166 static idm_status_t 167 iscsit_conn_lost(idm_conn_t *ic); 168 169 static idm_status_t 170 iscsit_conn_destroy(idm_conn_t *ic); 171 172 static stmf_data_buf_t * 173 iscsit_dbuf_alloc(scsi_task_t *task, uint32_t size, uint32_t *pminsize, 174 uint32_t flags); 175 176 static void 177 iscsit_dbuf_free(stmf_dbuf_store_t *ds, stmf_data_buf_t *dbuf); 178 179 static void 180 iscsit_buf_xfer_cb(idm_buf_t *idb, idm_status_t status); 181 182 static void 183 iscsit_send_good_status_done(idm_pdu_t *pdu, idm_status_t status); 184 185 static void 186 iscsit_send_status_done(idm_pdu_t *pdu, idm_status_t status); 187 188 static stmf_status_t 189 iscsit_idm_to_stmf(idm_status_t idmrc); 190 191 static iscsit_task_t * 192 iscsit_task_alloc(iscsit_conn_t *ict); 193 194 static void 195 iscsit_task_free(iscsit_task_t *itask); 196 197 static iscsit_task_t * 198 iscsit_tm_task_alloc(iscsit_conn_t *ict); 199 200 static void 201 iscsit_tm_task_free(iscsit_task_t *itask); 202 203 static int 204 iscsit_status_pdu_constructor(void *pdu_void, void *arg, int flags); 205 206 static void 207 iscsit_pp_cb(struct stmf_port_provider *pp, int cmd, void *arg, uint32_t flags); 208 209 static it_cfg_status_t 210 iscsit_config_merge(it_config_t *cfg); 211 212 static idm_status_t 213 iscsit_login_fail(idm_conn_t *ic); 214 215 int 216 _init(void) 217 { 218 int rc; 219 220 rw_init(&iscsit_global.global_rwlock, NULL, RW_DRIVER, NULL); 221 iscsit_global.global_svc_state = ISE_DETACHED; 222 223 if ((rc = mod_install(&modlinkage)) != 0) { 224 rw_destroy(&iscsit_global.global_rwlock); 225 return (rc); 226 } 227 228 return (rc); 229 } 230 231 int 232 _info(struct modinfo *modinfop) 233 { 234 return (mod_info(&modlinkage, modinfop)); 235 } 236 237 int 238 _fini(void) 239 { 240 int rc; 241 242 rc = mod_remove(&modlinkage); 243 244 if (rc == 0) { 245 rw_destroy(&iscsit_global.global_rwlock); 246 } 247 248 return (rc); 249 } 250 251 /* 252 * DDI entry points. 253 */ 254 255 /* ARGSUSED */ 256 static int 257 iscsit_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, 258 void **result) 259 { 260 ulong_t instance = getminor((dev_t)arg); 261 262 switch (cmd) { 263 case DDI_INFO_DEVT2DEVINFO: 264 *result = iscsit_global.global_dip; 265 return (DDI_SUCCESS); 266 267 case DDI_INFO_DEVT2INSTANCE: 268 *result = (void *)instance; 269 return (DDI_SUCCESS); 270 271 default: 272 break; 273 } 274 275 return (DDI_FAILURE); 276 } 277 278 static int 279 iscsit_drv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 280 { 281 if (cmd != DDI_ATTACH) { 282 return (DDI_FAILURE); 283 } 284 285 if (ddi_get_instance(dip) != 0) { 286 /* we only allow instance 0 to attach */ 287 return (DDI_FAILURE); 288 } 289 290 /* create the minor node */ 291 if (ddi_create_minor_node(dip, ISCSIT_MODNAME, S_IFCHR, 0, 292 DDI_PSEUDO, 0) != DDI_SUCCESS) { 293 cmn_err(CE_WARN, "iscsit_drv_attach: " 294 "failed creating minor node"); 295 return (DDI_FAILURE); 296 } 297 298 if (iscsit_init(dip) != IDM_STATUS_SUCCESS) { 299 cmn_err(CE_WARN, "iscsit_drv_attach: " 300 "failed to initialize"); 301 ddi_remove_minor_node(dip, NULL); 302 return (DDI_FAILURE); 303 } 304 305 iscsit_global.global_svc_state = ISE_DISABLED; 306 iscsit_global.global_dip = dip; 307 308 return (DDI_SUCCESS); 309 } 310 311 /*ARGSUSED*/ 312 static int 313 iscsit_drv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 314 { 315 if (cmd != DDI_DETACH) 316 return (DDI_FAILURE); 317 318 ISCSIT_GLOBAL_LOCK(RW_WRITER); 319 if (iscsit_drv_busy()) { 320 ISCSIT_GLOBAL_UNLOCK(); 321 return (EBUSY); 322 } 323 324 iscsit_global.global_dip = NULL; 325 ddi_remove_minor_node(dip, NULL); 326 327 ldi_ident_release(iscsit_global.global_li); 328 iscsit_global.global_svc_state = ISE_DETACHED; 329 330 ISCSIT_GLOBAL_UNLOCK(); 331 332 return (DDI_SUCCESS); 333 } 334 335 /*ARGSUSED*/ 336 static int 337 iscsit_drv_open(dev_t *devp, int flag, int otyp, cred_t *credp) 338 { 339 return (0); 340 } 341 342 /* ARGSUSED */ 343 static int 344 iscsit_drv_close(dev_t dev, int flag, int otyp, cred_t *credp) 345 { 346 return (0); 347 } 348 349 static boolean_t 350 iscsit_drv_busy(void) 351 { 352 switch (iscsit_global.global_svc_state) { 353 case ISE_DISABLED: 354 case ISE_DETACHED: 355 return (B_FALSE); 356 default: 357 return (B_TRUE); 358 } 359 /* NOTREACHED */ 360 } 361 362 /* ARGSUSED */ 363 static int 364 iscsit_drv_ioctl(dev_t drv, int cmd, intptr_t argp, int flag, cred_t *cred, 365 int *retval) 366 { 367 iscsit_ioc_set_config_t setcfg; 368 iscsit_ioc_set_config32_t setcfg32; 369 /* iscsit_ioc_get_config_t getcfg; */ 370 char *cfg_pnvlist; 371 nvlist_t *cfg_nvlist; 372 it_config_t *cfg; 373 idm_status_t idmrc; 374 int rc = 0; 375 376 if (drv_priv(cred) != 0) { 377 return (EPERM); 378 } 379 380 ISCSIT_GLOBAL_LOCK(RW_WRITER); 381 382 /* 383 * Validate ioctl requests against global service state 384 */ 385 switch (iscsit_global.global_svc_state) { 386 case ISE_ENABLED: 387 if (cmd == ISCSIT_IOC_DISABLE_SVC) { 388 iscsit_global.global_svc_state = ISE_DISABLING; 389 } else if (cmd == ISCSIT_IOC_ENABLE_SVC) { 390 /* Already enabled */ 391 ISCSIT_GLOBAL_UNLOCK(); 392 return (0); 393 } else { 394 iscsit_global.global_svc_state = ISE_BUSY; 395 } 396 break; 397 case ISE_DISABLED: 398 if (cmd == ISCSIT_IOC_ENABLE_SVC) { 399 iscsit_global.global_svc_state = ISE_ENABLING; 400 } else if (cmd == ISCSIT_IOC_DISABLE_SVC) { 401 /* Already disabled */ 402 ISCSIT_GLOBAL_UNLOCK(); 403 return (0); 404 } else { 405 rc = EFAULT; 406 } 407 break; 408 case ISE_ENABLING: 409 case ISE_DISABLING: 410 rc = EAGAIN; 411 break; 412 case ISE_DETACHED: 413 default: 414 rc = EFAULT; 415 break; 416 } 417 418 ISCSIT_GLOBAL_UNLOCK(); 419 if (rc != 0) 420 return (rc); 421 422 /* Handle ioctl request (enable/disable have already been handled) */ 423 switch (cmd) { 424 case ISCSIT_IOC_SET_CONFIG: 425 switch (ddi_model_convert_from(flag & FMODELS)) { 426 case DDI_MODEL_ILP32: 427 if (ddi_copyin((void *)argp, &setcfg32, 428 sizeof (iscsit_ioc_set_config32_t), flag) != 0) 429 return (EFAULT); 430 431 setcfg.set_cfg_pnvlist = 432 (char *)((uintptr_t)setcfg32.set_cfg_pnvlist); 433 setcfg.set_cfg_vers = setcfg32.set_cfg_vers; 434 setcfg.set_cfg_pnvlist_len = 435 setcfg32.set_cfg_pnvlist_len; 436 break; 437 case DDI_MODEL_NONE: 438 if (ddi_copyin((void *)argp, &setcfg, 439 sizeof (iscsit_ioc_set_config_t), flag) != 0) 440 return (EFAULT); 441 break; 442 } 443 444 /* Check API version */ 445 if (setcfg.set_cfg_vers != ISCSIT_API_VERS0) { 446 return (EINVAL); 447 } 448 449 /* Config is in packed nvlist format so unpack it */ 450 cfg_pnvlist = kmem_alloc(setcfg.set_cfg_pnvlist_len, 451 KM_SLEEP); 452 ASSERT(cfg_pnvlist != NULL); 453 454 if (ddi_copyin(setcfg.set_cfg_pnvlist, cfg_pnvlist, 455 setcfg.set_cfg_pnvlist_len, flag) != 0) { 456 kmem_free(cfg_pnvlist, setcfg.set_cfg_pnvlist_len); 457 return (EFAULT); 458 } 459 460 if (nvlist_unpack(cfg_pnvlist, setcfg.set_cfg_pnvlist_len, 461 &cfg_nvlist, KM_SLEEP) != 0) { 462 kmem_free(cfg_pnvlist, setcfg.set_cfg_pnvlist_len); 463 return (EINVAL); 464 } 465 466 /* Translate nvlist */ 467 if (it_nv_to_config(cfg_nvlist, &cfg) != 0) { 468 cmn_err(CE_WARN, "Configuration is invalid"); 469 kmem_free(cfg_pnvlist, setcfg.set_cfg_pnvlist_len); 470 nvlist_free(cfg_nvlist); 471 return (EINVAL); 472 } 473 474 /* Update config */ 475 if (iscsit_config_merge(cfg) != 0) { 476 kmem_free(cfg_pnvlist, setcfg.set_cfg_pnvlist_len); 477 nvlist_free(cfg_nvlist); 478 return (EIO); 479 } 480 481 it_config_free_cmn(cfg); 482 kmem_free(cfg_pnvlist, setcfg.set_cfg_pnvlist_len); 483 nvlist_free(cfg_nvlist); 484 485 /* 486 * Now that the reconfig is complete set our state back to 487 * enabled. 488 */ 489 ISCSIT_GLOBAL_LOCK(RW_WRITER); 490 iscsit_global.global_svc_state = ISE_ENABLED; 491 ISCSIT_GLOBAL_UNLOCK(); 492 break; 493 case ISCSIT_IOC_ENABLE_SVC: { 494 iscsit_hostinfo_t hostinfo; 495 496 if (ddi_copyin((void *)argp, &hostinfo.length, 497 sizeof (hostinfo.length), flag) != 0) { 498 iscsit_global.global_svc_state = ISE_DISABLED; 499 return (EFAULT); 500 } 501 502 if (hostinfo.length > sizeof (hostinfo.fqhn)) 503 hostinfo.length = sizeof (hostinfo.fqhn); 504 505 if (ddi_copyin((void *)((caddr_t)argp + 506 sizeof (hostinfo.length)), &hostinfo.fqhn, 507 hostinfo.length, flag) != 0) { 508 iscsit_global.global_svc_state = ISE_DISABLED; 509 return (EFAULT); 510 } 511 512 idmrc = iscsit_enable_svc(&hostinfo); 513 ISCSIT_GLOBAL_LOCK(RW_WRITER); 514 if (idmrc == IDM_STATUS_SUCCESS) { 515 iscsit_global.global_svc_state = ISE_ENABLED; 516 } else { 517 rc = EIO; 518 iscsit_global.global_svc_state = ISE_DISABLED; 519 } 520 ISCSIT_GLOBAL_UNLOCK(); 521 break; 522 } 523 case ISCSIT_IOC_DISABLE_SVC: 524 iscsit_disable_svc(); 525 ISCSIT_GLOBAL_LOCK(RW_WRITER); 526 iscsit_global.global_svc_state = ISE_DISABLED; 527 ISCSIT_GLOBAL_UNLOCK(); 528 break; 529 default: 530 rc = EINVAL; 531 } 532 533 /* Don't forget to clear ISE_BUSY state */ 534 ASSERT(iscsit_global.global_svc_state != ISE_BUSY); 535 536 return (rc); 537 } 538 539 static idm_status_t 540 iscsit_init(dev_info_t *dip) 541 { 542 int rc; 543 544 rc = ldi_ident_from_dip(dip, &iscsit_global.global_li); 545 ASSERT(rc == 0); /* Failure indicates invalid argument */ 546 547 iscsit_global.global_svc_state = ISE_DISABLED; 548 549 return (IDM_STATUS_SUCCESS); 550 } 551 552 /* 553 * iscsit_enable_svc 554 * 555 * registers all the configured targets and target portals with STMF 556 */ 557 static idm_status_t 558 iscsit_enable_svc(iscsit_hostinfo_t *hostinfo) 559 { 560 stmf_port_provider_t *pp; 561 stmf_dbuf_store_t *dbuf_store; 562 boolean_t did_iscsit_isns_init; 563 idm_status_t retval = IDM_STATUS_SUCCESS; 564 565 ASSERT(iscsit_global.global_svc_state == ISE_ENABLING); 566 567 /* 568 * Make sure that can tell if we have partially allocated 569 * in case we need to exit and tear down anything allocated. 570 */ 571 iscsit_global.global_tsih_pool = NULL; 572 iscsit_global.global_dbuf_store = NULL; 573 iscsit_status_pdu_cache = NULL; 574 pp = NULL; 575 iscsit_global.global_pp = NULL; 576 iscsit_global.global_default_tpg = NULL; 577 did_iscsit_isns_init = B_FALSE; 578 iscsit_global.global_dispatch_taskq = NULL; 579 580 /* Setup remaining fields in iscsit_global_t */ 581 idm_refcnt_init(&iscsit_global.global_refcnt, 582 &iscsit_global); 583 584 avl_create(&iscsit_global.global_discovery_sessions, 585 iscsit_sess_avl_compare, sizeof (iscsit_sess_t), 586 offsetof(iscsit_sess_t, ist_tgt_ln)); 587 588 avl_create(&iscsit_global.global_target_list, 589 iscsit_tgt_avl_compare, sizeof (iscsit_tgt_t), 590 offsetof(iscsit_tgt_t, target_global_ln)); 591 592 list_create(&iscsit_global.global_deleted_target_list, 593 sizeof (iscsit_tgt_t), 594 offsetof(iscsit_tgt_t, target_global_deleted_ln)); 595 596 avl_create(&iscsit_global.global_tpg_list, 597 iscsit_tpg_avl_compare, sizeof (iscsit_tpg_t), 598 offsetof(iscsit_tpg_t, tpg_global_ln)); 599 600 avl_create(&iscsit_global.global_ini_list, 601 iscsit_ini_avl_compare, sizeof (iscsit_ini_t), 602 offsetof(iscsit_ini_t, ini_global_ln)); 603 604 iscsit_global.global_tsih_pool = vmem_create("iscsit_tsih_pool", 605 (void *)1, ISCSI_MAX_TSIH, 1, NULL, NULL, NULL, 0, 606 VM_SLEEP | VMC_IDENTIFIER); 607 608 /* 609 * Setup STMF dbuf store. Our buffers are bound to a specific 610 * connection so we really can't let STMF cache buffers for us. 611 * Consequently we'll just allocate one global buffer store. 612 */ 613 dbuf_store = stmf_alloc(STMF_STRUCT_DBUF_STORE, 0, 0); 614 if (dbuf_store == NULL) { 615 retval = IDM_STATUS_FAIL; 616 goto tear_down_and_return; 617 } 618 dbuf_store->ds_alloc_data_buf = iscsit_dbuf_alloc; 619 dbuf_store->ds_free_data_buf = iscsit_dbuf_free; 620 dbuf_store->ds_port_private = NULL; 621 iscsit_global.global_dbuf_store = dbuf_store; 622 623 /* Status PDU cache */ 624 iscsit_status_pdu_cache = kmem_cache_create("iscsit_status_pdu_cache", 625 sizeof (idm_pdu_t) + sizeof (iscsi_scsi_rsp_hdr_t), 8, 626 &iscsit_status_pdu_constructor, 627 NULL, NULL, NULL, NULL, KM_SLEEP); 628 629 /* Default TPG and portal */ 630 iscsit_global.global_default_tpg = iscsit_tpg_createdefault(); 631 if (iscsit_global.global_default_tpg == NULL) { 632 retval = IDM_STATUS_FAIL; 633 goto tear_down_and_return; 634 } 635 636 /* initialize isns client */ 637 (void) iscsit_isns_init(hostinfo); 638 did_iscsit_isns_init = B_TRUE; 639 640 /* Register port provider */ 641 pp = stmf_alloc(STMF_STRUCT_PORT_PROVIDER, 0, 0); 642 if (pp == NULL) { 643 retval = IDM_STATUS_FAIL; 644 goto tear_down_and_return; 645 } 646 647 pp->pp_portif_rev = PORTIF_REV_1; 648 pp->pp_instance = 0; 649 pp->pp_name = ISCSIT_MODNAME; 650 pp->pp_cb = iscsit_pp_cb; 651 652 iscsit_global.global_pp = pp; 653 654 655 if (stmf_register_port_provider(pp) != STMF_SUCCESS) { 656 retval = IDM_STATUS_FAIL; 657 goto tear_down_and_return; 658 } 659 660 iscsit_global.global_dispatch_taskq = taskq_create("iscsit_dispatch", 661 1, minclsyspri, 16, 16, TASKQ_PREPOPULATE); 662 663 return (IDM_STATUS_SUCCESS); 664 665 tear_down_and_return: 666 667 if (iscsit_global.global_dispatch_taskq) { 668 taskq_destroy(iscsit_global.global_dispatch_taskq); 669 iscsit_global.global_dispatch_taskq = NULL; 670 } 671 672 if (did_iscsit_isns_init) 673 iscsit_isns_fini(); 674 675 if (iscsit_global.global_default_tpg) { 676 iscsit_tpg_destroydefault(iscsit_global.global_default_tpg); 677 iscsit_global.global_default_tpg = NULL; 678 } 679 680 if (iscsit_global.global_pp) 681 iscsit_global.global_pp = NULL; 682 683 if (pp) 684 stmf_free(pp); 685 686 if (iscsit_status_pdu_cache) { 687 kmem_cache_destroy(iscsit_status_pdu_cache); 688 iscsit_status_pdu_cache = NULL; 689 } 690 691 if (iscsit_global.global_dbuf_store) { 692 stmf_free(iscsit_global.global_dbuf_store); 693 iscsit_global.global_dbuf_store = NULL; 694 } 695 696 if (iscsit_global.global_tsih_pool) { 697 vmem_destroy(iscsit_global.global_tsih_pool); 698 iscsit_global.global_tsih_pool = NULL; 699 } 700 701 avl_destroy(&iscsit_global.global_ini_list); 702 avl_destroy(&iscsit_global.global_tpg_list); 703 list_destroy(&iscsit_global.global_deleted_target_list); 704 avl_destroy(&iscsit_global.global_target_list); 705 avl_destroy(&iscsit_global.global_discovery_sessions); 706 707 idm_refcnt_destroy(&iscsit_global.global_refcnt); 708 709 return (retval); 710 } 711 712 /* 713 * iscsit_disable_svc 714 * 715 * clean up all existing connections and deregister targets from STMF 716 */ 717 static void 718 iscsit_disable_svc(void) 719 { 720 iscsit_sess_t *sess; 721 722 ASSERT(iscsit_global.global_svc_state == ISE_DISABLING); 723 724 /* tear down discovery sessions */ 725 for (sess = avl_first(&iscsit_global.global_discovery_sessions); 726 sess != NULL; 727 sess = AVL_NEXT(&iscsit_global.global_discovery_sessions, sess)) 728 iscsit_sess_close(sess); 729 730 /* 731 * Passing NULL to iscsit_config_merge tells it to go to an empty 732 * config. 733 */ 734 (void) iscsit_config_merge(NULL); 735 736 /* 737 * Wait until there are no more global references 738 */ 739 idm_refcnt_wait_ref(&iscsit_global.global_refcnt); 740 idm_refcnt_destroy(&iscsit_global.global_refcnt); 741 742 /* 743 * Default TPG must be destroyed after global_refcnt is 0. 744 */ 745 iscsit_tpg_destroydefault(iscsit_global.global_default_tpg); 746 747 avl_destroy(&iscsit_global.global_discovery_sessions); 748 list_destroy(&iscsit_global.global_deleted_target_list); 749 avl_destroy(&iscsit_global.global_target_list); 750 avl_destroy(&iscsit_global.global_tpg_list); 751 avl_destroy(&iscsit_global.global_ini_list); 752 753 taskq_destroy(iscsit_global.global_dispatch_taskq); 754 755 iscsit_isns_fini(); 756 757 stmf_free(iscsit_global.global_dbuf_store); 758 iscsit_global.global_dbuf_store = NULL; 759 760 (void) stmf_deregister_port_provider(iscsit_global.global_pp); 761 stmf_free(iscsit_global.global_pp); 762 iscsit_global.global_pp = NULL; 763 764 kmem_cache_destroy(iscsit_status_pdu_cache); 765 iscsit_status_pdu_cache = NULL; 766 767 vmem_destroy(iscsit_global.global_tsih_pool); 768 iscsit_global.global_tsih_pool = NULL; 769 } 770 771 void 772 iscsit_global_hold() 773 { 774 idm_refcnt_hold(&iscsit_global.global_refcnt); 775 } 776 777 void 778 iscsit_global_rele() 779 { 780 idm_refcnt_rele(&iscsit_global.global_refcnt); 781 } 782 783 void 784 iscsit_global_wait_ref() 785 { 786 idm_refcnt_wait_ref(&iscsit_global.global_refcnt); 787 } 788 789 /* 790 * IDM callbacks 791 */ 792 793 /*ARGSUSED*/ 794 void 795 iscsit_rx_pdu(idm_conn_t *ic, idm_pdu_t *rx_pdu) 796 { 797 iscsit_conn_t *ict = ic->ic_handle; 798 switch (IDM_PDU_OPCODE(rx_pdu)) { 799 case ISCSI_OP_SCSI_CMD: 800 ASSERT(0); /* Shouldn't happen */ 801 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 802 break; 803 case ISCSI_OP_SNACK_CMD: 804 /* 805 * We'll need to handle this when we support ERL1/2. For 806 * now we treat it as a protocol error. 807 */ 808 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 809 idm_conn_event(ic, CE_TRANSPORT_FAIL, NULL); 810 break; 811 case ISCSI_OP_SCSI_TASK_MGT_MSG: 812 iscsit_set_cmdsn(ict, rx_pdu); 813 iscsit_op_scsi_task_mgmt(ict, rx_pdu); 814 break; 815 case ISCSI_OP_NOOP_OUT: 816 case ISCSI_OP_LOGIN_CMD: 817 case ISCSI_OP_TEXT_CMD: 818 case ISCSI_OP_LOGOUT_CMD: 819 /* 820 * If/when we switch to userland processing these PDU's 821 * will be handled by iscsitd. 822 */ 823 iscsit_deferred_dispatch(rx_pdu); 824 break; 825 default: 826 /* Protocol error */ 827 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 828 idm_conn_event(ic, CE_TRANSPORT_FAIL, NULL); 829 break; 830 } 831 } 832 833 /*ARGSUSED*/ 834 void 835 iscsit_rx_pdu_error(idm_conn_t *ic, idm_pdu_t *rx_pdu, idm_status_t status) 836 { 837 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 838 } 839 840 void 841 iscsit_task_aborted(idm_task_t *idt, idm_status_t status) 842 { 843 iscsit_task_t *itask = idt->idt_private; 844 845 switch (status) { 846 case IDM_STATUS_SUSPENDED: 847 break; 848 case IDM_STATUS_ABORTED: 849 mutex_enter(&itask->it_mutex); 850 itask->it_aborted = B_TRUE; 851 /* 852 * We rely on the fact that STMF tracks outstanding 853 * buffer transfers and will free all of our buffers 854 * before freeing the task so we don't need to 855 * explicitly free the buffers from iscsit/idm 856 */ 857 if (itask->it_stmf_abort) { 858 mutex_exit(&itask->it_mutex); 859 /* 860 * STMF has already asked for this task to be aborted 861 * 862 * STMF specification is wrong... says to return 863 * STMF_ABORTED, the code actually looks for 864 * STMF_ABORT_SUCCESS. 865 */ 866 stmf_task_lport_aborted(itask->it_stmf_task, 867 STMF_ABORT_SUCCESS, STMF_IOF_LPORT_DONE); 868 return; 869 } else { 870 mutex_exit(&itask->it_mutex); 871 /* 872 * Tell STMF to stop processing the task. 873 */ 874 stmf_abort(STMF_QUEUE_TASK_ABORT, itask->it_stmf_task, 875 STMF_ABORTED, NULL); 876 return; 877 } 878 /*NOTREACHED*/ 879 default: 880 ASSERT(0); 881 } 882 } 883 884 /*ARGSUSED*/ 885 idm_status_t 886 iscsit_client_notify(idm_conn_t *ic, idm_client_notify_t icn, 887 uintptr_t data) 888 { 889 idm_status_t rc = IDM_STATUS_SUCCESS; 890 891 /* 892 * IDM client notifications will never occur at interrupt level 893 * since they are generated from the connection state machine which 894 * running on taskq threads. 895 * 896 */ 897 switch (icn) { 898 case CN_CONNECT_ACCEPT: 899 rc = iscsit_conn_accept(ic); /* No data */ 900 break; 901 case CN_FFP_ENABLED: 902 rc = iscsit_ffp_enabled(ic); /* No data */ 903 break; 904 case CN_FFP_DISABLED: 905 /* 906 * Data indicates whether this was the result of an 907 * explicit logout request. 908 */ 909 rc = iscsit_ffp_disabled(ic, (idm_ffp_disable_t)data); 910 break; 911 case CN_CONNECT_LOST: 912 rc = iscsit_conn_lost(ic); 913 break; 914 case CN_CONNECT_DESTROY: 915 rc = iscsit_conn_destroy(ic); 916 break; 917 case CN_LOGIN_FAIL: 918 /* 919 * Force the login state machine to completion 920 */ 921 rc = iscsit_login_fail(ic); 922 break; 923 default: 924 rc = IDM_STATUS_REJECT; 925 break; 926 } 927 928 return (rc); 929 } 930 931 932 void 933 iscsit_build_hdr(idm_task_t *idm_task, idm_pdu_t *pdu, uint8_t opcode) 934 { 935 iscsit_task_t *itask = idm_task->idt_private; 936 iscsi_data_rsp_hdr_t *dh = (iscsi_data_rsp_hdr_t *)pdu->isp_hdr; 937 938 /* 939 * We acquired iscsit_sess_t.ist_sn_rwlock in iscsit_xfer_scsi_data 940 * in reader mode so we expect to be locked here 941 */ 942 943 /* 944 * Lun is only required if the opcode == ISCSI_OP_SCSI_DATA_RSP 945 * and the 'A' bit is to be set 946 */ 947 dh->opcode = opcode; 948 dh->itt = itask->it_itt; 949 dh->ttt = itask->it_ttt; 950 /* Statsn is only set during phase collapse */ 951 dh->expcmdsn = htonl(itask->it_ict->ict_sess->ist_expcmdsn); 952 dh->maxcmdsn = htonl(itask->it_ict->ict_sess->ist_maxcmdsn); 953 954 /* 955 * IDM must set: 956 * 957 * data.flags and rtt.flags 958 * data.dlength 959 * data.datasn 960 * data.offset 961 * residual_count and cmd_status (if we ever implement phase collapse) 962 * rtt.rttsn 963 * rtt.data_offset 964 * rtt.data_length 965 */ 966 } 967 968 static idm_status_t 969 iscsit_conn_accept(idm_conn_t *ic) 970 { 971 iscsit_conn_t *ict; 972 973 /* 974 * Allocate an associated iscsit structure to represent this 975 * connection. We shouldn't really create a session until we 976 * get the first login PDU. 977 */ 978 ict = kmem_zalloc(sizeof (*ict), KM_SLEEP); 979 980 ict->ict_ic = ic; 981 ict->ict_statsn = 1; 982 ic->ic_handle = ict; 983 mutex_init(&ict->ict_mutex, NULL, MUTEX_DRIVER, NULL); 984 idm_refcnt_init(&ict->ict_refcnt, ict); 985 986 /* 987 * Initialize login state machine 988 */ 989 if (iscsit_login_sm_init(ict) != IDM_STATUS_SUCCESS) { 990 return (IDM_STATUS_FAIL); 991 } 992 993 return (IDM_STATUS_SUCCESS); 994 } 995 996 idm_status_t 997 iscsit_conn_reinstate(iscsit_conn_t *reinstate_ict, iscsit_conn_t *new_ict) 998 { 999 idm_status_t result; 1000 1001 /* 1002 * Note in new connection state that this connection is 1003 * reinstating an existing connection. 1004 */ 1005 new_ict->ict_reinstating = B_TRUE; 1006 new_ict->ict_reinstate_conn = reinstate_ict; 1007 new_ict->ict_statsn = reinstate_ict->ict_statsn; 1008 1009 /* 1010 * Now generate connection state machine event to existing connection 1011 * so that it starts the cleanup process. 1012 */ 1013 result = idm_conn_reinstate_event(reinstate_ict->ict_ic, 1014 new_ict->ict_ic); 1015 1016 return (result); 1017 } 1018 1019 void 1020 iscsit_conn_hold(iscsit_conn_t *ict) 1021 { 1022 idm_refcnt_hold(&ict->ict_refcnt); 1023 } 1024 1025 void 1026 iscsit_conn_rele(iscsit_conn_t *ict) 1027 { 1028 idm_refcnt_rele(&ict->ict_refcnt); 1029 } 1030 1031 void 1032 iscsit_conn_dispatch_hold(iscsit_conn_t *ict) 1033 { 1034 idm_refcnt_hold(&ict->ict_dispatch_refcnt); 1035 } 1036 1037 void 1038 iscsit_conn_dispatch_rele(iscsit_conn_t *ict) 1039 { 1040 idm_refcnt_rele(&ict->ict_dispatch_refcnt); 1041 } 1042 1043 static idm_status_t 1044 iscsit_login_fail(idm_conn_t *ic) 1045 { 1046 iscsit_conn_t *ict = ic->ic_handle; 1047 1048 /* Generate login state machine event */ 1049 iscsit_login_sm_event(ict, ILE_LOGIN_CONN_ERROR, NULL); 1050 1051 return (IDM_STATUS_SUCCESS); 1052 } 1053 1054 static idm_status_t 1055 iscsit_ffp_enabled(idm_conn_t *ic) 1056 { 1057 iscsit_conn_t *ict = ic->ic_handle; 1058 1059 /* Generate session state machine event */ 1060 iscsit_sess_sm_event(ict->ict_sess, SE_CONN_LOGGED_IN, ict); 1061 1062 return (IDM_STATUS_SUCCESS); 1063 } 1064 1065 static idm_status_t 1066 iscsit_ffp_disabled(idm_conn_t *ic, idm_ffp_disable_t disable_class) 1067 { 1068 iscsit_conn_t *ict = ic->ic_handle; 1069 1070 /* Generate session state machine event */ 1071 switch (disable_class) { 1072 case FD_CONN_FAIL: 1073 iscsit_sess_sm_event(ict->ict_sess, SE_CONN_FFP_FAIL, ict); 1074 break; 1075 case FD_CONN_LOGOUT: 1076 iscsit_sess_sm_event(ict->ict_sess, SE_CONN_FFP_DISABLE, ict); 1077 break; 1078 case FD_SESS_LOGOUT: 1079 iscsit_sess_sm_event(ict->ict_sess, SE_SESSION_CLOSE, ict); 1080 break; 1081 default: 1082 ASSERT(0); 1083 } 1084 1085 return (IDM_STATUS_SUCCESS); 1086 } 1087 1088 static idm_status_t 1089 iscsit_conn_lost(idm_conn_t *ic) 1090 { 1091 iscsit_conn_t *ict = ic->ic_handle; 1092 1093 mutex_enter(&ict->ict_mutex); 1094 ict->ict_lost = B_TRUE; 1095 mutex_exit(&ict->ict_mutex); 1096 1097 /* 1098 * Make sure there aren't any PDU's transitioning from the receive 1099 * handler to the dispatch taskq. 1100 */ 1101 idm_refcnt_wait_ref(&ict->ict_dispatch_refcnt); 1102 1103 return (IDM_STATUS_SUCCESS); 1104 } 1105 1106 static idm_status_t 1107 iscsit_conn_destroy(idm_conn_t *ic) 1108 { 1109 iscsit_conn_t *ict = ic->ic_handle; 1110 1111 mutex_enter(&ict->ict_mutex); 1112 ict->ict_destroyed = B_TRUE; 1113 mutex_exit(&ict->ict_mutex); 1114 1115 /* Generate session state machine event */ 1116 if (ict->ict_sess != NULL) { 1117 /* 1118 * Session state machine will call iscsit_conn_destroy_done() 1119 * when it has removed references to this connection. 1120 */ 1121 iscsit_sess_sm_event(ict->ict_sess, SE_CONN_FAIL, ict); 1122 } 1123 1124 ict->ict_ic = NULL; 1125 1126 idm_refcnt_wait_ref(&ict->ict_refcnt); 1127 1128 mutex_destroy(&ict->ict_mutex); 1129 idm_refcnt_destroy(&ict->ict_refcnt); 1130 kmem_free(ict, sizeof (*ict)); 1131 1132 return (IDM_STATUS_SUCCESS); 1133 } 1134 1135 /* 1136 * STMF-related functions 1137 * 1138 * iSCSI to STMF mapping 1139 * 1140 * Session == ? 1141 * Connection == bound to local port but not itself a local port 1142 * Target 1143 * Target portal (group?) == local port (really but we're not going to do this) 1144 * iscsit needs to map connections to local ports (whatever we decide 1145 * they are) 1146 * Target == ? 1147 */ 1148 1149 /*ARGSUSED*/ 1150 static stmf_data_buf_t * 1151 iscsit_dbuf_alloc(scsi_task_t *task, uint32_t size, uint32_t *pminsize, 1152 uint32_t flags) 1153 { 1154 iscsit_task_t *itask = task->task_port_private; 1155 idm_buf_t *idm_buffer; 1156 iscsit_buf_t *ibuf; 1157 stmf_data_buf_t *result; 1158 1159 /* 1160 * Once the iSER picture is better understood it might make sense 1161 * to pre-allocate some registered buffers, similar to what 1162 * fct/qlt are doing. In the meantime hopefully stmf can allocate 1163 * these things quickly. 1164 * 1165 * We can't support a transfer larger than MaxBurstLength bytes. 1166 */ 1167 if (size > itask->it_ict->ict_op.op_max_burst_length) { 1168 *pminsize = itask->it_ict->ict_op.op_max_burst_length; 1169 return (NULL); 1170 } 1171 1172 /* Alloc buffer */ 1173 idm_buffer = idm_buf_alloc(itask->it_ict->ict_ic, NULL, size); 1174 if (idm_buffer != NULL) { 1175 result = stmf_alloc(STMF_STRUCT_DATA_BUF, 1176 sizeof (iscsit_buf_t), 0); 1177 if (result != NULL) { 1178 /* Fill in stmf_data_buf_t */ 1179 ibuf = result->db_port_private; 1180 ibuf->ibuf_idm_buf = idm_buffer; 1181 ibuf->ibuf_stmf_buf = result; 1182 ibuf->ibuf_is_immed = B_FALSE; 1183 result->db_flags = DB_DONT_CACHE; 1184 result->db_buf_size = size; 1185 result->db_data_size = size; 1186 result->db_sglist_length = 1; 1187 result->db_sglist[0].seg_addr = idm_buffer->idb_buf; 1188 result->db_sglist[0].seg_length = 1189 idm_buffer->idb_buflen; 1190 return (result); 1191 } 1192 1193 /* Couldn't get the stmf_data_buf_t so free the buffer */ 1194 idm_buf_free(idm_buffer); 1195 } 1196 1197 return (NULL); 1198 } 1199 1200 /*ARGSUSED*/ 1201 static void 1202 iscsit_dbuf_free(stmf_dbuf_store_t *ds, stmf_data_buf_t *dbuf) 1203 { 1204 iscsit_buf_t *ibuf = dbuf->db_port_private; 1205 1206 if (ibuf->ibuf_is_immed) { 1207 /* 1208 * The iscsit_buf_t structure itself will be freed with its 1209 * associated task. Here we just need to free the PDU that 1210 * held the immediate data. 1211 */ 1212 idm_pdu_complete(ibuf->ibuf_immed_data_pdu, IDM_STATUS_SUCCESS); 1213 ibuf->ibuf_immed_data_pdu = 0; 1214 } else { 1215 idm_buf_free(ibuf->ibuf_idm_buf); 1216 stmf_free(dbuf); 1217 } 1218 } 1219 1220 /*ARGSUSED*/ 1221 stmf_status_t 1222 iscsit_xfer_scsi_data(scsi_task_t *task, stmf_data_buf_t *dbuf, 1223 uint32_t ioflags) 1224 { 1225 iscsit_task_t *iscsit_task = task->task_port_private; 1226 iscsit_buf_t *ibuf = dbuf->db_port_private; 1227 int idm_rc; 1228 1229 /* 1230 * If we are aborting then we can ignore this request 1231 */ 1232 if (iscsit_task->it_stmf_abort) { 1233 return (STMF_SUCCESS); 1234 } 1235 1236 /* 1237 * If it's not immediate data then start the transfer 1238 */ 1239 ASSERT(ibuf->ibuf_is_immed == B_FALSE); 1240 if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) { 1241 1242 /* 1243 * IDM will call iscsit_build_hdr so lock now to serialize 1244 * access to the SN values. We need to lock here to enforce 1245 * lock ordering 1246 */ 1247 rw_enter(&iscsit_task->it_ict->ict_sess->ist_sn_rwlock, 1248 RW_READER); 1249 idm_rc = idm_buf_tx_to_ini(iscsit_task->it_idm_task, 1250 ibuf->ibuf_idm_buf, dbuf->db_relative_offset, 1251 dbuf->db_data_size, &iscsit_buf_xfer_cb, dbuf); 1252 rw_exit(&iscsit_task->it_ict->ict_sess->ist_sn_rwlock); 1253 1254 return (iscsit_idm_to_stmf(idm_rc)); 1255 } else if (dbuf->db_flags & DB_DIRECTION_FROM_RPORT) { 1256 /* Grab the SN lock (see comment above) */ 1257 rw_enter(&iscsit_task->it_ict->ict_sess->ist_sn_rwlock, 1258 RW_READER); 1259 idm_rc = idm_buf_rx_from_ini(iscsit_task->it_idm_task, 1260 ibuf->ibuf_idm_buf, dbuf->db_relative_offset, 1261 dbuf->db_data_size, &iscsit_buf_xfer_cb, dbuf); 1262 rw_exit(&iscsit_task->it_ict->ict_sess->ist_sn_rwlock); 1263 1264 return (iscsit_idm_to_stmf(idm_rc)); 1265 } 1266 1267 /* What are we supposed to do if there is no direction? */ 1268 return (STMF_INVALID_ARG); 1269 } 1270 1271 static void 1272 iscsit_buf_xfer_cb(idm_buf_t *idb, idm_status_t status) 1273 { 1274 iscsit_task_t *itask = idb->idb_task_binding->idt_private; 1275 stmf_data_buf_t *dbuf = idb->idb_cb_arg; 1276 1277 dbuf->db_xfer_status = iscsit_idm_to_stmf(status); 1278 1279 /* 1280 * If the task has been aborted then we don't need to call STMF 1281 */ 1282 if (itask->it_stmf_abort) { 1283 return; 1284 } 1285 1286 /* 1287 * COMSTAR currently requires port providers to support 1288 * the DB_SEND_STATUS_GOOD flag even if phase collapse is 1289 * not supported. So we will roll our own... pretend we are 1290 * COMSTAR and ask for a status PDU. 1291 */ 1292 if ((dbuf->db_flags & DB_SEND_STATUS_GOOD) && 1293 status == IDM_STATUS_SUCCESS) { 1294 /* 1295 * If iscsit_send_scsi_status succeeds then the TX PDU 1296 * callback will call stmf_send_status_done and set 1297 * STMF_IOF_LPORT_DONE. Consequently we don't need 1298 * to call stmf_data_xfer_done in that case. We 1299 * still need to call it if we get a failure. 1300 * 1301 * To elaborate on this some more, upon successful 1302 * return from iscsit_send_scsi_status it's possible 1303 * that itask and idb have been freed and are no 1304 * longer valid. 1305 */ 1306 if (iscsit_send_scsi_status(itask->it_stmf_task, 0) 1307 != STMF_SUCCESS) { 1308 /* Failed to send status */ 1309 dbuf->db_xfer_status = STMF_FAILURE; 1310 stmf_data_xfer_done(itask->it_stmf_task, dbuf, 1311 STMF_IOF_LPORT_DONE); 1312 } 1313 } else { 1314 stmf_data_xfer_done(itask->it_stmf_task, dbuf, 0); 1315 } 1316 } 1317 1318 1319 /*ARGSUSED*/ 1320 stmf_status_t 1321 iscsit_send_scsi_status(scsi_task_t *task, uint32_t ioflags) 1322 { 1323 iscsit_task_t *itask = task->task_port_private; 1324 iscsi_scsi_rsp_hdr_t *rsp; 1325 idm_pdu_t *pdu; 1326 int resp_datalen; 1327 1328 /* 1329 * If this task is aborted then we don't need to respond. 1330 */ 1331 if (itask->it_stmf_abort) { 1332 return (STMF_SUCCESS); 1333 } 1334 1335 /* 1336 * If this is a task management status, handle it elsewhere. 1337 */ 1338 if (task->task_mgmt_function != TM_NONE) { 1339 /* 1340 * Don't wait for the PDU completion to tell STMF 1341 * the task is done -- it doesn't really matter and 1342 * it makes life complicated if STMF later asks us to 1343 * abort the request and we don't know whether the 1344 * status has been sent or not. 1345 */ 1346 itask->it_tm_responded = B_TRUE; 1347 iscsit_send_task_mgmt_resp(itask->it_tm_pdu, 1348 (task->task_completion_status == STMF_SUCCESS) ? 1349 SCSI_TCP_TM_RESP_COMPLETE : SCSI_TCP_TM_RESP_FUNC_NOT_SUPP); 1350 stmf_send_status_done(task, STMF_SUCCESS, 1351 STMF_IOF_LPORT_DONE); 1352 return (STMF_SUCCESS); 1353 } 1354 1355 mutex_enter(&itask->it_idm_task->idt_mutex); 1356 if ((itask->it_idm_task->idt_state == TASK_ACTIVE) && 1357 (task->task_completion_status == STMF_SUCCESS) && 1358 (task->task_sense_length == 0) && 1359 (task->task_resid == 0)) { 1360 itask->it_idm_task->idt_state = TASK_COMPLETE; 1361 /* PDU callback releases task hold */ 1362 idm_task_hold(itask->it_idm_task); 1363 mutex_exit(&itask->it_idm_task->idt_mutex); 1364 /* 1365 * Fast path. Cached status PDU's are already 1366 * initialized. We just need to fill in 1367 * connection and task information. 1368 */ 1369 pdu = kmem_cache_alloc(iscsit_status_pdu_cache, KM_SLEEP); 1370 pdu->isp_ic = itask->it_ict->ict_ic; 1371 pdu->isp_private = itask; 1372 1373 rsp = (iscsi_scsi_rsp_hdr_t *)pdu->isp_hdr; 1374 rsp->itt = itask->it_itt; 1375 rsp->cmd_status = task->task_scsi_status; 1376 iscsit_pdu_tx(pdu); 1377 return (STMF_SUCCESS); 1378 } else { 1379 if (itask->it_idm_task->idt_state != TASK_ACTIVE) { 1380 mutex_exit(&itask->it_idm_task->idt_mutex); 1381 return (STMF_FAILURE); 1382 } 1383 itask->it_idm_task->idt_state = TASK_COMPLETE; 1384 /* PDU callback releases task hold */ 1385 idm_task_hold(itask->it_idm_task); 1386 mutex_exit(&itask->it_idm_task->idt_mutex); 1387 1388 resp_datalen = (task->task_sense_length == 0) ? 0 : 1389 (task->task_sense_length + sizeof (uint16_t)); 1390 1391 pdu = idm_pdu_alloc(sizeof (iscsi_hdr_t), resp_datalen); 1392 idm_pdu_init(pdu, itask->it_ict->ict_ic, itask, 1393 iscsit_send_status_done); 1394 1395 rsp = (iscsi_scsi_rsp_hdr_t *)pdu->isp_hdr; 1396 bzero(rsp, sizeof (*rsp)); 1397 rsp->opcode = ISCSI_OP_SCSI_RSP; 1398 1399 rsp->flags = ISCSI_FLAG_FINAL; 1400 if (task->task_status_ctrl & TASK_SCTRL_OVER) { 1401 rsp->flags |= ISCSI_FLAG_CMD_OVERFLOW; 1402 } else if (task->task_status_ctrl & TASK_SCTRL_UNDER) { 1403 rsp->flags |= ISCSI_FLAG_CMD_UNDERFLOW; 1404 } 1405 1406 rsp->bi_residual_count = 0; 1407 rsp->residual_count = htonl(task->task_resid); 1408 rsp->itt = itask->it_itt; 1409 rsp->response = ISCSI_STATUS_CMD_COMPLETED; 1410 rsp->cmd_status = task->task_scsi_status; 1411 if (task->task_sense_length != 0) { 1412 /* 1413 * Add a byte to provide the sense length in 1414 * the response 1415 */ 1416 *(uint16_t *)((void *)pdu->isp_data) = 1417 htons(task->task_sense_length); 1418 bcopy(task->task_sense_data, 1419 (uint8_t *)pdu->isp_data + 1420 sizeof (uint16_t), 1421 task->task_sense_length); 1422 hton24(rsp->dlength, resp_datalen); 1423 } 1424 1425 iscsit_pdu_tx(pdu); 1426 1427 return (STMF_SUCCESS); 1428 } 1429 } 1430 1431 /*ARGSUSED*/ 1432 static void 1433 iscsit_send_good_status_done(idm_pdu_t *pdu, idm_status_t status) 1434 { 1435 iscsit_task_t *itask; 1436 boolean_t aborted; 1437 1438 itask = pdu->isp_private; 1439 aborted = itask->it_stmf_abort; 1440 1441 /* 1442 * After releasing the hold the task may be freed at any time so 1443 * don't touch it. 1444 */ 1445 idm_task_rele(itask->it_idm_task); 1446 if (!aborted) { 1447 stmf_send_status_done(itask->it_stmf_task, 1448 iscsit_idm_to_stmf(pdu->isp_status), STMF_IOF_LPORT_DONE); 1449 } 1450 kmem_cache_free(iscsit_status_pdu_cache, pdu); 1451 } 1452 1453 /*ARGSUSED*/ 1454 static void 1455 iscsit_send_status_done(idm_pdu_t *pdu, idm_status_t status) 1456 { 1457 iscsit_task_t *itask; 1458 boolean_t aborted; 1459 1460 itask = pdu->isp_private; 1461 aborted = itask->it_stmf_abort; 1462 1463 /* 1464 * After releasing the hold the task may be freed at any time so 1465 * don't touch it. 1466 */ 1467 idm_task_rele(itask->it_idm_task); 1468 if (!aborted) { 1469 stmf_send_status_done(itask->it_stmf_task, 1470 iscsit_idm_to_stmf(pdu->isp_status), STMF_IOF_LPORT_DONE); 1471 } 1472 idm_pdu_free(pdu); 1473 } 1474 1475 1476 void 1477 iscsit_lport_task_free(scsi_task_t *task) 1478 { 1479 iscsit_task_t *itask = task->task_port_private; 1480 1481 /* We only call idm_task_start for regular tasks, not task management */ 1482 if (task->task_mgmt_function == TM_NONE) { 1483 idm_task_done(itask->it_idm_task); 1484 iscsit_task_free(itask); 1485 return; 1486 } else { 1487 iscsit_tm_task_free(itask); 1488 } 1489 } 1490 1491 /*ARGSUSED*/ 1492 stmf_status_t 1493 iscsit_abort(stmf_local_port_t *lport, int abort_cmd, void *arg, uint32_t flags) 1494 { 1495 scsi_task_t *st = (scsi_task_t *)arg; 1496 iscsit_task_t *iscsit_task; 1497 idm_task_t *idt; 1498 1499 /* 1500 * If this is a task management request then there's really not much to 1501 * do. 1502 */ 1503 if (st->task_mgmt_function != TM_NONE) { 1504 return (STMF_ABORT_SUCCESS); 1505 } 1506 1507 /* 1508 * Regular task, start cleaning up 1509 */ 1510 iscsit_task = st->task_port_private; 1511 idt = iscsit_task->it_idm_task; 1512 mutex_enter(&iscsit_task->it_mutex); 1513 iscsit_task->it_stmf_abort = B_TRUE; 1514 if (iscsit_task->it_aborted) { 1515 mutex_exit(&iscsit_task->it_mutex); 1516 /* 1517 * STMF specification is wrong... says to return 1518 * STMF_ABORTED, the code actually looks for 1519 * STMF_ABORT_SUCCESS. 1520 */ 1521 return (STMF_ABORT_SUCCESS); 1522 } else { 1523 mutex_exit(&iscsit_task->it_mutex); 1524 /* 1525 * Call IDM to abort the task. Due to a variety of 1526 * circumstances the task may already be in the process of 1527 * aborting. 1528 * We'll let IDM worry about rationalizing all that except 1529 * for one particular instance. If the state of the task 1530 * is TASK_COMPLETE, we need to indicate to the framework 1531 * that we are in fact done. This typically happens with 1532 * framework-initiated task management type requests 1533 * (e.g. abort task). 1534 */ 1535 if (idt->idt_state == TASK_COMPLETE) { 1536 idm_refcnt_wait_ref(&idt->idt_refcnt); 1537 return (STMF_ABORT_SUCCESS); 1538 } else { 1539 idm_task_abort(idt->idt_ic, idt, AT_TASK_MGMT_ABORT); 1540 return (STMF_SUCCESS); 1541 } 1542 } 1543 1544 /*NOTREACHED*/ 1545 } 1546 1547 /*ARGSUSED*/ 1548 void 1549 iscsit_ctl(stmf_local_port_t *lport, int cmd, void *arg) 1550 { 1551 iscsit_tgt_t *iscsit_tgt; 1552 1553 ASSERT((cmd == STMF_CMD_LPORT_ONLINE) || 1554 (cmd == STMF_ACK_LPORT_ONLINE_COMPLETE) || 1555 (cmd == STMF_CMD_LPORT_OFFLINE) || 1556 (cmd == STMF_ACK_LPORT_OFFLINE_COMPLETE)); 1557 1558 iscsit_tgt = (iscsit_tgt_t *)lport->lport_port_private; 1559 1560 switch (cmd) { 1561 case STMF_CMD_LPORT_ONLINE: 1562 iscsit_tgt_sm_event(iscsit_tgt, TE_STMF_ONLINE_REQ); 1563 break; 1564 case STMF_CMD_LPORT_OFFLINE: 1565 iscsit_tgt_sm_event(iscsit_tgt, TE_STMF_OFFLINE_REQ); 1566 break; 1567 case STMF_ACK_LPORT_ONLINE_COMPLETE: 1568 iscsit_tgt_sm_event(iscsit_tgt, TE_STMF_ONLINE_COMPLETE_ACK); 1569 break; 1570 case STMF_ACK_LPORT_OFFLINE_COMPLETE: 1571 iscsit_tgt_sm_event(iscsit_tgt, TE_STMF_OFFLINE_COMPLETE_ACK); 1572 break; 1573 1574 default: 1575 break; 1576 } 1577 } 1578 1579 static stmf_status_t 1580 iscsit_idm_to_stmf(idm_status_t idmrc) 1581 { 1582 switch (idmrc) { 1583 case IDM_STATUS_SUCCESS: 1584 return (STMF_SUCCESS); 1585 default: 1586 return (STMF_FAILURE); 1587 } 1588 /*NOTREACHED*/ 1589 } 1590 1591 1592 /* 1593 * ISCSI protocol 1594 */ 1595 1596 void 1597 iscsit_op_scsi_cmd(idm_conn_t *ic, idm_pdu_t *rx_pdu) 1598 { 1599 iscsit_conn_t *ict; 1600 iscsit_task_t *itask; 1601 scsi_task_t *task; 1602 iscsit_buf_t *ibuf; 1603 iscsi_scsi_cmd_hdr_t *iscsi_scsi = 1604 (iscsi_scsi_cmd_hdr_t *)rx_pdu->isp_hdr; 1605 iscsi_addl_hdr_t *ahs_hdr; 1606 uint16_t addl_cdb_len = 0; 1607 1608 ict = ic->ic_handle; 1609 1610 itask = iscsit_task_alloc(ict); 1611 if (itask == NULL) { 1612 iscsit_send_direct_scsi_resp(ict, rx_pdu, 1613 ISCSI_STATUS_CMD_COMPLETED, STATUS_BUSY); 1614 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 1615 return; 1616 } 1617 1618 /* Finish processing request */ 1619 iscsit_set_cmdsn(ict, rx_pdu); 1620 1621 /* 1622 * Note CmdSN and ITT in task. IDM will have already validated this 1623 * request against the connection state so we don't need to check 1624 * that (the connection may have changed state in the meantime but 1625 * we will catch that when we try to send a response) 1626 */ 1627 itask->it_cmdsn = ntohl(iscsi_scsi->cmdsn); 1628 itask->it_itt = iscsi_scsi->itt; 1629 1630 /* 1631 * Check for extended CDB AHS 1632 */ 1633 if (iscsi_scsi->hlength > 0) { 1634 ahs_hdr = (iscsi_addl_hdr_t *)iscsi_scsi; 1635 addl_cdb_len = ((ahs_hdr->ahs_hlen_hi << 8) | 1636 ahs_hdr->ahs_hlen_lo) - 1; /* Adjust for reserved byte */ 1637 if (((addl_cdb_len + 4) / sizeof (uint32_t)) > 1638 iscsi_scsi->hlength) { 1639 /* Mangled header info, drop it */ 1640 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 1641 return; 1642 } 1643 } 1644 1645 ict = rx_pdu->isp_ic->ic_handle; /* IDM client private */ 1646 1647 itask->it_stmf_task = stmf_task_alloc( 1648 itask->it_ict->ict_sess->ist_lport, 1649 itask->it_ict->ict_sess->ist_stmf_sess, iscsi_scsi->lun, 1650 16 + addl_cdb_len, 0); 1651 if (itask->it_stmf_task == NULL) { 1652 /* 1653 * Either stmf really couldn't get memory for a task or, 1654 * more likely, the LU is currently in reset. Either way 1655 * we have no choice but to fail the request. 1656 */ 1657 iscsit_task_free(itask); 1658 iscsit_send_direct_scsi_resp(ict, rx_pdu, 1659 ISCSI_STATUS_CMD_COMPLETED, STATUS_BUSY); 1660 idm_pdu_complete(rx_pdu, IDM_STATUS_FAIL); 1661 return; 1662 } 1663 1664 task = itask->it_stmf_task; 1665 task->task_port_private = itask; 1666 1667 bcopy(iscsi_scsi->lun, task->task_lun_no, sizeof (task->task_lun_no)); 1668 1669 /* 1670 * iSCSI and Comstar use the same values. Should we rely on this 1671 * or translate them bit-wise? 1672 */ 1673 1674 task->task_flags = 1675 (((iscsi_scsi->flags & ISCSI_FLAG_CMD_READ) ? TF_READ_DATA : 0) | 1676 ((iscsi_scsi->flags & ISCSI_FLAG_CMD_WRITE) ? TF_WRITE_DATA : 0) | 1677 ((rx_pdu->isp_datalen == 0) ? 0 : TF_INITIAL_BURST)); 1678 1679 switch (iscsi_scsi->flags & ISCSI_FLAG_CMD_ATTR_MASK) { 1680 case ISCSI_ATTR_UNTAGGED: 1681 break; 1682 case ISCSI_ATTR_SIMPLE: 1683 task->task_additional_flags |= TF_ATTR_SIMPLE_QUEUE; 1684 break; 1685 case ISCSI_ATTR_ORDERED: 1686 task->task_additional_flags |= TF_ATTR_ORDERED_QUEUE; 1687 break; 1688 case ISCSI_ATTR_HEAD_OF_QUEUE: 1689 task->task_additional_flags |= TF_ATTR_HEAD_OF_QUEUE; 1690 break; 1691 case ISCSI_ATTR_ACA: 1692 task->task_additional_flags |= TF_ATTR_ACA; 1693 break; 1694 default: 1695 /* Protocol error but just take it, treat as untagged */ 1696 break; 1697 } 1698 1699 1700 task->task_additional_flags = 0; 1701 task->task_priority = 0; 1702 task->task_mgmt_function = TM_NONE; 1703 1704 /* 1705 * This "task_max_nbufs" doesn't map well to BIDI. We probably need 1706 * parameter for each direction. "MaxOutstandingR2T" may very well 1707 * be set to one which could prevent us from doing simultaneous 1708 * transfers in each direction. 1709 */ 1710 task->task_max_nbufs = (iscsi_scsi->flags & ISCSI_FLAG_CMD_WRITE) ? 1711 ict->ict_op.op_max_outstanding_r2t : STMF_BUFS_MAX; 1712 task->task_cmd_seq_no = ntohl(iscsi_scsi->itt); 1713 task->task_expected_xfer_length = ntohl(iscsi_scsi->data_length); 1714 1715 /* Copy CDB */ 1716 bcopy(iscsi_scsi->scb, task->task_cdb, 16); 1717 if (addl_cdb_len > 0) { 1718 bcopy(ahs_hdr->ahs_extscb, task->task_cdb + 16, addl_cdb_len); 1719 } 1720 1721 /* 1722 * Copy the transport header into the task handle from the PDU 1723 * handle. The transport header describes this task's remote tagged 1724 * buffer. 1725 */ 1726 if (rx_pdu->isp_transport_hdrlen != 0) { 1727 bcopy(rx_pdu->isp_transport_hdr, 1728 itask->it_idm_task->idt_transport_hdr, 1729 rx_pdu->isp_transport_hdrlen); 1730 } 1731 1732 /* 1733 * Tell IDM about our new active task 1734 */ 1735 idm_task_start(itask->it_idm_task, (uintptr_t)itask->it_itt); 1736 1737 /* 1738 * If we have any immediate data then setup the immediate buffer 1739 * context that comes with the task 1740 */ 1741 if (rx_pdu->isp_datalen) { 1742 ibuf = itask->it_immed_data; 1743 ibuf->ibuf_immed_data_pdu = rx_pdu; 1744 ibuf->ibuf_stmf_buf->db_data_size = rx_pdu->isp_datalen; 1745 ibuf->ibuf_stmf_buf->db_buf_size = rx_pdu->isp_datalen; 1746 ibuf->ibuf_stmf_buf->db_relative_offset = 0; 1747 ibuf->ibuf_stmf_buf->db_sglist[0].seg_length = 1748 rx_pdu->isp_datalen; 1749 ibuf->ibuf_stmf_buf->db_sglist[0].seg_addr = rx_pdu->isp_data; 1750 1751 stmf_post_task(task, ibuf->ibuf_stmf_buf); 1752 } else { 1753 stmf_post_task(task, NULL); 1754 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 1755 } 1756 } 1757 1758 /*ARGSUSED*/ 1759 void 1760 iscsit_deferred_dispatch(idm_pdu_t *rx_pdu) 1761 { 1762 iscsit_conn_t *ict = rx_pdu->isp_ic->ic_handle; 1763 1764 /* 1765 * If the connection has been lost then ignore new PDU's 1766 */ 1767 mutex_enter(&ict->ict_mutex); 1768 if (ict->ict_lost) { 1769 mutex_exit(&ict->ict_mutex); 1770 idm_pdu_complete(rx_pdu, IDM_STATUS_FAIL); 1771 return; 1772 } 1773 1774 /* 1775 * Grab a hold on the connection to prevent it from going away 1776 * between now and when the taskq function is called. 1777 */ 1778 iscsit_conn_dispatch_hold(ict); 1779 mutex_exit(&ict->ict_mutex); 1780 1781 if (taskq_dispatch(iscsit_global.global_dispatch_taskq, 1782 iscsit_deferred, rx_pdu, DDI_NOSLEEP) == NULL) { 1783 /* 1784 * In the unlikely scenario that we couldn't get the resources 1785 * to dispatch the PDU then just drop it. 1786 */ 1787 idm_pdu_complete(rx_pdu, IDM_STATUS_FAIL); 1788 idm_conn_event(ict->ict_ic, CE_TRANSPORT_FAIL, NULL); 1789 iscsit_conn_dispatch_rele(ict); 1790 } 1791 } 1792 1793 static void 1794 iscsit_deferred(void *rx_pdu_void) 1795 { 1796 idm_pdu_t *rx_pdu = rx_pdu_void; 1797 idm_conn_t *ic = rx_pdu->isp_ic; 1798 iscsit_conn_t *ict = ic->ic_handle; 1799 1800 switch (IDM_PDU_OPCODE(rx_pdu)) { 1801 case ISCSI_OP_NOOP_OUT: 1802 iscsit_set_cmdsn(ict, rx_pdu); 1803 iscsit_pdu_op_noop(ict, rx_pdu); 1804 break; 1805 case ISCSI_OP_LOGIN_CMD: 1806 iscsit_pdu_op_login_cmd(ict, rx_pdu); 1807 break; 1808 case ISCSI_OP_TEXT_CMD: 1809 iscsit_set_cmdsn(ict, rx_pdu); 1810 iscsit_pdu_op_text_cmd(ict, rx_pdu); 1811 break; 1812 case ISCSI_OP_LOGOUT_CMD: 1813 iscsit_set_cmdsn(ict, rx_pdu); 1814 iscsit_pdu_op_logout_cmd(ict, rx_pdu); 1815 break; 1816 default: 1817 /* Protocol error. IDM should have caught this */ 1818 idm_pdu_complete(rx_pdu, IDM_STATUS_FAIL); 1819 ASSERT(0); 1820 break; 1821 } 1822 1823 iscsit_conn_dispatch_rele(ict); 1824 } 1825 1826 static void 1827 iscsit_send_direct_scsi_resp(iscsit_conn_t *ict, idm_pdu_t *rx_pdu, 1828 uint8_t response, uint8_t cmd_status) 1829 { 1830 idm_pdu_t *rsp_pdu; 1831 idm_conn_t *ic; 1832 iscsi_scsi_rsp_hdr_t *resp; 1833 1834 ic = ict->ict_ic; 1835 1836 rsp_pdu = idm_pdu_alloc(sizeof (iscsi_scsi_rsp_hdr_t), 0); 1837 idm_pdu_init(rsp_pdu, ic, NULL, NULL); 1838 resp = (iscsi_scsi_rsp_hdr_t *)rsp_pdu->isp_hdr; 1839 1840 resp->opcode = ISCSI_OP_SCSI_RSP; 1841 resp->flags = ISCSI_FLAG_FINAL; 1842 resp->response = response; 1843 resp->cmd_status = cmd_status; 1844 resp->itt = rx_pdu->isp_hdr->itt; 1845 1846 iscsit_pdu_tx(rsp_pdu); 1847 } 1848 1849 void 1850 iscsit_send_task_mgmt_resp(idm_pdu_t *tm_resp_pdu, uint8_t tm_status) 1851 { 1852 iscsi_scsi_task_mgt_rsp_hdr_t *tm_resp; 1853 1854 tm_resp = (iscsi_scsi_task_mgt_rsp_hdr_t *)tm_resp_pdu->isp_hdr; 1855 tm_resp->response = tm_status; 1856 iscsit_pdu_tx(tm_resp_pdu); 1857 } 1858 1859 void 1860 iscsit_op_scsi_task_mgmt(iscsit_conn_t *ict, idm_pdu_t *rx_pdu) 1861 { 1862 idm_pdu_t *tm_resp_pdu; 1863 iscsit_task_t *itask; 1864 iscsit_task_t *tm_itask; 1865 scsi_task_t *task; 1866 iscsi_scsi_task_mgt_hdr_t *iscsi_tm = 1867 (iscsi_scsi_task_mgt_hdr_t *)rx_pdu->isp_hdr; 1868 iscsi_scsi_task_mgt_rsp_hdr_t *iscsi_tm_rsp = 1869 (iscsi_scsi_task_mgt_rsp_hdr_t *)rx_pdu->isp_hdr; 1870 uint32_t rtt, cmdsn, refcmdsn; 1871 uint8_t tm_func; 1872 1873 /* 1874 * Setup response PDU (response field will get filled in later) 1875 */ 1876 tm_resp_pdu = idm_pdu_alloc(sizeof (iscsi_scsi_task_mgt_rsp_hdr_t), 0); 1877 if (tm_resp_pdu == NULL) { 1878 /* Can't respond, just drop it */ 1879 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 1880 return; 1881 } 1882 idm_pdu_init(tm_resp_pdu, ict->ict_ic, NULL, NULL); 1883 iscsi_tm_rsp = (iscsi_scsi_task_mgt_rsp_hdr_t *)tm_resp_pdu->isp_hdr; 1884 bzero(iscsi_tm_rsp, sizeof (iscsi_scsi_task_mgt_rsp_hdr_t)); 1885 iscsi_tm_rsp->opcode = ISCSI_OP_SCSI_TASK_MGT_RSP; 1886 iscsi_tm_rsp->flags = ISCSI_FLAG_FINAL; 1887 iscsi_tm_rsp->itt = rx_pdu->isp_hdr->itt; 1888 1889 /* 1890 * Figure out what we're being asked to do. 1891 */ 1892 switch (iscsi_tm->function & ISCSI_FLAG_TASK_MGMT_FUNCTION_MASK) { 1893 case ISCSI_TM_FUNC_ABORT_TASK: 1894 /* 1895 * STMF doesn't currently support the "abort task" task 1896 * management command although it does support aborting 1897 * an individual task. We'll get STMF to abort the task 1898 * for us but handle the details of the task management 1899 * command ourselves. 1900 * 1901 * Find the task associated with the referenced task tag. 1902 */ 1903 rtt = iscsi_tm->rtt; 1904 itask = (iscsit_task_t *)idm_task_find_by_handle(ict->ict_ic, 1905 (uintptr_t)rtt); 1906 1907 if (itask == NULL) { 1908 cmdsn = ntohl(iscsi_tm->cmdsn); 1909 refcmdsn = ntohl(iscsi_tm->refcmdsn); 1910 1911 /* 1912 * Task was not found. If RefCmdSN is within the CmdSN 1913 * window and less than CmdSN of the TM function, return 1914 * "Function Complete". Otherwise, return 1915 * "Task Does Not Exist". 1916 */ 1917 1918 if (iscsit_cmdsn_in_window(ict, refcmdsn) && 1919 (refcmdsn < cmdsn)) { 1920 iscsit_send_task_mgmt_resp(tm_resp_pdu, 1921 SCSI_TCP_TM_RESP_COMPLETE); 1922 } else { 1923 iscsit_send_task_mgmt_resp(tm_resp_pdu, 1924 SCSI_TCP_TM_RESP_NO_TASK); 1925 } 1926 } else { 1927 1928 /* 1929 * Tell STMF to abort the task. This will do no harm 1930 * if the task is already complete. 1931 */ 1932 stmf_abort(STMF_QUEUE_TASK_ABORT, itask->it_stmf_task, 1933 STMF_ABORTED, NULL); 1934 1935 /* 1936 * Make sure the task hasn't already completed 1937 */ 1938 mutex_enter(&itask->it_idm_task->idt_mutex); 1939 if ((itask->it_idm_task->idt_state == TASK_COMPLETE) || 1940 (itask->it_idm_task->idt_state == TASK_IDLE)) { 1941 /* 1942 * Task is complete, return "Task Does Not 1943 * Exist" 1944 */ 1945 mutex_exit(&itask->it_idm_task->idt_mutex); 1946 iscsit_send_task_mgmt_resp(tm_resp_pdu, 1947 SCSI_TCP_TM_RESP_NO_TASK); 1948 } else { 1949 /* 1950 * STMF is now aborting the task, return 1951 * "Function Complete" 1952 */ 1953 mutex_exit(&itask->it_idm_task->idt_mutex); 1954 iscsit_send_task_mgmt_resp(tm_resp_pdu, 1955 SCSI_TCP_TM_RESP_COMPLETE); 1956 } 1957 idm_task_rele(itask->it_idm_task); 1958 } 1959 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 1960 return; 1961 1962 case ISCSI_TM_FUNC_ABORT_TASK_SET: 1963 tm_func = TM_ABORT_TASK_SET; 1964 break; 1965 1966 case ISCSI_TM_FUNC_CLEAR_ACA: 1967 tm_func = TM_CLEAR_ACA; 1968 break; 1969 1970 case ISCSI_TM_FUNC_CLEAR_TASK_SET: 1971 tm_func = TM_CLEAR_TASK_SET; 1972 break; 1973 1974 case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET: 1975 tm_func = TM_LUN_RESET; 1976 break; 1977 1978 case ISCSI_TM_FUNC_TARGET_WARM_RESET: 1979 tm_func = TM_TARGET_WARM_RESET; 1980 break; 1981 1982 case ISCSI_TM_FUNC_TARGET_COLD_RESET: 1983 tm_func = TM_TARGET_COLD_RESET; 1984 break; 1985 1986 case ISCSI_TM_FUNC_TASK_REASSIGN: 1987 /* 1988 * We do not currently support allegiance reassignment. When 1989 * we start supporting ERL1+, we will need to. 1990 */ 1991 iscsit_send_task_mgmt_resp(tm_resp_pdu, 1992 SCSI_TCP_TM_RESP_NO_ALLG_REASSN); 1993 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 1994 return; 1995 1996 default: 1997 iscsit_send_task_mgmt_resp(tm_resp_pdu, 1998 SCSI_TCP_TM_RESP_REJECTED); 1999 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 2000 return; 2001 } 2002 2003 tm_itask = iscsit_tm_task_alloc(ict); 2004 if (tm_itask == NULL) { 2005 iscsit_send_task_mgmt_resp(tm_resp_pdu, 2006 SCSI_TCP_TM_RESP_REJECTED); 2007 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 2008 return; 2009 } 2010 2011 2012 task = stmf_task_alloc(ict->ict_sess->ist_lport, 2013 ict->ict_sess->ist_stmf_sess, iscsi_tm->lun, 2014 0, STMF_TASK_EXT_NONE); 2015 if (task == NULL) { 2016 /* 2017 * If this happens, either the LU is in reset, couldn't 2018 * get memory, or some other condition in which we simply 2019 * can't complete this request. It would be nice to return 2020 * an error code like "busy" but the closest we have is 2021 * "rejected". 2022 */ 2023 iscsit_send_task_mgmt_resp(tm_resp_pdu, 2024 SCSI_TCP_TM_RESP_REJECTED); 2025 iscsit_tm_task_free(tm_itask); 2026 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 2027 return; 2028 } 2029 2030 tm_itask->it_tm_pdu = tm_resp_pdu; 2031 tm_itask->it_stmf_task = task; 2032 task->task_port_private = tm_itask; 2033 task->task_mgmt_function = tm_func; 2034 task->task_additional_flags = TASK_AF_NO_EXPECTED_XFER_LENGTH; 2035 task->task_priority = 0; 2036 task->task_max_nbufs = STMF_BUFS_MAX; 2037 task->task_cmd_seq_no = iscsi_tm->itt; 2038 task->task_expected_xfer_length = 0; 2039 2040 stmf_post_task(task, NULL); 2041 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 2042 } 2043 2044 static void 2045 iscsit_pdu_op_noop(iscsit_conn_t *ict, idm_pdu_t *rx_pdu) 2046 { 2047 iscsi_nop_out_hdr_t *out = (iscsi_nop_out_hdr_t *)rx_pdu->isp_hdr; 2048 iscsi_nop_in_hdr_t *in; 2049 int resp_datalen; 2050 idm_pdu_t *resp; 2051 2052 /* Get iSCSI session handle */ 2053 /* Ignore the response from initiator */ 2054 if (out->ttt != ISCSI_RSVD_TASK_TAG) 2055 return; 2056 2057 /* Allocate a PDU to respond */ 2058 resp_datalen = ntoh24(out->dlength); 2059 resp = idm_pdu_alloc(sizeof (iscsi_hdr_t), resp_datalen); 2060 idm_pdu_init(resp, ict->ict_ic, NULL, NULL); 2061 if (resp_datalen > 0) { 2062 bcopy(rx_pdu->isp_data, resp->isp_data, resp_datalen); 2063 } 2064 2065 in = (iscsi_nop_in_hdr_t *)resp->isp_hdr; 2066 bzero(in, sizeof (*in)); 2067 in->opcode = ISCSI_OP_NOOP_IN; 2068 in->flags = ISCSI_FLAG_FINAL; 2069 bcopy(out->lun, in->lun, 8); 2070 in->itt = out->itt; 2071 in->ttt = ISCSI_RSVD_TASK_TAG; 2072 hton24(in->dlength, resp_datalen); 2073 2074 /* Any other field in resp to be set? */ 2075 iscsit_pdu_tx(resp); 2076 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 2077 } 2078 2079 static void 2080 iscsit_pdu_op_login_cmd(iscsit_conn_t *ict, idm_pdu_t *rx_pdu) 2081 { 2082 2083 /* 2084 * Submit PDU to login state machine. State machine will free the 2085 * PDU. 2086 */ 2087 iscsit_login_sm_event(ict, ILE_LOGIN_RCV, rx_pdu); 2088 } 2089 2090 void 2091 iscsit_pdu_op_logout_cmd(iscsit_conn_t *ict, idm_pdu_t *rx_pdu) 2092 { 2093 iscsi_logout_hdr_t *logout_req = 2094 (iscsi_logout_hdr_t *)rx_pdu->isp_hdr; 2095 iscsi_logout_rsp_hdr_t *logout_rsp; 2096 idm_pdu_t *resp; 2097 2098 /* Allocate a PDU to respond */ 2099 resp = idm_pdu_alloc(sizeof (iscsi_hdr_t), 0); 2100 idm_pdu_init(resp, ict->ict_ic, NULL, NULL); 2101 2102 /* 2103 * Logout results in the immediate termination of all tasks except 2104 * if the logout reason is ISCSI_LOGOUT_REASON_RECOVERY. The 2105 * connection state machine will drive this task cleanup automatically 2106 * so we don't need to handle that here. 2107 */ 2108 logout_rsp = (iscsi_logout_rsp_hdr_t *)resp->isp_hdr; 2109 bzero(logout_rsp, sizeof (*logout_rsp)); 2110 logout_rsp->opcode = ISCSI_OP_LOGOUT_RSP; 2111 logout_rsp->flags = ISCSI_FLAG_FINAL; 2112 logout_rsp->itt = logout_req->itt; 2113 if ((logout_req->flags & ISCSI_FLAG_LOGOUT_REASON_MASK) > 2114 ISCSI_LOGOUT_REASON_RECOVERY) { 2115 logout_rsp->response = ISCSI_LOGOUT_RECOVERY_UNSUPPORTED; 2116 } else { 2117 logout_rsp->response = ISCSI_LOGOUT_SUCCESS; 2118 } 2119 2120 iscsit_pdu_tx(resp); 2121 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 2122 } 2123 2124 /* 2125 * Calculate the number of outstanding commands we can process 2126 */ 2127 int 2128 iscsit_cmd_window() 2129 { 2130 /* Will be better later */ 2131 return (1024); 2132 } 2133 2134 /* 2135 * Set local registers based on incoming PDU 2136 */ 2137 void 2138 iscsit_set_cmdsn(iscsit_conn_t *ict, idm_pdu_t *rx_pdu) 2139 { 2140 iscsit_sess_t *ist; 2141 iscsi_scsi_cmd_hdr_t *req; 2142 2143 ist = ict->ict_sess; 2144 2145 req = (iscsi_scsi_cmd_hdr_t *)rx_pdu->isp_hdr; 2146 2147 rw_enter(&ist->ist_sn_rwlock, RW_WRITER); 2148 ist->ist_expcmdsn = ntohl(req->cmdsn) + 1; 2149 ist->ist_maxcmdsn = ntohl(req->cmdsn) + iscsit_cmd_window(); 2150 rw_exit(&ist->ist_sn_rwlock); 2151 } 2152 2153 /* 2154 * Update local StatSN and set SNs in response 2155 */ 2156 static void 2157 iscsit_calc_rspsn(iscsit_conn_t *ict, idm_pdu_t *resp) 2158 { 2159 iscsit_sess_t *ist; 2160 iscsi_scsi_rsp_hdr_t *rsp; 2161 2162 /* Get iSCSI session handle */ 2163 ist = ict->ict_sess; 2164 2165 rsp = (iscsi_scsi_rsp_hdr_t *)resp->isp_hdr; 2166 2167 /* Update StatSN */ 2168 rsp->statsn = htonl(ict->ict_statsn); 2169 switch (IDM_PDU_OPCODE(resp)) { 2170 case ISCSI_OP_RTT_RSP: 2171 /* Do nothing */ 2172 break; 2173 case ISCSI_OP_NOOP_IN: 2174 /* 2175 * Refer to section 10.19.1, RFC3720. 2176 * Advance only if target is responding initiator 2177 */ 2178 if (((iscsi_nop_in_hdr_t *)rsp)->ttt == ISCSI_RSVD_TASK_TAG) 2179 ict->ict_statsn++; 2180 break; 2181 case ISCSI_OP_SCSI_DATA_RSP: 2182 if (rsp->flags & ISCSI_FLAG_DATA_STATUS) 2183 ict->ict_statsn++; 2184 else 2185 rsp->statsn = 0; 2186 break; 2187 default: 2188 ict->ict_statsn++; 2189 break; 2190 } 2191 2192 /* Set ExpCmdSN and MaxCmdSN */ 2193 rsp->maxcmdsn = htonl(ist->ist_maxcmdsn); 2194 rsp->expcmdsn = htonl(ist->ist_expcmdsn); 2195 } 2196 2197 /* 2198 * Wrapper funtion, calls iscsi_calc_rspsn and idm_pdu_tx 2199 */ 2200 void 2201 iscsit_pdu_tx(idm_pdu_t *pdu) 2202 { 2203 iscsit_conn_t *ict = pdu->isp_ic->ic_handle; 2204 2205 /* 2206 * Protect ict->ict_statsn, ist->ist_maxcmdsn, and ist->ist_expcmdsn 2207 * (which are used by iscsit_calc_rspsn) with the session mutex 2208 * (ist->ist_sn_mutex). 2209 */ 2210 rw_enter(&ict->ict_sess->ist_sn_rwlock, RW_WRITER); 2211 iscsit_calc_rspsn(ict, pdu); 2212 idm_pdu_tx(pdu); 2213 rw_exit(&ict->ict_sess->ist_sn_rwlock); 2214 } 2215 2216 /* 2217 * Internal functions 2218 */ 2219 2220 void 2221 iscsit_send_async_event(iscsit_conn_t *ict, uint8_t event) 2222 { 2223 idm_pdu_t *abt; 2224 iscsi_async_evt_hdr_t *async_abt; 2225 2226 /* 2227 * Get a PDU to build the abort request. 2228 */ 2229 abt = idm_pdu_alloc(sizeof (iscsi_hdr_t), 0); 2230 if (abt == NULL) { 2231 idm_conn_event(ict->ict_ic, CE_TRANSPORT_FAIL, NULL); 2232 return; 2233 } 2234 idm_pdu_init(abt, ict->ict_ic, NULL, NULL); 2235 2236 ASSERT(abt != NULL); 2237 abt->isp_datalen = 0; 2238 2239 async_abt = (iscsi_async_evt_hdr_t *)abt->isp_hdr; 2240 bzero(async_abt, sizeof (*async_abt)); 2241 async_abt->opcode = ISCSI_OP_ASYNC_EVENT; 2242 async_abt->async_event = event; 2243 async_abt->flags = ISCSI_FLAG_FINAL; 2244 async_abt->rsvd4[0] = 0xff; 2245 async_abt->rsvd4[1] = 0xff; 2246 async_abt->rsvd4[2] = 0xff; 2247 async_abt->rsvd4[3] = 0xff; 2248 2249 switch (event) { 2250 case ISCSI_ASYNC_EVENT_REQUEST_LOGOUT: 2251 async_abt->param3 = htons(IDM_LOGOUT_SECONDS); 2252 break; 2253 case ISCSI_ASYNC_EVENT_SCSI_EVENT: 2254 case ISCSI_ASYNC_EVENT_DROPPING_CONNECTION: 2255 case ISCSI_ASYNC_EVENT_DROPPING_ALL_CONNECTIONS: 2256 case ISCSI_ASYNC_EVENT_PARAM_NEGOTIATION: 2257 default: 2258 ASSERT(0); 2259 } 2260 2261 iscsit_pdu_tx(abt); 2262 } 2263 2264 2265 static iscsit_task_t * 2266 iscsit_task_alloc(iscsit_conn_t *ict) 2267 { 2268 iscsit_task_t *itask; 2269 iscsit_buf_t *immed_ibuf; 2270 2271 /* 2272 * Possible items to pre-alloc if we cache iscsit_task_t's: 2273 * 2274 * Status PDU w/ sense buffer 2275 * stmf_data_buf_t for immediate data 2276 */ 2277 itask = kmem_alloc(sizeof (iscsit_task_t) + sizeof (iscsit_buf_t) + 2278 sizeof (stmf_data_buf_t), KM_NOSLEEP); 2279 if (itask != NULL) { 2280 mutex_init(&itask->it_mutex, NULL, MUTEX_DRIVER, NULL); 2281 itask->it_aborted = itask->it_stmf_abort = 2282 itask->it_tm_task = 0; 2283 2284 immed_ibuf = (iscsit_buf_t *)(itask + 1); 2285 bzero(immed_ibuf, sizeof (*immed_ibuf)); 2286 immed_ibuf->ibuf_is_immed = B_TRUE; 2287 immed_ibuf->ibuf_stmf_buf = (stmf_data_buf_t *)(immed_ibuf + 1); 2288 2289 bzero(immed_ibuf->ibuf_stmf_buf, sizeof (stmf_data_buf_t)); 2290 immed_ibuf->ibuf_stmf_buf->db_port_private = immed_ibuf; 2291 immed_ibuf->ibuf_stmf_buf->db_sglist_length = 1; 2292 immed_ibuf->ibuf_stmf_buf->db_flags = DB_DIRECTION_FROM_RPORT | 2293 DB_DONT_CACHE; 2294 itask->it_immed_data = immed_ibuf; 2295 itask->it_idm_task = idm_task_alloc(ict->ict_ic); 2296 if (itask->it_idm_task != NULL) { 2297 itask->it_idm_task->idt_private = itask; 2298 itask->it_ict = ict; 2299 itask->it_ttt = itask->it_idm_task->idt_tt; 2300 return (itask); 2301 } else { 2302 kmem_free(itask, sizeof (iscsit_task_t) + 2303 sizeof (iscsit_buf_t) + sizeof (stmf_data_buf_t)); 2304 } 2305 } 2306 2307 return (NULL); 2308 } 2309 2310 static void 2311 iscsit_task_free(iscsit_task_t *itask) 2312 { 2313 idm_task_free(itask->it_idm_task); 2314 mutex_destroy(&itask->it_mutex); 2315 kmem_free(itask, sizeof (iscsit_task_t) + 2316 sizeof (iscsit_buf_t) + sizeof (stmf_data_buf_t)); 2317 } 2318 2319 static iscsit_task_t * 2320 iscsit_tm_task_alloc(iscsit_conn_t *ict) 2321 { 2322 iscsit_task_t *itask; 2323 2324 itask = kmem_zalloc(sizeof (iscsit_task_t), KM_NOSLEEP); 2325 if (itask != NULL) { 2326 idm_conn_hold(ict->ict_ic); 2327 mutex_init(&itask->it_mutex, NULL, MUTEX_DRIVER, NULL); 2328 itask->it_aborted = itask->it_stmf_abort = 2329 itask->it_tm_responded = 0; 2330 itask->it_tm_pdu = NULL; 2331 itask->it_tm_task = 1; 2332 itask->it_ict = ict; 2333 } 2334 2335 return (itask); 2336 } 2337 2338 static void 2339 iscsit_tm_task_free(iscsit_task_t *itask) 2340 { 2341 /* 2342 * If we responded then the call to idm_pdu_complete will free the 2343 * PDU. Otherwise we got aborted before the TM function could 2344 * complete and we need to free the PDU explicitly. 2345 */ 2346 if (itask->it_tm_pdu != NULL && !itask->it_tm_responded) 2347 idm_pdu_free(itask->it_tm_pdu); 2348 idm_conn_rele(itask->it_ict->ict_ic); 2349 mutex_destroy(&itask->it_mutex); 2350 kmem_free(itask, sizeof (iscsit_task_t)); 2351 } 2352 2353 /* 2354 * iscsit status PDU cache 2355 */ 2356 2357 /*ARGSUSED*/ 2358 static int 2359 iscsit_status_pdu_constructor(void *pdu_void, void *arg, int flags) 2360 { 2361 idm_pdu_t *pdu = pdu_void; 2362 iscsi_scsi_rsp_hdr_t *rsp; 2363 2364 bzero(pdu, sizeof (idm_pdu_t)); 2365 pdu->isp_callback = iscsit_send_good_status_done; 2366 pdu->isp_magic = IDM_PDU_MAGIC; 2367 pdu->isp_hdr = (iscsi_hdr_t *)(pdu + 1); /* Ptr arithmetic */ 2368 pdu->isp_hdrlen = sizeof (iscsi_hdr_t); 2369 2370 /* Setup status response */ 2371 rsp = (iscsi_scsi_rsp_hdr_t *)pdu->isp_hdr; 2372 bzero(rsp, sizeof (*rsp)); 2373 rsp->opcode = ISCSI_OP_SCSI_RSP; 2374 rsp->flags = ISCSI_FLAG_FINAL; 2375 rsp->response = ISCSI_STATUS_CMD_COMPLETED; 2376 2377 return (0); 2378 } 2379 2380 /* 2381 * iscsit private data handler 2382 */ 2383 2384 /*ARGSUSED*/ 2385 static void 2386 iscsit_pp_cb(struct stmf_port_provider *pp, int cmd, void *arg, uint32_t flags) 2387 { 2388 it_config_t *cfg; 2389 nvlist_t *nvl; 2390 2391 if ((cmd != STMF_PROVIDER_DATA_UPDATED) || (arg == NULL)) { 2392 return; 2393 } 2394 2395 nvl = (nvlist_t *)arg; 2396 2397 /* Translate nvlist */ 2398 if (it_nv_to_config(nvl, &cfg) != 0) { 2399 cmn_err(CE_WARN, "Configuration is invalid"); 2400 return; 2401 } 2402 2403 /* Update config */ 2404 (void) iscsit_config_merge(cfg); 2405 2406 it_config_free_cmn(cfg); 2407 } 2408 2409 2410 static it_cfg_status_t 2411 iscsit_config_merge(it_config_t *in_cfg) 2412 { 2413 it_cfg_status_t status; 2414 it_config_t *cfg; 2415 it_config_t tmp_cfg; 2416 list_t tpg_del_list; 2417 2418 if (in_cfg) { 2419 cfg = in_cfg; 2420 } else { 2421 /* Make empty config */ 2422 bzero(&tmp_cfg, sizeof (tmp_cfg)); 2423 cfg = &tmp_cfg; 2424 } 2425 2426 list_create(&tpg_del_list, sizeof (iscsit_tpg_t), 2427 offsetof(iscsit_tpg_t, tpg_delete_ln)); 2428 2429 /* 2430 * Update targets, initiator contexts, target portal groups, 2431 * and iSNS client 2432 */ 2433 ISCSIT_GLOBAL_LOCK(RW_WRITER); 2434 if (((status = iscsit_config_merge_tpg(cfg, &tpg_del_list)) 2435 != 0) || 2436 ((status = iscsit_config_merge_tgt(cfg)) != 0) || 2437 ((status = iscsit_config_merge_ini(cfg)) != 0) || 2438 ((status = isnst_config_merge(cfg)) != 0)) { 2439 ISCSIT_GLOBAL_UNLOCK(); 2440 return (status); 2441 } 2442 2443 /* Update other global config parameters */ 2444 if (iscsit_global.global_props) { 2445 nvlist_free(iscsit_global.global_props); 2446 iscsit_global.global_props = NULL; 2447 } 2448 if (in_cfg) { 2449 (void) nvlist_dup(cfg->config_global_properties, 2450 &iscsit_global.global_props, KM_SLEEP); 2451 } 2452 ISCSIT_GLOBAL_UNLOCK(); 2453 2454 iscsit_config_destroy_tpgs(&tpg_del_list); 2455 2456 list_destroy(&tpg_del_list); 2457 2458 return (ITCFG_SUCCESS); 2459 } 2460 2461 /* 2462 * iscsit_sna_lt[e] 2463 * 2464 * Compare serial numbers using serial number arithmetic as defined in 2465 * RFC 1982. 2466 * 2467 * NOTE: This code is duplicated in the isns server as well as iscsitgtd. It 2468 * ought to be common. 2469 */ 2470 2471 static int 2472 iscsit_sna_lt(uint32_t sn1, uint32_t sn2) 2473 { 2474 return ((sn1 != sn2) && 2475 (((sn1 < sn2) && ((sn2 - sn1) < ISCSIT_SNA32_CHECK)) || 2476 ((sn1 > sn2) && ((sn1 - sn2) > ISCSIT_SNA32_CHECK)))); 2477 } 2478 2479 static int 2480 iscsit_sna_lte(uint32_t sn1, uint32_t sn2) 2481 { 2482 return ((sn1 == sn2) || 2483 (((sn1 < sn2) && ((sn2 - sn1) < ISCSIT_SNA32_CHECK)) || 2484 ((sn1 > sn2) && ((sn1 - sn2) > ISCSIT_SNA32_CHECK)))); 2485 } 2486 2487 2488 static boolean_t 2489 iscsit_cmdsn_in_window(iscsit_conn_t *ict, uint32_t cmdsn) 2490 { 2491 iscsit_sess_t *ist = ict->ict_sess; 2492 int rval = B_TRUE; 2493 2494 ist = ict->ict_sess; 2495 2496 rw_enter(&ist->ist_sn_rwlock, RW_READER); 2497 2498 /* 2499 * If cmdsn is less than ist_expcmdsn - iscsit_cmd_window() or 2500 * greater than ist_expcmdsn, it's not in the window. 2501 */ 2502 2503 if (iscsit_sna_lt(cmdsn, (ist->ist_expcmdsn - iscsit_cmd_window())) || 2504 !iscsit_sna_lte(cmdsn, ist->ist_expcmdsn)) { 2505 rval = B_FALSE; 2506 } 2507 2508 rw_exit(&ist->ist_sn_rwlock); 2509 2510 return (rval); 2511 } 2512