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 * We need to get a global hold here to ensure that the service 975 * doesn't get shutdown prior to establishing a session. This 976 * gets released in iscsit_conn_destroy(). 977 */ 978 iscsit_global_hold(); 979 980 /* 981 * Allocate an associated iscsit structure to represent this 982 * connection. We shouldn't really create a session until we 983 * get the first login PDU. 984 */ 985 ict = kmem_zalloc(sizeof (*ict), KM_SLEEP); 986 987 ict->ict_ic = ic; 988 ict->ict_statsn = 1; 989 ic->ic_handle = ict; 990 mutex_init(&ict->ict_mutex, NULL, MUTEX_DRIVER, NULL); 991 idm_refcnt_init(&ict->ict_refcnt, ict); 992 993 /* 994 * Initialize login state machine 995 */ 996 if (iscsit_login_sm_init(ict) != IDM_STATUS_SUCCESS) { 997 return (IDM_STATUS_FAIL); 998 } 999 1000 return (IDM_STATUS_SUCCESS); 1001 } 1002 1003 idm_status_t 1004 iscsit_conn_reinstate(iscsit_conn_t *reinstate_ict, iscsit_conn_t *new_ict) 1005 { 1006 idm_status_t result; 1007 1008 /* 1009 * Note in new connection state that this connection is 1010 * reinstating an existing connection. 1011 */ 1012 new_ict->ict_reinstating = B_TRUE; 1013 new_ict->ict_reinstate_conn = reinstate_ict; 1014 new_ict->ict_statsn = reinstate_ict->ict_statsn; 1015 1016 /* 1017 * Now generate connection state machine event to existing connection 1018 * so that it starts the cleanup process. 1019 */ 1020 result = idm_conn_reinstate_event(reinstate_ict->ict_ic, 1021 new_ict->ict_ic); 1022 1023 return (result); 1024 } 1025 1026 void 1027 iscsit_conn_hold(iscsit_conn_t *ict) 1028 { 1029 idm_refcnt_hold(&ict->ict_refcnt); 1030 } 1031 1032 void 1033 iscsit_conn_rele(iscsit_conn_t *ict) 1034 { 1035 idm_refcnt_rele(&ict->ict_refcnt); 1036 } 1037 1038 void 1039 iscsit_conn_dispatch_hold(iscsit_conn_t *ict) 1040 { 1041 idm_refcnt_hold(&ict->ict_dispatch_refcnt); 1042 } 1043 1044 void 1045 iscsit_conn_dispatch_rele(iscsit_conn_t *ict) 1046 { 1047 idm_refcnt_rele(&ict->ict_dispatch_refcnt); 1048 } 1049 1050 static idm_status_t 1051 iscsit_login_fail(idm_conn_t *ic) 1052 { 1053 iscsit_conn_t *ict = ic->ic_handle; 1054 1055 /* Generate login state machine event */ 1056 iscsit_login_sm_event(ict, ILE_LOGIN_CONN_ERROR, NULL); 1057 1058 return (IDM_STATUS_SUCCESS); 1059 } 1060 1061 static idm_status_t 1062 iscsit_ffp_enabled(idm_conn_t *ic) 1063 { 1064 iscsit_conn_t *ict = ic->ic_handle; 1065 1066 /* Generate session state machine event */ 1067 iscsit_sess_sm_event(ict->ict_sess, SE_CONN_LOGGED_IN, ict); 1068 1069 return (IDM_STATUS_SUCCESS); 1070 } 1071 1072 static idm_status_t 1073 iscsit_ffp_disabled(idm_conn_t *ic, idm_ffp_disable_t disable_class) 1074 { 1075 iscsit_conn_t *ict = ic->ic_handle; 1076 1077 /* Generate session state machine event */ 1078 switch (disable_class) { 1079 case FD_CONN_FAIL: 1080 iscsit_sess_sm_event(ict->ict_sess, SE_CONN_FFP_FAIL, ict); 1081 break; 1082 case FD_CONN_LOGOUT: 1083 iscsit_sess_sm_event(ict->ict_sess, SE_CONN_FFP_DISABLE, ict); 1084 break; 1085 case FD_SESS_LOGOUT: 1086 iscsit_sess_sm_event(ict->ict_sess, SE_SESSION_CLOSE, ict); 1087 break; 1088 default: 1089 ASSERT(0); 1090 } 1091 1092 return (IDM_STATUS_SUCCESS); 1093 } 1094 1095 static idm_status_t 1096 iscsit_conn_lost(idm_conn_t *ic) 1097 { 1098 iscsit_conn_t *ict = ic->ic_handle; 1099 1100 mutex_enter(&ict->ict_mutex); 1101 ict->ict_lost = B_TRUE; 1102 mutex_exit(&ict->ict_mutex); 1103 1104 /* 1105 * Make sure there aren't any PDU's transitioning from the receive 1106 * handler to the dispatch taskq. 1107 */ 1108 idm_refcnt_wait_ref(&ict->ict_dispatch_refcnt); 1109 1110 return (IDM_STATUS_SUCCESS); 1111 } 1112 1113 static idm_status_t 1114 iscsit_conn_destroy(idm_conn_t *ic) 1115 { 1116 iscsit_conn_t *ict = ic->ic_handle; 1117 1118 mutex_enter(&ict->ict_mutex); 1119 ict->ict_destroyed = B_TRUE; 1120 mutex_exit(&ict->ict_mutex); 1121 1122 /* Generate session state machine event */ 1123 if (ict->ict_sess != NULL) { 1124 /* 1125 * Session state machine will call iscsit_conn_destroy_done() 1126 * when it has removed references to this connection. 1127 */ 1128 iscsit_sess_sm_event(ict->ict_sess, SE_CONN_FAIL, ict); 1129 } 1130 1131 ict->ict_ic = NULL; 1132 1133 idm_refcnt_wait_ref(&ict->ict_refcnt); 1134 1135 mutex_destroy(&ict->ict_mutex); 1136 idm_refcnt_destroy(&ict->ict_refcnt); 1137 kmem_free(ict, sizeof (*ict)); 1138 1139 iscsit_global_rele(); 1140 1141 return (IDM_STATUS_SUCCESS); 1142 } 1143 1144 /* 1145 * STMF-related functions 1146 * 1147 * iSCSI to STMF mapping 1148 * 1149 * Session == ? 1150 * Connection == bound to local port but not itself a local port 1151 * Target 1152 * Target portal (group?) == local port (really but we're not going to do this) 1153 * iscsit needs to map connections to local ports (whatever we decide 1154 * they are) 1155 * Target == ? 1156 */ 1157 1158 /*ARGSUSED*/ 1159 static stmf_data_buf_t * 1160 iscsit_dbuf_alloc(scsi_task_t *task, uint32_t size, uint32_t *pminsize, 1161 uint32_t flags) 1162 { 1163 iscsit_task_t *itask = task->task_port_private; 1164 idm_buf_t *idm_buffer; 1165 iscsit_buf_t *ibuf; 1166 stmf_data_buf_t *result; 1167 1168 /* 1169 * Once the iSER picture is better understood it might make sense 1170 * to pre-allocate some registered buffers, similar to what 1171 * fct/qlt are doing. In the meantime hopefully stmf can allocate 1172 * these things quickly. 1173 * 1174 * We can't support a transfer larger than MaxBurstLength bytes. 1175 */ 1176 if (size > itask->it_ict->ict_op.op_max_burst_length) { 1177 *pminsize = itask->it_ict->ict_op.op_max_burst_length; 1178 return (NULL); 1179 } 1180 1181 /* Alloc buffer */ 1182 idm_buffer = idm_buf_alloc(itask->it_ict->ict_ic, NULL, size); 1183 if (idm_buffer != NULL) { 1184 result = stmf_alloc(STMF_STRUCT_DATA_BUF, 1185 sizeof (iscsit_buf_t), 0); 1186 if (result != NULL) { 1187 /* Fill in stmf_data_buf_t */ 1188 ibuf = result->db_port_private; 1189 ibuf->ibuf_idm_buf = idm_buffer; 1190 ibuf->ibuf_stmf_buf = result; 1191 ibuf->ibuf_is_immed = B_FALSE; 1192 result->db_flags = DB_DONT_CACHE; 1193 result->db_buf_size = size; 1194 result->db_data_size = size; 1195 result->db_sglist_length = 1; 1196 result->db_sglist[0].seg_addr = idm_buffer->idb_buf; 1197 result->db_sglist[0].seg_length = 1198 idm_buffer->idb_buflen; 1199 return (result); 1200 } 1201 1202 /* Couldn't get the stmf_data_buf_t so free the buffer */ 1203 idm_buf_free(idm_buffer); 1204 } 1205 1206 return (NULL); 1207 } 1208 1209 /*ARGSUSED*/ 1210 static void 1211 iscsit_dbuf_free(stmf_dbuf_store_t *ds, stmf_data_buf_t *dbuf) 1212 { 1213 iscsit_buf_t *ibuf = dbuf->db_port_private; 1214 1215 if (ibuf->ibuf_is_immed) { 1216 /* 1217 * The iscsit_buf_t structure itself will be freed with its 1218 * associated task. Here we just need to free the PDU that 1219 * held the immediate data. 1220 */ 1221 idm_pdu_complete(ibuf->ibuf_immed_data_pdu, IDM_STATUS_SUCCESS); 1222 ibuf->ibuf_immed_data_pdu = 0; 1223 } else { 1224 idm_buf_free(ibuf->ibuf_idm_buf); 1225 stmf_free(dbuf); 1226 } 1227 } 1228 1229 /*ARGSUSED*/ 1230 stmf_status_t 1231 iscsit_xfer_scsi_data(scsi_task_t *task, stmf_data_buf_t *dbuf, 1232 uint32_t ioflags) 1233 { 1234 iscsit_task_t *iscsit_task = task->task_port_private; 1235 iscsit_buf_t *ibuf = dbuf->db_port_private; 1236 int idm_rc; 1237 1238 /* 1239 * If we are aborting then we can ignore this request 1240 */ 1241 if (iscsit_task->it_stmf_abort) { 1242 return (STMF_SUCCESS); 1243 } 1244 1245 /* 1246 * If it's not immediate data then start the transfer 1247 */ 1248 ASSERT(ibuf->ibuf_is_immed == B_FALSE); 1249 if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) { 1250 1251 /* 1252 * IDM will call iscsit_build_hdr so lock now to serialize 1253 * access to the SN values. We need to lock here to enforce 1254 * lock ordering 1255 */ 1256 rw_enter(&iscsit_task->it_ict->ict_sess->ist_sn_rwlock, 1257 RW_READER); 1258 idm_rc = idm_buf_tx_to_ini(iscsit_task->it_idm_task, 1259 ibuf->ibuf_idm_buf, dbuf->db_relative_offset, 1260 dbuf->db_data_size, &iscsit_buf_xfer_cb, dbuf); 1261 rw_exit(&iscsit_task->it_ict->ict_sess->ist_sn_rwlock); 1262 1263 return (iscsit_idm_to_stmf(idm_rc)); 1264 } else if (dbuf->db_flags & DB_DIRECTION_FROM_RPORT) { 1265 /* Grab the SN lock (see comment above) */ 1266 rw_enter(&iscsit_task->it_ict->ict_sess->ist_sn_rwlock, 1267 RW_READER); 1268 idm_rc = idm_buf_rx_from_ini(iscsit_task->it_idm_task, 1269 ibuf->ibuf_idm_buf, dbuf->db_relative_offset, 1270 dbuf->db_data_size, &iscsit_buf_xfer_cb, dbuf); 1271 rw_exit(&iscsit_task->it_ict->ict_sess->ist_sn_rwlock); 1272 1273 return (iscsit_idm_to_stmf(idm_rc)); 1274 } 1275 1276 /* What are we supposed to do if there is no direction? */ 1277 return (STMF_INVALID_ARG); 1278 } 1279 1280 static void 1281 iscsit_buf_xfer_cb(idm_buf_t *idb, idm_status_t status) 1282 { 1283 iscsit_task_t *itask = idb->idb_task_binding->idt_private; 1284 stmf_data_buf_t *dbuf = idb->idb_cb_arg; 1285 1286 dbuf->db_xfer_status = iscsit_idm_to_stmf(status); 1287 1288 /* 1289 * If the task has been aborted then we don't need to call STMF 1290 */ 1291 if (itask->it_stmf_abort) { 1292 return; 1293 } 1294 1295 /* 1296 * COMSTAR currently requires port providers to support 1297 * the DB_SEND_STATUS_GOOD flag even if phase collapse is 1298 * not supported. So we will roll our own... pretend we are 1299 * COMSTAR and ask for a status PDU. 1300 */ 1301 if ((dbuf->db_flags & DB_SEND_STATUS_GOOD) && 1302 status == IDM_STATUS_SUCCESS) { 1303 /* 1304 * If iscsit_send_scsi_status succeeds then the TX PDU 1305 * callback will call stmf_send_status_done and set 1306 * STMF_IOF_LPORT_DONE. Consequently we don't need 1307 * to call stmf_data_xfer_done in that case. We 1308 * still need to call it if we get a failure. 1309 * 1310 * To elaborate on this some more, upon successful 1311 * return from iscsit_send_scsi_status it's possible 1312 * that itask and idb have been freed and are no 1313 * longer valid. 1314 */ 1315 if (iscsit_send_scsi_status(itask->it_stmf_task, 0) 1316 != STMF_SUCCESS) { 1317 /* Failed to send status */ 1318 dbuf->db_xfer_status = STMF_FAILURE; 1319 stmf_data_xfer_done(itask->it_stmf_task, dbuf, 1320 STMF_IOF_LPORT_DONE); 1321 } 1322 } else { 1323 stmf_data_xfer_done(itask->it_stmf_task, dbuf, 0); 1324 } 1325 } 1326 1327 1328 /*ARGSUSED*/ 1329 stmf_status_t 1330 iscsit_send_scsi_status(scsi_task_t *task, uint32_t ioflags) 1331 { 1332 iscsit_task_t *itask = task->task_port_private; 1333 iscsi_scsi_rsp_hdr_t *rsp; 1334 idm_pdu_t *pdu; 1335 int resp_datalen; 1336 1337 /* 1338 * If this task is aborted then we don't need to respond. 1339 */ 1340 if (itask->it_stmf_abort) { 1341 return (STMF_SUCCESS); 1342 } 1343 1344 /* 1345 * If this is a task management status, handle it elsewhere. 1346 */ 1347 if (task->task_mgmt_function != TM_NONE) { 1348 /* 1349 * Don't wait for the PDU completion to tell STMF 1350 * the task is done -- it doesn't really matter and 1351 * it makes life complicated if STMF later asks us to 1352 * abort the request and we don't know whether the 1353 * status has been sent or not. 1354 */ 1355 itask->it_tm_responded = B_TRUE; 1356 iscsit_send_task_mgmt_resp(itask->it_tm_pdu, 1357 (task->task_completion_status == STMF_SUCCESS) ? 1358 SCSI_TCP_TM_RESP_COMPLETE : SCSI_TCP_TM_RESP_FUNC_NOT_SUPP); 1359 stmf_send_status_done(task, STMF_SUCCESS, 1360 STMF_IOF_LPORT_DONE); 1361 return (STMF_SUCCESS); 1362 } 1363 1364 mutex_enter(&itask->it_idm_task->idt_mutex); 1365 if ((itask->it_idm_task->idt_state == TASK_ACTIVE) && 1366 (task->task_completion_status == STMF_SUCCESS) && 1367 (task->task_sense_length == 0) && 1368 (task->task_resid == 0)) { 1369 itask->it_idm_task->idt_state = TASK_COMPLETE; 1370 /* PDU callback releases task hold */ 1371 idm_task_hold(itask->it_idm_task); 1372 mutex_exit(&itask->it_idm_task->idt_mutex); 1373 /* 1374 * Fast path. Cached status PDU's are already 1375 * initialized. We just need to fill in 1376 * connection and task information. 1377 */ 1378 pdu = kmem_cache_alloc(iscsit_status_pdu_cache, KM_SLEEP); 1379 pdu->isp_ic = itask->it_ict->ict_ic; 1380 pdu->isp_private = itask; 1381 1382 rsp = (iscsi_scsi_rsp_hdr_t *)pdu->isp_hdr; 1383 rsp->itt = itask->it_itt; 1384 rsp->cmd_status = task->task_scsi_status; 1385 iscsit_pdu_tx(pdu); 1386 return (STMF_SUCCESS); 1387 } else { 1388 if (itask->it_idm_task->idt_state != TASK_ACTIVE) { 1389 mutex_exit(&itask->it_idm_task->idt_mutex); 1390 return (STMF_FAILURE); 1391 } 1392 itask->it_idm_task->idt_state = TASK_COMPLETE; 1393 /* PDU callback releases task hold */ 1394 idm_task_hold(itask->it_idm_task); 1395 mutex_exit(&itask->it_idm_task->idt_mutex); 1396 1397 resp_datalen = (task->task_sense_length == 0) ? 0 : 1398 (task->task_sense_length + sizeof (uint16_t)); 1399 1400 pdu = idm_pdu_alloc(sizeof (iscsi_hdr_t), resp_datalen); 1401 idm_pdu_init(pdu, itask->it_ict->ict_ic, itask, 1402 iscsit_send_status_done); 1403 1404 rsp = (iscsi_scsi_rsp_hdr_t *)pdu->isp_hdr; 1405 bzero(rsp, sizeof (*rsp)); 1406 rsp->opcode = ISCSI_OP_SCSI_RSP; 1407 1408 rsp->flags = ISCSI_FLAG_FINAL; 1409 if (task->task_status_ctrl & TASK_SCTRL_OVER) { 1410 rsp->flags |= ISCSI_FLAG_CMD_OVERFLOW; 1411 } else if (task->task_status_ctrl & TASK_SCTRL_UNDER) { 1412 rsp->flags |= ISCSI_FLAG_CMD_UNDERFLOW; 1413 } 1414 1415 rsp->bi_residual_count = 0; 1416 rsp->residual_count = htonl(task->task_resid); 1417 rsp->itt = itask->it_itt; 1418 rsp->response = ISCSI_STATUS_CMD_COMPLETED; 1419 rsp->cmd_status = task->task_scsi_status; 1420 if (task->task_sense_length != 0) { 1421 /* 1422 * Add a byte to provide the sense length in 1423 * the response 1424 */ 1425 *(uint16_t *)((void *)pdu->isp_data) = 1426 htons(task->task_sense_length); 1427 bcopy(task->task_sense_data, 1428 (uint8_t *)pdu->isp_data + 1429 sizeof (uint16_t), 1430 task->task_sense_length); 1431 hton24(rsp->dlength, resp_datalen); 1432 } 1433 1434 DTRACE_PROBE5(iscsi__scsi__response, 1435 iscsit_conn_t *, itask->it_ict, 1436 uint8_t, rsp->response, 1437 uint8_t, rsp->cmd_status, 1438 idm_pdu_t *, pdu, 1439 scsi_task_t *, task); 1440 1441 iscsit_pdu_tx(pdu); 1442 1443 return (STMF_SUCCESS); 1444 } 1445 } 1446 1447 /*ARGSUSED*/ 1448 static void 1449 iscsit_send_good_status_done(idm_pdu_t *pdu, idm_status_t status) 1450 { 1451 iscsit_task_t *itask; 1452 boolean_t aborted; 1453 1454 itask = pdu->isp_private; 1455 aborted = itask->it_stmf_abort; 1456 1457 /* 1458 * After releasing the hold the task may be freed at any time so 1459 * don't touch it. 1460 */ 1461 idm_task_rele(itask->it_idm_task); 1462 if (!aborted) { 1463 stmf_send_status_done(itask->it_stmf_task, 1464 iscsit_idm_to_stmf(pdu->isp_status), STMF_IOF_LPORT_DONE); 1465 } 1466 kmem_cache_free(iscsit_status_pdu_cache, pdu); 1467 } 1468 1469 /*ARGSUSED*/ 1470 static void 1471 iscsit_send_status_done(idm_pdu_t *pdu, idm_status_t status) 1472 { 1473 iscsit_task_t *itask; 1474 boolean_t aborted; 1475 1476 itask = pdu->isp_private; 1477 aborted = itask->it_stmf_abort; 1478 1479 /* 1480 * After releasing the hold the task may be freed at any time so 1481 * don't touch it. 1482 */ 1483 idm_task_rele(itask->it_idm_task); 1484 if (!aborted) { 1485 stmf_send_status_done(itask->it_stmf_task, 1486 iscsit_idm_to_stmf(pdu->isp_status), STMF_IOF_LPORT_DONE); 1487 } 1488 idm_pdu_free(pdu); 1489 } 1490 1491 1492 void 1493 iscsit_lport_task_free(scsi_task_t *task) 1494 { 1495 iscsit_task_t *itask = task->task_port_private; 1496 1497 /* We only call idm_task_start for regular tasks, not task management */ 1498 if (task->task_mgmt_function == TM_NONE) { 1499 idm_task_done(itask->it_idm_task); 1500 iscsit_task_free(itask); 1501 return; 1502 } else { 1503 iscsit_tm_task_free(itask); 1504 } 1505 } 1506 1507 /*ARGSUSED*/ 1508 stmf_status_t 1509 iscsit_abort(stmf_local_port_t *lport, int abort_cmd, void *arg, uint32_t flags) 1510 { 1511 scsi_task_t *st = (scsi_task_t *)arg; 1512 iscsit_task_t *iscsit_task; 1513 idm_task_t *idt; 1514 1515 /* 1516 * If this is a task management request then there's really not much to 1517 * do. 1518 */ 1519 if (st->task_mgmt_function != TM_NONE) { 1520 return (STMF_ABORT_SUCCESS); 1521 } 1522 1523 /* 1524 * Regular task, start cleaning up 1525 */ 1526 iscsit_task = st->task_port_private; 1527 idt = iscsit_task->it_idm_task; 1528 mutex_enter(&iscsit_task->it_mutex); 1529 iscsit_task->it_stmf_abort = B_TRUE; 1530 if (iscsit_task->it_aborted) { 1531 mutex_exit(&iscsit_task->it_mutex); 1532 /* 1533 * STMF specification is wrong... says to return 1534 * STMF_ABORTED, the code actually looks for 1535 * STMF_ABORT_SUCCESS. 1536 */ 1537 return (STMF_ABORT_SUCCESS); 1538 } else { 1539 mutex_exit(&iscsit_task->it_mutex); 1540 /* 1541 * Call IDM to abort the task. Due to a variety of 1542 * circumstances the task may already be in the process of 1543 * aborting. 1544 * We'll let IDM worry about rationalizing all that except 1545 * for one particular instance. If the state of the task 1546 * is TASK_COMPLETE, we need to indicate to the framework 1547 * that we are in fact done. This typically happens with 1548 * framework-initiated task management type requests 1549 * (e.g. abort task). 1550 */ 1551 if (idt->idt_state == TASK_COMPLETE) { 1552 idm_refcnt_wait_ref(&idt->idt_refcnt); 1553 return (STMF_ABORT_SUCCESS); 1554 } else { 1555 idm_task_abort(idt->idt_ic, idt, AT_TASK_MGMT_ABORT); 1556 return (STMF_SUCCESS); 1557 } 1558 } 1559 1560 /*NOTREACHED*/ 1561 } 1562 1563 /*ARGSUSED*/ 1564 void 1565 iscsit_ctl(stmf_local_port_t *lport, int cmd, void *arg) 1566 { 1567 iscsit_tgt_t *iscsit_tgt; 1568 1569 ASSERT((cmd == STMF_CMD_LPORT_ONLINE) || 1570 (cmd == STMF_ACK_LPORT_ONLINE_COMPLETE) || 1571 (cmd == STMF_CMD_LPORT_OFFLINE) || 1572 (cmd == STMF_ACK_LPORT_OFFLINE_COMPLETE)); 1573 1574 iscsit_tgt = (iscsit_tgt_t *)lport->lport_port_private; 1575 1576 switch (cmd) { 1577 case STMF_CMD_LPORT_ONLINE: 1578 iscsit_tgt_sm_event(iscsit_tgt, TE_STMF_ONLINE_REQ); 1579 break; 1580 case STMF_CMD_LPORT_OFFLINE: 1581 iscsit_tgt_sm_event(iscsit_tgt, TE_STMF_OFFLINE_REQ); 1582 break; 1583 case STMF_ACK_LPORT_ONLINE_COMPLETE: 1584 iscsit_tgt_sm_event(iscsit_tgt, TE_STMF_ONLINE_COMPLETE_ACK); 1585 break; 1586 case STMF_ACK_LPORT_OFFLINE_COMPLETE: 1587 iscsit_tgt_sm_event(iscsit_tgt, TE_STMF_OFFLINE_COMPLETE_ACK); 1588 break; 1589 1590 default: 1591 break; 1592 } 1593 } 1594 1595 static stmf_status_t 1596 iscsit_idm_to_stmf(idm_status_t idmrc) 1597 { 1598 switch (idmrc) { 1599 case IDM_STATUS_SUCCESS: 1600 return (STMF_SUCCESS); 1601 default: 1602 return (STMF_FAILURE); 1603 } 1604 /*NOTREACHED*/ 1605 } 1606 1607 1608 /* 1609 * ISCSI protocol 1610 */ 1611 1612 void 1613 iscsit_op_scsi_cmd(idm_conn_t *ic, idm_pdu_t *rx_pdu) 1614 { 1615 iscsit_conn_t *ict; 1616 iscsit_task_t *itask; 1617 scsi_task_t *task; 1618 iscsit_buf_t *ibuf; 1619 iscsi_scsi_cmd_hdr_t *iscsi_scsi = 1620 (iscsi_scsi_cmd_hdr_t *)rx_pdu->isp_hdr; 1621 iscsi_addl_hdr_t *ahs_hdr; 1622 uint16_t addl_cdb_len = 0; 1623 1624 ict = ic->ic_handle; 1625 1626 itask = iscsit_task_alloc(ict); 1627 if (itask == NULL) { 1628 iscsit_send_direct_scsi_resp(ict, rx_pdu, 1629 ISCSI_STATUS_CMD_COMPLETED, STATUS_BUSY); 1630 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 1631 return; 1632 } 1633 1634 /* Finish processing request */ 1635 iscsit_set_cmdsn(ict, rx_pdu); 1636 1637 /* 1638 * Note CmdSN and ITT in task. IDM will have already validated this 1639 * request against the connection state so we don't need to check 1640 * that (the connection may have changed state in the meantime but 1641 * we will catch that when we try to send a response) 1642 */ 1643 itask->it_cmdsn = ntohl(iscsi_scsi->cmdsn); 1644 itask->it_itt = iscsi_scsi->itt; 1645 1646 /* 1647 * Check for extended CDB AHS 1648 */ 1649 if (iscsi_scsi->hlength > 0) { 1650 ahs_hdr = (iscsi_addl_hdr_t *)iscsi_scsi; 1651 addl_cdb_len = ((ahs_hdr->ahs_hlen_hi << 8) | 1652 ahs_hdr->ahs_hlen_lo) - 1; /* Adjust for reserved byte */ 1653 if (((addl_cdb_len + 4) / sizeof (uint32_t)) > 1654 iscsi_scsi->hlength) { 1655 /* Mangled header info, drop it */ 1656 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 1657 return; 1658 } 1659 } 1660 1661 ict = rx_pdu->isp_ic->ic_handle; /* IDM client private */ 1662 1663 itask->it_stmf_task = stmf_task_alloc( 1664 itask->it_ict->ict_sess->ist_lport, 1665 itask->it_ict->ict_sess->ist_stmf_sess, iscsi_scsi->lun, 1666 16 + addl_cdb_len, 0); 1667 if (itask->it_stmf_task == NULL) { 1668 /* 1669 * Either stmf really couldn't get memory for a task or, 1670 * more likely, the LU is currently in reset. Either way 1671 * we have no choice but to fail the request. 1672 */ 1673 iscsit_task_free(itask); 1674 iscsit_send_direct_scsi_resp(ict, rx_pdu, 1675 ISCSI_STATUS_CMD_COMPLETED, STATUS_BUSY); 1676 idm_pdu_complete(rx_pdu, IDM_STATUS_FAIL); 1677 return; 1678 } 1679 1680 task = itask->it_stmf_task; 1681 task->task_port_private = itask; 1682 1683 bcopy(iscsi_scsi->lun, task->task_lun_no, sizeof (task->task_lun_no)); 1684 1685 /* 1686 * iSCSI and Comstar use the same values. Should we rely on this 1687 * or translate them bit-wise? 1688 */ 1689 1690 task->task_flags = 1691 (((iscsi_scsi->flags & ISCSI_FLAG_CMD_READ) ? TF_READ_DATA : 0) | 1692 ((iscsi_scsi->flags & ISCSI_FLAG_CMD_WRITE) ? TF_WRITE_DATA : 0) | 1693 ((rx_pdu->isp_datalen == 0) ? 0 : TF_INITIAL_BURST)); 1694 1695 switch (iscsi_scsi->flags & ISCSI_FLAG_CMD_ATTR_MASK) { 1696 case ISCSI_ATTR_UNTAGGED: 1697 break; 1698 case ISCSI_ATTR_SIMPLE: 1699 task->task_additional_flags |= TF_ATTR_SIMPLE_QUEUE; 1700 break; 1701 case ISCSI_ATTR_ORDERED: 1702 task->task_additional_flags |= TF_ATTR_ORDERED_QUEUE; 1703 break; 1704 case ISCSI_ATTR_HEAD_OF_QUEUE: 1705 task->task_additional_flags |= TF_ATTR_HEAD_OF_QUEUE; 1706 break; 1707 case ISCSI_ATTR_ACA: 1708 task->task_additional_flags |= TF_ATTR_ACA; 1709 break; 1710 default: 1711 /* Protocol error but just take it, treat as untagged */ 1712 break; 1713 } 1714 1715 1716 task->task_additional_flags = 0; 1717 task->task_priority = 0; 1718 task->task_mgmt_function = TM_NONE; 1719 1720 /* 1721 * This "task_max_nbufs" doesn't map well to BIDI. We probably need 1722 * parameter for each direction. "MaxOutstandingR2T" may very well 1723 * be set to one which could prevent us from doing simultaneous 1724 * transfers in each direction. 1725 */ 1726 task->task_max_nbufs = (iscsi_scsi->flags & ISCSI_FLAG_CMD_WRITE) ? 1727 ict->ict_op.op_max_outstanding_r2t : STMF_BUFS_MAX; 1728 task->task_cmd_seq_no = ntohl(iscsi_scsi->itt); 1729 task->task_expected_xfer_length = ntohl(iscsi_scsi->data_length); 1730 1731 /* Copy CDB */ 1732 bcopy(iscsi_scsi->scb, task->task_cdb, 16); 1733 if (addl_cdb_len > 0) { 1734 bcopy(ahs_hdr->ahs_extscb, task->task_cdb + 16, addl_cdb_len); 1735 } 1736 1737 /* 1738 * Copy the transport header into the task handle from the PDU 1739 * handle. The transport header describes this task's remote tagged 1740 * buffer. 1741 */ 1742 if (rx_pdu->isp_transport_hdrlen != 0) { 1743 bcopy(rx_pdu->isp_transport_hdr, 1744 itask->it_idm_task->idt_transport_hdr, 1745 rx_pdu->isp_transport_hdrlen); 1746 } 1747 1748 /* 1749 * Tell IDM about our new active task 1750 */ 1751 idm_task_start(itask->it_idm_task, (uintptr_t)itask->it_itt); 1752 1753 /* 1754 * If we have any immediate data then setup the immediate buffer 1755 * context that comes with the task 1756 */ 1757 if (rx_pdu->isp_datalen) { 1758 ibuf = itask->it_immed_data; 1759 ibuf->ibuf_immed_data_pdu = rx_pdu; 1760 ibuf->ibuf_stmf_buf->db_data_size = rx_pdu->isp_datalen; 1761 ibuf->ibuf_stmf_buf->db_buf_size = rx_pdu->isp_datalen; 1762 ibuf->ibuf_stmf_buf->db_relative_offset = 0; 1763 ibuf->ibuf_stmf_buf->db_sglist[0].seg_length = 1764 rx_pdu->isp_datalen; 1765 ibuf->ibuf_stmf_buf->db_sglist[0].seg_addr = rx_pdu->isp_data; 1766 1767 stmf_post_task(task, ibuf->ibuf_stmf_buf); 1768 } else { 1769 stmf_post_task(task, NULL); 1770 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 1771 } 1772 } 1773 1774 /*ARGSUSED*/ 1775 void 1776 iscsit_deferred_dispatch(idm_pdu_t *rx_pdu) 1777 { 1778 iscsit_conn_t *ict = rx_pdu->isp_ic->ic_handle; 1779 1780 /* 1781 * If the connection has been lost then ignore new PDU's 1782 */ 1783 mutex_enter(&ict->ict_mutex); 1784 if (ict->ict_lost) { 1785 mutex_exit(&ict->ict_mutex); 1786 idm_pdu_complete(rx_pdu, IDM_STATUS_FAIL); 1787 return; 1788 } 1789 1790 /* 1791 * Grab a hold on the connection to prevent it from going away 1792 * between now and when the taskq function is called. 1793 */ 1794 iscsit_conn_dispatch_hold(ict); 1795 mutex_exit(&ict->ict_mutex); 1796 1797 if (taskq_dispatch(iscsit_global.global_dispatch_taskq, 1798 iscsit_deferred, rx_pdu, DDI_NOSLEEP) == NULL) { 1799 /* 1800 * In the unlikely scenario that we couldn't get the resources 1801 * to dispatch the PDU then just drop it. 1802 */ 1803 idm_pdu_complete(rx_pdu, IDM_STATUS_FAIL); 1804 idm_conn_event(ict->ict_ic, CE_TRANSPORT_FAIL, NULL); 1805 iscsit_conn_dispatch_rele(ict); 1806 } 1807 } 1808 1809 static void 1810 iscsit_deferred(void *rx_pdu_void) 1811 { 1812 idm_pdu_t *rx_pdu = rx_pdu_void; 1813 idm_conn_t *ic = rx_pdu->isp_ic; 1814 iscsit_conn_t *ict = ic->ic_handle; 1815 1816 switch (IDM_PDU_OPCODE(rx_pdu)) { 1817 case ISCSI_OP_NOOP_OUT: 1818 iscsit_set_cmdsn(ict, rx_pdu); 1819 iscsit_pdu_op_noop(ict, rx_pdu); 1820 break; 1821 case ISCSI_OP_LOGIN_CMD: 1822 iscsit_pdu_op_login_cmd(ict, rx_pdu); 1823 break; 1824 case ISCSI_OP_TEXT_CMD: 1825 iscsit_set_cmdsn(ict, rx_pdu); 1826 iscsit_pdu_op_text_cmd(ict, rx_pdu); 1827 break; 1828 case ISCSI_OP_LOGOUT_CMD: 1829 iscsit_set_cmdsn(ict, rx_pdu); 1830 iscsit_pdu_op_logout_cmd(ict, rx_pdu); 1831 break; 1832 default: 1833 /* Protocol error. IDM should have caught this */ 1834 idm_pdu_complete(rx_pdu, IDM_STATUS_FAIL); 1835 ASSERT(0); 1836 break; 1837 } 1838 1839 iscsit_conn_dispatch_rele(ict); 1840 } 1841 1842 static void 1843 iscsit_send_direct_scsi_resp(iscsit_conn_t *ict, idm_pdu_t *rx_pdu, 1844 uint8_t response, uint8_t cmd_status) 1845 { 1846 idm_pdu_t *rsp_pdu; 1847 idm_conn_t *ic; 1848 iscsi_scsi_rsp_hdr_t *resp; 1849 iscsi_scsi_cmd_hdr_t *req = 1850 (iscsi_scsi_cmd_hdr_t *)rx_pdu->isp_hdr; 1851 1852 ic = ict->ict_ic; 1853 1854 rsp_pdu = idm_pdu_alloc(sizeof (iscsi_scsi_rsp_hdr_t), 0); 1855 idm_pdu_init(rsp_pdu, ic, NULL, NULL); 1856 resp = (iscsi_scsi_rsp_hdr_t *)rsp_pdu->isp_hdr; 1857 1858 resp->opcode = ISCSI_OP_SCSI_RSP; 1859 resp->flags = ISCSI_FLAG_FINAL; 1860 resp->response = response; 1861 resp->cmd_status = cmd_status; 1862 resp->itt = req->itt; 1863 if ((response == ISCSI_STATUS_CMD_COMPLETED) && 1864 (req->data_length != 0) && 1865 ((req->flags & ISCSI_FLAG_CMD_READ) || 1866 (req->flags & ISCSI_FLAG_CMD_WRITE))) { 1867 resp->flags |= ISCSI_FLAG_CMD_UNDERFLOW; 1868 resp->residual_count = req->data_length; 1869 } 1870 1871 DTRACE_PROBE4(iscsi__scsi__direct__response, 1872 iscsit_conn_t *, ict, 1873 uint8_t, resp->response, 1874 uint8_t, resp->cmd_status, 1875 idm_pdu_t *, rsp_pdu); 1876 1877 iscsit_pdu_tx(rsp_pdu); 1878 } 1879 1880 void 1881 iscsit_send_task_mgmt_resp(idm_pdu_t *tm_resp_pdu, uint8_t tm_status) 1882 { 1883 iscsi_scsi_task_mgt_rsp_hdr_t *tm_resp; 1884 1885 tm_resp = (iscsi_scsi_task_mgt_rsp_hdr_t *)tm_resp_pdu->isp_hdr; 1886 tm_resp->response = tm_status; 1887 1888 DTRACE_PROBE3(iscsi__scsi__tm__response, 1889 iscsit_conn_t *, tm_resp_pdu->isp_ic->ic_handle, 1890 uint8_t, tm_resp->response, 1891 idm_pdu_t *, tm_resp_pdu); 1892 iscsit_pdu_tx(tm_resp_pdu); 1893 } 1894 1895 void 1896 iscsit_op_scsi_task_mgmt(iscsit_conn_t *ict, idm_pdu_t *rx_pdu) 1897 { 1898 idm_pdu_t *tm_resp_pdu; 1899 iscsit_task_t *itask; 1900 iscsit_task_t *tm_itask; 1901 scsi_task_t *task; 1902 iscsi_scsi_task_mgt_hdr_t *iscsi_tm = 1903 (iscsi_scsi_task_mgt_hdr_t *)rx_pdu->isp_hdr; 1904 iscsi_scsi_task_mgt_rsp_hdr_t *iscsi_tm_rsp = 1905 (iscsi_scsi_task_mgt_rsp_hdr_t *)rx_pdu->isp_hdr; 1906 uint32_t rtt, cmdsn, refcmdsn; 1907 uint8_t tm_func; 1908 1909 /* 1910 * Setup response PDU (response field will get filled in later) 1911 */ 1912 tm_resp_pdu = idm_pdu_alloc(sizeof (iscsi_scsi_task_mgt_rsp_hdr_t), 0); 1913 if (tm_resp_pdu == NULL) { 1914 /* Can't respond, just drop it */ 1915 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 1916 return; 1917 } 1918 idm_pdu_init(tm_resp_pdu, ict->ict_ic, NULL, NULL); 1919 iscsi_tm_rsp = (iscsi_scsi_task_mgt_rsp_hdr_t *)tm_resp_pdu->isp_hdr; 1920 bzero(iscsi_tm_rsp, sizeof (iscsi_scsi_task_mgt_rsp_hdr_t)); 1921 iscsi_tm_rsp->opcode = ISCSI_OP_SCSI_TASK_MGT_RSP; 1922 iscsi_tm_rsp->flags = ISCSI_FLAG_FINAL; 1923 iscsi_tm_rsp->itt = rx_pdu->isp_hdr->itt; 1924 1925 /* 1926 * Figure out what we're being asked to do. 1927 */ 1928 DTRACE_PROBE4(iscsi__scsi__tm__request, 1929 iscsit_conn_t *, ict, 1930 uint8_t, (iscsi_tm->function & ISCSI_FLAG_TASK_MGMT_FUNCTION_MASK), 1931 uint32_t, iscsi_tm->rtt, 1932 idm_pdu_t *, rx_pdu); 1933 switch (iscsi_tm->function & ISCSI_FLAG_TASK_MGMT_FUNCTION_MASK) { 1934 case ISCSI_TM_FUNC_ABORT_TASK: 1935 /* 1936 * STMF doesn't currently support the "abort task" task 1937 * management command although it does support aborting 1938 * an individual task. We'll get STMF to abort the task 1939 * for us but handle the details of the task management 1940 * command ourselves. 1941 * 1942 * Find the task associated with the referenced task tag. 1943 */ 1944 rtt = iscsi_tm->rtt; 1945 itask = (iscsit_task_t *)idm_task_find_by_handle(ict->ict_ic, 1946 (uintptr_t)rtt); 1947 1948 if (itask == NULL) { 1949 cmdsn = ntohl(iscsi_tm->cmdsn); 1950 refcmdsn = ntohl(iscsi_tm->refcmdsn); 1951 1952 /* 1953 * Task was not found. If RefCmdSN is within the CmdSN 1954 * window and less than CmdSN of the TM function, return 1955 * "Function Complete". Otherwise, return 1956 * "Task Does Not Exist". 1957 */ 1958 1959 if (iscsit_cmdsn_in_window(ict, refcmdsn) && 1960 (refcmdsn < cmdsn)) { 1961 iscsit_send_task_mgmt_resp(tm_resp_pdu, 1962 SCSI_TCP_TM_RESP_COMPLETE); 1963 } else { 1964 iscsit_send_task_mgmt_resp(tm_resp_pdu, 1965 SCSI_TCP_TM_RESP_NO_TASK); 1966 } 1967 } else { 1968 1969 /* 1970 * Tell STMF to abort the task. This will do no harm 1971 * if the task is already complete. 1972 */ 1973 stmf_abort(STMF_QUEUE_TASK_ABORT, itask->it_stmf_task, 1974 STMF_ABORTED, NULL); 1975 1976 /* 1977 * Make sure the task hasn't already completed 1978 */ 1979 mutex_enter(&itask->it_idm_task->idt_mutex); 1980 if ((itask->it_idm_task->idt_state == TASK_COMPLETE) || 1981 (itask->it_idm_task->idt_state == TASK_IDLE)) { 1982 /* 1983 * Task is complete, return "Task Does Not 1984 * Exist" 1985 */ 1986 mutex_exit(&itask->it_idm_task->idt_mutex); 1987 iscsit_send_task_mgmt_resp(tm_resp_pdu, 1988 SCSI_TCP_TM_RESP_NO_TASK); 1989 } else { 1990 /* 1991 * STMF is now aborting the task, return 1992 * "Function Complete" 1993 */ 1994 mutex_exit(&itask->it_idm_task->idt_mutex); 1995 iscsit_send_task_mgmt_resp(tm_resp_pdu, 1996 SCSI_TCP_TM_RESP_COMPLETE); 1997 } 1998 idm_task_rele(itask->it_idm_task); 1999 } 2000 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 2001 return; 2002 2003 case ISCSI_TM_FUNC_ABORT_TASK_SET: 2004 tm_func = TM_ABORT_TASK_SET; 2005 break; 2006 2007 case ISCSI_TM_FUNC_CLEAR_ACA: 2008 tm_func = TM_CLEAR_ACA; 2009 break; 2010 2011 case ISCSI_TM_FUNC_CLEAR_TASK_SET: 2012 tm_func = TM_CLEAR_TASK_SET; 2013 break; 2014 2015 case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET: 2016 tm_func = TM_LUN_RESET; 2017 break; 2018 2019 case ISCSI_TM_FUNC_TARGET_WARM_RESET: 2020 tm_func = TM_TARGET_WARM_RESET; 2021 break; 2022 2023 case ISCSI_TM_FUNC_TARGET_COLD_RESET: 2024 tm_func = TM_TARGET_COLD_RESET; 2025 break; 2026 2027 case ISCSI_TM_FUNC_TASK_REASSIGN: 2028 /* 2029 * We do not currently support allegiance reassignment. When 2030 * we start supporting ERL1+, we will need to. 2031 */ 2032 iscsit_send_task_mgmt_resp(tm_resp_pdu, 2033 SCSI_TCP_TM_RESP_NO_ALLG_REASSN); 2034 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 2035 return; 2036 2037 default: 2038 iscsit_send_task_mgmt_resp(tm_resp_pdu, 2039 SCSI_TCP_TM_RESP_REJECTED); 2040 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 2041 return; 2042 } 2043 2044 tm_itask = iscsit_tm_task_alloc(ict); 2045 if (tm_itask == NULL) { 2046 iscsit_send_task_mgmt_resp(tm_resp_pdu, 2047 SCSI_TCP_TM_RESP_REJECTED); 2048 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 2049 return; 2050 } 2051 2052 2053 task = stmf_task_alloc(ict->ict_sess->ist_lport, 2054 ict->ict_sess->ist_stmf_sess, iscsi_tm->lun, 2055 0, STMF_TASK_EXT_NONE); 2056 if (task == NULL) { 2057 /* 2058 * If this happens, either the LU is in reset, couldn't 2059 * get memory, or some other condition in which we simply 2060 * can't complete this request. It would be nice to return 2061 * an error code like "busy" but the closest we have is 2062 * "rejected". 2063 */ 2064 iscsit_send_task_mgmt_resp(tm_resp_pdu, 2065 SCSI_TCP_TM_RESP_REJECTED); 2066 iscsit_tm_task_free(tm_itask); 2067 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 2068 return; 2069 } 2070 2071 tm_itask->it_tm_pdu = tm_resp_pdu; 2072 tm_itask->it_stmf_task = task; 2073 task->task_port_private = tm_itask; 2074 task->task_mgmt_function = tm_func; 2075 task->task_additional_flags = TASK_AF_NO_EXPECTED_XFER_LENGTH; 2076 task->task_priority = 0; 2077 task->task_max_nbufs = STMF_BUFS_MAX; 2078 task->task_cmd_seq_no = iscsi_tm->itt; 2079 task->task_expected_xfer_length = 0; 2080 2081 stmf_post_task(task, NULL); 2082 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 2083 } 2084 2085 static void 2086 iscsit_pdu_op_noop(iscsit_conn_t *ict, idm_pdu_t *rx_pdu) 2087 { 2088 iscsi_nop_out_hdr_t *out = (iscsi_nop_out_hdr_t *)rx_pdu->isp_hdr; 2089 iscsi_nop_in_hdr_t *in; 2090 int resp_datalen; 2091 idm_pdu_t *resp; 2092 2093 /* Get iSCSI session handle */ 2094 /* Ignore the response from initiator */ 2095 if (out->ttt != ISCSI_RSVD_TASK_TAG) 2096 return; 2097 2098 /* Allocate a PDU to respond */ 2099 resp_datalen = ntoh24(out->dlength); 2100 resp = idm_pdu_alloc(sizeof (iscsi_hdr_t), resp_datalen); 2101 idm_pdu_init(resp, ict->ict_ic, NULL, NULL); 2102 if (resp_datalen > 0) { 2103 bcopy(rx_pdu->isp_data, resp->isp_data, resp_datalen); 2104 } 2105 2106 in = (iscsi_nop_in_hdr_t *)resp->isp_hdr; 2107 bzero(in, sizeof (*in)); 2108 in->opcode = ISCSI_OP_NOOP_IN; 2109 in->flags = ISCSI_FLAG_FINAL; 2110 bcopy(out->lun, in->lun, 8); 2111 in->itt = out->itt; 2112 in->ttt = ISCSI_RSVD_TASK_TAG; 2113 hton24(in->dlength, resp_datalen); 2114 2115 /* Any other field in resp to be set? */ 2116 iscsit_pdu_tx(resp); 2117 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 2118 } 2119 2120 static void 2121 iscsit_pdu_op_login_cmd(iscsit_conn_t *ict, idm_pdu_t *rx_pdu) 2122 { 2123 2124 /* 2125 * Submit PDU to login state machine. State machine will free the 2126 * PDU. 2127 */ 2128 iscsit_login_sm_event(ict, ILE_LOGIN_RCV, rx_pdu); 2129 } 2130 2131 void 2132 iscsit_pdu_op_logout_cmd(iscsit_conn_t *ict, idm_pdu_t *rx_pdu) 2133 { 2134 iscsi_logout_hdr_t *logout_req = 2135 (iscsi_logout_hdr_t *)rx_pdu->isp_hdr; 2136 iscsi_logout_rsp_hdr_t *logout_rsp; 2137 idm_pdu_t *resp; 2138 2139 /* Allocate a PDU to respond */ 2140 resp = idm_pdu_alloc(sizeof (iscsi_hdr_t), 0); 2141 idm_pdu_init(resp, ict->ict_ic, NULL, NULL); 2142 2143 /* 2144 * Logout results in the immediate termination of all tasks except 2145 * if the logout reason is ISCSI_LOGOUT_REASON_RECOVERY. The 2146 * connection state machine will drive this task cleanup automatically 2147 * so we don't need to handle that here. 2148 */ 2149 logout_rsp = (iscsi_logout_rsp_hdr_t *)resp->isp_hdr; 2150 bzero(logout_rsp, sizeof (*logout_rsp)); 2151 logout_rsp->opcode = ISCSI_OP_LOGOUT_RSP; 2152 logout_rsp->flags = ISCSI_FLAG_FINAL; 2153 logout_rsp->itt = logout_req->itt; 2154 if ((logout_req->flags & ISCSI_FLAG_LOGOUT_REASON_MASK) > 2155 ISCSI_LOGOUT_REASON_RECOVERY) { 2156 logout_rsp->response = ISCSI_LOGOUT_RECOVERY_UNSUPPORTED; 2157 } else { 2158 logout_rsp->response = ISCSI_LOGOUT_SUCCESS; 2159 } 2160 2161 iscsit_pdu_tx(resp); 2162 idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS); 2163 } 2164 2165 /* 2166 * Calculate the number of outstanding commands we can process 2167 */ 2168 int 2169 iscsit_cmd_window() 2170 { 2171 /* Will be better later */ 2172 return (1024); 2173 } 2174 2175 /* 2176 * Set local registers based on incoming PDU 2177 */ 2178 void 2179 iscsit_set_cmdsn(iscsit_conn_t *ict, idm_pdu_t *rx_pdu) 2180 { 2181 iscsit_sess_t *ist; 2182 iscsi_scsi_cmd_hdr_t *req; 2183 2184 ist = ict->ict_sess; 2185 2186 req = (iscsi_scsi_cmd_hdr_t *)rx_pdu->isp_hdr; 2187 2188 rw_enter(&ist->ist_sn_rwlock, RW_WRITER); 2189 ist->ist_expcmdsn = ntohl(req->cmdsn) + 1; 2190 ist->ist_maxcmdsn = ntohl(req->cmdsn) + iscsit_cmd_window(); 2191 rw_exit(&ist->ist_sn_rwlock); 2192 } 2193 2194 /* 2195 * Update local StatSN and set SNs in response 2196 */ 2197 static void 2198 iscsit_calc_rspsn(iscsit_conn_t *ict, idm_pdu_t *resp) 2199 { 2200 iscsit_sess_t *ist; 2201 iscsi_scsi_rsp_hdr_t *rsp; 2202 2203 /* Get iSCSI session handle */ 2204 ist = ict->ict_sess; 2205 2206 rsp = (iscsi_scsi_rsp_hdr_t *)resp->isp_hdr; 2207 2208 /* Update StatSN */ 2209 rsp->statsn = htonl(ict->ict_statsn); 2210 switch (IDM_PDU_OPCODE(resp)) { 2211 case ISCSI_OP_RTT_RSP: 2212 /* Do nothing */ 2213 break; 2214 case ISCSI_OP_NOOP_IN: 2215 /* 2216 * Refer to section 10.19.1, RFC3720. 2217 * Advance only if target is responding initiator 2218 */ 2219 if (((iscsi_nop_in_hdr_t *)rsp)->ttt == ISCSI_RSVD_TASK_TAG) 2220 ict->ict_statsn++; 2221 break; 2222 case ISCSI_OP_SCSI_DATA_RSP: 2223 if (rsp->flags & ISCSI_FLAG_DATA_STATUS) 2224 ict->ict_statsn++; 2225 else 2226 rsp->statsn = 0; 2227 break; 2228 default: 2229 ict->ict_statsn++; 2230 break; 2231 } 2232 2233 /* Set ExpCmdSN and MaxCmdSN */ 2234 rsp->maxcmdsn = htonl(ist->ist_maxcmdsn); 2235 rsp->expcmdsn = htonl(ist->ist_expcmdsn); 2236 } 2237 2238 /* 2239 * Wrapper funtion, calls iscsi_calc_rspsn and idm_pdu_tx 2240 */ 2241 void 2242 iscsit_pdu_tx(idm_pdu_t *pdu) 2243 { 2244 iscsit_conn_t *ict = pdu->isp_ic->ic_handle; 2245 2246 /* 2247 * Protect ict->ict_statsn, ist->ist_maxcmdsn, and ist->ist_expcmdsn 2248 * (which are used by iscsit_calc_rspsn) with the session mutex 2249 * (ist->ist_sn_mutex). 2250 */ 2251 rw_enter(&ict->ict_sess->ist_sn_rwlock, RW_WRITER); 2252 iscsit_calc_rspsn(ict, pdu); 2253 idm_pdu_tx(pdu); 2254 rw_exit(&ict->ict_sess->ist_sn_rwlock); 2255 } 2256 2257 /* 2258 * Internal functions 2259 */ 2260 2261 void 2262 iscsit_send_async_event(iscsit_conn_t *ict, uint8_t event) 2263 { 2264 idm_pdu_t *abt; 2265 iscsi_async_evt_hdr_t *async_abt; 2266 2267 /* 2268 * Get a PDU to build the abort request. 2269 */ 2270 abt = idm_pdu_alloc(sizeof (iscsi_hdr_t), 0); 2271 if (abt == NULL) { 2272 idm_conn_event(ict->ict_ic, CE_TRANSPORT_FAIL, NULL); 2273 return; 2274 } 2275 idm_pdu_init(abt, ict->ict_ic, NULL, NULL); 2276 2277 ASSERT(abt != NULL); 2278 abt->isp_datalen = 0; 2279 2280 async_abt = (iscsi_async_evt_hdr_t *)abt->isp_hdr; 2281 bzero(async_abt, sizeof (*async_abt)); 2282 async_abt->opcode = ISCSI_OP_ASYNC_EVENT; 2283 async_abt->async_event = event; 2284 async_abt->flags = ISCSI_FLAG_FINAL; 2285 async_abt->rsvd4[0] = 0xff; 2286 async_abt->rsvd4[1] = 0xff; 2287 async_abt->rsvd4[2] = 0xff; 2288 async_abt->rsvd4[3] = 0xff; 2289 2290 switch (event) { 2291 case ISCSI_ASYNC_EVENT_REQUEST_LOGOUT: 2292 async_abt->param3 = htons(IDM_LOGOUT_SECONDS); 2293 break; 2294 case ISCSI_ASYNC_EVENT_SCSI_EVENT: 2295 case ISCSI_ASYNC_EVENT_DROPPING_CONNECTION: 2296 case ISCSI_ASYNC_EVENT_DROPPING_ALL_CONNECTIONS: 2297 case ISCSI_ASYNC_EVENT_PARAM_NEGOTIATION: 2298 default: 2299 ASSERT(0); 2300 } 2301 2302 iscsit_pdu_tx(abt); 2303 } 2304 2305 2306 static iscsit_task_t * 2307 iscsit_task_alloc(iscsit_conn_t *ict) 2308 { 2309 iscsit_task_t *itask; 2310 iscsit_buf_t *immed_ibuf; 2311 2312 /* 2313 * Possible items to pre-alloc if we cache iscsit_task_t's: 2314 * 2315 * Status PDU w/ sense buffer 2316 * stmf_data_buf_t for immediate data 2317 */ 2318 itask = kmem_alloc(sizeof (iscsit_task_t) + sizeof (iscsit_buf_t) + 2319 sizeof (stmf_data_buf_t), KM_NOSLEEP); 2320 if (itask != NULL) { 2321 mutex_init(&itask->it_mutex, NULL, MUTEX_DRIVER, NULL); 2322 itask->it_aborted = itask->it_stmf_abort = 2323 itask->it_tm_task = 0; 2324 2325 immed_ibuf = (iscsit_buf_t *)(itask + 1); 2326 bzero(immed_ibuf, sizeof (*immed_ibuf)); 2327 immed_ibuf->ibuf_is_immed = B_TRUE; 2328 immed_ibuf->ibuf_stmf_buf = (stmf_data_buf_t *)(immed_ibuf + 1); 2329 2330 bzero(immed_ibuf->ibuf_stmf_buf, sizeof (stmf_data_buf_t)); 2331 immed_ibuf->ibuf_stmf_buf->db_port_private = immed_ibuf; 2332 immed_ibuf->ibuf_stmf_buf->db_sglist_length = 1; 2333 immed_ibuf->ibuf_stmf_buf->db_flags = DB_DIRECTION_FROM_RPORT | 2334 DB_DONT_CACHE; 2335 itask->it_immed_data = immed_ibuf; 2336 itask->it_idm_task = idm_task_alloc(ict->ict_ic); 2337 if (itask->it_idm_task != NULL) { 2338 itask->it_idm_task->idt_private = itask; 2339 itask->it_ict = ict; 2340 itask->it_ttt = itask->it_idm_task->idt_tt; 2341 return (itask); 2342 } else { 2343 kmem_free(itask, sizeof (iscsit_task_t) + 2344 sizeof (iscsit_buf_t) + sizeof (stmf_data_buf_t)); 2345 } 2346 } 2347 2348 return (NULL); 2349 } 2350 2351 static void 2352 iscsit_task_free(iscsit_task_t *itask) 2353 { 2354 idm_task_free(itask->it_idm_task); 2355 mutex_destroy(&itask->it_mutex); 2356 kmem_free(itask, sizeof (iscsit_task_t) + 2357 sizeof (iscsit_buf_t) + sizeof (stmf_data_buf_t)); 2358 } 2359 2360 static iscsit_task_t * 2361 iscsit_tm_task_alloc(iscsit_conn_t *ict) 2362 { 2363 iscsit_task_t *itask; 2364 2365 itask = kmem_zalloc(sizeof (iscsit_task_t), KM_NOSLEEP); 2366 if (itask != NULL) { 2367 idm_conn_hold(ict->ict_ic); 2368 mutex_init(&itask->it_mutex, NULL, MUTEX_DRIVER, NULL); 2369 itask->it_aborted = itask->it_stmf_abort = 2370 itask->it_tm_responded = 0; 2371 itask->it_tm_pdu = NULL; 2372 itask->it_tm_task = 1; 2373 itask->it_ict = ict; 2374 } 2375 2376 return (itask); 2377 } 2378 2379 static void 2380 iscsit_tm_task_free(iscsit_task_t *itask) 2381 { 2382 /* 2383 * If we responded then the call to idm_pdu_complete will free the 2384 * PDU. Otherwise we got aborted before the TM function could 2385 * complete and we need to free the PDU explicitly. 2386 */ 2387 if (itask->it_tm_pdu != NULL && !itask->it_tm_responded) 2388 idm_pdu_free(itask->it_tm_pdu); 2389 idm_conn_rele(itask->it_ict->ict_ic); 2390 mutex_destroy(&itask->it_mutex); 2391 kmem_free(itask, sizeof (iscsit_task_t)); 2392 } 2393 2394 /* 2395 * iscsit status PDU cache 2396 */ 2397 2398 /*ARGSUSED*/ 2399 static int 2400 iscsit_status_pdu_constructor(void *pdu_void, void *arg, int flags) 2401 { 2402 idm_pdu_t *pdu = pdu_void; 2403 iscsi_scsi_rsp_hdr_t *rsp; 2404 2405 bzero(pdu, sizeof (idm_pdu_t)); 2406 pdu->isp_callback = iscsit_send_good_status_done; 2407 pdu->isp_magic = IDM_PDU_MAGIC; 2408 pdu->isp_hdr = (iscsi_hdr_t *)(pdu + 1); /* Ptr arithmetic */ 2409 pdu->isp_hdrlen = sizeof (iscsi_hdr_t); 2410 2411 /* Setup status response */ 2412 rsp = (iscsi_scsi_rsp_hdr_t *)pdu->isp_hdr; 2413 bzero(rsp, sizeof (*rsp)); 2414 rsp->opcode = ISCSI_OP_SCSI_RSP; 2415 rsp->flags = ISCSI_FLAG_FINAL; 2416 rsp->response = ISCSI_STATUS_CMD_COMPLETED; 2417 2418 return (0); 2419 } 2420 2421 /* 2422 * iscsit private data handler 2423 */ 2424 2425 /*ARGSUSED*/ 2426 static void 2427 iscsit_pp_cb(struct stmf_port_provider *pp, int cmd, void *arg, uint32_t flags) 2428 { 2429 it_config_t *cfg; 2430 nvlist_t *nvl; 2431 2432 if ((cmd != STMF_PROVIDER_DATA_UPDATED) || (arg == NULL)) { 2433 return; 2434 } 2435 2436 nvl = (nvlist_t *)arg; 2437 2438 /* Translate nvlist */ 2439 if (it_nv_to_config(nvl, &cfg) != 0) { 2440 cmn_err(CE_WARN, "Configuration is invalid"); 2441 return; 2442 } 2443 2444 /* Update config */ 2445 (void) iscsit_config_merge(cfg); 2446 2447 it_config_free_cmn(cfg); 2448 } 2449 2450 2451 static it_cfg_status_t 2452 iscsit_config_merge(it_config_t *in_cfg) 2453 { 2454 it_cfg_status_t status; 2455 it_config_t *cfg; 2456 it_config_t tmp_cfg; 2457 list_t tpg_del_list; 2458 2459 if (in_cfg) { 2460 cfg = in_cfg; 2461 } else { 2462 /* Make empty config */ 2463 bzero(&tmp_cfg, sizeof (tmp_cfg)); 2464 cfg = &tmp_cfg; 2465 } 2466 2467 list_create(&tpg_del_list, sizeof (iscsit_tpg_t), 2468 offsetof(iscsit_tpg_t, tpg_delete_ln)); 2469 2470 /* 2471 * Update targets, initiator contexts, target portal groups, 2472 * and iSNS client 2473 */ 2474 ISCSIT_GLOBAL_LOCK(RW_WRITER); 2475 if (((status = iscsit_config_merge_tpg(cfg, &tpg_del_list)) 2476 != 0) || 2477 ((status = iscsit_config_merge_tgt(cfg)) != 0) || 2478 ((status = iscsit_config_merge_ini(cfg)) != 0) || 2479 ((status = isnst_config_merge(cfg)) != 0)) { 2480 ISCSIT_GLOBAL_UNLOCK(); 2481 return (status); 2482 } 2483 2484 /* Update other global config parameters */ 2485 if (iscsit_global.global_props) { 2486 nvlist_free(iscsit_global.global_props); 2487 iscsit_global.global_props = NULL; 2488 } 2489 if (in_cfg) { 2490 (void) nvlist_dup(cfg->config_global_properties, 2491 &iscsit_global.global_props, KM_SLEEP); 2492 } 2493 ISCSIT_GLOBAL_UNLOCK(); 2494 2495 iscsit_config_destroy_tpgs(&tpg_del_list); 2496 2497 list_destroy(&tpg_del_list); 2498 2499 return (ITCFG_SUCCESS); 2500 } 2501 2502 /* 2503 * iscsit_sna_lt[e] 2504 * 2505 * Compare serial numbers using serial number arithmetic as defined in 2506 * RFC 1982. 2507 * 2508 * NOTE: This code is duplicated in the isns server as well as iscsitgtd. It 2509 * ought to be common. 2510 */ 2511 2512 static int 2513 iscsit_sna_lt(uint32_t sn1, uint32_t sn2) 2514 { 2515 return ((sn1 != sn2) && 2516 (((sn1 < sn2) && ((sn2 - sn1) < ISCSIT_SNA32_CHECK)) || 2517 ((sn1 > sn2) && ((sn1 - sn2) > ISCSIT_SNA32_CHECK)))); 2518 } 2519 2520 static int 2521 iscsit_sna_lte(uint32_t sn1, uint32_t sn2) 2522 { 2523 return ((sn1 == sn2) || 2524 (((sn1 < sn2) && ((sn2 - sn1) < ISCSIT_SNA32_CHECK)) || 2525 ((sn1 > sn2) && ((sn1 - sn2) > ISCSIT_SNA32_CHECK)))); 2526 } 2527 2528 2529 static boolean_t 2530 iscsit_cmdsn_in_window(iscsit_conn_t *ict, uint32_t cmdsn) 2531 { 2532 iscsit_sess_t *ist = ict->ict_sess; 2533 int rval = B_TRUE; 2534 2535 ist = ict->ict_sess; 2536 2537 rw_enter(&ist->ist_sn_rwlock, RW_READER); 2538 2539 /* 2540 * If cmdsn is less than ist_expcmdsn - iscsit_cmd_window() or 2541 * greater than ist_expcmdsn, it's not in the window. 2542 */ 2543 2544 if (iscsit_sna_lt(cmdsn, (ist->ist_expcmdsn - iscsit_cmd_window())) || 2545 !iscsit_sna_lte(cmdsn, ist->ist_expcmdsn)) { 2546 rval = B_FALSE; 2547 } 2548 2549 rw_exit(&ist->ist_sn_rwlock); 2550 2551 return (rval); 2552 } 2553