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/conf.h> 28 #include <sys/file.h> 29 #include <sys/ddi.h> 30 #include <sys/sunddi.h> 31 #include <sys/modctl.h> 32 33 #include <sys/socket.h> 34 #include <sys/strsubr.h> 35 #include <sys/sysmacros.h> 36 37 #include <sys/socketvar.h> 38 #include <netinet/in.h> 39 40 #include <sys/idm/idm.h> 41 #include <sys/idm/idm_so.h> 42 43 #define IDM_NAME_VERSION "iSCSI Data Mover" 44 45 extern struct mod_ops mod_miscops; 46 extern struct mod_ops mod_miscops; 47 48 static struct modlmisc modlmisc = { 49 &mod_miscops, /* Type of module */ 50 IDM_NAME_VERSION 51 }; 52 53 static struct modlinkage modlinkage = { 54 MODREV_1, (void *)&modlmisc, NULL 55 }; 56 57 extern int idm_task_compare(const void *t1, const void *t2); 58 extern void idm_wd_thread(void *arg); 59 60 static int _idm_init(void); 61 static int _idm_fini(void); 62 static void idm_buf_bind_in_locked(idm_task_t *idt, idm_buf_t *buf); 63 static void idm_buf_bind_out_locked(idm_task_t *idt, idm_buf_t *buf); 64 static void idm_buf_unbind_in_locked(idm_task_t *idt, idm_buf_t *buf); 65 static void idm_buf_unbind_out_locked(idm_task_t *idt, idm_buf_t *buf); 66 static void idm_task_abort_one(idm_conn_t *ic, idm_task_t *idt, 67 idm_abort_type_t abort_type); 68 static void idm_task_aborted(idm_task_t *idt, idm_status_t status); 69 static idm_pdu_t *idm_pdu_alloc_common(uint_t hdrlen, uint_t datalen, 70 int sleepflag); 71 72 boolean_t idm_conn_logging = 0; 73 boolean_t idm_svc_logging = 0; 74 #ifdef DEBUG 75 boolean_t idm_pattern_checking = 1; 76 #else 77 boolean_t idm_pattern_checking = 0; 78 #endif 79 80 /* 81 * Potential tuneable for the maximum number of tasks. Default to 82 * IDM_TASKIDS_MAX 83 */ 84 85 uint32_t idm_max_taskids = IDM_TASKIDS_MAX; 86 87 /* 88 * Global list of transport handles 89 * These are listed in preferential order, so we can simply take the 90 * first "it_conn_is_capable" hit. Note also that the order maps to 91 * the order of the idm_transport_type_t list. 92 */ 93 idm_transport_t idm_transport_list[] = { 94 95 /* iSER on InfiniBand transport handle */ 96 {IDM_TRANSPORT_TYPE_ISER, /* type */ 97 "/devices/ib/iser@0:iser", /* device path */ 98 NULL, /* LDI handle */ 99 NULL, /* transport ops */ 100 NULL}, /* transport caps */ 101 102 /* IDM native sockets transport handle */ 103 {IDM_TRANSPORT_TYPE_SOCKETS, /* type */ 104 NULL, /* device path */ 105 NULL, /* LDI handle */ 106 NULL, /* transport ops */ 107 NULL} /* transport caps */ 108 109 }; 110 111 int 112 _init(void) 113 { 114 int rc; 115 116 if ((rc = _idm_init()) != 0) { 117 return (rc); 118 } 119 120 return (mod_install(&modlinkage)); 121 } 122 123 int 124 _fini(void) 125 { 126 int rc; 127 128 if ((rc = _idm_fini()) != 0) { 129 return (rc); 130 } 131 132 if ((rc = mod_remove(&modlinkage)) != 0) { 133 return (rc); 134 } 135 136 return (rc); 137 } 138 139 int 140 _info(struct modinfo *modinfop) 141 { 142 return (mod_info(&modlinkage, modinfop)); 143 } 144 145 /* 146 * idm_transport_register() 147 * 148 * Provides a mechanism for an IDM transport driver to register its 149 * transport ops and caps with the IDM kernel module. Invoked during 150 * a transport driver's attach routine. 151 */ 152 idm_status_t 153 idm_transport_register(idm_transport_attr_t *attr) 154 { 155 ASSERT(attr->it_ops != NULL); 156 ASSERT(attr->it_caps != NULL); 157 158 switch (attr->type) { 159 /* All known non-native transports here; for now, iSER */ 160 case IDM_TRANSPORT_TYPE_ISER: 161 idm_transport_list[attr->type].it_ops = attr->it_ops; 162 idm_transport_list[attr->type].it_caps = attr->it_caps; 163 return (IDM_STATUS_SUCCESS); 164 165 default: 166 cmn_err(CE_NOTE, "idm: unknown transport type (0x%x) in " 167 "idm_transport_register", attr->type); 168 return (IDM_STATUS_SUCCESS); 169 } 170 } 171 172 /* 173 * idm_ini_conn_create 174 * 175 * This function is invoked by the iSCSI layer to create a connection context. 176 * This does not actually establish the socket connection. 177 * 178 * cr - Connection request parameters 179 * new_con - Output parameter that contains the new request if successful 180 * 181 */ 182 idm_status_t 183 idm_ini_conn_create(idm_conn_req_t *cr, idm_conn_t **new_con) 184 { 185 idm_transport_t *it; 186 idm_conn_t *ic; 187 int rc; 188 189 it = idm_transport_lookup(cr); 190 191 retry: 192 ic = idm_conn_create_common(CONN_TYPE_INI, it->it_type, 193 &cr->icr_conn_ops); 194 195 bcopy(&cr->cr_ini_dst_addr, &ic->ic_ini_dst_addr, 196 sizeof (cr->cr_ini_dst_addr)); 197 198 /* create the transport-specific connection components */ 199 rc = it->it_ops->it_ini_conn_create(cr, ic); 200 if (rc != IDM_STATUS_SUCCESS) { 201 /* cleanup the failed connection */ 202 idm_conn_destroy_common(ic); 203 kmem_free(ic, sizeof (idm_conn_t)); 204 205 /* 206 * It is possible for an IB client to connect to 207 * an ethernet-only client via an IB-eth gateway. 208 * Therefore, if we are attempting to use iSER and 209 * fail, retry with sockets before ultimately 210 * failing the connection. 211 */ 212 if (it->it_type == IDM_TRANSPORT_TYPE_ISER) { 213 it = &idm_transport_list[IDM_TRANSPORT_TYPE_SOCKETS]; 214 goto retry; 215 } 216 217 return (IDM_STATUS_FAIL); 218 } 219 220 *new_con = ic; 221 222 mutex_enter(&idm.idm_global_mutex); 223 list_insert_tail(&idm.idm_ini_conn_list, ic); 224 mutex_exit(&idm.idm_global_mutex); 225 226 return (IDM_STATUS_SUCCESS); 227 } 228 229 /* 230 * idm_ini_conn_destroy 231 * 232 * Releases any resources associated with the connection. This is the 233 * complement to idm_ini_conn_create. 234 * ic - idm_conn_t structure representing the relevant connection 235 * 236 */ 237 void 238 idm_ini_conn_destroy_task(void *ic_void) 239 { 240 idm_conn_t *ic = ic_void; 241 242 ic->ic_transport_ops->it_ini_conn_destroy(ic); 243 idm_conn_destroy_common(ic); 244 } 245 246 void 247 idm_ini_conn_destroy(idm_conn_t *ic) 248 { 249 /* 250 * It's reasonable for the initiator to call idm_ini_conn_destroy 251 * from within the context of the CN_CONNECT_DESTROY notification. 252 * That's a problem since we want to destroy the taskq for the 253 * state machine associated with the connection. Remove the 254 * connection from the list right away then handle the remaining 255 * work via the idm_global_taskq. 256 */ 257 mutex_enter(&idm.idm_global_mutex); 258 list_remove(&idm.idm_ini_conn_list, ic); 259 mutex_exit(&idm.idm_global_mutex); 260 261 if (taskq_dispatch(idm.idm_global_taskq, 262 &idm_ini_conn_destroy_task, ic, TQ_SLEEP) == NULL) { 263 cmn_err(CE_WARN, 264 "idm_ini_conn_destroy: Couldn't dispatch task"); 265 } 266 } 267 268 /* 269 * idm_ini_conn_connect 270 * 271 * Establish connection to the remote system identified in idm_conn_t. 272 * The connection parameters including the remote IP address were established 273 * in the call to idm_ini_conn_create. The IDM state machine will 274 * perform client notifications as necessary to prompt the initiator through 275 * the login process. IDM also keeps a timer running so that if the login 276 * process doesn't complete in a timely manner it will fail. 277 * 278 * ic - idm_conn_t structure representing the relevant connection 279 * 280 * Returns success if the connection was established, otherwise some kind 281 * of meaningful error code. 282 * 283 * Upon return the login has either failed or is loggin in (ffp) 284 */ 285 idm_status_t 286 idm_ini_conn_connect(idm_conn_t *ic) 287 { 288 idm_status_t rc = IDM_STATUS_SUCCESS; 289 290 rc = idm_conn_sm_init(ic); 291 if (rc != IDM_STATUS_SUCCESS) { 292 return (ic->ic_conn_sm_status); 293 } 294 295 /* Hold connection until we return */ 296 idm_conn_hold(ic); 297 298 /* Kick state machine */ 299 idm_conn_event(ic, CE_CONNECT_REQ, NULL); 300 301 /* Wait for login flag */ 302 mutex_enter(&ic->ic_state_mutex); 303 while (!(ic->ic_state_flags & CF_LOGIN_READY) && 304 !(ic->ic_state_flags & CF_ERROR)) { 305 cv_wait(&ic->ic_state_cv, &ic->ic_state_mutex); 306 } 307 mutex_exit(&ic->ic_state_mutex); 308 309 if (ic->ic_state_flags & CF_ERROR) { 310 /* ic->ic_conn_sm_status will contains failure status */ 311 idm_conn_rele(ic); 312 return (ic->ic_conn_sm_status); 313 } 314 315 /* Ready to login */ 316 ASSERT(ic->ic_state_flags & CF_LOGIN_READY); 317 (void) idm_notify_client(ic, CN_READY_FOR_LOGIN, NULL); 318 319 idm_conn_rele(ic); 320 321 return (rc); 322 } 323 324 /* 325 * idm_ini_conn_disconnect 326 * 327 * Forces a connection (previously established using idm_ini_conn_connect) 328 * to perform a controlled shutdown, cleaning up any outstanding requests. 329 * 330 * ic - idm_conn_t structure representing the relevant connection 331 * 332 * This is asynchronous and will return before the connection is properly 333 * shutdown 334 */ 335 /* ARGSUSED */ 336 void 337 idm_ini_conn_disconnect(idm_conn_t *ic) 338 { 339 idm_conn_event(ic, CE_TRANSPORT_FAIL, NULL); 340 } 341 342 /* 343 * idm_ini_conn_disconnect_wait 344 * 345 * Forces a connection (previously established using idm_ini_conn_connect) 346 * to perform a controlled shutdown. Blocks until the connection is 347 * disconnected. 348 * 349 * ic - idm_conn_t structure representing the relevant connection 350 */ 351 /* ARGSUSED */ 352 void 353 idm_ini_conn_disconnect_sync(idm_conn_t *ic) 354 { 355 mutex_enter(&ic->ic_state_mutex); 356 if ((ic->ic_state != CS_S9_INIT_ERROR) && 357 (ic->ic_state != CS_S11_COMPLETE)) { 358 idm_conn_event_locked(ic, CE_TRANSPORT_FAIL, NULL, CT_NONE); 359 while ((ic->ic_state != CS_S9_INIT_ERROR) && 360 (ic->ic_state != CS_S11_COMPLETE)) 361 cv_wait(&ic->ic_state_cv, &ic->ic_state_mutex); 362 } 363 mutex_exit(&ic->ic_state_mutex); 364 } 365 366 /* 367 * idm_tgt_svc_create 368 * 369 * The target calls this service to obtain a service context for each available 370 * transport, starting a service of each type related to the IP address and port 371 * passed. The idm_svc_req_t contains the service parameters. 372 */ 373 idm_status_t 374 idm_tgt_svc_create(idm_svc_req_t *sr, idm_svc_t **new_svc) 375 { 376 idm_transport_type_t type; 377 idm_transport_t *it; 378 idm_svc_t *is; 379 int rc; 380 381 *new_svc = NULL; 382 is = kmem_zalloc(sizeof (idm_svc_t), KM_SLEEP); 383 384 /* Initialize transport-agnostic components of the service handle */ 385 is->is_svc_req = *sr; 386 mutex_init(&is->is_mutex, NULL, MUTEX_DEFAULT, NULL); 387 cv_init(&is->is_cv, NULL, CV_DEFAULT, NULL); 388 mutex_init(&is->is_count_mutex, NULL, MUTEX_DEFAULT, NULL); 389 cv_init(&is->is_count_cv, NULL, CV_DEFAULT, NULL); 390 idm_refcnt_init(&is->is_refcnt, is); 391 392 /* 393 * Make sure all available transports are setup. We call this now 394 * instead of at initialization time in case IB has become available 395 * since we started (hotplug, etc). 396 */ 397 idm_transport_setup(sr->sr_li); 398 399 /* 400 * Loop through the transports, configuring the transport-specific 401 * components of each one. 402 */ 403 for (type = 0; type < IDM_TRANSPORT_NUM_TYPES; type++) { 404 405 it = &idm_transport_list[type]; 406 /* 407 * If it_ops is NULL then the transport is unconfigured 408 * and we shouldn't try to start the service. 409 */ 410 if (it->it_ops == NULL) { 411 continue; 412 } 413 414 rc = it->it_ops->it_tgt_svc_create(sr, is); 415 if (rc != IDM_STATUS_SUCCESS) { 416 /* Teardown any configured services */ 417 while (type--) { 418 it = &idm_transport_list[type]; 419 if (it->it_ops == NULL) { 420 continue; 421 } 422 it->it_ops->it_tgt_svc_destroy(is); 423 } 424 /* Free the svc context and return */ 425 kmem_free(is, sizeof (idm_svc_t)); 426 return (rc); 427 } 428 } 429 430 *new_svc = is; 431 432 mutex_enter(&idm.idm_global_mutex); 433 list_insert_tail(&idm.idm_tgt_svc_list, is); 434 mutex_exit(&idm.idm_global_mutex); 435 436 return (IDM_STATUS_SUCCESS); 437 } 438 439 /* 440 * idm_tgt_svc_destroy 441 * 442 * is - idm_svc_t returned by the call to idm_tgt_svc_create 443 * 444 * Cleanup any resources associated with the idm_svc_t. 445 */ 446 void 447 idm_tgt_svc_destroy(idm_svc_t *is) 448 { 449 idm_transport_type_t type; 450 idm_transport_t *it; 451 452 mutex_enter(&idm.idm_global_mutex); 453 /* remove this service from the global list */ 454 list_remove(&idm.idm_tgt_svc_list, is); 455 /* wakeup any waiters for service change */ 456 cv_broadcast(&idm.idm_tgt_svc_cv); 457 mutex_exit(&idm.idm_global_mutex); 458 459 /* teardown each transport-specific service */ 460 for (type = 0; type < IDM_TRANSPORT_NUM_TYPES; type++) { 461 it = &idm_transport_list[type]; 462 if (it->it_ops == NULL) { 463 continue; 464 } 465 466 it->it_ops->it_tgt_svc_destroy(is); 467 } 468 469 /* tear down the svc resources */ 470 idm_refcnt_destroy(&is->is_refcnt); 471 cv_destroy(&is->is_count_cv); 472 mutex_destroy(&is->is_count_mutex); 473 cv_destroy(&is->is_cv); 474 mutex_destroy(&is->is_mutex); 475 476 /* free the svc handle */ 477 kmem_free(is, sizeof (idm_svc_t)); 478 } 479 480 void 481 idm_tgt_svc_hold(idm_svc_t *is) 482 { 483 idm_refcnt_hold(&is->is_refcnt); 484 } 485 486 void 487 idm_tgt_svc_rele_and_destroy(idm_svc_t *is) 488 { 489 idm_refcnt_rele_and_destroy(&is->is_refcnt, 490 (idm_refcnt_cb_t *)&idm_tgt_svc_destroy); 491 } 492 493 /* 494 * idm_tgt_svc_online 495 * 496 * is - idm_svc_t returned by the call to idm_tgt_svc_create 497 * 498 * Online each transport service, as we want this target to be accessible 499 * via any configured transport. 500 * 501 * When the initiator establishes a new connection to the target, IDM will 502 * call the "new connect" callback defined in the idm_svc_req_t structure 503 * and it will pass an idm_conn_t structure representing that new connection. 504 */ 505 idm_status_t 506 idm_tgt_svc_online(idm_svc_t *is) 507 { 508 509 idm_transport_type_t type, last_type; 510 idm_transport_t *it; 511 int rc = IDM_STATUS_SUCCESS; 512 513 mutex_enter(&is->is_mutex); 514 if (is->is_online == 0) { 515 /* Walk through each of the transports and online them */ 516 for (type = 0; type < IDM_TRANSPORT_NUM_TYPES; type++) { 517 it = &idm_transport_list[type]; 518 if (it->it_ops == NULL) { 519 /* transport is not registered */ 520 continue; 521 } 522 523 mutex_exit(&is->is_mutex); 524 rc = it->it_ops->it_tgt_svc_online(is); 525 mutex_enter(&is->is_mutex); 526 if (rc != IDM_STATUS_SUCCESS) { 527 last_type = type; 528 break; 529 } 530 } 531 if (rc != IDM_STATUS_SUCCESS) { 532 /* 533 * The last transport failed to online. 534 * Offline any transport onlined above and 535 * do not online the target. 536 */ 537 for (type = 0; type < last_type; type++) { 538 it = &idm_transport_list[type]; 539 if (it->it_ops == NULL) { 540 /* transport is not registered */ 541 continue; 542 } 543 544 mutex_exit(&is->is_mutex); 545 it->it_ops->it_tgt_svc_offline(is); 546 mutex_enter(&is->is_mutex); 547 } 548 } else { 549 /* Target service now online */ 550 is->is_online = 1; 551 } 552 } else { 553 /* Target service already online, just bump the count */ 554 is->is_online++; 555 } 556 mutex_exit(&is->is_mutex); 557 558 return (rc); 559 } 560 561 /* 562 * idm_tgt_svc_offline 563 * 564 * is - idm_svc_t returned by the call to idm_tgt_svc_create 565 * 566 * Shutdown any online target services. 567 */ 568 void 569 idm_tgt_svc_offline(idm_svc_t *is) 570 { 571 idm_transport_type_t type; 572 idm_transport_t *it; 573 574 mutex_enter(&is->is_mutex); 575 is->is_online--; 576 if (is->is_online == 0) { 577 /* Walk through each of the transports and offline them */ 578 for (type = 0; type < IDM_TRANSPORT_NUM_TYPES; type++) { 579 it = &idm_transport_list[type]; 580 if (it->it_ops == NULL) { 581 /* transport is not registered */ 582 continue; 583 } 584 585 mutex_exit(&is->is_mutex); 586 it->it_ops->it_tgt_svc_offline(is); 587 mutex_enter(&is->is_mutex); 588 } 589 } 590 mutex_exit(&is->is_mutex); 591 } 592 593 /* 594 * idm_tgt_svc_lookup 595 * 596 * Lookup a service instance listening on the specified port 597 */ 598 599 idm_svc_t * 600 idm_tgt_svc_lookup(uint16_t port) 601 { 602 idm_svc_t *result; 603 604 retry: 605 mutex_enter(&idm.idm_global_mutex); 606 for (result = list_head(&idm.idm_tgt_svc_list); 607 result != NULL; 608 result = list_next(&idm.idm_tgt_svc_list, result)) { 609 if (result->is_svc_req.sr_port == port) { 610 if (result->is_online == 0) { 611 /* 612 * A service exists on this port, but it 613 * is going away, wait for it to cleanup. 614 */ 615 cv_wait(&idm.idm_tgt_svc_cv, 616 &idm.idm_global_mutex); 617 mutex_exit(&idm.idm_global_mutex); 618 goto retry; 619 } 620 idm_tgt_svc_hold(result); 621 mutex_exit(&idm.idm_global_mutex); 622 return (result); 623 } 624 } 625 mutex_exit(&idm.idm_global_mutex); 626 627 return (NULL); 628 } 629 630 /* 631 * idm_negotiate_key_values() 632 * Give IDM level a chance to negotiate any login parameters it should own. 633 * -- leave unhandled parameters alone on request_nvl 634 * -- move all handled parameters to response_nvl with an appropriate response 635 * -- also add an entry to negotiated_nvl for any accepted parameters 636 */ 637 kv_status_t 638 idm_negotiate_key_values(idm_conn_t *ic, nvlist_t *request_nvl, 639 nvlist_t *response_nvl, nvlist_t *negotiated_nvl) 640 { 641 ASSERT(ic->ic_transport_ops != NULL); 642 return (ic->ic_transport_ops->it_negotiate_key_values(ic, 643 request_nvl, response_nvl, negotiated_nvl)); 644 } 645 646 /* 647 * idm_notice_key_values() 648 * Activate at the IDM level any parameters that have been negotiated. 649 * Passes the set of key value pairs to the transport for activation. 650 * This will be invoked as the connection is entering full-feature mode. 651 */ 652 void 653 idm_notice_key_values(idm_conn_t *ic, nvlist_t *negotiated_nvl) 654 { 655 ASSERT(ic->ic_transport_ops != NULL); 656 ic->ic_transport_ops->it_notice_key_values(ic, negotiated_nvl); 657 } 658 659 /* 660 * idm_buf_tx_to_ini 661 * 662 * This is IDM's implementation of the 'Put_Data' operational primitive. 663 * 664 * This function is invoked by a target iSCSI layer to request its local 665 * Datamover layer to transmit the Data-In PDU to the peer iSCSI layer 666 * on the remote iSCSI node. The I/O buffer represented by 'idb' is 667 * transferred to the initiator associated with task 'idt'. The connection 668 * info, contents of the Data-In PDU header, the DataDescriptorIn, BHS, 669 * and the callback (idb->idb_buf_cb) at transfer completion are 670 * provided as input. 671 * 672 * This data transfer takes place transparently to the remote iSCSI layer, 673 * i.e. without its participation. 674 * 675 * Using sockets, IDM implements the data transfer by segmenting the data 676 * buffer into appropriately sized iSCSI PDUs and transmitting them to the 677 * initiator. iSER performs the transfer using RDMA write. 678 * 679 */ 680 idm_status_t 681 idm_buf_tx_to_ini(idm_task_t *idt, idm_buf_t *idb, 682 uint32_t offset, uint32_t xfer_len, 683 idm_buf_cb_t idb_buf_cb, void *cb_arg) 684 { 685 idm_status_t rc; 686 687 idb->idb_bufoffset = offset; 688 idb->idb_xfer_len = xfer_len; 689 idb->idb_buf_cb = idb_buf_cb; 690 idb->idb_cb_arg = cb_arg; 691 gethrestime(&idb->idb_xfer_start); 692 693 /* 694 * Buffer should not contain the pattern. If the pattern is 695 * present then we've been asked to transmit initialized data 696 */ 697 IDM_BUFPAT_CHECK(idb, xfer_len, BP_CHECK_ASSERT); 698 699 mutex_enter(&idt->idt_mutex); 700 switch (idt->idt_state) { 701 case TASK_ACTIVE: 702 idt->idt_tx_to_ini_start++; 703 idm_task_hold(idt); 704 idm_buf_bind_in_locked(idt, idb); 705 idb->idb_in_transport = B_TRUE; 706 rc = (*idt->idt_ic->ic_transport_ops->it_buf_tx_to_ini) 707 (idt, idb); 708 return (rc); 709 710 case TASK_SUSPENDING: 711 case TASK_SUSPENDED: 712 /* 713 * Bind buffer but don't start a transfer since the task 714 * is suspended 715 */ 716 idm_buf_bind_in_locked(idt, idb); 717 mutex_exit(&idt->idt_mutex); 718 return (IDM_STATUS_SUCCESS); 719 720 case TASK_ABORTING: 721 case TASK_ABORTED: 722 /* 723 * Once the task is aborted, any buffers added to the 724 * idt_inbufv will never get cleaned up, so just return 725 * SUCCESS. The buffer should get cleaned up by the 726 * client or framework once task_aborted has completed. 727 */ 728 mutex_exit(&idt->idt_mutex); 729 return (IDM_STATUS_SUCCESS); 730 731 default: 732 ASSERT(0); 733 break; 734 } 735 mutex_exit(&idt->idt_mutex); 736 737 return (IDM_STATUS_FAIL); 738 } 739 740 /* 741 * idm_buf_rx_from_ini 742 * 743 * This is IDM's implementation of the 'Get_Data' operational primitive. 744 * 745 * This function is invoked by a target iSCSI layer to request its local 746 * Datamover layer to retrieve certain data identified by the R2T PDU from the 747 * peer iSCSI layer on the remote node. The retrieved Data-Out PDU will be 748 * mapped to the respective buffer by the task tags (ITT & TTT). 749 * The connection information, contents of an R2T PDU, DataDescriptor, BHS, and 750 * the callback (idb->idb_buf_cb) notification for data transfer completion are 751 * are provided as input. 752 * 753 * When an iSCSI node sends an R2T PDU to its local Datamover layer, the local 754 * Datamover layer, the local and remote Datamover layers transparently bring 755 * about the data transfer requested by the R2T PDU, without the participation 756 * of the iSCSI layers. 757 * 758 * Using sockets, IDM transmits an R2T PDU for each buffer and the rx_data_out() 759 * assembles the Data-Out PDUs into the buffer. iSER uses RDMA read. 760 * 761 */ 762 idm_status_t 763 idm_buf_rx_from_ini(idm_task_t *idt, idm_buf_t *idb, 764 uint32_t offset, uint32_t xfer_len, 765 idm_buf_cb_t idb_buf_cb, void *cb_arg) 766 { 767 idm_status_t rc; 768 769 idb->idb_bufoffset = offset; 770 idb->idb_xfer_len = xfer_len; 771 idb->idb_buf_cb = idb_buf_cb; 772 idb->idb_cb_arg = cb_arg; 773 gethrestime(&idb->idb_xfer_start); 774 775 /* 776 * "In" buf list is for "Data In" PDU's, "Out" buf list is for 777 * "Data Out" PDU's 778 */ 779 mutex_enter(&idt->idt_mutex); 780 switch (idt->idt_state) { 781 case TASK_ACTIVE: 782 idt->idt_rx_from_ini_start++; 783 idm_task_hold(idt); 784 idm_buf_bind_out_locked(idt, idb); 785 idb->idb_in_transport = B_TRUE; 786 rc = (*idt->idt_ic->ic_transport_ops->it_buf_rx_from_ini) 787 (idt, idb); 788 return (rc); 789 case TASK_SUSPENDING: 790 case TASK_SUSPENDED: 791 case TASK_ABORTING: 792 case TASK_ABORTED: 793 /* 794 * Bind buffer but don't start a transfer since the task 795 * is suspended 796 */ 797 idm_buf_bind_out_locked(idt, idb); 798 mutex_exit(&idt->idt_mutex); 799 return (IDM_STATUS_SUCCESS); 800 default: 801 ASSERT(0); 802 break; 803 } 804 mutex_exit(&idt->idt_mutex); 805 806 return (IDM_STATUS_FAIL); 807 } 808 809 /* 810 * idm_buf_tx_to_ini_done 811 * 812 * The transport calls this after it has completed a transfer requested by 813 * a call to transport_buf_tx_to_ini 814 * 815 * Caller holds idt->idt_mutex, idt->idt_mutex is released before returning. 816 * idt may be freed after the call to idb->idb_buf_cb. 817 */ 818 void 819 idm_buf_tx_to_ini_done(idm_task_t *idt, idm_buf_t *idb, idm_status_t status) 820 { 821 ASSERT(mutex_owned(&idt->idt_mutex)); 822 idb->idb_in_transport = B_FALSE; 823 idb->idb_tx_thread = B_FALSE; 824 idt->idt_tx_to_ini_done++; 825 gethrestime(&idb->idb_xfer_done); 826 827 /* 828 * idm_refcnt_rele may cause TASK_SUSPENDING --> TASK_SUSPENDED or 829 * TASK_ABORTING --> TASK_ABORTED transistion if the refcount goes 830 * to 0. 831 */ 832 idm_task_rele(idt); 833 idb->idb_status = status; 834 835 switch (idt->idt_state) { 836 case TASK_ACTIVE: 837 idm_buf_unbind_in_locked(idt, idb); 838 mutex_exit(&idt->idt_mutex); 839 (*idb->idb_buf_cb)(idb, status); 840 return; 841 case TASK_SUSPENDING: 842 case TASK_SUSPENDED: 843 case TASK_ABORTING: 844 case TASK_ABORTED: 845 /* 846 * To keep things simple we will ignore the case where the 847 * transfer was successful and leave all buffers bound to the 848 * task. This allows us to also ignore the case where we've 849 * been asked to abort a task but the last transfer of the 850 * task has completed. IDM has no idea whether this was, in 851 * fact, the last transfer of the task so it would be difficult 852 * to handle this case. Everything should get sorted out again 853 * after task reassignment is complete. 854 * 855 * In the case of TASK_ABORTING we could conceivably call the 856 * buffer callback here but the timing of when the client's 857 * client_task_aborted callback is invoked vs. when the client's 858 * buffer callback gets invoked gets sticky. We don't want 859 * the client to here from us again after the call to 860 * client_task_aborted() but we don't want to give it a bunch 861 * of failed buffer transfers until we've called 862 * client_task_aborted(). Instead we'll just leave all the 863 * buffers bound and allow the client to cleanup. 864 */ 865 break; 866 default: 867 ASSERT(0); 868 } 869 mutex_exit(&idt->idt_mutex); 870 } 871 872 /* 873 * idm_buf_rx_from_ini_done 874 * 875 * The transport calls this after it has completed a transfer requested by 876 * a call totransport_buf_tx_to_ini 877 * 878 * Caller holds idt->idt_mutex, idt->idt_mutex is released before returning. 879 * idt may be freed after the call to idb->idb_buf_cb. 880 */ 881 void 882 idm_buf_rx_from_ini_done(idm_task_t *idt, idm_buf_t *idb, idm_status_t status) 883 { 884 ASSERT(mutex_owned(&idt->idt_mutex)); 885 idb->idb_in_transport = B_FALSE; 886 idt->idt_rx_from_ini_done++; 887 gethrestime(&idb->idb_xfer_done); 888 889 /* 890 * idm_refcnt_rele may cause TASK_SUSPENDING --> TASK_SUSPENDED or 891 * TASK_ABORTING --> TASK_ABORTED transistion if the refcount goes 892 * to 0. 893 */ 894 idm_task_rele(idt); 895 idb->idb_status = status; 896 897 if (status == IDM_STATUS_SUCCESS) { 898 /* 899 * Buffer should not contain the pattern. If it does then 900 * we did not get the data from the remote host. 901 */ 902 IDM_BUFPAT_CHECK(idb, idb->idb_xfer_len, BP_CHECK_ASSERT); 903 } 904 905 switch (idt->idt_state) { 906 case TASK_ACTIVE: 907 idm_buf_unbind_out_locked(idt, idb); 908 mutex_exit(&idt->idt_mutex); 909 (*idb->idb_buf_cb)(idb, status); 910 return; 911 case TASK_SUSPENDING: 912 case TASK_SUSPENDED: 913 case TASK_ABORTING: 914 case TASK_ABORTED: 915 /* 916 * To keep things simple we will ignore the case where the 917 * transfer was successful and leave all buffers bound to the 918 * task. This allows us to also ignore the case where we've 919 * been asked to abort a task but the last transfer of the 920 * task has completed. IDM has no idea whether this was, in 921 * fact, the last transfer of the task so it would be difficult 922 * to handle this case. Everything should get sorted out again 923 * after task reassignment is complete. 924 * 925 * In the case of TASK_ABORTING we could conceivably call the 926 * buffer callback here but the timing of when the client's 927 * client_task_aborted callback is invoked vs. when the client's 928 * buffer callback gets invoked gets sticky. We don't want 929 * the client to here from us again after the call to 930 * client_task_aborted() but we don't want to give it a bunch 931 * of failed buffer transfers until we've called 932 * client_task_aborted(). Instead we'll just leave all the 933 * buffers bound and allow the client to cleanup. 934 */ 935 break; 936 default: 937 ASSERT(0); 938 } 939 mutex_exit(&idt->idt_mutex); 940 } 941 942 /* 943 * idm_buf_alloc 944 * 945 * Allocates a buffer handle and registers it for use with the transport 946 * layer. If a buffer is not passed on bufptr, the buffer will be allocated 947 * as well as the handle. 948 * 949 * ic - connection on which the buffer will be transferred 950 * bufptr - allocate memory for buffer if NULL, else assign to buffer 951 * buflen - length of buffer 952 * 953 * Returns idm_buf_t handle if successful, otherwise NULL 954 */ 955 idm_buf_t * 956 idm_buf_alloc(idm_conn_t *ic, void *bufptr, uint64_t buflen) 957 { 958 idm_buf_t *buf = NULL; 959 int rc; 960 961 ASSERT(ic != NULL); 962 ASSERT(idm.idm_buf_cache != NULL); 963 ASSERT(buflen > 0); 964 965 /* Don't allocate new buffers if we are not in FFP */ 966 mutex_enter(&ic->ic_state_mutex); 967 if (!ic->ic_ffp) { 968 mutex_exit(&ic->ic_state_mutex); 969 return (NULL); 970 } 971 972 973 idm_conn_hold(ic); 974 mutex_exit(&ic->ic_state_mutex); 975 976 buf = kmem_cache_alloc(idm.idm_buf_cache, KM_NOSLEEP); 977 if (buf == NULL) { 978 idm_conn_rele(ic); 979 return (NULL); 980 } 981 982 buf->idb_ic = ic; 983 buf->idb_buflen = buflen; 984 buf->idb_exp_offset = 0; 985 buf->idb_bufoffset = 0; 986 buf->idb_xfer_len = 0; 987 buf->idb_magic = IDM_BUF_MAGIC; 988 buf->idb_in_transport = B_FALSE; 989 buf->idb_bufbcopy = B_FALSE; 990 991 /* 992 * If bufptr is NULL, we have an implicit request to allocate 993 * memory for this IDM buffer handle and register it for use 994 * with the transport. To simplify this, and to give more freedom 995 * to the transport layer for it's own buffer management, both of 996 * these actions will take place in the transport layer. 997 * If bufptr is set, then the caller has allocated memory (or more 998 * likely it's been passed from an upper layer), and we need only 999 * register the buffer for use with the transport layer. 1000 */ 1001 if (bufptr == NULL) { 1002 /* 1003 * Allocate a buffer from the transport layer (which 1004 * will also register the buffer for use). 1005 */ 1006 rc = ic->ic_transport_ops->it_buf_alloc(buf, buflen); 1007 if (rc != 0) { 1008 idm_conn_rele(ic); 1009 kmem_cache_free(idm.idm_buf_cache, buf); 1010 return (NULL); 1011 } 1012 /* Set the bufalloc'd flag */ 1013 buf->idb_bufalloc = B_TRUE; 1014 } else { 1015 /* 1016 * For large transfers, Set the passed bufptr into 1017 * the buf handle, and register the handle with the 1018 * transport layer. As memory registration with the 1019 * transport layer is a time/cpu intensive operation, 1020 * for small transfers (up to a pre-defined bcopy 1021 * threshold), use pre-registered memory buffers 1022 * and bcopy data at the appropriate time. 1023 */ 1024 buf->idb_buf = bufptr; 1025 1026 rc = ic->ic_transport_ops->it_buf_setup(buf); 1027 if (rc != 0) { 1028 idm_conn_rele(ic); 1029 kmem_cache_free(idm.idm_buf_cache, buf); 1030 return (NULL); 1031 } 1032 /* 1033 * The transport layer is now expected to set the idb_bufalloc 1034 * correctly to indicate if resources have been allocated. 1035 */ 1036 } 1037 1038 IDM_BUFPAT_SET(buf); 1039 1040 return (buf); 1041 } 1042 1043 /* 1044 * idm_buf_free 1045 * 1046 * Release a buffer handle along with the associated buffer that was allocated 1047 * or assigned with idm_buf_alloc 1048 */ 1049 void 1050 idm_buf_free(idm_buf_t *buf) 1051 { 1052 idm_conn_t *ic = buf->idb_ic; 1053 1054 1055 buf->idb_task_binding = NULL; 1056 1057 if (buf->idb_bufalloc) { 1058 ic->ic_transport_ops->it_buf_free(buf); 1059 } else { 1060 ic->ic_transport_ops->it_buf_teardown(buf); 1061 } 1062 kmem_cache_free(idm.idm_buf_cache, buf); 1063 idm_conn_rele(ic); 1064 } 1065 1066 /* 1067 * idm_buf_bind_in 1068 * 1069 * This function associates a buffer with a task. This is only for use by the 1070 * iSCSI initiator that will have only one buffer per transfer direction 1071 * 1072 */ 1073 void 1074 idm_buf_bind_in(idm_task_t *idt, idm_buf_t *buf) 1075 { 1076 mutex_enter(&idt->idt_mutex); 1077 idm_buf_bind_in_locked(idt, buf); 1078 mutex_exit(&idt->idt_mutex); 1079 } 1080 1081 static void 1082 idm_buf_bind_in_locked(idm_task_t *idt, idm_buf_t *buf) 1083 { 1084 buf->idb_task_binding = idt; 1085 buf->idb_ic = idt->idt_ic; 1086 idm_listbuf_insert(&idt->idt_inbufv, buf); 1087 } 1088 1089 void 1090 idm_buf_bind_out(idm_task_t *idt, idm_buf_t *buf) 1091 { 1092 /* 1093 * For small transfers, the iSER transport delegates the IDM 1094 * layer to bcopy the SCSI Write data for faster IOPS. 1095 */ 1096 if (buf->idb_bufbcopy == B_TRUE) { 1097 1098 bcopy(buf->idb_bufptr, buf->idb_buf, buf->idb_buflen); 1099 } 1100 mutex_enter(&idt->idt_mutex); 1101 idm_buf_bind_out_locked(idt, buf); 1102 mutex_exit(&idt->idt_mutex); 1103 } 1104 1105 static void 1106 idm_buf_bind_out_locked(idm_task_t *idt, idm_buf_t *buf) 1107 { 1108 buf->idb_task_binding = idt; 1109 buf->idb_ic = idt->idt_ic; 1110 idm_listbuf_insert(&idt->idt_outbufv, buf); 1111 } 1112 1113 void 1114 idm_buf_unbind_in(idm_task_t *idt, idm_buf_t *buf) 1115 { 1116 /* 1117 * For small transfers, the iSER transport delegates the IDM 1118 * layer to bcopy the SCSI Read data into the read buufer 1119 * for faster IOPS. 1120 */ 1121 if (buf->idb_bufbcopy == B_TRUE) { 1122 bcopy(buf->idb_buf, buf->idb_bufptr, buf->idb_buflen); 1123 } 1124 mutex_enter(&idt->idt_mutex); 1125 idm_buf_unbind_in_locked(idt, buf); 1126 mutex_exit(&idt->idt_mutex); 1127 } 1128 1129 static void 1130 idm_buf_unbind_in_locked(idm_task_t *idt, idm_buf_t *buf) 1131 { 1132 list_remove(&idt->idt_inbufv, buf); 1133 } 1134 1135 void 1136 idm_buf_unbind_out(idm_task_t *idt, idm_buf_t *buf) 1137 { 1138 mutex_enter(&idt->idt_mutex); 1139 idm_buf_unbind_out_locked(idt, buf); 1140 mutex_exit(&idt->idt_mutex); 1141 } 1142 1143 static void 1144 idm_buf_unbind_out_locked(idm_task_t *idt, idm_buf_t *buf) 1145 { 1146 list_remove(&idt->idt_outbufv, buf); 1147 } 1148 1149 /* 1150 * idm_buf_find() will lookup the idm_buf_t based on the relative offset in the 1151 * iSCSI PDU 1152 */ 1153 idm_buf_t * 1154 idm_buf_find(void *lbuf, size_t data_offset) 1155 { 1156 idm_buf_t *idb; 1157 list_t *lst = (list_t *)lbuf; 1158 1159 /* iterate through the list to find the buffer */ 1160 for (idb = list_head(lst); idb != NULL; idb = list_next(lst, idb)) { 1161 1162 ASSERT((idb->idb_ic->ic_conn_type == CONN_TYPE_TGT) || 1163 (idb->idb_bufoffset == 0)); 1164 1165 if ((data_offset >= idb->idb_bufoffset) && 1166 (data_offset < (idb->idb_bufoffset + idb->idb_buflen))) { 1167 1168 return (idb); 1169 } 1170 } 1171 1172 return (NULL); 1173 } 1174 1175 void 1176 idm_bufpat_set(idm_buf_t *idb) 1177 { 1178 idm_bufpat_t *bufpat; 1179 int len, i; 1180 1181 len = idb->idb_buflen; 1182 len = (len / sizeof (idm_bufpat_t)) * sizeof (idm_bufpat_t); 1183 1184 bufpat = idb->idb_buf; 1185 for (i = 0; i < len; i += sizeof (idm_bufpat_t)) { 1186 bufpat->bufpat_idb = idb; 1187 bufpat->bufpat_bufmagic = IDM_BUF_MAGIC; 1188 bufpat->bufpat_offset = i; 1189 bufpat++; 1190 } 1191 } 1192 1193 boolean_t 1194 idm_bufpat_check(idm_buf_t *idb, int check_len, idm_bufpat_check_type_t type) 1195 { 1196 idm_bufpat_t *bufpat; 1197 int len, i; 1198 1199 len = (type == BP_CHECK_QUICK) ? sizeof (idm_bufpat_t) : check_len; 1200 len = (len / sizeof (idm_bufpat_t)) * sizeof (idm_bufpat_t); 1201 ASSERT(len <= idb->idb_buflen); 1202 bufpat = idb->idb_buf; 1203 1204 /* 1205 * Don't check the pattern in buffers that came from outside IDM 1206 * (these will be buffers from the initiator that we opted not 1207 * to double-buffer) 1208 */ 1209 if (!idb->idb_bufalloc) 1210 return (B_FALSE); 1211 1212 /* 1213 * Return true if we find the pattern anywhere in the buffer 1214 */ 1215 for (i = 0; i < len; i += sizeof (idm_bufpat_t)) { 1216 if (BUFPAT_MATCH(bufpat, idb)) { 1217 IDM_CONN_LOG(CE_WARN, "idm_bufpat_check found: " 1218 "idb %p bufpat %p " 1219 "bufpat_idb=%p bufmagic=%08x offset=%08x", 1220 (void *)idb, (void *)bufpat, bufpat->bufpat_idb, 1221 bufpat->bufpat_bufmagic, bufpat->bufpat_offset); 1222 DTRACE_PROBE2(bufpat__pattern__found, 1223 idm_buf_t *, idb, idm_bufpat_t *, bufpat); 1224 if (type == BP_CHECK_ASSERT) { 1225 ASSERT(0); 1226 } 1227 return (B_TRUE); 1228 } 1229 bufpat++; 1230 } 1231 1232 return (B_FALSE); 1233 } 1234 1235 /* 1236 * idm_task_alloc 1237 * 1238 * This function will allocate a idm_task_t structure. A task tag is also 1239 * generated and saved in idt_tt. The task is not active. 1240 */ 1241 idm_task_t * 1242 idm_task_alloc(idm_conn_t *ic) 1243 { 1244 idm_task_t *idt; 1245 1246 ASSERT(ic != NULL); 1247 1248 /* Don't allocate new tasks if we are not in FFP */ 1249 mutex_enter(&ic->ic_state_mutex); 1250 if (!ic->ic_ffp) { 1251 mutex_exit(&ic->ic_state_mutex); 1252 return (NULL); 1253 } 1254 idt = kmem_cache_alloc(idm.idm_task_cache, KM_NOSLEEP); 1255 if (idt == NULL) { 1256 mutex_exit(&ic->ic_state_mutex); 1257 return (NULL); 1258 } 1259 1260 ASSERT(list_is_empty(&idt->idt_inbufv)); 1261 ASSERT(list_is_empty(&idt->idt_outbufv)); 1262 1263 idm_conn_hold(ic); 1264 mutex_exit(&ic->ic_state_mutex); 1265 1266 idt->idt_state = TASK_IDLE; 1267 idt->idt_ic = ic; 1268 idt->idt_private = NULL; 1269 idt->idt_exp_datasn = 0; 1270 idt->idt_exp_rttsn = 0; 1271 1272 return (idt); 1273 } 1274 1275 /* 1276 * idm_task_start 1277 * 1278 * Mark the task active and initialize some stats. The caller 1279 * sets up the idm_task_t structure with a prior call to idm_task_alloc(). 1280 * The task service does not function as a task/work engine, it is the 1281 * responsibility of the initiator to start the data transfer and free the 1282 * resources. 1283 */ 1284 void 1285 idm_task_start(idm_task_t *idt, uintptr_t handle) 1286 { 1287 ASSERT(idt != NULL); 1288 1289 /* mark the task as ACTIVE */ 1290 idt->idt_state = TASK_ACTIVE; 1291 idt->idt_client_handle = handle; 1292 idt->idt_tx_to_ini_start = idt->idt_tx_to_ini_done = 1293 idt->idt_rx_from_ini_start = idt->idt_rx_from_ini_done = 1294 idt->idt_tx_bytes = idt->idt_rx_bytes = 0; 1295 } 1296 1297 /* 1298 * idm_task_done 1299 * 1300 * This function sets the state to indicate that the task is no longer active. 1301 */ 1302 void 1303 idm_task_done(idm_task_t *idt) 1304 { 1305 ASSERT(idt != NULL); 1306 1307 mutex_enter(&idt->idt_mutex); 1308 idt->idt_state = TASK_IDLE; 1309 mutex_exit(&idt->idt_mutex); 1310 1311 /* 1312 * Although unlikely it is possible for a reference to come in after 1313 * the client has decided the task is over but before we've marked 1314 * the task idle. One specific unavoidable scenario is the case where 1315 * received PDU with the matching ITT/TTT results in a successful 1316 * lookup of this task. We are at the mercy of the remote node in 1317 * that case so we need to handle it. Now that the task state 1318 * has changed no more references will occur so a simple call to 1319 * idm_refcnt_wait_ref should deal with the situation. 1320 */ 1321 idm_refcnt_wait_ref(&idt->idt_refcnt); 1322 idm_refcnt_reset(&idt->idt_refcnt); 1323 } 1324 1325 /* 1326 * idm_task_free 1327 * 1328 * This function will free the Task Tag and the memory allocated for the task 1329 * idm_task_done should be called prior to this call 1330 */ 1331 void 1332 idm_task_free(idm_task_t *idt) 1333 { 1334 idm_conn_t *ic; 1335 1336 ASSERT(idt != NULL); 1337 ASSERT(idt->idt_refcnt.ir_refcnt == 0); 1338 ASSERT(idt->idt_state == TASK_IDLE); 1339 1340 ic = idt->idt_ic; 1341 1342 /* 1343 * It's possible for items to still be in the idt_inbufv list if 1344 * they were added after idm_task_cleanup was called. We rely on 1345 * STMF to free all buffers associated with the task however STMF 1346 * doesn't know that we have this reference to the buffers. 1347 * Use list_create so that we don't end up with stale references 1348 * to these buffers. 1349 */ 1350 list_create(&idt->idt_inbufv, sizeof (idm_buf_t), 1351 offsetof(idm_buf_t, idb_buflink)); 1352 list_create(&idt->idt_outbufv, sizeof (idm_buf_t), 1353 offsetof(idm_buf_t, idb_buflink)); 1354 1355 kmem_cache_free(idm.idm_task_cache, idt); 1356 1357 idm_conn_rele(ic); 1358 } 1359 1360 /* 1361 * idm_task_find_common 1362 * common code for idm_task_find() and idm_task_find_and_complete() 1363 */ 1364 /*ARGSUSED*/ 1365 static idm_task_t * 1366 idm_task_find_common(idm_conn_t *ic, uint32_t itt, uint32_t ttt, 1367 boolean_t complete) 1368 { 1369 uint32_t tt, client_handle; 1370 idm_task_t *idt; 1371 1372 /* 1373 * Must match both itt and ttt. The table is indexed by itt 1374 * for initiator connections and ttt for target connections. 1375 */ 1376 if (IDM_CONN_ISTGT(ic)) { 1377 tt = ttt; 1378 client_handle = itt; 1379 } else { 1380 tt = itt; 1381 client_handle = ttt; 1382 } 1383 1384 rw_enter(&idm.idm_taskid_table_lock, RW_READER); 1385 if (tt >= idm.idm_taskid_max) { 1386 rw_exit(&idm.idm_taskid_table_lock); 1387 return (NULL); 1388 } 1389 1390 idt = idm.idm_taskid_table[tt]; 1391 1392 if (idt != NULL) { 1393 mutex_enter(&idt->idt_mutex); 1394 if ((idt->idt_state != TASK_ACTIVE) || 1395 (idt->idt_ic != ic) || 1396 (IDM_CONN_ISTGT(ic) && 1397 (idt->idt_client_handle != client_handle))) { 1398 /* 1399 * Task doesn't match or task is aborting and 1400 * we don't want any more references. 1401 */ 1402 if ((idt->idt_ic != ic) && 1403 (idt->idt_state == TASK_ACTIVE) && 1404 (IDM_CONN_ISINI(ic) || idt->idt_client_handle == 1405 client_handle)) { 1406 IDM_CONN_LOG(CE_WARN, 1407 "idm_task_find: wrong connection %p != %p", 1408 (void *)ic, (void *)idt->idt_ic); 1409 } 1410 mutex_exit(&idt->idt_mutex); 1411 rw_exit(&idm.idm_taskid_table_lock); 1412 return (NULL); 1413 } 1414 idm_task_hold(idt); 1415 /* 1416 * Set the task state to TASK_COMPLETE so it can no longer 1417 * be found or aborted. 1418 */ 1419 if (B_TRUE == complete) 1420 idt->idt_state = TASK_COMPLETE; 1421 mutex_exit(&idt->idt_mutex); 1422 } 1423 rw_exit(&idm.idm_taskid_table_lock); 1424 1425 return (idt); 1426 } 1427 1428 /* 1429 * This function looks up a task by task tag. 1430 */ 1431 idm_task_t * 1432 idm_task_find(idm_conn_t *ic, uint32_t itt, uint32_t ttt) 1433 { 1434 return (idm_task_find_common(ic, itt, ttt, B_FALSE)); 1435 } 1436 1437 /* 1438 * This function looks up a task by task tag. If found, the task state 1439 * is atomically set to TASK_COMPLETE so it can longer be found or aborted. 1440 */ 1441 idm_task_t * 1442 idm_task_find_and_complete(idm_conn_t *ic, uint32_t itt, uint32_t ttt) 1443 { 1444 return (idm_task_find_common(ic, itt, ttt, B_TRUE)); 1445 } 1446 1447 /* 1448 * idm_task_find_by_handle 1449 * 1450 * This function looks up a task by the client-private idt_client_handle. 1451 * 1452 * This function should NEVER be called in the performance path. It is 1453 * intended strictly for error recovery/task management. 1454 */ 1455 /*ARGSUSED*/ 1456 void * 1457 idm_task_find_by_handle(idm_conn_t *ic, uintptr_t handle) 1458 { 1459 idm_task_t *idt = NULL; 1460 int idx = 0; 1461 1462 rw_enter(&idm.idm_taskid_table_lock, RW_READER); 1463 1464 for (idx = 0; idx < idm.idm_taskid_max; idx++) { 1465 idt = idm.idm_taskid_table[idx]; 1466 1467 if (idt == NULL) 1468 continue; 1469 1470 mutex_enter(&idt->idt_mutex); 1471 1472 if (idt->idt_state != TASK_ACTIVE) { 1473 /* 1474 * Task is either in suspend, abort, or already 1475 * complete. 1476 */ 1477 mutex_exit(&idt->idt_mutex); 1478 continue; 1479 } 1480 1481 if (idt->idt_client_handle == handle) { 1482 idm_task_hold(idt); 1483 mutex_exit(&idt->idt_mutex); 1484 break; 1485 } 1486 1487 mutex_exit(&idt->idt_mutex); 1488 } 1489 1490 rw_exit(&idm.idm_taskid_table_lock); 1491 1492 if ((idt == NULL) || (idx == idm.idm_taskid_max)) 1493 return (NULL); 1494 1495 return (idt->idt_private); 1496 } 1497 1498 void 1499 idm_task_hold(idm_task_t *idt) 1500 { 1501 idm_refcnt_hold(&idt->idt_refcnt); 1502 } 1503 1504 void 1505 idm_task_rele(idm_task_t *idt) 1506 { 1507 idm_refcnt_rele(&idt->idt_refcnt); 1508 } 1509 1510 void 1511 idm_task_abort(idm_conn_t *ic, idm_task_t *idt, idm_abort_type_t abort_type) 1512 { 1513 idm_task_t *task; 1514 int idx; 1515 1516 /* 1517 * Passing NULL as the task indicates that all tasks 1518 * for this connection should be aborted. 1519 */ 1520 if (idt == NULL) { 1521 /* 1522 * Only the connection state machine should ask for 1523 * all tasks to abort and this should never happen in FFP. 1524 */ 1525 ASSERT(!ic->ic_ffp); 1526 rw_enter(&idm.idm_taskid_table_lock, RW_READER); 1527 for (idx = 0; idx < idm.idm_taskid_max; idx++) { 1528 task = idm.idm_taskid_table[idx]; 1529 if (task == NULL) 1530 continue; 1531 mutex_enter(&task->idt_mutex); 1532 if ((task->idt_state != TASK_IDLE) && 1533 (task->idt_state != TASK_COMPLETE) && 1534 (task->idt_ic == ic)) { 1535 rw_exit(&idm.idm_taskid_table_lock); 1536 idm_task_abort_one(ic, task, abort_type); 1537 rw_enter(&idm.idm_taskid_table_lock, RW_READER); 1538 } else 1539 mutex_exit(&task->idt_mutex); 1540 } 1541 rw_exit(&idm.idm_taskid_table_lock); 1542 } else { 1543 mutex_enter(&idt->idt_mutex); 1544 idm_task_abort_one(ic, idt, abort_type); 1545 } 1546 } 1547 1548 static void 1549 idm_task_abort_unref_cb(void *ref) 1550 { 1551 idm_task_t *idt = ref; 1552 1553 mutex_enter(&idt->idt_mutex); 1554 switch (idt->idt_state) { 1555 case TASK_SUSPENDING: 1556 idt->idt_state = TASK_SUSPENDED; 1557 mutex_exit(&idt->idt_mutex); 1558 idm_task_aborted(idt, IDM_STATUS_SUSPENDED); 1559 return; 1560 case TASK_ABORTING: 1561 idt->idt_state = TASK_ABORTED; 1562 mutex_exit(&idt->idt_mutex); 1563 idm_task_aborted(idt, IDM_STATUS_ABORTED); 1564 return; 1565 default: 1566 mutex_exit(&idt->idt_mutex); 1567 ASSERT(0); 1568 break; 1569 } 1570 } 1571 1572 /* 1573 * Abort the idm task. 1574 * Caller must hold the task mutex, which will be released before return 1575 */ 1576 static void 1577 idm_task_abort_one(idm_conn_t *ic, idm_task_t *idt, idm_abort_type_t abort_type) 1578 { 1579 /* Caller must hold connection mutex */ 1580 ASSERT(mutex_owned(&idt->idt_mutex)); 1581 switch (idt->idt_state) { 1582 case TASK_ACTIVE: 1583 switch (abort_type) { 1584 case AT_INTERNAL_SUSPEND: 1585 /* Call transport to release any resources */ 1586 idt->idt_state = TASK_SUSPENDING; 1587 mutex_exit(&idt->idt_mutex); 1588 ic->ic_transport_ops->it_free_task_rsrc(idt); 1589 1590 /* 1591 * Wait for outstanding references. When all 1592 * references are released the callback will call 1593 * idm_task_aborted(). 1594 */ 1595 idm_refcnt_async_wait_ref(&idt->idt_refcnt, 1596 &idm_task_abort_unref_cb); 1597 return; 1598 case AT_INTERNAL_ABORT: 1599 case AT_TASK_MGMT_ABORT: 1600 idt->idt_state = TASK_ABORTING; 1601 mutex_exit(&idt->idt_mutex); 1602 ic->ic_transport_ops->it_free_task_rsrc(idt); 1603 1604 /* 1605 * Wait for outstanding references. When all 1606 * references are released the callback will call 1607 * idm_task_aborted(). 1608 */ 1609 idm_refcnt_async_wait_ref(&idt->idt_refcnt, 1610 &idm_task_abort_unref_cb); 1611 return; 1612 default: 1613 ASSERT(0); 1614 } 1615 break; 1616 case TASK_SUSPENDING: 1617 /* Already called transport_free_task_rsrc(); */ 1618 switch (abort_type) { 1619 case AT_INTERNAL_SUSPEND: 1620 /* Already doing it */ 1621 break; 1622 case AT_INTERNAL_ABORT: 1623 case AT_TASK_MGMT_ABORT: 1624 idt->idt_state = TASK_ABORTING; 1625 break; 1626 default: 1627 ASSERT(0); 1628 } 1629 break; 1630 case TASK_SUSPENDED: 1631 /* Already called transport_free_task_rsrc(); */ 1632 switch (abort_type) { 1633 case AT_INTERNAL_SUSPEND: 1634 /* Already doing it */ 1635 break; 1636 case AT_INTERNAL_ABORT: 1637 case AT_TASK_MGMT_ABORT: 1638 idt->idt_state = TASK_ABORTING; 1639 mutex_exit(&idt->idt_mutex); 1640 1641 /* 1642 * We could probably call idm_task_aborted directly 1643 * here but we may be holding the conn lock. It's 1644 * easier to just switch contexts. Even though 1645 * we shouldn't really have any references we'll 1646 * set the state to TASK_ABORTING instead of 1647 * TASK_ABORTED so we can use the same code path. 1648 */ 1649 idm_refcnt_async_wait_ref(&idt->idt_refcnt, 1650 &idm_task_abort_unref_cb); 1651 return; 1652 default: 1653 ASSERT(0); 1654 } 1655 break; 1656 case TASK_ABORTING: 1657 case TASK_ABORTED: 1658 switch (abort_type) { 1659 case AT_INTERNAL_SUSPEND: 1660 /* We're already past this point... */ 1661 case AT_INTERNAL_ABORT: 1662 case AT_TASK_MGMT_ABORT: 1663 /* Already doing it */ 1664 break; 1665 default: 1666 ASSERT(0); 1667 } 1668 break; 1669 case TASK_COMPLETE: 1670 /* 1671 * In this case, let it go. The status has already been 1672 * sent (which may or may not get successfully transmitted) 1673 * and we don't want to end up in a race between completing 1674 * the status PDU and marking the task suspended. 1675 */ 1676 break; 1677 default: 1678 ASSERT(0); 1679 } 1680 mutex_exit(&idt->idt_mutex); 1681 } 1682 1683 static void 1684 idm_task_aborted(idm_task_t *idt, idm_status_t status) 1685 { 1686 (*idt->idt_ic->ic_conn_ops.icb_task_aborted)(idt, status); 1687 } 1688 1689 void 1690 idm_task_cleanup(idm_task_t *idt) 1691 { 1692 idm_buf_t *idb, *next_idb; 1693 list_t tmp_buflist; 1694 ASSERT((idt->idt_state == TASK_SUSPENDED) || 1695 (idt->idt_state == TASK_ABORTED)); 1696 1697 list_create(&tmp_buflist, sizeof (idm_buf_t), 1698 offsetof(idm_buf_t, idb_buflink)); 1699 1700 /* 1701 * Remove all the buffers from the task and add them to a 1702 * temporary local list -- we do this so that we can hold 1703 * the task lock and prevent the task from going away if 1704 * the client decides to call idm_task_done/idm_task_free. 1705 * This could happen during abort in iscsit. 1706 */ 1707 mutex_enter(&idt->idt_mutex); 1708 for (idb = list_head(&idt->idt_inbufv); 1709 idb != NULL; 1710 idb = next_idb) { 1711 next_idb = list_next(&idt->idt_inbufv, idb); 1712 idm_buf_unbind_in_locked(idt, idb); 1713 list_insert_tail(&tmp_buflist, idb); 1714 } 1715 1716 for (idb = list_head(&idt->idt_outbufv); 1717 idb != NULL; 1718 idb = next_idb) { 1719 next_idb = list_next(&idt->idt_outbufv, idb); 1720 idm_buf_unbind_out_locked(idt, idb); 1721 list_insert_tail(&tmp_buflist, idb); 1722 } 1723 mutex_exit(&idt->idt_mutex); 1724 1725 for (idb = list_head(&tmp_buflist); idb != NULL; idb = next_idb) { 1726 next_idb = list_next(&tmp_buflist, idb); 1727 list_remove(&tmp_buflist, idb); 1728 (*idb->idb_buf_cb)(idb, IDM_STATUS_ABORTED); 1729 } 1730 list_destroy(&tmp_buflist); 1731 } 1732 1733 1734 /* 1735 * idm_pdu_tx 1736 * 1737 * This is IDM's implementation of the 'Send_Control' operational primitive. 1738 * This function is invoked by an initiator iSCSI layer requesting the transfer 1739 * of a iSCSI command PDU or a target iSCSI layer requesting the transfer of a 1740 * iSCSI response PDU. The PDU will be transmitted as-is by the local Datamover 1741 * layer to the peer iSCSI layer in the remote iSCSI node. The connection info 1742 * and iSCSI PDU-specific qualifiers namely BHS, AHS, DataDescriptor and Size 1743 * are provided as input. 1744 * 1745 */ 1746 void 1747 idm_pdu_tx(idm_pdu_t *pdu) 1748 { 1749 idm_conn_t *ic = pdu->isp_ic; 1750 iscsi_async_evt_hdr_t *async_evt; 1751 1752 /* 1753 * If we are in full-featured mode then route SCSI-related 1754 * commands to the appropriate function vector without checking 1755 * the connection state. We will only be in full-feature mode 1756 * when we are in an acceptable state for SCSI PDU's. 1757 * 1758 * We also need to ensure that there are no PDU events outstanding 1759 * on the state machine. Any non-SCSI PDU's received in full-feature 1760 * mode will result in PDU events and until these have been handled 1761 * we need to route all PDU's through the state machine as PDU 1762 * events to maintain ordering. 1763 * 1764 * Note that IDM cannot enter FFP mode until it processes in 1765 * its state machine the last xmit of the login process. 1766 * Hence, checking the IDM_PDU_LOGIN_TX flag here would be 1767 * superfluous. 1768 */ 1769 mutex_enter(&ic->ic_state_mutex); 1770 if (ic->ic_ffp && (ic->ic_pdu_events == 0)) { 1771 mutex_exit(&ic->ic_state_mutex); 1772 switch (IDM_PDU_OPCODE(pdu)) { 1773 case ISCSI_OP_SCSI_RSP: 1774 /* Target only */ 1775 idm_pdu_tx_forward(ic, pdu); 1776 return; 1777 case ISCSI_OP_SCSI_TASK_MGT_RSP: 1778 /* Target only */ 1779 idm_pdu_tx_forward(ic, pdu); 1780 return; 1781 case ISCSI_OP_SCSI_DATA_RSP: 1782 /* Target only */ 1783 idm_pdu_tx_forward(ic, pdu); 1784 return; 1785 case ISCSI_OP_RTT_RSP: 1786 /* Target only */ 1787 idm_pdu_tx_forward(ic, pdu); 1788 return; 1789 case ISCSI_OP_NOOP_IN: 1790 /* Target only */ 1791 idm_pdu_tx_forward(ic, pdu); 1792 return; 1793 case ISCSI_OP_TEXT_RSP: 1794 /* Target only */ 1795 idm_pdu_tx_forward(ic, pdu); 1796 return; 1797 case ISCSI_OP_TEXT_CMD: 1798 case ISCSI_OP_NOOP_OUT: 1799 case ISCSI_OP_SCSI_CMD: 1800 case ISCSI_OP_SCSI_DATA: 1801 case ISCSI_OP_SCSI_TASK_MGT_MSG: 1802 /* Initiator only */ 1803 idm_pdu_tx_forward(ic, pdu); 1804 return; 1805 default: 1806 break; 1807 } 1808 1809 mutex_enter(&ic->ic_state_mutex); 1810 } 1811 1812 /* 1813 * Any PDU's processed outside of full-feature mode and non-SCSI 1814 * PDU's in full-feature mode are handled by generating an 1815 * event to the connection state machine. The state machine 1816 * will validate the PDU against the current state and either 1817 * transmit the PDU if the opcode is allowed or handle an 1818 * error if the PDU is not allowed. 1819 * 1820 * This code-path will also generate any events that are implied 1821 * by the PDU opcode. For example a "login response" with success 1822 * status generates a CE_LOGOUT_SUCCESS_SND event. 1823 */ 1824 switch (IDM_PDU_OPCODE(pdu)) { 1825 case ISCSI_OP_LOGIN_CMD: 1826 idm_conn_tx_pdu_event(ic, CE_LOGIN_SND, (uintptr_t)pdu); 1827 break; 1828 case ISCSI_OP_LOGIN_RSP: 1829 idm_parse_login_rsp(ic, pdu, /* Is RX */ B_FALSE); 1830 break; 1831 case ISCSI_OP_LOGOUT_CMD: 1832 idm_parse_logout_req(ic, pdu, /* Is RX */ B_FALSE); 1833 break; 1834 case ISCSI_OP_LOGOUT_RSP: 1835 idm_parse_logout_rsp(ic, pdu, /* Is RX */ B_FALSE); 1836 break; 1837 case ISCSI_OP_ASYNC_EVENT: 1838 async_evt = (iscsi_async_evt_hdr_t *)pdu->isp_hdr; 1839 switch (async_evt->async_event) { 1840 case ISCSI_ASYNC_EVENT_REQUEST_LOGOUT: 1841 idm_conn_tx_pdu_event(ic, CE_ASYNC_LOGOUT_SND, 1842 (uintptr_t)pdu); 1843 break; 1844 case ISCSI_ASYNC_EVENT_DROPPING_CONNECTION: 1845 idm_conn_tx_pdu_event(ic, CE_ASYNC_DROP_CONN_SND, 1846 (uintptr_t)pdu); 1847 break; 1848 case ISCSI_ASYNC_EVENT_DROPPING_ALL_CONNECTIONS: 1849 idm_conn_tx_pdu_event(ic, CE_ASYNC_DROP_ALL_CONN_SND, 1850 (uintptr_t)pdu); 1851 break; 1852 case ISCSI_ASYNC_EVENT_SCSI_EVENT: 1853 case ISCSI_ASYNC_EVENT_PARAM_NEGOTIATION: 1854 default: 1855 idm_conn_tx_pdu_event(ic, CE_MISC_TX, 1856 (uintptr_t)pdu); 1857 break; 1858 } 1859 break; 1860 case ISCSI_OP_SCSI_RSP: 1861 /* Target only */ 1862 idm_conn_tx_pdu_event(ic, CE_MISC_TX, (uintptr_t)pdu); 1863 break; 1864 case ISCSI_OP_SCSI_TASK_MGT_RSP: 1865 /* Target only */ 1866 idm_conn_tx_pdu_event(ic, CE_MISC_TX, (uintptr_t)pdu); 1867 break; 1868 case ISCSI_OP_SCSI_DATA_RSP: 1869 /* Target only */ 1870 idm_conn_tx_pdu_event(ic, CE_MISC_TX, (uintptr_t)pdu); 1871 break; 1872 case ISCSI_OP_RTT_RSP: 1873 /* Target only */ 1874 idm_conn_tx_pdu_event(ic, CE_MISC_TX, (uintptr_t)pdu); 1875 break; 1876 case ISCSI_OP_NOOP_IN: 1877 /* Target only */ 1878 idm_conn_tx_pdu_event(ic, CE_MISC_TX, (uintptr_t)pdu); 1879 break; 1880 case ISCSI_OP_TEXT_RSP: 1881 /* Target only */ 1882 idm_conn_tx_pdu_event(ic, CE_MISC_TX, (uintptr_t)pdu); 1883 break; 1884 /* Initiator only */ 1885 case ISCSI_OP_SCSI_CMD: 1886 case ISCSI_OP_SCSI_TASK_MGT_MSG: 1887 case ISCSI_OP_SCSI_DATA: 1888 case ISCSI_OP_NOOP_OUT: 1889 case ISCSI_OP_TEXT_CMD: 1890 case ISCSI_OP_SNACK_CMD: 1891 case ISCSI_OP_REJECT_MSG: 1892 default: 1893 /* 1894 * Connection state machine will validate these PDU's against 1895 * the current state. A PDU not allowed in the current 1896 * state will cause a protocol error. 1897 */ 1898 idm_conn_tx_pdu_event(ic, CE_MISC_TX, (uintptr_t)pdu); 1899 break; 1900 } 1901 mutex_exit(&ic->ic_state_mutex); 1902 } 1903 1904 /* 1905 * Common allocation of a PDU along with memory for header and data. 1906 */ 1907 static idm_pdu_t * 1908 idm_pdu_alloc_common(uint_t hdrlen, uint_t datalen, int sleepflag) 1909 { 1910 idm_pdu_t *result; 1911 1912 /* 1913 * IDM clients should cache these structures for performance 1914 * critical paths. We can't cache effectively in IDM because we 1915 * don't know the correct header and data size. 1916 * 1917 * Valid header length is assumed to be hdrlen and valid data 1918 * length is assumed to be datalen. isp_hdrlen and isp_datalen 1919 * can be adjusted after the PDU is returned if necessary. 1920 */ 1921 result = kmem_zalloc(sizeof (idm_pdu_t) + hdrlen + datalen, sleepflag); 1922 if (result != NULL) { 1923 /* For idm_pdu_free sanity check */ 1924 result->isp_flags |= IDM_PDU_ALLOC; 1925 /* pointer arithmetic */ 1926 result->isp_hdr = (iscsi_hdr_t *)(result + 1); 1927 result->isp_hdrlen = hdrlen; 1928 result->isp_hdrbuflen = hdrlen; 1929 result->isp_transport_hdrlen = 0; 1930 result->isp_data = (uint8_t *)result->isp_hdr + hdrlen; 1931 result->isp_datalen = datalen; 1932 result->isp_databuflen = datalen; 1933 result->isp_magic = IDM_PDU_MAGIC; 1934 } 1935 1936 return (result); 1937 } 1938 1939 /* 1940 * Typical idm_pdu_alloc invocation, will block for resources. 1941 */ 1942 idm_pdu_t * 1943 idm_pdu_alloc(uint_t hdrlen, uint_t datalen) 1944 { 1945 return (idm_pdu_alloc_common(hdrlen, datalen, KM_SLEEP)); 1946 } 1947 1948 /* 1949 * Non-blocking idm_pdu_alloc implementation, returns NULL if resources 1950 * are not available. Needed for transport-layer allocations which may 1951 * be invoking in interrupt context. 1952 */ 1953 idm_pdu_t * 1954 idm_pdu_alloc_nosleep(uint_t hdrlen, uint_t datalen) 1955 { 1956 return (idm_pdu_alloc_common(hdrlen, datalen, KM_NOSLEEP)); 1957 } 1958 1959 /* 1960 * Free a PDU previously allocated with idm_pdu_alloc() including any 1961 * header and data space allocated as part of the original request. 1962 * Additional memory regions referenced by subsequent modification of 1963 * the isp_hdr and/or isp_data fields will not be freed. 1964 */ 1965 void 1966 idm_pdu_free(idm_pdu_t *pdu) 1967 { 1968 /* Make sure the structure was allocated using idm_pdu_alloc() */ 1969 ASSERT(pdu->isp_flags & IDM_PDU_ALLOC); 1970 kmem_free(pdu, 1971 sizeof (idm_pdu_t) + pdu->isp_hdrbuflen + pdu->isp_databuflen); 1972 } 1973 1974 /* 1975 * Initialize the connection, private and callback fields in a PDU. 1976 */ 1977 void 1978 idm_pdu_init(idm_pdu_t *pdu, idm_conn_t *ic, void *private, idm_pdu_cb_t *cb) 1979 { 1980 /* 1981 * idm_pdu_complete() will call idm_pdu_free if the callback is 1982 * NULL. This will only work if the PDU was originally allocated 1983 * with idm_pdu_alloc(). 1984 */ 1985 ASSERT((pdu->isp_flags & IDM_PDU_ALLOC) || 1986 (cb != NULL)); 1987 pdu->isp_magic = IDM_PDU_MAGIC; 1988 pdu->isp_ic = ic; 1989 pdu->isp_private = private; 1990 pdu->isp_callback = cb; 1991 } 1992 1993 /* 1994 * Initialize the header and header length field. This function should 1995 * not be used to adjust the header length in a buffer allocated via 1996 * pdu_pdu_alloc since it overwrites the existing header pointer. 1997 */ 1998 void 1999 idm_pdu_init_hdr(idm_pdu_t *pdu, uint8_t *hdr, uint_t hdrlen) 2000 { 2001 pdu->isp_hdr = (iscsi_hdr_t *)((void *)hdr); 2002 pdu->isp_hdrlen = hdrlen; 2003 } 2004 2005 /* 2006 * Initialize the data and data length fields. This function should 2007 * not be used to adjust the data length of a buffer allocated via 2008 * idm_pdu_alloc since it overwrites the existing data pointer. 2009 */ 2010 void 2011 idm_pdu_init_data(idm_pdu_t *pdu, uint8_t *data, uint_t datalen) 2012 { 2013 pdu->isp_data = data; 2014 pdu->isp_datalen = datalen; 2015 } 2016 2017 void 2018 idm_pdu_complete(idm_pdu_t *pdu, idm_status_t status) 2019 { 2020 if (pdu->isp_callback) { 2021 pdu->isp_status = status; 2022 (*pdu->isp_callback)(pdu, status); 2023 } else { 2024 idm_pdu_free(pdu); 2025 } 2026 } 2027 2028 /* 2029 * State machine auditing 2030 */ 2031 2032 void 2033 idm_sm_audit_init(sm_audit_buf_t *audit_buf) 2034 { 2035 bzero(audit_buf, sizeof (sm_audit_buf_t)); 2036 audit_buf->sab_max_index = SM_AUDIT_BUF_MAX_REC - 1; 2037 } 2038 2039 static 2040 sm_audit_record_t * 2041 idm_sm_audit_common(sm_audit_buf_t *audit_buf, sm_audit_record_type_t r_type, 2042 sm_audit_sm_type_t sm_type, 2043 int current_state) 2044 { 2045 sm_audit_record_t *sar; 2046 2047 sar = audit_buf->sab_records; 2048 sar += audit_buf->sab_index; 2049 audit_buf->sab_index++; 2050 audit_buf->sab_index &= audit_buf->sab_max_index; 2051 2052 sar->sar_type = r_type; 2053 gethrestime(&sar->sar_timestamp); 2054 sar->sar_sm_type = sm_type; 2055 sar->sar_state = current_state; 2056 2057 return (sar); 2058 } 2059 2060 void 2061 idm_sm_audit_event(sm_audit_buf_t *audit_buf, 2062 sm_audit_sm_type_t sm_type, int current_state, 2063 int event, uintptr_t event_info) 2064 { 2065 sm_audit_record_t *sar; 2066 2067 sar = idm_sm_audit_common(audit_buf, SAR_STATE_EVENT, 2068 sm_type, current_state); 2069 sar->sar_event = event; 2070 sar->sar_event_info = event_info; 2071 } 2072 2073 void 2074 idm_sm_audit_state_change(sm_audit_buf_t *audit_buf, 2075 sm_audit_sm_type_t sm_type, int current_state, int new_state) 2076 { 2077 sm_audit_record_t *sar; 2078 2079 sar = idm_sm_audit_common(audit_buf, SAR_STATE_CHANGE, 2080 sm_type, current_state); 2081 sar->sar_new_state = new_state; 2082 } 2083 2084 2085 /* 2086 * Object reference tracking 2087 */ 2088 2089 void 2090 idm_refcnt_init(idm_refcnt_t *refcnt, void *referenced_obj) 2091 { 2092 bzero(refcnt, sizeof (*refcnt)); 2093 idm_refcnt_reset(refcnt); 2094 refcnt->ir_referenced_obj = referenced_obj; 2095 bzero(&refcnt->ir_audit_buf, sizeof (refcnt_audit_buf_t)); 2096 refcnt->ir_audit_buf.anb_max_index = REFCNT_AUDIT_BUF_MAX_REC - 1; 2097 mutex_init(&refcnt->ir_mutex, NULL, MUTEX_DEFAULT, NULL); 2098 cv_init(&refcnt->ir_cv, NULL, CV_DEFAULT, NULL); 2099 } 2100 2101 void 2102 idm_refcnt_destroy(idm_refcnt_t *refcnt) 2103 { 2104 ASSERT(refcnt->ir_refcnt == 0); 2105 cv_destroy(&refcnt->ir_cv); 2106 mutex_destroy(&refcnt->ir_mutex); 2107 } 2108 2109 void 2110 idm_refcnt_reset(idm_refcnt_t *refcnt) 2111 { 2112 refcnt->ir_waiting = REF_NOWAIT; 2113 refcnt->ir_refcnt = 0; 2114 } 2115 2116 void 2117 idm_refcnt_hold(idm_refcnt_t *refcnt) 2118 { 2119 /* 2120 * Nothing should take a hold on an object after a call to 2121 * idm_refcnt_wait_ref or idm_refcnd_async_wait_ref 2122 */ 2123 ASSERT(refcnt->ir_waiting == REF_NOWAIT); 2124 2125 mutex_enter(&refcnt->ir_mutex); 2126 refcnt->ir_refcnt++; 2127 REFCNT_AUDIT(refcnt); 2128 mutex_exit(&refcnt->ir_mutex); 2129 } 2130 2131 static void 2132 idm_refcnt_unref_task(void *refcnt_void) 2133 { 2134 idm_refcnt_t *refcnt = refcnt_void; 2135 2136 REFCNT_AUDIT(refcnt); 2137 (*refcnt->ir_cb)(refcnt->ir_referenced_obj); 2138 } 2139 2140 void 2141 idm_refcnt_rele(idm_refcnt_t *refcnt) 2142 { 2143 mutex_enter(&refcnt->ir_mutex); 2144 ASSERT(refcnt->ir_refcnt > 0); 2145 refcnt->ir_refcnt--; 2146 REFCNT_AUDIT(refcnt); 2147 if (refcnt->ir_waiting == REF_NOWAIT) { 2148 /* No one is waiting on this object */ 2149 mutex_exit(&refcnt->ir_mutex); 2150 return; 2151 } 2152 2153 /* 2154 * Someone is waiting for this object to go idle so check if 2155 * refcnt is 0. Waiting on an object then later grabbing another 2156 * reference is not allowed so we don't need to handle that case. 2157 */ 2158 if (refcnt->ir_refcnt == 0) { 2159 if (refcnt->ir_waiting == REF_WAIT_ASYNC) { 2160 if (taskq_dispatch(idm.idm_global_taskq, 2161 &idm_refcnt_unref_task, refcnt, TQ_SLEEP) == NULL) { 2162 cmn_err(CE_WARN, 2163 "idm_refcnt_rele: Couldn't dispatch task"); 2164 } 2165 } else if (refcnt->ir_waiting == REF_WAIT_SYNC) { 2166 cv_signal(&refcnt->ir_cv); 2167 } 2168 } 2169 mutex_exit(&refcnt->ir_mutex); 2170 } 2171 2172 void 2173 idm_refcnt_rele_and_destroy(idm_refcnt_t *refcnt, idm_refcnt_cb_t *cb_func) 2174 { 2175 mutex_enter(&refcnt->ir_mutex); 2176 ASSERT(refcnt->ir_refcnt > 0); 2177 refcnt->ir_refcnt--; 2178 REFCNT_AUDIT(refcnt); 2179 2180 /* 2181 * Someone is waiting for this object to go idle so check if 2182 * refcnt is 0. Waiting on an object then later grabbing another 2183 * reference is not allowed so we don't need to handle that case. 2184 */ 2185 if (refcnt->ir_refcnt == 0) { 2186 refcnt->ir_cb = cb_func; 2187 refcnt->ir_waiting = REF_WAIT_ASYNC; 2188 if (taskq_dispatch(idm.idm_global_taskq, 2189 &idm_refcnt_unref_task, refcnt, TQ_SLEEP) == NULL) { 2190 cmn_err(CE_WARN, 2191 "idm_refcnt_rele: Couldn't dispatch task"); 2192 } 2193 } 2194 mutex_exit(&refcnt->ir_mutex); 2195 } 2196 2197 void 2198 idm_refcnt_wait_ref(idm_refcnt_t *refcnt) 2199 { 2200 mutex_enter(&refcnt->ir_mutex); 2201 refcnt->ir_waiting = REF_WAIT_SYNC; 2202 REFCNT_AUDIT(refcnt); 2203 while (refcnt->ir_refcnt != 0) 2204 cv_wait(&refcnt->ir_cv, &refcnt->ir_mutex); 2205 mutex_exit(&refcnt->ir_mutex); 2206 } 2207 2208 void 2209 idm_refcnt_async_wait_ref(idm_refcnt_t *refcnt, idm_refcnt_cb_t *cb_func) 2210 { 2211 mutex_enter(&refcnt->ir_mutex); 2212 refcnt->ir_waiting = REF_WAIT_ASYNC; 2213 refcnt->ir_cb = cb_func; 2214 REFCNT_AUDIT(refcnt); 2215 /* 2216 * It's possible we don't have any references. To make things easier 2217 * on the caller use a taskq to call the callback instead of 2218 * calling it synchronously 2219 */ 2220 if (refcnt->ir_refcnt == 0) { 2221 if (taskq_dispatch(idm.idm_global_taskq, 2222 &idm_refcnt_unref_task, refcnt, TQ_SLEEP) == NULL) { 2223 cmn_err(CE_WARN, 2224 "idm_refcnt_async_wait_ref: " 2225 "Couldn't dispatch task"); 2226 } 2227 } 2228 mutex_exit(&refcnt->ir_mutex); 2229 } 2230 2231 void 2232 idm_refcnt_destroy_unref_obj(idm_refcnt_t *refcnt, 2233 idm_refcnt_cb_t *cb_func) 2234 { 2235 mutex_enter(&refcnt->ir_mutex); 2236 if (refcnt->ir_refcnt == 0) { 2237 mutex_exit(&refcnt->ir_mutex); 2238 (*cb_func)(refcnt->ir_referenced_obj); 2239 return; 2240 } 2241 mutex_exit(&refcnt->ir_mutex); 2242 } 2243 2244 void 2245 idm_conn_hold(idm_conn_t *ic) 2246 { 2247 idm_refcnt_hold(&ic->ic_refcnt); 2248 } 2249 2250 void 2251 idm_conn_rele(idm_conn_t *ic) 2252 { 2253 idm_refcnt_rele(&ic->ic_refcnt); 2254 } 2255 2256 2257 static int 2258 _idm_init(void) 2259 { 2260 /* Initialize the rwlock for the taskid table */ 2261 rw_init(&idm.idm_taskid_table_lock, NULL, RW_DRIVER, NULL); 2262 2263 /* Initialize the global mutex and taskq */ 2264 mutex_init(&idm.idm_global_mutex, NULL, MUTEX_DEFAULT, NULL); 2265 2266 cv_init(&idm.idm_tgt_svc_cv, NULL, CV_DEFAULT, NULL); 2267 cv_init(&idm.idm_wd_cv, NULL, CV_DEFAULT, NULL); 2268 2269 /* 2270 * The maximum allocation needs to be high here since there can be 2271 * many concurrent tasks using the global taskq. 2272 */ 2273 idm.idm_global_taskq = taskq_create("idm_global_taskq", 1, minclsyspri, 2274 128, 16384, TASKQ_PREPOPULATE); 2275 if (idm.idm_global_taskq == NULL) { 2276 cv_destroy(&idm.idm_wd_cv); 2277 cv_destroy(&idm.idm_tgt_svc_cv); 2278 mutex_destroy(&idm.idm_global_mutex); 2279 rw_destroy(&idm.idm_taskid_table_lock); 2280 return (ENOMEM); 2281 } 2282 2283 /* Start watchdog thread */ 2284 idm.idm_wd_thread = thread_create(NULL, 0, 2285 idm_wd_thread, NULL, 0, &p0, TS_RUN, minclsyspri); 2286 if (idm.idm_wd_thread == NULL) { 2287 /* Couldn't create the watchdog thread */ 2288 taskq_destroy(idm.idm_global_taskq); 2289 cv_destroy(&idm.idm_wd_cv); 2290 cv_destroy(&idm.idm_tgt_svc_cv); 2291 mutex_destroy(&idm.idm_global_mutex); 2292 rw_destroy(&idm.idm_taskid_table_lock); 2293 return (ENOMEM); 2294 } 2295 2296 /* Pause until the watchdog thread is running */ 2297 mutex_enter(&idm.idm_global_mutex); 2298 while (!idm.idm_wd_thread_running) 2299 cv_wait(&idm.idm_wd_cv, &idm.idm_global_mutex); 2300 mutex_exit(&idm.idm_global_mutex); 2301 2302 /* 2303 * Allocate the task ID table and set "next" to 0. 2304 */ 2305 2306 idm.idm_taskid_max = idm_max_taskids; 2307 idm.idm_taskid_table = (idm_task_t **) 2308 kmem_zalloc(idm.idm_taskid_max * sizeof (idm_task_t *), KM_SLEEP); 2309 idm.idm_taskid_next = 0; 2310 2311 /* Create the global buffer and task kmem caches */ 2312 idm.idm_buf_cache = kmem_cache_create("idm_buf_cache", 2313 sizeof (idm_buf_t), 8, NULL, NULL, NULL, NULL, NULL, KM_SLEEP); 2314 2315 /* 2316 * Note, we're explicitly allocating an additional iSER header- 2317 * sized chunk for each of these elements. See idm_task_constructor(). 2318 */ 2319 idm.idm_task_cache = kmem_cache_create("idm_task_cache", 2320 sizeof (idm_task_t) + IDM_TRANSPORT_HEADER_LENGTH, 8, 2321 &idm_task_constructor, &idm_task_destructor, 2322 NULL, NULL, NULL, KM_SLEEP); 2323 2324 /* Create the service and connection context lists */ 2325 list_create(&idm.idm_tgt_svc_list, sizeof (idm_svc_t), 2326 offsetof(idm_svc_t, is_list_node)); 2327 list_create(&idm.idm_tgt_conn_list, sizeof (idm_conn_t), 2328 offsetof(idm_conn_t, ic_list_node)); 2329 list_create(&idm.idm_ini_conn_list, sizeof (idm_conn_t), 2330 offsetof(idm_conn_t, ic_list_node)); 2331 2332 /* Initialize the native sockets transport */ 2333 idm_so_init(&idm_transport_list[IDM_TRANSPORT_TYPE_SOCKETS]); 2334 2335 /* Create connection ID pool */ 2336 (void) idm_idpool_create(&idm.idm_conn_id_pool); 2337 2338 return (DDI_SUCCESS); 2339 } 2340 2341 static int 2342 _idm_fini(void) 2343 { 2344 if (!list_is_empty(&idm.idm_ini_conn_list) || 2345 !list_is_empty(&idm.idm_tgt_conn_list) || 2346 !list_is_empty(&idm.idm_tgt_svc_list)) { 2347 return (EBUSY); 2348 } 2349 2350 mutex_enter(&idm.idm_global_mutex); 2351 idm.idm_wd_thread_running = B_FALSE; 2352 cv_signal(&idm.idm_wd_cv); 2353 mutex_exit(&idm.idm_global_mutex); 2354 2355 thread_join(idm.idm_wd_thread_did); 2356 2357 idm_idpool_destroy(&idm.idm_conn_id_pool); 2358 2359 /* Close any LDI handles we have open on transport drivers */ 2360 mutex_enter(&idm.idm_global_mutex); 2361 idm_transport_teardown(); 2362 mutex_exit(&idm.idm_global_mutex); 2363 2364 /* Teardown the native sockets transport */ 2365 idm_so_fini(); 2366 2367 list_destroy(&idm.idm_ini_conn_list); 2368 list_destroy(&idm.idm_tgt_conn_list); 2369 list_destroy(&idm.idm_tgt_svc_list); 2370 kmem_cache_destroy(idm.idm_task_cache); 2371 kmem_cache_destroy(idm.idm_buf_cache); 2372 kmem_free(idm.idm_taskid_table, 2373 idm.idm_taskid_max * sizeof (idm_task_t *)); 2374 mutex_destroy(&idm.idm_global_mutex); 2375 cv_destroy(&idm.idm_wd_cv); 2376 cv_destroy(&idm.idm_tgt_svc_cv); 2377 rw_destroy(&idm.idm_taskid_table_lock); 2378 2379 return (0); 2380 } 2381