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