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 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/param.h> 28 #include <sys/modctl.h> 29 #include <sys/sysmacros.h> 30 #include <sys/kmem.h> 31 #include <sys/cmn_err.h> 32 #include <sys/ddi.h> 33 #include <sys/sunddi.h> 34 #include <sys/spl.h> 35 #include <sys/time.h> 36 #include <sys/varargs.h> 37 #include <ipp/ipp.h> 38 #include <ipp/ipp_impl.h> 39 #include <ipp/ipgpc/ipgpc.h> 40 41 /* 42 * Debug switch. 43 */ 44 45 #if defined(DEBUG) 46 #define IPP_DBG 47 #endif 48 49 /* 50 * Globals 51 */ 52 53 /* 54 * ipp_action_count is not static because it is imported by inet/ipp_common.h 55 */ 56 uint32_t ipp_action_count = 0; 57 58 static kmem_cache_t *ipp_mod_cache = NULL; 59 static uint32_t ipp_mod_count = 0; 60 static uint32_t ipp_max_mod = IPP_NMOD; 61 static ipp_mod_t **ipp_mod_byid; 62 static krwlock_t ipp_mod_byid_lock[1]; 63 64 static ipp_mod_id_t ipp_next_mid = IPP_MOD_RESERVED + 1; 65 static ipp_mod_id_t ipp_mid_limit; 66 67 static ipp_ref_t *ipp_mod_byname[IPP_NBUCKET]; 68 static krwlock_t ipp_mod_byname_lock[1]; 69 70 static kmem_cache_t *ipp_action_cache = NULL; 71 static uint32_t ipp_max_action = IPP_NACTION; 72 static ipp_action_t **ipp_action_byid; 73 static krwlock_t ipp_action_byid_lock[1]; 74 75 static ipp_action_id_t ipp_next_aid = IPP_ACTION_RESERVED + 1; 76 static ipp_action_id_t ipp_aid_limit; 77 78 static ipp_ref_t *ipp_action_byname[IPP_NBUCKET]; 79 static krwlock_t ipp_action_byname_lock[1]; 80 static ipp_ref_t *ipp_action_noname; 81 82 static kmem_cache_t *ipp_packet_cache = NULL; 83 static uint_t ipp_packet_classes = IPP_NCLASS; 84 static uint_t ipp_packet_logging = 0; 85 static uint_t ipp_packet_log_entries = IPP_NLOG; 86 87 /* 88 * Prototypes 89 */ 90 91 void ipp_init(void); 92 93 int ipp_list_mods(ipp_mod_id_t **, int *); 94 95 ipp_mod_id_t ipp_mod_lookup(const char *); 96 int ipp_mod_name(ipp_mod_id_t, char **); 97 int ipp_mod_register(const char *, ipp_ops_t *); 98 int ipp_mod_unregister(ipp_mod_id_t); 99 int ipp_mod_list_actions(ipp_mod_id_t, ipp_action_id_t **, 100 int *); 101 102 ipp_action_id_t ipp_action_lookup(const char *); 103 int ipp_action_name(ipp_action_id_t, char **); 104 int ipp_action_mod(ipp_action_id_t, ipp_mod_id_t *); 105 int ipp_action_create(ipp_mod_id_t, const char *, 106 nvlist_t **, ipp_flags_t, ipp_action_id_t *); 107 int ipp_action_modify(ipp_action_id_t, nvlist_t **, 108 ipp_flags_t); 109 int ipp_action_destroy(ipp_action_id_t, ipp_flags_t); 110 int ipp_action_info(ipp_action_id_t, int (*)(nvlist_t *, 111 void *), void *, ipp_flags_t); 112 void ipp_action_set_ptr(ipp_action_id_t, void *); 113 void *ipp_action_get_ptr(ipp_action_id_t); 114 int ipp_action_ref(ipp_action_id_t, ipp_action_id_t, 115 ipp_flags_t); 116 int ipp_action_unref(ipp_action_id_t, ipp_action_id_t, 117 ipp_flags_t); 118 119 int ipp_packet_alloc(ipp_packet_t **, const char *, 120 ipp_action_id_t); 121 void ipp_packet_free(ipp_packet_t *); 122 int ipp_packet_add_class(ipp_packet_t *, const char *, 123 ipp_action_id_t); 124 int ipp_packet_process(ipp_packet_t **); 125 int ipp_packet_next(ipp_packet_t *, ipp_action_id_t); 126 void ipp_packet_set_data(ipp_packet_t *, mblk_t *); 127 mblk_t *ipp_packet_get_data(ipp_packet_t *); 128 void ipp_packet_set_private(ipp_packet_t *, void *, 129 void (*)(void *)); 130 void *ipp_packet_get_private(ipp_packet_t *); 131 132 int ipp_stat_create(ipp_action_id_t, const char *, int, 133 int (*)(ipp_stat_t *, void *, int), void *, ipp_stat_t **); 134 void ipp_stat_install(ipp_stat_t *); 135 void ipp_stat_destroy(ipp_stat_t *); 136 int ipp_stat_named_init(ipp_stat_t *, const char *, uchar_t, 137 ipp_named_t *); 138 int ipp_stat_named_op(ipp_named_t *, void *, int); 139 140 static int ref_mod(ipp_action_t *, ipp_mod_t *); 141 static void unref_mod(ipp_action_t *, ipp_mod_t *); 142 static int is_mod_busy(ipp_mod_t *); 143 static int get_mod_ref(ipp_mod_t *, ipp_action_id_t **, int *); 144 static int get_mods(ipp_mod_id_t **bufp, int *); 145 static ipp_mod_id_t find_mod(const char *); 146 static int alloc_mod(const char *, ipp_mod_id_t *); 147 static void free_mod(ipp_mod_t *); 148 static ipp_mod_t *hold_mod(ipp_mod_id_t); 149 static void rele_mod(ipp_mod_t *); 150 static ipp_mod_id_t get_mid(void); 151 152 static int condemn_action(ipp_ref_t **, ipp_action_t *); 153 static int destroy_action(ipp_action_t *, ipp_flags_t); 154 static int ref_action(ipp_action_t *, ipp_action_t *); 155 static int unref_action(ipp_action_t *, ipp_action_t *); 156 static int is_action_refd(ipp_action_t *); 157 static ipp_action_id_t find_action(const char *); 158 static int alloc_action(const char *, ipp_action_id_t *); 159 static void free_action(ipp_action_t *); 160 static ipp_action_t *hold_action(ipp_action_id_t); 161 static void rele_action(ipp_action_t *); 162 static ipp_action_id_t get_aid(void); 163 164 static int alloc_packet(const char *, ipp_action_id_t, 165 ipp_packet_t **); 166 static int realloc_packet(ipp_packet_t *); 167 static void free_packet(ipp_packet_t *); 168 169 static int hash(const char *); 170 static int update_stats(kstat_t *, int); 171 static void init_mods(void); 172 static void init_actions(void); 173 static void init_packets(void); 174 static int mod_constructor(void *, void *, int); 175 static void mod_destructor(void *, void *); 176 static int action_constructor(void *, void *, int); 177 static void action_destructor(void *, void *); 178 static int packet_constructor(void *, void *, int); 179 static void packet_destructor(void *, void *); 180 181 /* 182 * Debug message macros 183 */ 184 185 #ifdef IPP_DBG 186 187 #define DBG_MOD 0x00000001ull 188 #define DBG_ACTION 0x00000002ull 189 #define DBG_PACKET 0x00000004ull 190 #define DBG_STATS 0x00000008ull 191 #define DBG_LIST 0x00000010ull 192 193 static uint64_t ipp_debug_flags = 194 /* 195 * DBG_PACKET | 196 * DBG_STATS | 197 * DBG_LIST | 198 * DBG_MOD | 199 * DBG_ACTION | 200 */ 201 0; 202 203 static kmutex_t debug_mutex[1]; 204 205 /*PRINTFLIKE3*/ 206 static void ipp_debug(uint64_t, const char *, char *, ...) 207 __KPRINTFLIKE(3); 208 209 #define DBG0(_type, _fmt) \ 210 ipp_debug((_type), __FN__, (_fmt)); 211 212 #define DBG1(_type, _fmt, _a1) \ 213 ipp_debug((_type), __FN__, (_fmt), (_a1)); 214 215 #define DBG2(_type, _fmt, _a1, _a2) \ 216 ipp_debug((_type), __FN__, (_fmt), (_a1), (_a2)); 217 218 #define DBG3(_type, _fmt, _a1, _a2, _a3) \ 219 ipp_debug((_type), __FN__, (_fmt), (_a1), (_a2), \ 220 (_a3)); 221 222 #define DBG4(_type, _fmt, _a1, _a2, _a3, _a4) \ 223 ipp_debug((_type), __FN__, (_fmt), (_a1), (_a2), \ 224 (_a3), (_a4)); 225 226 #define DBG5(_type, _fmt, _a1, _a2, _a3, _a4, _a5) \ 227 ipp_debug((_type), __FN__, (_fmt), (_a1), (_a2), \ 228 (_a3), (_a4), (_a5)); 229 230 #else /* IPP_DBG */ 231 232 #define DBG0(_type, _fmt) 233 #define DBG1(_type, _fmt, _a1) 234 #define DBG2(_type, _fmt, _a1, _a2) 235 #define DBG3(_type, _fmt, _a1, _a2, _a3) 236 #define DBG4(_type, _fmt, _a1, _a2, _a3, _a4) 237 #define DBG5(_type, _fmt, _a1, _a2, _a3, _a4, _a5) 238 239 #endif /* IPP_DBG */ 240 241 /* 242 * Lock macros 243 */ 244 245 #define LOCK_MOD(_imp, _rw) \ 246 rw_enter((_imp)->ippm_lock, (_rw)) 247 #define UNLOCK_MOD(_imp) \ 248 rw_exit((_imp)->ippm_lock) 249 250 #define LOCK_ACTION(_ap, _rw) \ 251 rw_enter((_ap)->ippa_lock, (_rw)) 252 #define UNLOCK_ACTION(_imp) \ 253 rw_exit((_imp)->ippa_lock) 254 255 #define CONFIG_WRITE_START(_ap) \ 256 CONFIG_LOCK_ENTER((_ap)->ippa_config_lock, CL_WRITE) 257 258 #define CONFIG_WRITE_END(_ap) \ 259 CONFIG_LOCK_EXIT((_ap)->ippa_config_lock) 260 261 #define CONFIG_READ_START(_ap) \ 262 CONFIG_LOCK_ENTER((_ap)->ippa_config_lock, CL_READ) 263 264 #define CONFIG_READ_END(_ap) \ 265 CONFIG_LOCK_EXIT((_ap)->ippa_config_lock) 266 267 /* 268 * Exported functions 269 */ 270 271 #define __FN__ "ipp_init" 272 void 273 ipp_init( 274 void) 275 { 276 #ifdef IPP_DBG 277 mutex_init(debug_mutex, NULL, MUTEX_ADAPTIVE, 278 (void *)ipltospl(LOCK_LEVEL)); 279 #endif /* IPP_DBG */ 280 281 /* 282 * Initialize module and action structure caches and associated locks. 283 */ 284 285 init_mods(); 286 init_actions(); 287 init_packets(); 288 } 289 #undef __FN__ 290 291 #define __FN__ "ipp_list_mods" 292 int 293 ipp_list_mods( 294 ipp_mod_id_t **bufp, 295 int *neltp) 296 { 297 ASSERT(bufp != NULL); 298 ASSERT(neltp != NULL); 299 300 return (get_mods(bufp, neltp)); 301 } 302 #undef __FN__ 303 304 /* 305 * Module manipulation interface. 306 */ 307 308 #define __FN__ "ipp_mod_lookup" 309 ipp_mod_id_t 310 ipp_mod_lookup( 311 const char *modname) 312 { 313 ipp_mod_id_t mid; 314 #define FIRST_TIME 0 315 int try = FIRST_TIME; 316 317 /* 318 * Sanity check the module name. 319 */ 320 321 if (modname == NULL || strlen(modname) > MAXNAMELEN - 1) 322 return (IPP_MOD_INVAL); 323 324 try_again: 325 if ((mid = find_mod(modname)) == IPP_MOD_INVAL) { 326 327 /* 328 * Module not installed. 329 */ 330 331 if (try++ == FIRST_TIME) { 332 333 /* 334 * This is the first attempt to find the module so 335 * try to 'demand load' it. 336 */ 337 338 DBG1(DBG_MOD, "loading module '%s'\n", modname); 339 (void) modload("ipp", (char *)modname); 340 goto try_again; 341 } 342 } 343 344 return (mid); 345 346 #undef FIRST_TIME 347 } 348 #undef __FN__ 349 350 #define __FN__ "ipp_mod_name" 351 int 352 ipp_mod_name( 353 ipp_mod_id_t mid, 354 char **modnamep) 355 { 356 ipp_mod_t *imp; 357 char *modname; 358 char *buf; 359 360 ASSERT(modnamep != NULL); 361 362 /* 363 * Translate the module id into the module pointer. 364 */ 365 366 if ((imp = hold_mod(mid)) == NULL) 367 return (ENOENT); 368 369 LOCK_MOD(imp, RW_READER); 370 modname = imp->ippm_name; 371 372 /* 373 * Allocate a buffer to pass back to the caller. 374 */ 375 376 if ((buf = kmem_zalloc(strlen(modname) + 1, KM_NOSLEEP)) == NULL) { 377 UNLOCK_MOD(imp); 378 rele_mod(imp); 379 return (ENOMEM); 380 } 381 382 /* 383 * Copy the module name into the buffer. 384 */ 385 386 (void) strcpy(buf, modname); 387 UNLOCK_MOD(imp); 388 389 *modnamep = buf; 390 391 rele_mod(imp); 392 return (0); 393 } 394 #undef __FN__ 395 396 #define __FN__ "ipp_mod_register" 397 int 398 ipp_mod_register( 399 const char *modname, 400 ipp_ops_t *ipp_ops) 401 { 402 ipp_mod_id_t mid; 403 ipp_mod_t *imp; 404 int rc; 405 406 ASSERT(ipp_ops != NULL); 407 408 /* 409 * Sanity check the module name. 410 */ 411 412 if (modname == NULL || strlen(modname) > MAXNAMELEN - 1) 413 return (EINVAL); 414 415 /* 416 * Allocate a module structure. 417 */ 418 419 if ((rc = alloc_mod(modname, &mid)) != 0) 420 return (rc); 421 422 imp = hold_mod(mid); 423 ASSERT(imp != NULL); 424 425 /* 426 * Make module available for use. 427 */ 428 429 LOCK_MOD(imp, RW_WRITER); 430 DBG1(DBG_MOD, "registering module '%s'\n", imp->ippm_name); 431 imp->ippm_ops = ipp_ops; 432 imp->ippm_state = IPP_MODSTATE_AVAILABLE; 433 UNLOCK_MOD(imp); 434 435 rele_mod(imp); 436 return (0); 437 } 438 #undef __FN__ 439 440 #define __FN__ "ipp_mod_unregister" 441 int 442 ipp_mod_unregister( 443 ipp_mod_id_t mid) 444 { 445 ipp_mod_t *imp; 446 447 /* 448 * Translate the module id into the module pointer. 449 */ 450 451 if ((imp = hold_mod(mid)) == NULL) 452 return (ENOENT); 453 454 LOCK_MOD(imp, RW_WRITER); 455 ASSERT(imp->ippm_state == IPP_MODSTATE_AVAILABLE); 456 457 /* 458 * Check to see if there are any actions that reference the module. 459 */ 460 461 if (is_mod_busy(imp)) { 462 UNLOCK_MOD(imp); 463 rele_mod(imp); 464 return (EBUSY); 465 } 466 467 /* 468 * Prevent further use of the module. 469 */ 470 471 DBG1(DBG_MOD, "unregistering module '%s'\n", imp->ippm_name); 472 imp->ippm_state = IPP_MODSTATE_PROTO; 473 imp->ippm_ops = NULL; 474 UNLOCK_MOD(imp); 475 476 /* 477 * Free the module structure. 478 */ 479 480 free_mod(imp); 481 rele_mod(imp); 482 483 return (0); 484 } 485 #undef __FN__ 486 487 #define __FN__ "ipp_mod_list_actions" 488 int 489 ipp_mod_list_actions( 490 ipp_mod_id_t mid, 491 ipp_action_id_t **bufp, 492 int *neltp) 493 { 494 ipp_mod_t *imp; 495 int rc; 496 497 ASSERT(bufp != NULL); 498 ASSERT(neltp != NULL); 499 500 /* 501 * Translate the module id into the module pointer. 502 */ 503 504 if ((imp = hold_mod(mid)) == NULL) 505 return (ENOENT); 506 507 /* 508 * Get the list of actions referencing the module. 509 */ 510 511 LOCK_MOD(imp, RW_READER); 512 rc = get_mod_ref(imp, bufp, neltp); 513 UNLOCK_MOD(imp); 514 515 rele_mod(imp); 516 return (rc); 517 } 518 #undef __FN__ 519 520 /* 521 * Action manipulation interface. 522 */ 523 524 #define __FN__ "ipp_action_lookup" 525 ipp_action_id_t 526 ipp_action_lookup( 527 const char *aname) 528 { 529 if (aname == NULL) 530 return (IPP_ACTION_INVAL); 531 532 /* 533 * Check for special case 'virtual action' names. 534 */ 535 536 if (strcmp(aname, IPP_ANAME_CONT) == 0) 537 return (IPP_ACTION_CONT); 538 else if (strcmp(aname, IPP_ANAME_DEFER) == 0) 539 return (IPP_ACTION_DEFER); 540 else if (strcmp(aname, IPP_ANAME_DROP) == 0) 541 return (IPP_ACTION_DROP); 542 543 /* 544 * Now check real actions. 545 */ 546 547 return (find_action(aname)); 548 } 549 #undef __FN__ 550 551 #define __FN__ "ipp_action_name" 552 int 553 ipp_action_name( 554 ipp_action_id_t aid, 555 char **anamep) 556 { 557 ipp_action_t *ap; 558 char *aname; 559 char *buf; 560 int rc; 561 562 ASSERT(anamep != NULL); 563 564 /* 565 * Check for special case 'virtual action' ids. 566 */ 567 568 switch (aid) { 569 case IPP_ACTION_CONT: 570 ap = NULL; 571 aname = IPP_ANAME_CONT; 572 break; 573 case IPP_ACTION_DEFER: 574 ap = NULL; 575 aname = IPP_ANAME_DEFER; 576 break; 577 case IPP_ACTION_DROP: 578 ap = NULL; 579 aname = IPP_ANAME_DROP; 580 break; 581 default: 582 583 /* 584 * Not a special case. Check for a real action. 585 */ 586 587 if ((ap = hold_action(aid)) == NULL) 588 return (ENOENT); 589 590 LOCK_ACTION(ap, RW_READER); 591 aname = ap->ippa_name; 592 break; 593 } 594 595 /* 596 * Allocate a buffer to pass back to the caller. 597 */ 598 599 if ((buf = kmem_zalloc(strlen(aname) + 1, KM_NOSLEEP)) == NULL) { 600 rc = ENOMEM; 601 goto done; 602 } 603 604 /* 605 * Copy the action name into the buffer. 606 */ 607 608 (void) strcpy(buf, aname); 609 *anamep = buf; 610 rc = 0; 611 done: 612 /* 613 * Unlock the action if necessary (i.e. it wasn't a virtual action). 614 */ 615 616 if (ap != NULL) { 617 UNLOCK_ACTION(ap); 618 rele_action(ap); 619 } 620 621 return (rc); 622 } 623 #undef __FN__ 624 625 #define __FN__ "ipp_action_mod" 626 int 627 ipp_action_mod( 628 ipp_action_id_t aid, 629 ipp_mod_id_t *midp) 630 { 631 ipp_action_t *ap; 632 ipp_mod_t *imp; 633 634 ASSERT(midp != NULL); 635 636 /* 637 * Return an error for 'virtual action' ids. 638 */ 639 640 switch (aid) { 641 case IPP_ACTION_CONT: 642 /*FALLTHRU*/ 643 case IPP_ACTION_DEFER: 644 /*FALLTHRU*/ 645 case IPP_ACTION_DROP: 646 return (EINVAL); 647 default: 648 break; 649 } 650 651 /* 652 * This is a real action. 653 */ 654 655 if ((ap = hold_action(aid)) == NULL) 656 return (ENOENT); 657 658 /* 659 * Check that the action is not in prototype state. 660 */ 661 662 LOCK_ACTION(ap, RW_READER); 663 if (ap->ippa_state == IPP_ASTATE_PROTO) { 664 UNLOCK_ACTION(ap); 665 rele_action(ap); 666 return (ENOENT); 667 } 668 669 imp = ap->ippa_mod; 670 ASSERT(imp != NULL); 671 UNLOCK_ACTION(ap); 672 673 *midp = imp->ippm_id; 674 675 rele_action(ap); 676 return (0); 677 } 678 #undef __FN__ 679 680 #define __FN__ "ipp_action_create" 681 int 682 ipp_action_create( 683 ipp_mod_id_t mid, 684 const char *aname, 685 nvlist_t **nvlpp, 686 ipp_flags_t flags, 687 ipp_action_id_t *aidp) 688 { 689 ipp_ops_t *ippo; 690 ipp_mod_t *imp; 691 ipp_action_id_t aid; 692 ipp_action_t *ap; 693 int rc; 694 695 ASSERT(nvlpp != NULL); 696 ASSERT(*nvlpp != NULL); 697 698 /* 699 * Sanity check the action name (NULL means the framework chooses the 700 * name). 701 */ 702 703 if (aname != NULL && strlen(aname) > MAXNAMELEN - 1) 704 return (EINVAL); 705 706 /* 707 * Translate the module id into the module pointer. 708 */ 709 710 if ((imp = hold_mod(mid)) == NULL) 711 return (ENOENT); 712 713 /* 714 * Allocate an action. 715 */ 716 717 if ((rc = alloc_action(aname, &aid)) != 0) { 718 rele_mod(imp); 719 return (rc); 720 } 721 722 ap = hold_action(aid); 723 ASSERT(ap != NULL); 724 725 /* 726 * Note that the action is in the process of creation/destruction. 727 */ 728 729 LOCK_ACTION(ap, RW_WRITER); 730 ap->ippa_state = IPP_ASTATE_CONFIG_PENDING; 731 732 /* 733 * Reference the module for which the action is being created. 734 */ 735 736 LOCK_MOD(imp, RW_WRITER); 737 if ((rc = ref_mod(ap, imp)) != 0) { 738 UNLOCK_MOD(imp); 739 ap->ippa_state = IPP_ASTATE_PROTO; 740 UNLOCK_ACTION(ap); 741 742 free_action(ap); 743 rele_action(ap); 744 rele_mod(imp); 745 return (rc); 746 } 747 748 UNLOCK_ACTION(ap); 749 750 ippo = imp->ippm_ops; 751 ASSERT(ippo != NULL); 752 UNLOCK_MOD(imp); 753 754 /* 755 * Call into the module to create the action context. 756 */ 757 758 CONFIG_WRITE_START(ap); 759 DBG2(DBG_ACTION, "creating action '%s' in module '%s'\n", 760 ap->ippa_name, imp->ippm_name); 761 if ((rc = ippo->ippo_action_create(ap->ippa_id, nvlpp, flags)) != 0) { 762 LOCK_ACTION(ap, RW_WRITER); 763 LOCK_MOD(imp, RW_WRITER); 764 unref_mod(ap, imp); 765 UNLOCK_MOD(imp); 766 ap->ippa_state = IPP_ASTATE_PROTO; 767 UNLOCK_ACTION(ap); 768 769 CONFIG_WRITE_END(ap); 770 771 free_action(ap); 772 rele_action(ap); 773 rele_mod(imp); 774 return (rc); 775 } 776 CONFIG_WRITE_END(ap); 777 778 /* 779 * Make the action available for use. 780 */ 781 782 LOCK_ACTION(ap, RW_WRITER); 783 ap->ippa_state = IPP_ASTATE_AVAILABLE; 784 if (aidp != NULL) 785 *aidp = ap->ippa_id; 786 UNLOCK_ACTION(ap); 787 788 rele_action(ap); 789 rele_mod(imp); 790 return (0); 791 } 792 #undef __FN__ 793 794 #define __FN__ "ipp_action_destroy" 795 int 796 ipp_action_destroy( 797 ipp_action_id_t aid, 798 ipp_flags_t flags) 799 { 800 ipp_ref_t *rp = NULL; 801 ipp_ref_t *tmp; 802 ipp_action_t *ap; 803 int rc; 804 805 /* 806 * Translate the action id into the action pointer. 807 */ 808 809 if ((ap = hold_action(aid)) == NULL) 810 return (ENOENT); 811 812 /* 813 * Set the condemned action list pointer and destroy the action. 814 */ 815 816 ap->ippa_condemned = &rp; 817 if ((rc = destroy_action(ap, flags)) == 0) { 818 819 /* 820 * Destroy any other actions condemned by the destruction of 821 * the first action. 822 */ 823 824 for (tmp = rp; tmp != NULL; tmp = tmp->ippr_nextp) { 825 ap = tmp->ippr_action; 826 ap->ippa_condemned = &rp; 827 (void) destroy_action(ap, flags); 828 } 829 } else { 830 831 /* 832 * Unreference any condemned actions since the destruction of 833 * the first action failed. 834 */ 835 836 for (tmp = rp; tmp != NULL; tmp = tmp->ippr_nextp) { 837 ap = tmp->ippr_action; 838 rele_action(ap); 839 } 840 } 841 842 /* 843 * Clean up the condemned list. 844 */ 845 846 while (rp != NULL) { 847 tmp = rp; 848 rp = rp->ippr_nextp; 849 kmem_free(tmp, sizeof (ipp_ref_t)); 850 } 851 852 return (rc); 853 } 854 #undef __FN__ 855 856 #define __FN__ "ipp_action_modify" 857 int 858 ipp_action_modify( 859 ipp_action_id_t aid, 860 nvlist_t **nvlpp, 861 ipp_flags_t flags) 862 { 863 ipp_action_t *ap; 864 ipp_ops_t *ippo; 865 ipp_mod_t *imp; 866 int rc; 867 868 ASSERT(nvlpp != NULL); 869 ASSERT(*nvlpp != NULL); 870 871 /* 872 * Translate the action id into the action pointer. 873 */ 874 875 if ((ap = hold_action(aid)) == NULL) 876 return (ENOENT); 877 878 /* 879 * Check that the action is either available for use or is in the 880 * process of creation/destruction. 881 * 882 * NOTE: It is up to the module to lock multiple configuration 883 * operations against each other if necessary. 884 */ 885 886 LOCK_ACTION(ap, RW_READER); 887 if (ap->ippa_state != IPP_ASTATE_AVAILABLE && 888 ap->ippa_state != IPP_ASTATE_CONFIG_PENDING) { 889 UNLOCK_ACTION(ap); 890 rele_action(ap); 891 return (EPROTO); 892 } 893 894 imp = ap->ippa_mod; 895 ASSERT(imp != NULL); 896 UNLOCK_ACTION(ap); 897 898 ippo = imp->ippm_ops; 899 ASSERT(ippo != NULL); 900 901 /* 902 * Call into the module to modify the action context. 903 */ 904 905 DBG1(DBG_ACTION, "modifying action '%s'\n", ap->ippa_name); 906 CONFIG_WRITE_START(ap); 907 rc = ippo->ippo_action_modify(aid, nvlpp, flags); 908 CONFIG_WRITE_END(ap); 909 910 rele_action(ap); 911 return (rc); 912 } 913 #undef __FN__ 914 915 #define __FN__ "ipp_action_info" 916 int 917 ipp_action_info( 918 ipp_action_id_t aid, 919 int (*fn)(nvlist_t *, void *), 920 void *arg, 921 ipp_flags_t flags) 922 { 923 ipp_action_t *ap; 924 ipp_mod_t *imp; 925 ipp_ops_t *ippo; 926 int rc; 927 928 /* 929 * Translate the action id into the action pointer. 930 */ 931 932 if ((ap = hold_action(aid)) == NULL) 933 return (ENOENT); 934 935 /* 936 * Check that the action is available for use. We don't want to 937 * read back parameters while the action is in the process of 938 * creation/destruction. 939 */ 940 941 LOCK_ACTION(ap, RW_READER); 942 if (ap->ippa_state != IPP_ASTATE_AVAILABLE) { 943 UNLOCK_ACTION(ap); 944 rele_action(ap); 945 return (EPROTO); 946 } 947 948 imp = ap->ippa_mod; 949 ASSERT(imp != NULL); 950 UNLOCK_ACTION(ap); 951 952 ippo = imp->ippm_ops; 953 ASSERT(ippo != NULL); 954 955 /* 956 * Call into the module to get the action configuration information. 957 */ 958 959 DBG1(DBG_ACTION, 960 "getting configuration information from action '%s'\n", 961 ap->ippa_name); 962 CONFIG_READ_START(ap); 963 if ((rc = ippo->ippo_action_info(aid, fn, arg, flags)) != 0) { 964 CONFIG_READ_END(ap); 965 rele_action(ap); 966 return (rc); 967 } 968 CONFIG_READ_END(ap); 969 970 rele_action(ap); 971 return (0); 972 } 973 #undef __FN__ 974 975 #define __FN__ "ipp_action_set_ptr" 976 void 977 ipp_action_set_ptr( 978 ipp_action_id_t aid, 979 void *ptr) 980 { 981 ipp_action_t *ap; 982 983 /* 984 * Translate the action id into the action pointer. 985 */ 986 987 ap = hold_action(aid); 988 ASSERT(ap != NULL); 989 990 /* 991 * Set the private data pointer. 992 */ 993 994 ap->ippa_ptr = ptr; 995 rele_action(ap); 996 } 997 #undef __FN__ 998 999 #define __FN__ "ipp_action_get_ptr" 1000 void * 1001 ipp_action_get_ptr( 1002 ipp_action_id_t aid) 1003 { 1004 ipp_action_t *ap; 1005 void *ptr; 1006 1007 /* 1008 * Translate the action id into the action pointer. 1009 */ 1010 1011 ap = hold_action(aid); 1012 ASSERT(ap != NULL); 1013 1014 /* 1015 * Return the private data pointer. 1016 */ 1017 1018 ptr = ap->ippa_ptr; 1019 rele_action(ap); 1020 1021 return (ptr); 1022 } 1023 #undef __FN__ 1024 1025 #define __FN__ "ipp_action_ref" 1026 /*ARGSUSED*/ 1027 int 1028 ipp_action_ref( 1029 ipp_action_id_t aid, 1030 ipp_action_id_t ref_aid, 1031 ipp_flags_t flags) 1032 { 1033 ipp_action_t *ap; 1034 ipp_action_t *ref_ap; 1035 int rc; 1036 1037 /* 1038 * Actions are not allowed to reference themselves. 1039 */ 1040 1041 if (aid == ref_aid) 1042 return (EINVAL); 1043 1044 /* 1045 * Check for a special case 'virtual action' id. 1046 */ 1047 1048 switch (ref_aid) { 1049 case IPP_ACTION_CONT: 1050 /*FALLTHRU*/ 1051 case IPP_ACTION_DEFER: 1052 /*FALLTHRU*/ 1053 case IPP_ACTION_DROP: 1054 return (0); 1055 default: 1056 break; 1057 } 1058 1059 /* 1060 * Translate the action ids into action pointers. 1061 */ 1062 1063 if ((ap = hold_action(aid)) == NULL) 1064 return (ENOENT); 1065 1066 if ((ref_ap = hold_action(ref_aid)) == NULL) { 1067 rele_action(ap); 1068 return (ENOENT); 1069 } 1070 1071 LOCK_ACTION(ap, RW_WRITER); 1072 LOCK_ACTION(ref_ap, RW_WRITER); 1073 1074 if (ref_ap->ippa_state != IPP_ASTATE_AVAILABLE) { 1075 UNLOCK_ACTION(ref_ap); 1076 UNLOCK_ACTION(ap); 1077 1078 rele_action(ref_ap); 1079 rele_action(ap); 1080 return (EPROTO); 1081 } 1082 1083 /* 1084 * Create references between the two actions. 1085 */ 1086 1087 rc = ref_action(ap, ref_ap); 1088 UNLOCK_ACTION(ref_ap); 1089 UNLOCK_ACTION(ap); 1090 1091 rele_action(ref_ap); 1092 rele_action(ap); 1093 return (rc); 1094 } 1095 #undef __FN__ 1096 1097 #define __FN__ "ipp_action_unref" 1098 int 1099 ipp_action_unref( 1100 ipp_action_id_t aid, 1101 ipp_action_id_t ref_aid, 1102 ipp_flags_t flags) 1103 { 1104 ipp_action_t *ap; 1105 ipp_action_t *ref_ap; 1106 int ref_is_busy; 1107 int rc; 1108 1109 if (aid == ref_aid) 1110 return (EINVAL); 1111 1112 /* 1113 * Check for a special case 'virtual action' id. 1114 */ 1115 1116 switch (ref_aid) { 1117 case IPP_ACTION_CONT: 1118 /*FALLTHRU*/ 1119 case IPP_ACTION_DEFER: 1120 /*FALLTHRU*/ 1121 case IPP_ACTION_DROP: 1122 return (0); 1123 default: 1124 break; 1125 } 1126 1127 /* 1128 * Translate the action ids into action pointers. 1129 */ 1130 1131 if ((ap = hold_action(aid)) == NULL) 1132 return (ENOENT); 1133 1134 if ((ref_ap = hold_action(ref_aid)) == NULL) { 1135 rele_action(ap); 1136 return (ENOENT); 1137 } 1138 1139 LOCK_ACTION(ap, RW_WRITER); 1140 LOCK_ACTION(ref_ap, RW_WRITER); 1141 1142 /* 1143 * Remove the reference between the actions. 1144 */ 1145 1146 if ((rc = unref_action(ap, ref_ap)) != 0) { 1147 UNLOCK_ACTION(ref_ap); 1148 UNLOCK_ACTION(ap); 1149 rele_action(ref_ap); 1150 rele_action(ap); 1151 return (rc); 1152 } 1153 1154 ref_is_busy = is_action_refd(ref_ap); 1155 1156 UNLOCK_ACTION(ref_ap); 1157 UNLOCK_ACTION(ap); 1158 1159 if (flags & IPP_DESTROY_REF) { 1160 if (!ref_is_busy) { 1161 1162 /* 1163 * Condemn the action so that it will be destroyed. 1164 */ 1165 1166 (void) condemn_action(ap->ippa_condemned, ref_ap); 1167 return (0); 1168 } 1169 } 1170 1171 rele_action(ref_ap); 1172 rele_action(ap); 1173 return (0); 1174 } 1175 #undef __FN__ 1176 1177 /* 1178 * Packet manipulation interface. 1179 */ 1180 1181 #define __FN__ "ipp_packet_alloc" 1182 int 1183 ipp_packet_alloc( 1184 ipp_packet_t **ppp, 1185 const char *name, 1186 ipp_action_id_t aid) 1187 { 1188 ipp_packet_t *pp; 1189 int rc; 1190 1191 ASSERT(ppp != NULL); 1192 1193 /* 1194 * A name is required. 1195 */ 1196 1197 if (name == NULL || strlen(name) > MAXNAMELEN - 1) 1198 return (EINVAL); 1199 1200 /* 1201 * Allocate a packet structure from the cache. 1202 */ 1203 1204 if ((rc = alloc_packet(name, aid, &pp)) != 0) 1205 return (rc); 1206 1207 if (ipp_packet_logging != 0 && pp->ippp_log == NULL) { 1208 1209 /* 1210 * Logging is turned on but there's no log buffer. We need 1211 * to allocate one. 1212 */ 1213 if ((pp->ippp_log = kmem_alloc( 1214 ipp_packet_log_entries * sizeof (ipp_log_t), 1215 KM_NOSLEEP)) != NULL) { 1216 pp->ippp_log_limit = ipp_packet_log_entries - 1; 1217 pp->ippp_log_windex = 0; 1218 } 1219 } else if (ipp_packet_logging == 0 && pp->ippp_log != NULL) { 1220 1221 /* 1222 * A log buffer is present but logging has been turned off. 1223 * Free the buffer now, 1224 */ 1225 1226 kmem_free(pp->ippp_log, 1227 (pp->ippp_log_limit + 1) * sizeof (ipp_log_t)); 1228 pp->ippp_log = NULL; 1229 pp->ippp_log_limit = 0; 1230 pp->ippp_log_windex = 0; 1231 } 1232 1233 *ppp = pp; 1234 return (0); 1235 } 1236 #undef __FN__ 1237 1238 #define __FN__ "ipp_packet_free" 1239 void 1240 ipp_packet_free( 1241 ipp_packet_t *pp) 1242 { 1243 1244 ASSERT(pp != NULL); 1245 1246 /* 1247 * If there is a private structure pointer set, call its free 1248 * function. 1249 */ 1250 1251 if (pp->ippp_private) { 1252 pp->ippp_private_free(pp->ippp_private); 1253 pp->ippp_private = NULL; 1254 pp->ippp_private_free = NULL; 1255 } 1256 1257 /* 1258 * Free the packet structure back to the cache. 1259 */ 1260 1261 free_packet(pp); 1262 } 1263 #undef __FN__ 1264 1265 #define __FN__ "ipp_packet_add_class" 1266 int 1267 ipp_packet_add_class( 1268 ipp_packet_t *pp, 1269 const char *name, 1270 ipp_action_id_t aid) 1271 { 1272 ipp_class_t *cp; 1273 int rc; 1274 1275 ASSERT(pp != NULL); 1276 1277 /* 1278 * A name is required. 1279 */ 1280 1281 if (name == NULL || strlen(name) > MAXNAMELEN - 1) 1282 return (EINVAL); 1283 1284 /* 1285 * Check if there is an available class structure. 1286 */ 1287 1288 if (pp->ippp_class_windex == pp->ippp_class_limit) { 1289 1290 /* 1291 * No more structures. Re-allocate the array. 1292 */ 1293 1294 if ((rc = realloc_packet(pp)) != 0) 1295 return (rc); 1296 } 1297 ASSERT(pp->ippp_class_windex < pp->ippp_class_limit); 1298 1299 /* 1300 * Set up a new class structure. 1301 */ 1302 1303 cp = &(pp->ippp_class_array[pp->ippp_class_windex++]); 1304 (void) strcpy(cp->ippc_name, name); 1305 cp->ippc_aid = aid; 1306 1307 return (0); 1308 } 1309 #undef __FN__ 1310 1311 #define __FN__ "ipp_packet_process" 1312 int 1313 ipp_packet_process( 1314 ipp_packet_t **ppp) 1315 { 1316 ipp_packet_t *pp; 1317 ipp_action_id_t aid; 1318 ipp_class_t *cp; 1319 ipp_log_t *lp; 1320 ipp_action_t *ap; 1321 ipp_mod_t *imp; 1322 ipp_ops_t *ippo; 1323 int rc; 1324 1325 ASSERT(ppp != NULL); 1326 pp = *ppp; 1327 ASSERT(pp != NULL); 1328 1329 /* 1330 * Walk the class list. 1331 */ 1332 1333 while (pp->ippp_class_rindex < pp->ippp_class_windex) { 1334 cp = &(pp->ippp_class_array[pp->ippp_class_rindex]); 1335 1336 /* 1337 * While there is a real action to invoke... 1338 */ 1339 1340 aid = cp->ippc_aid; 1341 while (aid != IPP_ACTION_CONT && 1342 aid != IPP_ACTION_DEFER && 1343 aid != IPP_ACTION_DROP) { 1344 1345 ASSERT(aid != IPP_ACTION_INVAL); 1346 1347 /* 1348 * Translate the action id to the action pointer. 1349 */ 1350 1351 if ((ap = hold_action(aid)) == NULL) { 1352 DBG1(DBG_PACKET, 1353 "action id '%d' not found\n", aid); 1354 return (ENOENT); 1355 } 1356 1357 /* 1358 * Check that the action is available for use... 1359 */ 1360 LOCK_ACTION(ap, RW_READER); 1361 if (ap->ippa_state != IPP_ASTATE_AVAILABLE) { 1362 UNLOCK_ACTION(ap); 1363 rele_action(ap); 1364 return (EPROTO); 1365 } 1366 1367 /* 1368 * Increment the action's packet count to note that 1369 * it's being used. 1370 * 1371 * NOTE: We only have a read lock, so we need to use 1372 * atomic_add_32(). The read lock is still 1373 * important though as it is crucial to block 1374 * out a destroy operation between the action 1375 * state being checked and the packet count 1376 * being incremented. 1377 */ 1378 1379 atomic_inc_32(&(ap->ippa_packets)); 1380 1381 imp = ap->ippa_mod; 1382 ASSERT(imp != NULL); 1383 UNLOCK_ACTION(ap); 1384 1385 ippo = imp->ippm_ops; 1386 ASSERT(ippo != NULL); 1387 1388 /* 1389 * If there's a log, grab the next entry and fill it 1390 * in. 1391 */ 1392 1393 if (pp->ippp_log != NULL && 1394 pp->ippp_log_windex <= pp->ippp_log_limit) { 1395 lp = &(pp->ippp_log[pp->ippp_log_windex++]); 1396 lp->ippl_aid = aid; 1397 (void) strcpy(lp->ippl_name, cp->ippc_name); 1398 gethrestime(&lp->ippl_begin); 1399 } else { 1400 lp = NULL; 1401 } 1402 1403 /* 1404 * Invoke the action. 1405 */ 1406 1407 rc = ippo->ippo_action_invoke(aid, pp); 1408 1409 /* 1410 * Also log the time that the action finished 1411 * processing. 1412 */ 1413 1414 if (lp != NULL) 1415 gethrestime(&lp->ippl_end); 1416 1417 /* 1418 * Decrement the packet count. 1419 */ 1420 1421 atomic_dec_32(&(ap->ippa_packets)); 1422 1423 /* 1424 * If the class' action id is the same now as it was 1425 * before then clearly no 'next action' has been set. 1426 * This is a protocol error. 1427 */ 1428 1429 if (cp->ippc_aid == aid) { 1430 DBG1(DBG_PACKET, 1431 "action '%s' did not set next action\n", 1432 ap->ippa_name); 1433 rele_action(ap); 1434 return (EPROTO); 1435 } 1436 1437 /* 1438 * The action did not complete successfully. Terminate 1439 * packet processing. 1440 */ 1441 1442 if (rc != 0) { 1443 DBG2(DBG_PACKET, 1444 "action error '%d' from action '%s'\n", 1445 rc, ap->ippa_name); 1446 rele_action(ap); 1447 return (rc); 1448 } 1449 1450 rele_action(ap); 1451 1452 /* 1453 * Look at the next action. 1454 */ 1455 1456 aid = cp->ippc_aid; 1457 } 1458 1459 /* 1460 * No more real actions to invoke, check for 'virtual' ones. 1461 */ 1462 1463 /* 1464 * Packet deferred: module has held onto packet for processing 1465 * later. 1466 */ 1467 1468 if (cp->ippc_aid == IPP_ACTION_DEFER) { 1469 *ppp = NULL; 1470 return (0); 1471 } 1472 1473 /* 1474 * Packet dropped: free the packet and discontinue processing. 1475 */ 1476 1477 if (cp->ippc_aid == IPP_ACTION_DROP) { 1478 freemsg(pp->ippp_data); 1479 ipp_packet_free(pp); 1480 *ppp = NULL; 1481 return (0); 1482 } 1483 1484 /* 1485 * Must be 'continue processing': move onto the next class. 1486 */ 1487 1488 ASSERT(cp->ippc_aid == IPP_ACTION_CONT); 1489 pp->ippp_class_rindex++; 1490 } 1491 1492 return (0); 1493 } 1494 #undef __FN__ 1495 1496 #define __FN__ "ipp_packet_next" 1497 int 1498 ipp_packet_next( 1499 ipp_packet_t *pp, 1500 ipp_action_id_t aid) 1501 { 1502 ipp_action_t *ap; 1503 ipp_class_t *cp; 1504 1505 ASSERT(pp != NULL); 1506 1507 cp = &(pp->ippp_class_array[pp->ippp_class_rindex]); 1508 ASSERT(cp != NULL); 1509 1510 /* 1511 * Check for a special case 'virtual action' id. 1512 */ 1513 1514 switch (aid) { 1515 case IPP_ACTION_INVAL: 1516 return (EINVAL); 1517 case IPP_ACTION_DEFER: 1518 /*FALLTHRU*/ 1519 case IPP_ACTION_CONT: 1520 /*FALLTHRU*/ 1521 case IPP_ACTION_DROP: 1522 break; 1523 default: 1524 1525 /* 1526 * Not a virtual action so try to translate the action id 1527 * into the action pointer to confirm the actions existence. 1528 */ 1529 1530 if ((ap = hold_action(aid)) == NULL) { 1531 DBG0(DBG_PACKET, "invalid action\n"); 1532 return (ENOENT); 1533 } 1534 rele_action(ap); 1535 1536 break; 1537 } 1538 1539 /* 1540 * Set the class' new action id. 1541 */ 1542 1543 cp->ippc_aid = aid; 1544 1545 return (0); 1546 } 1547 #undef __FN__ 1548 1549 #define __FN__ "ipp_packet_set_data" 1550 void 1551 ipp_packet_set_data( 1552 ipp_packet_t *pp, 1553 mblk_t *data) 1554 { 1555 ASSERT(pp != NULL); 1556 pp->ippp_data = data; 1557 } 1558 #undef __FN__ 1559 1560 #define __FN__ "ipp_packet_get_data" 1561 mblk_t * 1562 ipp_packet_get_data( 1563 ipp_packet_t *pp) 1564 { 1565 ASSERT(pp != NULL); 1566 return (pp->ippp_data); 1567 } 1568 #undef __FN__ 1569 1570 #define __FN__ "ipp_packet_set_private" 1571 void 1572 ipp_packet_set_private( 1573 ipp_packet_t *pp, 1574 void *buf, 1575 void (*free_func)(void *)) 1576 { 1577 ASSERT(pp != NULL); 1578 ASSERT(free_func != NULL); 1579 1580 pp->ippp_private = buf; 1581 pp->ippp_private_free = free_func; 1582 } 1583 #undef __FN__ 1584 1585 #define __FN__ "ipp_packet_get_private" 1586 void * 1587 ipp_packet_get_private( 1588 ipp_packet_t *pp) 1589 { 1590 ASSERT(pp != NULL); 1591 return (pp->ippp_private); 1592 } 1593 #undef __FN__ 1594 1595 /* 1596 * Statistics interface. 1597 */ 1598 1599 #define __FN__ "ipp_stat_create" 1600 int 1601 ipp_stat_create( 1602 ipp_action_id_t aid, 1603 const char *name, 1604 int nstat, 1605 int (*update)(ipp_stat_t *, void *, int), 1606 void *arg, 1607 ipp_stat_t **spp) 1608 { 1609 ipp_action_t *ap; 1610 ipp_mod_t *imp; 1611 ipp_stat_impl_t *sip; 1612 ipp_stat_t *sp; 1613 kstat_t *ksp; 1614 char *class; 1615 char *modname; 1616 int instance; 1617 1618 ASSERT(spp != NULL); 1619 1620 /* 1621 * Sanity check the arguments. 1622 */ 1623 1624 if (name == NULL || nstat <= 0 || update == NULL) 1625 return (EINVAL); 1626 1627 /* 1628 * Translate the action id into the action pointer. 1629 */ 1630 1631 if ((ap = hold_action(aid)) == NULL) 1632 return (ENOENT); 1633 1634 /* 1635 * Grab relevant action and module information. 1636 */ 1637 1638 LOCK_ACTION(ap, RW_READER); 1639 class = ap->ippa_name; 1640 instance = (int)ap->ippa_id; 1641 1642 imp = ap->ippa_mod; 1643 ASSERT(imp != NULL); 1644 1645 LOCK_MOD(imp, RW_READER); 1646 modname = imp->ippm_name; 1647 1648 /* 1649 * Allocate a stats info structure. 1650 */ 1651 1652 if ((sip = kmem_alloc(sizeof (ipp_stat_impl_t), KM_NOSLEEP)) == NULL) 1653 return (ENOMEM); 1654 1655 /* 1656 * Create a set of kstats. 1657 */ 1658 1659 DBG2(DBG_STATS, "creating stat set '%s' for action '%s'\n", 1660 name, class); 1661 if ((ksp = kstat_create(modname, instance, name, class, 1662 KSTAT_TYPE_NAMED, nstat, KSTAT_FLAG_WRITABLE)) == NULL) { 1663 kmem_free(sip, sizeof (ipp_stat_impl_t)); 1664 UNLOCK_ACTION(ap); 1665 UNLOCK_MOD(imp); 1666 return (EINVAL); /* Assume EINVAL was the cause */ 1667 } 1668 1669 UNLOCK_ACTION(ap); 1670 UNLOCK_MOD(imp); 1671 1672 DBG1(DBG_STATS, "ks_data = %p\n", ksp->ks_data); 1673 1674 /* 1675 * Set up the kstats structure with a private data pointer and an 1676 * 'update' function. 1677 */ 1678 1679 ksp->ks_update = update_stats; 1680 ksp->ks_private = (void *)sip; 1681 1682 /* 1683 * Keep a reference to the kstats structure in our own stats info 1684 * structure. 1685 */ 1686 1687 sip->ippsi_ksp = ksp; 1688 sip->ippsi_data = ksp->ks_data; 1689 1690 /* 1691 * Fill in the rest of the stats info structure. 1692 */ 1693 1694 (void) strcpy(sip->ippsi_name, name); 1695 sip->ippsi_arg = arg; 1696 sip->ippsi_update = update; 1697 sip->ippsi_limit = nstat; 1698 sip->ippsi_count = 0; 1699 mutex_init(sip->ippsi_lock, NULL, MUTEX_ADAPTIVE, 1700 (void *)ipltospl(LOCK_LEVEL)); 1701 1702 /* 1703 * Case the stats info structure to a semi-opaque structure that 1704 * we pass back to the caller. 1705 */ 1706 1707 sp = (ipp_stat_t *)sip; 1708 ASSERT(sp->ipps_data == sip->ippsi_data); 1709 *spp = sp; 1710 1711 rele_action(ap); 1712 return (0); 1713 } 1714 #undef __FN__ 1715 1716 #define __FN__ "ipp_stat_install" 1717 void 1718 ipp_stat_install( 1719 ipp_stat_t *sp) 1720 { 1721 ipp_stat_impl_t *sip = (ipp_stat_impl_t *)sp; 1722 1723 ASSERT(sp != NULL); 1724 1725 /* 1726 * Install the set of kstats referenced by the stats info structure. 1727 */ 1728 1729 DBG1(DBG_STATS, "installing stat set '%s'\n", sip->ippsi_name); 1730 kstat_install(sip->ippsi_ksp); 1731 } 1732 #undef __FN__ 1733 1734 #define __FN__ "ipp_stat_destroy" 1735 void 1736 ipp_stat_destroy( 1737 ipp_stat_t *sp) 1738 { 1739 ipp_stat_impl_t *sip = (ipp_stat_impl_t *)sp; 1740 1741 ASSERT(sp != NULL); 1742 1743 /* 1744 * Destroy the set of kstats referenced by the stats info structure. 1745 */ 1746 1747 DBG1(DBG_STATS, "destroying stat set '%s'\n", sip->ippsi_name); 1748 kstat_delete(sip->ippsi_ksp); 1749 1750 /* 1751 * Destroy the stats info structure itself. 1752 */ 1753 1754 mutex_destroy(sip->ippsi_lock); 1755 kmem_free(sip, sizeof (ipp_stat_impl_t)); 1756 } 1757 #undef __FN__ 1758 1759 #define __FN__ "ipp_stat_named_init" 1760 int 1761 ipp_stat_named_init( 1762 ipp_stat_t *sp, 1763 const char *name, 1764 uchar_t type, 1765 ipp_named_t *np) 1766 { 1767 ipp_stat_impl_t *sip = (ipp_stat_impl_t *)sp; 1768 uchar_t ktype; 1769 1770 ASSERT(sp != NULL); 1771 ASSERT(np != NULL); 1772 1773 if (name == NULL) 1774 return (EINVAL); 1775 1776 if ((type & IPP_STAT_TAG) == 0) 1777 return (EINVAL); 1778 ktype = type & ~IPP_STAT_TAG; 1779 1780 /* 1781 * Check we will not exceed the maximum number of a stats that was 1782 * indicated during set creation. 1783 */ 1784 1785 mutex_enter(sip->ippsi_lock); 1786 if (sip->ippsi_count >= sip->ippsi_limit) { 1787 mutex_exit(sip->ippsi_lock); 1788 return (ENOSPC); 1789 } 1790 1791 /* 1792 * Bump the count. 1793 */ 1794 1795 sip->ippsi_count++; 1796 1797 /* 1798 * Create a new named kstat. 1799 */ 1800 1801 DBG3(DBG_STATS, "%s.%s: knp = %p\n", sip->ippsi_name, name, np); 1802 kstat_named_init(np, name, ktype); 1803 mutex_exit(sip->ippsi_lock); 1804 1805 return (0); 1806 } 1807 #undef __FN__ 1808 1809 #define __FN__ "ipp_stat_named_op" 1810 int 1811 ipp_stat_named_op( 1812 ipp_named_t *np, 1813 void *valp, 1814 int rw) 1815 { 1816 kstat_named_t *knp; 1817 uchar_t type; 1818 int rc = 0; 1819 1820 ASSERT(np != NULL); 1821 ASSERT(valp != NULL); 1822 1823 knp = np; 1824 type = knp->data_type | IPP_STAT_TAG; 1825 1826 /* 1827 * Copy data to or from the named kstat, depending on the specified 1828 * opcode. 1829 */ 1830 1831 switch (rw) { 1832 case IPP_STAT_WRITE: 1833 switch (type) { 1834 case IPP_STAT_INT32: 1835 *(int32_t *)valp = knp->value.i32; 1836 break; 1837 case IPP_STAT_UINT32: 1838 *(uint32_t *)valp = knp->value.ui32; 1839 break; 1840 case IPP_STAT_INT64: 1841 *(int64_t *)valp = knp->value.i64; 1842 break; 1843 case IPP_STAT_UINT64: 1844 *(uint64_t *)valp = knp->value.ui64; 1845 break; 1846 case IPP_STAT_STRING: 1847 (void) strncpy(valp, knp->value.c, 16); 1848 break; 1849 default: 1850 ASSERT(0); /* should not reach here */ 1851 break; 1852 } 1853 1854 break; 1855 case IPP_STAT_READ: 1856 switch (type) { 1857 case IPP_STAT_INT32: 1858 knp->value.i32 = *(int32_t *)valp; 1859 break; 1860 case IPP_STAT_UINT32: 1861 knp->value.ui32 = *(uint32_t *)valp; 1862 break; 1863 case IPP_STAT_INT64: 1864 knp->value.i64 = *(int64_t *)valp; 1865 break; 1866 case IPP_STAT_UINT64: 1867 knp->value.ui64 = *(uint64_t *)valp; 1868 break; 1869 case IPP_STAT_STRING: 1870 (void) strncpy(knp->value.c, valp, 16); 1871 break; 1872 default: 1873 ASSERT(0); /* should not reach here */ 1874 break; 1875 } 1876 1877 break; 1878 default: 1879 rc = EINVAL; 1880 } 1881 1882 return (rc); 1883 } 1884 #undef __FN__ 1885 1886 /* 1887 * Local functions (for local people. There's nothing for you here!) 1888 */ 1889 1890 #define __FN__ "ref_mod" 1891 static int 1892 ref_mod( 1893 ipp_action_t *ap, 1894 ipp_mod_t *imp) 1895 { 1896 ipp_ref_t **rpp; 1897 ipp_ref_t *rp; 1898 1899 ASSERT(rw_write_held(ap->ippa_lock)); 1900 ASSERT(rw_write_held(imp->ippm_lock)); 1901 1902 /* 1903 * Add the new reference at the end of the module's list. 1904 */ 1905 1906 rpp = &(imp->ippm_action); 1907 while ((rp = *rpp) != NULL) { 1908 ASSERT(rp->ippr_action != ap); 1909 rpp = &(rp->ippr_nextp); 1910 } 1911 1912 /* 1913 * Allocate a reference structure. 1914 */ 1915 1916 if ((rp = kmem_zalloc(sizeof (ipp_ref_t), KM_NOSLEEP)) == NULL) 1917 return (ENOMEM); 1918 1919 /* 1920 * Set the reference to the action and link it onto the module's list. 1921 */ 1922 1923 rp->ippr_action = ap; 1924 *rpp = rp; 1925 1926 /* 1927 * Keep a 'back pointer' from the action structure to the module 1928 * structure. 1929 */ 1930 1931 ap->ippa_mod = imp; 1932 1933 return (0); 1934 } 1935 #undef __FN__ 1936 1937 #define __FN__ "unref_mod" 1938 static void 1939 unref_mod( 1940 ipp_action_t *ap, 1941 ipp_mod_t *imp) 1942 { 1943 ipp_ref_t **rpp; 1944 ipp_ref_t *rp; 1945 1946 ASSERT(rw_write_held(ap->ippa_lock)); 1947 ASSERT(rw_write_held(imp->ippm_lock)); 1948 1949 /* 1950 * Scan the module's list for the reference to the action. 1951 */ 1952 1953 rpp = &(imp->ippm_action); 1954 while ((rp = *rpp) != NULL) { 1955 if (rp->ippr_action == ap) 1956 break; 1957 rpp = &(rp->ippr_nextp); 1958 } 1959 ASSERT(rp != NULL); 1960 1961 /* 1962 * Unlink the reference structure and free it. 1963 */ 1964 1965 *rpp = rp->ippr_nextp; 1966 kmem_free(rp, sizeof (ipp_ref_t)); 1967 1968 /* 1969 * NULL the 'back pointer'. 1970 */ 1971 1972 ap->ippa_mod = NULL; 1973 } 1974 #undef __FN__ 1975 1976 #define __FN__ "is_mod_busy" 1977 static int 1978 is_mod_busy( 1979 ipp_mod_t *imp) 1980 { 1981 /* 1982 * Return a value which is true (non-zero) iff the module refers 1983 * to no actions. 1984 */ 1985 1986 return (imp->ippm_action != NULL); 1987 } 1988 #undef __FN__ 1989 1990 #define __FN__ "get_mod_ref" 1991 static int 1992 get_mod_ref( 1993 ipp_mod_t *imp, 1994 ipp_action_id_t **bufp, 1995 int *neltp) 1996 { 1997 ipp_ref_t *rp; 1998 int nelt; 1999 ipp_action_t *ap; 2000 ipp_action_id_t *buf; 2001 int length; 2002 2003 ASSERT(rw_lock_held(imp->ippm_lock)); 2004 2005 /* 2006 * Count the number of actions referred to from the module structure. 2007 */ 2008 2009 nelt = 0; 2010 for (rp = imp->ippm_action; rp != NULL; rp = rp->ippr_nextp) { 2011 nelt++; 2012 } 2013 DBG1(DBG_LIST, "%d actions found\n", nelt); 2014 2015 /* 2016 * If there are no actions referred to then there's nothing to do. 2017 */ 2018 2019 if (nelt == 0) { 2020 *bufp = NULL; 2021 *neltp = 0; 2022 return (0); 2023 } 2024 2025 /* 2026 * Allocate a buffer to pass back to the caller. 2027 */ 2028 2029 length = nelt * sizeof (ipp_action_id_t); 2030 if ((buf = kmem_alloc(length, KM_NOSLEEP)) == NULL) 2031 return (ENOMEM); 2032 2033 /* 2034 * Fill the buffer with an array of action ids. 2035 */ 2036 2037 *bufp = buf; 2038 *neltp = nelt; 2039 2040 for (rp = imp->ippm_action; rp != NULL; rp = rp->ippr_nextp) { 2041 ap = rp->ippr_action; 2042 *buf++ = ap->ippa_id; 2043 } 2044 2045 ASSERT((uintptr_t)buf == (uintptr_t)*bufp + length); 2046 return (0); 2047 } 2048 #undef __FN__ 2049 2050 #define __FN__ "get_mods" 2051 static int 2052 get_mods( 2053 ipp_mod_id_t **bufp, 2054 int *neltp) 2055 { 2056 ipp_mod_id_t *buf; 2057 int length; 2058 ipp_mod_id_t mid; 2059 ipp_mod_t *imp; 2060 2061 2062 rw_enter(ipp_mod_byname_lock, RW_READER); 2063 2064 /* 2065 * If there are no modules registered then there's nothing to do. 2066 */ 2067 2068 if (ipp_mod_count == 0) { 2069 DBG0(DBG_LIST, "no modules registered\n"); 2070 *bufp = NULL; 2071 *neltp = 0; 2072 rw_exit(ipp_mod_byname_lock); 2073 return (0); 2074 } 2075 2076 /* 2077 * Allocate a buffer to pass back to the caller. 2078 */ 2079 2080 DBG1(DBG_LIST, "%d modules registered\n", ipp_mod_count); 2081 length = ipp_mod_count * sizeof (ipp_mod_id_t); 2082 if ((buf = kmem_alloc(length, KM_NOSLEEP)) == NULL) { 2083 rw_exit(ipp_mod_byname_lock); 2084 return (ENOMEM); 2085 } 2086 2087 rw_enter(ipp_mod_byid_lock, RW_READER); 2088 2089 /* 2090 * Search the array of all modules. 2091 */ 2092 2093 *bufp = buf; 2094 *neltp = ipp_mod_count; 2095 2096 for (mid = IPP_MOD_RESERVED + 1; mid <= ipp_mid_limit; mid++) { 2097 if ((imp = ipp_mod_byid[mid]) == NULL) 2098 continue; 2099 2100 /* 2101 * If the module has 'destruct pending' set then it means it 2102 * is either still in the cache (i.e not allocated) or in the 2103 * process of being set up by alloc_mod(). 2104 */ 2105 2106 LOCK_MOD(imp, RW_READER); 2107 ASSERT(imp->ippm_id == mid); 2108 2109 if (imp->ippm_destruct_pending) { 2110 UNLOCK_MOD(imp); 2111 continue; 2112 } 2113 UNLOCK_MOD(imp); 2114 2115 *buf++ = mid; 2116 } 2117 2118 rw_exit(ipp_mod_byid_lock); 2119 rw_exit(ipp_mod_byname_lock); 2120 2121 ASSERT((uintptr_t)buf == (uintptr_t)*bufp + length); 2122 return (0); 2123 } 2124 #undef __FN__ 2125 2126 #define __FN__ "find_mod" 2127 static ipp_mod_id_t 2128 find_mod( 2129 const char *modname) 2130 { 2131 ipp_mod_id_t mid; 2132 ipp_mod_t *imp; 2133 ipp_ref_t *rp; 2134 int hb; 2135 2136 ASSERT(modname != NULL); 2137 2138 rw_enter(ipp_mod_byname_lock, RW_READER); 2139 2140 /* 2141 * Quick return if no modules are registered. 2142 */ 2143 2144 if (ipp_mod_count == 0) { 2145 rw_exit(ipp_mod_byname_lock); 2146 return (IPP_MOD_INVAL); 2147 } 2148 2149 /* 2150 * Find the hash bucket where the module structure should be. 2151 */ 2152 2153 hb = hash(modname); 2154 rp = ipp_mod_byname[hb]; 2155 2156 /* 2157 * Scan the bucket for a match. 2158 */ 2159 2160 while (rp != NULL) { 2161 imp = rp->ippr_mod; 2162 if (strcmp(imp->ippm_name, modname) == 0) 2163 break; 2164 rp = rp->ippr_nextp; 2165 } 2166 2167 if (rp == NULL) { 2168 rw_exit(ipp_mod_byname_lock); 2169 return (IPP_MOD_INVAL); 2170 } 2171 2172 if (imp->ippm_state == IPP_MODSTATE_PROTO) { 2173 rw_exit(ipp_mod_byname_lock); 2174 return (IPP_MOD_INVAL); 2175 } 2176 2177 mid = imp->ippm_id; 2178 rw_exit(ipp_mod_byname_lock); 2179 2180 return (mid); 2181 } 2182 #undef __FN__ 2183 2184 #define __FN__ "alloc_mod" 2185 static int 2186 alloc_mod( 2187 const char *modname, 2188 ipp_mod_id_t *midp) 2189 { 2190 ipp_mod_t *imp; 2191 ipp_ref_t **rpp; 2192 ipp_ref_t *rp; 2193 int hb; 2194 2195 ASSERT(modname != NULL); 2196 ASSERT(midp != NULL); 2197 2198 rw_enter(ipp_mod_byname_lock, RW_WRITER); 2199 2200 /* 2201 * Find the right hash bucket for a module of the given name. 2202 */ 2203 2204 hb = hash(modname); 2205 rpp = &ipp_mod_byname[hb]; 2206 2207 /* 2208 * Scan the bucket making sure the module isn't already 2209 * registered. 2210 */ 2211 2212 while ((rp = *rpp) != NULL) { 2213 imp = rp->ippr_mod; 2214 if (strcmp(imp->ippm_name, modname) == 0) { 2215 DBG1(DBG_MOD, "module '%s' already exists\n", modname); 2216 rw_exit(ipp_mod_byname_lock); 2217 return (EEXIST); 2218 } 2219 rpp = &(rp->ippr_nextp); 2220 } 2221 2222 /* 2223 * Allocate a new reference structure and a new module structure. 2224 */ 2225 2226 if ((rp = kmem_zalloc(sizeof (ipp_ref_t), KM_NOSLEEP)) == NULL) { 2227 rw_exit(ipp_mod_byname_lock); 2228 return (ENOMEM); 2229 } 2230 2231 if ((imp = kmem_cache_alloc(ipp_mod_cache, KM_NOSLEEP)) == NULL) { 2232 kmem_free(rp, sizeof (ipp_ref_t)); 2233 rw_exit(ipp_mod_byname_lock); 2234 return (ENOMEM); 2235 } 2236 2237 /* 2238 * Set up the name of the new structure. 2239 */ 2240 2241 (void) strcpy(imp->ippm_name, modname); 2242 2243 /* 2244 * Make sure the 'destruct pending' flag is clear. This indicates 2245 * that the structure is no longer part of the cache. 2246 */ 2247 2248 LOCK_MOD(imp, RW_WRITER); 2249 imp->ippm_destruct_pending = B_FALSE; 2250 UNLOCK_MOD(imp); 2251 2252 /* 2253 * Set the reference and link it into the hash bucket. 2254 */ 2255 2256 rp->ippr_mod = imp; 2257 *rpp = rp; 2258 2259 /* 2260 * Increment the module count. 2261 */ 2262 2263 ipp_mod_count++; 2264 2265 *midp = imp->ippm_id; 2266 rw_exit(ipp_mod_byname_lock); 2267 return (0); 2268 } 2269 #undef __FN__ 2270 2271 #define __FN__ "free_mod" 2272 static void 2273 free_mod( 2274 ipp_mod_t *imp) 2275 { 2276 ipp_ref_t **rpp; 2277 ipp_ref_t *rp; 2278 int hb; 2279 2280 rw_enter(ipp_mod_byname_lock, RW_WRITER); 2281 2282 /* 2283 * Find the hash bucket where the module structure should be. 2284 */ 2285 2286 hb = hash(imp->ippm_name); 2287 rpp = &ipp_mod_byname[hb]; 2288 2289 /* 2290 * Scan the bucket for a match. 2291 */ 2292 2293 while ((rp = *rpp) != NULL) { 2294 if (rp->ippr_mod == imp) 2295 break; 2296 rpp = &(rp->ippr_nextp); 2297 } 2298 ASSERT(rp != NULL); 2299 2300 /* 2301 * Unlink the reference structure and free it. 2302 */ 2303 2304 *rpp = rp->ippr_nextp; 2305 kmem_free(rp, sizeof (ipp_ref_t)); 2306 2307 /* 2308 * Decrement the module count. 2309 */ 2310 2311 ipp_mod_count--; 2312 2313 /* 2314 * Empty the name. 2315 */ 2316 2317 *imp->ippm_name = '\0'; 2318 2319 /* 2320 * If the hold count is zero then we can free the structure 2321 * immediately, otherwise we defer to rele_mod(). 2322 */ 2323 2324 LOCK_MOD(imp, RW_WRITER); 2325 imp->ippm_destruct_pending = B_TRUE; 2326 if (imp->ippm_hold_count == 0) { 2327 UNLOCK_MOD(imp); 2328 kmem_cache_free(ipp_mod_cache, imp); 2329 rw_exit(ipp_mod_byname_lock); 2330 return; 2331 } 2332 UNLOCK_MOD(imp); 2333 2334 rw_exit(ipp_mod_byname_lock); 2335 } 2336 #undef __FN__ 2337 2338 #define __FN__ "hold_mod" 2339 static ipp_mod_t * 2340 hold_mod( 2341 ipp_mod_id_t mid) 2342 { 2343 ipp_mod_t *imp; 2344 2345 if (mid < 0) 2346 return (NULL); 2347 2348 /* 2349 * Use the module id as an index into the array of all module 2350 * structures. 2351 */ 2352 2353 rw_enter(ipp_mod_byid_lock, RW_READER); 2354 if ((imp = ipp_mod_byid[mid]) == NULL) { 2355 rw_exit(ipp_mod_byid_lock); 2356 return (NULL); 2357 } 2358 2359 ASSERT(imp->ippm_id == mid); 2360 2361 /* 2362 * If the modul has 'destruct pending' set then it means it is either 2363 * still in the cache (i.e not allocated) or in the process of 2364 * being set up by alloc_mod(). 2365 */ 2366 2367 LOCK_MOD(imp, RW_READER); 2368 if (imp->ippm_destruct_pending) { 2369 UNLOCK_MOD(imp); 2370 rw_exit(ipp_mod_byid_lock); 2371 return (NULL); 2372 } 2373 UNLOCK_MOD(imp); 2374 2375 /* 2376 * Increment the hold count to prevent the structure from being 2377 * freed. 2378 */ 2379 2380 atomic_inc_32(&(imp->ippm_hold_count)); 2381 rw_exit(ipp_mod_byid_lock); 2382 2383 return (imp); 2384 } 2385 #undef __FN__ 2386 2387 #define __FN__ "rele_mod" 2388 static void 2389 rele_mod( 2390 ipp_mod_t *imp) 2391 { 2392 /* 2393 * This call means we're done with the pointer so we can drop the 2394 * hold count. 2395 */ 2396 2397 ASSERT(imp->ippm_hold_count != 0); 2398 atomic_dec_32(&(imp->ippm_hold_count)); 2399 2400 /* 2401 * If the structure has 'destruct pending' set then we tried to free 2402 * it but couldn't, so do it now. 2403 */ 2404 2405 LOCK_MOD(imp, RW_READER); 2406 if (imp->ippm_destruct_pending && imp->ippm_hold_count == 0) { 2407 UNLOCK_MOD(imp); 2408 kmem_cache_free(ipp_mod_cache, imp); 2409 return; 2410 } 2411 2412 UNLOCK_MOD(imp); 2413 } 2414 #undef __FN__ 2415 2416 #define __FN__ "get_mid" 2417 static ipp_mod_id_t 2418 get_mid( 2419 void) 2420 { 2421 int index; 2422 int start; 2423 int limit; 2424 2425 ASSERT(rw_write_held(ipp_mod_byid_lock)); 2426 2427 /* 2428 * Start searching after the last module id we allocated. 2429 */ 2430 2431 start = (int)ipp_next_mid; 2432 limit = (int)ipp_mid_limit; 2433 2434 /* 2435 * Look for a spare slot in the array. 2436 */ 2437 2438 index = start; 2439 while (ipp_mod_byid[index] != NULL) { 2440 index++; 2441 if (index > limit) 2442 index = IPP_MOD_RESERVED + 1; 2443 if (index == start) 2444 return (IPP_MOD_INVAL); 2445 } 2446 2447 /* 2448 * Note that we've just allocated a new module id so that we can 2449 * start our search there next time. 2450 */ 2451 2452 index++; 2453 if (index > limit) { 2454 ipp_next_mid = IPP_MOD_RESERVED + 1; 2455 } else 2456 ipp_next_mid = (ipp_mod_id_t)index; 2457 2458 return ((ipp_mod_id_t)(--index)); 2459 } 2460 #undef __FN__ 2461 2462 #define __FN__ "condemn_action" 2463 static int 2464 condemn_action( 2465 ipp_ref_t **rpp, 2466 ipp_action_t *ap) 2467 { 2468 ipp_ref_t *rp; 2469 2470 DBG1(DBG_ACTION, "condemning action '%s'\n", ap->ippa_name); 2471 2472 /* 2473 * Check to see if the action is already condemned. 2474 */ 2475 2476 while ((rp = *rpp) != NULL) { 2477 if (rp->ippr_action == ap) 2478 break; 2479 rpp = &(rp->ippr_nextp); 2480 } 2481 2482 /* 2483 * Create a new entry for the action. 2484 */ 2485 2486 if (rp == NULL) { 2487 if ((rp = kmem_zalloc(sizeof (ipp_ref_t), KM_NOSLEEP)) == NULL) 2488 return (ENOMEM); 2489 2490 rp->ippr_action = ap; 2491 *rpp = rp; 2492 } 2493 2494 return (0); 2495 } 2496 #undef __FN__ 2497 2498 #define __FN__ "destroy_action" 2499 static int 2500 destroy_action( 2501 ipp_action_t *ap, 2502 ipp_flags_t flags) 2503 { 2504 ipp_ops_t *ippo; 2505 ipp_mod_t *imp; 2506 #define MAXWAIT 10 2507 uint32_t wait; 2508 int rc; 2509 2510 /* 2511 * Check that the action is available. 2512 */ 2513 2514 LOCK_ACTION(ap, RW_WRITER); 2515 if (ap->ippa_state != IPP_ASTATE_AVAILABLE) { 2516 UNLOCK_ACTION(ap); 2517 rele_action(ap); 2518 return (EPROTO); 2519 } 2520 2521 /* 2522 * Note that the action is in the process of creation/destruction. 2523 */ 2524 2525 ap->ippa_state = IPP_ASTATE_CONFIG_PENDING; 2526 2527 /* 2528 * Wait for the in-transit packet count for this action to fall to 2529 * zero (checking at millisecond intervals). 2530 * 2531 * NOTE: no new packets will enter the action now that the 2532 * state has been changed. 2533 */ 2534 2535 for (wait = 0; ap->ippa_packets > 0 && wait < (MAXWAIT * 1000000); 2536 wait += 1000) { 2537 2538 /* 2539 * NOTE: We can hang onto the lock because the packet count is 2540 * decremented without needing to take the lock. 2541 */ 2542 2543 drv_usecwait(1000); 2544 } 2545 2546 /* 2547 * The packet count did not fall to zero. 2548 */ 2549 if (ap->ippa_packets > 0) { 2550 ap->ippa_state = IPP_ASTATE_AVAILABLE; 2551 UNLOCK_ACTION(ap); 2552 rele_action(ap); 2553 return (EAGAIN); 2554 } 2555 2556 /* 2557 * Check to see if any other action has a dependency on this one. 2558 */ 2559 2560 if (is_action_refd(ap)) { 2561 ap->ippa_state = IPP_ASTATE_AVAILABLE; 2562 UNLOCK_ACTION(ap); 2563 rele_action(ap); 2564 return (EBUSY); 2565 } 2566 2567 imp = ap->ippa_mod; 2568 ASSERT(imp != NULL); 2569 UNLOCK_ACTION(ap); 2570 2571 ippo = imp->ippm_ops; 2572 ASSERT(ippo != NULL); 2573 2574 /* 2575 * Call into the module to destroy the action context. 2576 */ 2577 2578 CONFIG_WRITE_START(ap); 2579 DBG1(DBG_ACTION, "destroying action '%s'\n", ap->ippa_name); 2580 if ((rc = ippo->ippo_action_destroy(ap->ippa_id, flags)) != 0) { 2581 LOCK_ACTION(ap, RW_WRITER); 2582 ap->ippa_state = IPP_ASTATE_AVAILABLE; 2583 UNLOCK_ACTION(ap); 2584 2585 CONFIG_WRITE_END(ap); 2586 2587 rele_action(ap); 2588 return (rc); 2589 } 2590 CONFIG_WRITE_END(ap); 2591 2592 LOCK_ACTION(ap, RW_WRITER); 2593 LOCK_MOD(imp, RW_WRITER); 2594 unref_mod(ap, imp); 2595 UNLOCK_MOD(imp); 2596 ap->ippa_state = IPP_ASTATE_PROTO; 2597 UNLOCK_ACTION(ap); 2598 2599 /* 2600 * Free the action structure. 2601 */ 2602 2603 ASSERT(ap->ippa_ref == NULL); 2604 free_action(ap); 2605 rele_action(ap); 2606 return (0); 2607 #undef MAXWAIT 2608 } 2609 #undef __FN__ 2610 2611 #define __FN__ "ref_action" 2612 static int 2613 ref_action( 2614 ipp_action_t *refby_ap, 2615 ipp_action_t *ref_ap) 2616 { 2617 ipp_ref_t **rpp; 2618 ipp_ref_t **save_rpp; 2619 ipp_ref_t *rp; 2620 2621 ASSERT(rw_write_held(refby_ap->ippa_lock)); 2622 ASSERT(rw_write_held(ref_ap->ippa_lock)); 2623 2624 /* 2625 * We want to add the new reference at the end of the refering 2626 * action's list. 2627 */ 2628 2629 rpp = &(refby_ap->ippa_ref); 2630 while ((rp = *rpp) != NULL) { 2631 if (rp->ippr_action == ref_ap) 2632 break; 2633 rpp = &(rp->ippr_nextp); 2634 } 2635 2636 if ((rp = *rpp) != NULL) { 2637 2638 /* 2639 * There is an existing reference so increment its counter. 2640 */ 2641 2642 rp->ippr_count++; 2643 2644 /* 2645 * Find the 'back pointer' and increment its counter too. 2646 */ 2647 2648 rp = ref_ap->ippa_refby; 2649 while (rp != NULL) { 2650 if (rp->ippr_action == refby_ap) 2651 break; 2652 rp = rp->ippr_nextp; 2653 } 2654 ASSERT(rp != NULL); 2655 2656 rp->ippr_count++; 2657 } else { 2658 2659 /* 2660 * Allocate, fill in and link a new reference structure. 2661 */ 2662 2663 if ((rp = kmem_zalloc(sizeof (ipp_ref_t), KM_NOSLEEP)) == NULL) 2664 return (ENOMEM); 2665 2666 rp->ippr_action = ref_ap; 2667 rp->ippr_count = 1; 2668 *rpp = rp; 2669 save_rpp = rpp; 2670 2671 /* 2672 * We keep a 'back pointer' which we want to add at the end of 2673 * a list in the referred action's structure. 2674 */ 2675 2676 rpp = &(ref_ap->ippa_refby); 2677 while ((rp = *rpp) != NULL) { 2678 ASSERT(rp->ippr_action != refby_ap); 2679 rpp = &(rp->ippr_nextp); 2680 } 2681 2682 /* 2683 * Allocate another reference structure and, if this fails, 2684 * remember to clean up the first reference structure we 2685 * allocated. 2686 */ 2687 2688 if ((rp = kmem_zalloc(sizeof (ipp_ref_t), 2689 KM_NOSLEEP)) == NULL) { 2690 rpp = save_rpp; 2691 rp = *rpp; 2692 *rpp = NULL; 2693 kmem_free(rp, sizeof (ipp_ref_t)); 2694 2695 return (ENOMEM); 2696 } 2697 2698 /* 2699 * Fill in the reference structure with the 'back pointer' and 2700 * link it into the list. 2701 */ 2702 2703 rp->ippr_action = refby_ap; 2704 rp->ippr_count = 1; 2705 *rpp = rp; 2706 } 2707 2708 return (0); 2709 } 2710 #undef __FN__ 2711 2712 #define __FN__ "unref_action" 2713 static int 2714 unref_action( 2715 ipp_action_t *refby_ap, 2716 ipp_action_t *ref_ap) 2717 { 2718 ipp_ref_t **rpp; 2719 ipp_ref_t *rp; 2720 2721 ASSERT(rw_write_held(refby_ap->ippa_lock)); 2722 ASSERT(rw_write_held(ref_ap->ippa_lock)); 2723 2724 /* 2725 * Scan for the reference in the referring action's list. 2726 */ 2727 2728 rpp = &(refby_ap->ippa_ref); 2729 while ((rp = *rpp) != NULL) { 2730 if (rp->ippr_action == ref_ap) 2731 break; 2732 rpp = &(rp->ippr_nextp); 2733 } 2734 2735 if (rp == NULL) 2736 return (ENOENT); 2737 2738 if (rp->ippr_count > 1) { 2739 2740 /* 2741 * There are currently multiple references so decrement the 2742 * count. 2743 */ 2744 2745 rp->ippr_count--; 2746 2747 /* 2748 * Find the 'back pointer' and decrement its counter too. 2749 */ 2750 2751 rp = ref_ap->ippa_refby; 2752 while (rp != NULL) { 2753 if (rp->ippr_action == refby_ap) 2754 break; 2755 rp = rp->ippr_nextp; 2756 } 2757 ASSERT(rp != NULL); 2758 2759 rp->ippr_count--; 2760 } else { 2761 2762 /* 2763 * There is currently only a single reference, so unlink and 2764 * free the reference structure. 2765 */ 2766 2767 *rpp = rp->ippr_nextp; 2768 kmem_free(rp, sizeof (ipp_ref_t)); 2769 2770 /* 2771 * Scan for the 'back pointer' in the referred action's list. 2772 */ 2773 2774 rpp = &(ref_ap->ippa_refby); 2775 while ((rp = *rpp) != NULL) { 2776 if (rp->ippr_action == refby_ap) 2777 break; 2778 rpp = &(rp->ippr_nextp); 2779 } 2780 ASSERT(rp != NULL); 2781 2782 /* 2783 * Unlink and free this reference structure too. 2784 */ 2785 2786 *rpp = rp->ippr_nextp; 2787 kmem_free(rp, sizeof (ipp_ref_t)); 2788 } 2789 2790 return (0); 2791 } 2792 #undef __FN__ 2793 2794 #define __FN__ "is_action_refd" 2795 static int 2796 is_action_refd( 2797 ipp_action_t *ap) 2798 { 2799 /* 2800 * Return a value which is true (non-zero) iff the action is not 2801 * referred to by any other actions. 2802 */ 2803 2804 return (ap->ippa_refby != NULL); 2805 } 2806 #undef __FN__ 2807 2808 #define __FN__ "find_action" 2809 static ipp_action_id_t 2810 find_action( 2811 const char *aname) 2812 { 2813 ipp_action_id_t aid; 2814 ipp_action_t *ap; 2815 ipp_ref_t *rp; 2816 int hb; 2817 2818 ASSERT(aname != NULL); 2819 2820 rw_enter(ipp_action_byname_lock, RW_READER); 2821 2822 /* 2823 * Quick return if there are no actions defined at all. 2824 */ 2825 2826 if (ipp_action_count == 0) { 2827 rw_exit(ipp_action_byname_lock); 2828 return (IPP_ACTION_INVAL); 2829 } 2830 2831 /* 2832 * Find the hash bucket where the action structure should be. 2833 */ 2834 2835 hb = hash(aname); 2836 rp = ipp_action_byname[hb]; 2837 2838 /* 2839 * Scan the bucket looking for a match. 2840 */ 2841 2842 while (rp != NULL) { 2843 ap = rp->ippr_action; 2844 if (strcmp(ap->ippa_name, aname) == 0) 2845 break; 2846 rp = rp->ippr_nextp; 2847 } 2848 2849 if (rp == NULL) { 2850 rw_exit(ipp_action_byname_lock); 2851 return (IPP_ACTION_INVAL); 2852 } 2853 2854 if (ap->ippa_state == IPP_ASTATE_PROTO) { 2855 rw_exit(ipp_action_byname_lock); 2856 return (IPP_ACTION_INVAL); 2857 } 2858 2859 aid = ap->ippa_id; 2860 rw_exit(ipp_action_byname_lock); 2861 2862 return (aid); 2863 } 2864 #undef __FN__ 2865 2866 #define __FN__ "alloc_action" 2867 static int 2868 alloc_action( 2869 const char *aname, 2870 ipp_action_id_t *aidp) 2871 { 2872 ipp_action_t *ap; 2873 ipp_ref_t **rpp; 2874 ipp_ref_t *rp; 2875 int hb; 2876 2877 ASSERT(aidp != NULL); 2878 2879 rw_enter(ipp_action_byname_lock, RW_WRITER); 2880 2881 /* 2882 * Find the right hash bucket for an action of the given name. 2883 * (Nameless actions always go in a special bucket). 2884 */ 2885 2886 if (aname != NULL) { 2887 hb = hash(aname); 2888 rpp = &ipp_action_byname[hb]; 2889 } else 2890 rpp = &ipp_action_noname; 2891 2892 /* 2893 * Scan the bucket to make sure that an action with the given name 2894 * does not already exist. 2895 */ 2896 2897 while ((rp = *rpp) != NULL) { 2898 ap = rp->ippr_action; 2899 if (aname != NULL && strcmp(ap->ippa_name, aname) == 0) { 2900 DBG1(DBG_ACTION, "action '%s' already exists\n", 2901 aname); 2902 rw_exit(ipp_action_byname_lock); 2903 return (EEXIST); 2904 } 2905 rpp = &(rp->ippr_nextp); 2906 } 2907 2908 /* 2909 * Allocate a new reference structure and a new action structure. 2910 */ 2911 2912 if ((rp = kmem_zalloc(sizeof (ipp_ref_t), KM_NOSLEEP)) == NULL) { 2913 rw_exit(ipp_action_byname_lock); 2914 return (ENOMEM); 2915 } 2916 2917 if ((ap = kmem_cache_alloc(ipp_action_cache, KM_NOSLEEP)) == NULL) { 2918 kmem_free(rp, sizeof (ipp_ref_t)); 2919 rw_exit(ipp_action_byname_lock); 2920 return (ENOMEM); 2921 } 2922 2923 /* 2924 * Dream up a name if there isn't a real one and note that the action is 2925 * really nameless. 2926 */ 2927 2928 if (aname == NULL) { 2929 (void) sprintf(ap->ippa_name, "$%08X", ap->ippa_id); 2930 ap->ippa_nameless = B_TRUE; 2931 } else 2932 (void) strcpy(ap->ippa_name, aname); 2933 2934 /* 2935 * Make sure the 'destruct pending' flag is clear. This indicates that 2936 * the structure is no longer part of the cache. 2937 */ 2938 2939 LOCK_ACTION(ap, RW_WRITER); 2940 ap->ippa_destruct_pending = B_FALSE; 2941 UNLOCK_ACTION(ap); 2942 2943 /* 2944 * Fill in the reference structure and lint it onto the list. 2945 */ 2946 2947 rp->ippr_action = ap; 2948 *rpp = rp; 2949 2950 /* 2951 * Increment the action count. 2952 */ 2953 2954 ipp_action_count++; 2955 2956 *aidp = ap->ippa_id; 2957 rw_exit(ipp_action_byname_lock); 2958 return (0); 2959 } 2960 #undef __FN__ 2961 2962 #define __FN__ "free_action" 2963 static void 2964 free_action( 2965 ipp_action_t *ap) 2966 { 2967 ipp_ref_t **rpp; 2968 ipp_ref_t *rp; 2969 int hb; 2970 2971 rw_enter(ipp_action_byname_lock, RW_WRITER); 2972 2973 /* 2974 * Find the hash bucket where the action structure should be. 2975 */ 2976 2977 if (!ap->ippa_nameless) { 2978 hb = hash(ap->ippa_name); 2979 rpp = &ipp_action_byname[hb]; 2980 } else 2981 rpp = &ipp_action_noname; 2982 2983 /* 2984 * Scan the bucket for a match. 2985 */ 2986 2987 while ((rp = *rpp) != NULL) { 2988 if (rp->ippr_action == ap) 2989 break; 2990 rpp = &(rp->ippr_nextp); 2991 } 2992 ASSERT(rp != NULL); 2993 2994 /* 2995 * Unlink and free the reference structure. 2996 */ 2997 2998 *rpp = rp->ippr_nextp; 2999 kmem_free(rp, sizeof (ipp_ref_t)); 3000 3001 /* 3002 * Decrement the action count. 3003 */ 3004 3005 ipp_action_count--; 3006 3007 /* 3008 * Empty the name. 3009 */ 3010 3011 *ap->ippa_name = '\0'; 3012 3013 /* 3014 * If the hold count is zero then we can free the structure 3015 * immediately, otherwise we defer to rele_action(). 3016 */ 3017 3018 LOCK_ACTION(ap, RW_WRITER); 3019 ap->ippa_destruct_pending = B_TRUE; 3020 if (ap->ippa_hold_count == 0) { 3021 UNLOCK_ACTION(ap); 3022 kmem_cache_free(ipp_action_cache, ap); 3023 rw_exit(ipp_action_byname_lock); 3024 return; 3025 } 3026 UNLOCK_ACTION(ap); 3027 3028 rw_exit(ipp_action_byname_lock); 3029 } 3030 #undef __FN__ 3031 3032 #define __FN__ "hold_action" 3033 static ipp_action_t * 3034 hold_action( 3035 ipp_action_id_t aid) 3036 { 3037 ipp_action_t *ap; 3038 3039 if (aid < 0) 3040 return (NULL); 3041 3042 /* 3043 * Use the action id as an index into the array of all action 3044 * structures. 3045 */ 3046 3047 rw_enter(ipp_action_byid_lock, RW_READER); 3048 if ((ap = ipp_action_byid[aid]) == NULL) { 3049 rw_exit(ipp_action_byid_lock); 3050 return (NULL); 3051 } 3052 3053 /* 3054 * If the action has 'destruct pending' set then it means it is either 3055 * still in the cache (i.e not allocated) or in the process of 3056 * being set up by alloc_action(). 3057 */ 3058 3059 LOCK_ACTION(ap, RW_READER); 3060 if (ap->ippa_destruct_pending) { 3061 UNLOCK_ACTION(ap); 3062 rw_exit(ipp_action_byid_lock); 3063 return (NULL); 3064 } 3065 UNLOCK_ACTION(ap); 3066 3067 /* 3068 * Increment the hold count to prevent the structure from being 3069 * freed. 3070 */ 3071 3072 atomic_inc_32(&(ap->ippa_hold_count)); 3073 rw_exit(ipp_action_byid_lock); 3074 3075 return (ap); 3076 } 3077 #undef __FN__ 3078 3079 #define __FN__ "rele_action" 3080 static void 3081 rele_action( 3082 ipp_action_t *ap) 3083 { 3084 /* 3085 * This call means we're done with the pointer so we can drop the 3086 * hold count. 3087 */ 3088 3089 ASSERT(ap->ippa_hold_count != 0); 3090 atomic_dec_32(&(ap->ippa_hold_count)); 3091 3092 /* 3093 * If the structure has 'destruct pending' set then we tried to free 3094 * it but couldn't, so do it now. 3095 */ 3096 3097 LOCK_ACTION(ap, RW_READER); 3098 if (ap->ippa_destruct_pending && ap->ippa_hold_count == 0) { 3099 UNLOCK_ACTION(ap); 3100 kmem_cache_free(ipp_action_cache, ap); 3101 return; 3102 } 3103 UNLOCK_ACTION(ap); 3104 } 3105 #undef __FN__ 3106 3107 #define __FN__ "get_aid" 3108 static ipp_action_id_t 3109 get_aid( 3110 void) 3111 { 3112 int index; 3113 int start; 3114 int limit; 3115 3116 ASSERT(rw_write_held(ipp_action_byid_lock)); 3117 3118 /* 3119 * Start searching after the last action id that we allocated. 3120 */ 3121 3122 start = (int)ipp_next_aid; 3123 limit = (int)ipp_aid_limit; 3124 3125 /* 3126 * Look for a spare slot in the array. 3127 */ 3128 3129 index = start; 3130 while (ipp_action_byid[index] != NULL) { 3131 index++; 3132 if (index > limit) 3133 index = IPP_ACTION_RESERVED + 1; 3134 if (index == start) 3135 return (IPP_ACTION_INVAL); 3136 } 3137 3138 /* 3139 * Note that we've just allocated a new action id so that we can 3140 * start our search there next time. 3141 */ 3142 3143 index++; 3144 if (index > limit) 3145 ipp_next_aid = IPP_ACTION_RESERVED + 1; 3146 else 3147 ipp_next_aid = (ipp_action_id_t)index; 3148 3149 return ((ipp_action_id_t)(--index)); 3150 } 3151 #undef __FN__ 3152 3153 #define __FN__ "alloc_packet" 3154 static int 3155 alloc_packet( 3156 const char *name, 3157 ipp_action_id_t aid, 3158 ipp_packet_t **ppp) 3159 { 3160 ipp_packet_t *pp; 3161 ipp_class_t *cp; 3162 3163 if ((pp = kmem_cache_alloc(ipp_packet_cache, KM_NOSLEEP)) == NULL) 3164 return (ENOMEM); 3165 3166 /* 3167 * Set the packet up with a single class. 3168 */ 3169 3170 cp = &(pp->ippp_class_array[0]); 3171 pp->ippp_class_windex = 1; 3172 3173 (void) strcpy(cp->ippc_name, name); 3174 cp->ippc_aid = aid; 3175 3176 *ppp = pp; 3177 return (0); 3178 } 3179 #undef __FN__ 3180 3181 #define __FN__ "realloc_packet" 3182 static int 3183 realloc_packet( 3184 ipp_packet_t *pp) 3185 { 3186 uint_t length; 3187 ipp_class_t *array; 3188 3189 length = (pp->ippp_class_limit + 1) << 1; 3190 if ((array = kmem_alloc(length * sizeof (ipp_class_t), 3191 KM_NOSLEEP)) == NULL) 3192 return (ENOMEM); 3193 3194 bcopy(pp->ippp_class_array, array, 3195 (length >> 1) * sizeof (ipp_class_t)); 3196 3197 kmem_free(pp->ippp_class_array, 3198 (length >> 1) * sizeof (ipp_class_t)); 3199 3200 pp->ippp_class_array = array; 3201 pp->ippp_class_limit = length - 1; 3202 3203 return (0); 3204 } 3205 #undef __FN__ 3206 3207 #define __FN__ "free_packet" 3208 static void 3209 free_packet( 3210 ipp_packet_t *pp) 3211 { 3212 pp->ippp_class_windex = 0; 3213 pp->ippp_class_rindex = 0; 3214 3215 pp->ippp_data = NULL; 3216 pp->ippp_private = NULL; 3217 3218 kmem_cache_free(ipp_packet_cache, pp); 3219 } 3220 #undef __FN__ 3221 3222 #define __FN__ "hash" 3223 static int 3224 hash( 3225 const char *name) 3226 { 3227 int val = 0; 3228 char *ptr; 3229 3230 /* 3231 * Make a hash value by XORing all the ascii codes in the text string. 3232 */ 3233 3234 for (ptr = (char *)name; *ptr != '\0'; ptr++) { 3235 val ^= *ptr; 3236 } 3237 3238 /* 3239 * Return the value modulo the number of hash buckets we allow. 3240 */ 3241 3242 return (val % IPP_NBUCKET); 3243 } 3244 #undef __FN__ 3245 3246 #define __FN__ "update_stats" 3247 static int 3248 update_stats( 3249 kstat_t *ksp, 3250 int rw) 3251 { 3252 ipp_stat_impl_t *sip; 3253 3254 ASSERT(ksp->ks_private != NULL); 3255 sip = (ipp_stat_impl_t *)ksp->ks_private; 3256 3257 /* 3258 * Call the update function passed to ipp_stat_create() for the given 3259 * set of kstats. 3260 */ 3261 3262 return (sip->ippsi_update((ipp_stat_t *)sip, sip->ippsi_arg, rw)); 3263 } 3264 #undef __FN__ 3265 3266 #define __FN__ "init_mods" 3267 static void 3268 init_mods( 3269 void) 3270 { 3271 /* 3272 * Initialise the array of all module structures and the module 3273 * structure kmem cache. 3274 */ 3275 3276 rw_init(ipp_mod_byid_lock, NULL, RW_DEFAULT, 3277 (void *)ipltospl(LOCK_LEVEL)); 3278 ipp_mod_byid = kmem_zalloc(sizeof (ipp_mod_t *) * (ipp_max_mod + 1), 3279 KM_SLEEP); 3280 ipp_mod_byid[ipp_max_mod] = (ipp_mod_t *)-1; 3281 ipp_mid_limit = (ipp_mod_id_t)(ipp_max_mod - 1); 3282 3283 ipp_mod_cache = kmem_cache_create("ipp_mod", sizeof (ipp_mod_t), 3284 IPP_ALIGN, mod_constructor, mod_destructor, NULL, NULL, NULL, 0); 3285 ASSERT(ipp_mod_cache != NULL); 3286 3287 /* 3288 * Initialize the 'module by name' hash bucket array. 3289 */ 3290 3291 rw_init(ipp_mod_byname_lock, NULL, RW_DEFAULT, 3292 (void *)ipltospl(LOCK_LEVEL)); 3293 bzero(ipp_mod_byname, IPP_NBUCKET * sizeof (ipp_ref_t *)); 3294 } 3295 #undef __FN__ 3296 3297 #define __FN__ "init_actions" 3298 static void 3299 init_actions( 3300 void) 3301 { 3302 /* 3303 * Initialise the array of all action structures and the action 3304 * structure cache. 3305 */ 3306 3307 rw_init(ipp_action_byid_lock, NULL, RW_DEFAULT, 3308 (void *)ipltospl(LOCK_LEVEL)); 3309 ipp_action_byid = kmem_zalloc(sizeof (ipp_action_t *) * 3310 (ipp_max_action + 1), KM_SLEEP); 3311 ipp_action_byid[ipp_max_action] = (ipp_action_t *)-1; 3312 ipp_aid_limit = (ipp_action_id_t)(ipp_max_action - 1); 3313 3314 ipp_action_cache = kmem_cache_create("ipp_action", 3315 sizeof (ipp_action_t), IPP_ALIGN, action_constructor, 3316 action_destructor, NULL, NULL, NULL, 0); 3317 ASSERT(ipp_action_cache != NULL); 3318 3319 /* 3320 * Initialize the 'action by name' hash bucket array (and the special 3321 * 'hash' bucket for nameless actions). 3322 */ 3323 3324 rw_init(ipp_action_byname_lock, NULL, RW_DEFAULT, 3325 (void *)ipltospl(LOCK_LEVEL)); 3326 bzero(ipp_action_byname, IPP_NBUCKET * sizeof (ipp_ref_t *)); 3327 ipp_action_noname = NULL; 3328 } 3329 #undef __FN__ 3330 3331 #define __FN__ "init_packets" 3332 static void 3333 init_packets( 3334 void) 3335 { 3336 /* 3337 * Initialise the packet structure cache. 3338 */ 3339 3340 ipp_packet_cache = kmem_cache_create("ipp_packet", 3341 sizeof (ipp_packet_t), IPP_ALIGN, packet_constructor, 3342 packet_destructor, NULL, NULL, NULL, 0); 3343 ASSERT(ipp_packet_cache != NULL); 3344 } 3345 #undef __FN__ 3346 3347 /* 3348 * Kmem cache constructor/destructor functions. 3349 */ 3350 3351 #define __FN__ "mod_constructor" 3352 /*ARGSUSED*/ 3353 static int 3354 mod_constructor( 3355 void *buf, 3356 void *cdrarg, 3357 int kmflags) 3358 { 3359 ipp_mod_t *imp; 3360 ipp_mod_id_t mid; 3361 3362 ASSERT(buf != NULL); 3363 bzero(buf, sizeof (ipp_mod_t)); 3364 imp = (ipp_mod_t *)buf; 3365 3366 rw_enter(ipp_mod_byid_lock, RW_WRITER); 3367 3368 /* 3369 * Get a new module id. 3370 */ 3371 3372 if ((mid = get_mid()) <= IPP_MOD_RESERVED) { 3373 rw_exit(ipp_mod_byid_lock); 3374 return (-1); 3375 } 3376 3377 /* 3378 * Initialize the buffer as a module structure in PROTO form. 3379 */ 3380 3381 imp->ippm_destruct_pending = B_TRUE; 3382 imp->ippm_state = IPP_MODSTATE_PROTO; 3383 rw_init(imp->ippm_lock, NULL, RW_DEFAULT, 3384 (void *)ipltospl(LOCK_LEVEL)); 3385 3386 /* 3387 * Insert it into the array of all module structures. 3388 */ 3389 3390 imp->ippm_id = mid; 3391 ipp_mod_byid[mid] = imp; 3392 3393 rw_exit(ipp_mod_byid_lock); 3394 3395 return (0); 3396 } 3397 #undef __FN__ 3398 3399 #define __FN__ "mod_destructor" 3400 /*ARGSUSED*/ 3401 static void 3402 mod_destructor( 3403 void *buf, 3404 void *cdrarg) 3405 { 3406 ipp_mod_t *imp; 3407 3408 ASSERT(buf != NULL); 3409 imp = (ipp_mod_t *)buf; 3410 3411 ASSERT(imp->ippm_state == IPP_MODSTATE_PROTO); 3412 ASSERT(imp->ippm_action == NULL); 3413 ASSERT(*imp->ippm_name == '\0'); 3414 ASSERT(imp->ippm_destruct_pending); 3415 3416 rw_enter(ipp_mod_byid_lock, RW_WRITER); 3417 ASSERT(imp->ippm_hold_count == 0); 3418 3419 /* 3420 * NULL the entry in the array of all module structures. 3421 */ 3422 3423 ipp_mod_byid[imp->ippm_id] = NULL; 3424 3425 /* 3426 * Clean up any remnants of the module structure as the buffer is 3427 * about to disappear. 3428 */ 3429 3430 rw_destroy(imp->ippm_lock); 3431 rw_exit(ipp_mod_byid_lock); 3432 } 3433 #undef __FN__ 3434 3435 #define __FN__ "action_constructor" 3436 /*ARGSUSED*/ 3437 static int 3438 action_constructor( 3439 void *buf, 3440 void *cdrarg, 3441 int kmflags) 3442 { 3443 ipp_action_t *ap; 3444 ipp_action_id_t aid; 3445 3446 ASSERT(buf != NULL); 3447 bzero(buf, sizeof (ipp_action_t)); 3448 ap = (ipp_action_t *)buf; 3449 3450 rw_enter(ipp_action_byid_lock, RW_WRITER); 3451 3452 /* 3453 * Get a new action id. 3454 */ 3455 3456 if ((aid = get_aid()) <= IPP_ACTION_RESERVED) { 3457 rw_exit(ipp_action_byid_lock); 3458 return (-1); 3459 } 3460 3461 /* 3462 * Initialize the buffer as an action structure in PROTO form. 3463 */ 3464 3465 ap->ippa_state = IPP_ASTATE_PROTO; 3466 ap->ippa_destruct_pending = B_TRUE; 3467 rw_init(ap->ippa_lock, NULL, RW_DEFAULT, 3468 (void *)ipltospl(LOCK_LEVEL)); 3469 CONFIG_LOCK_INIT(ap->ippa_config_lock); 3470 3471 /* 3472 * Insert it into the array of all action structures. 3473 */ 3474 3475 ap->ippa_id = aid; 3476 ipp_action_byid[aid] = ap; 3477 3478 rw_exit(ipp_action_byid_lock); 3479 return (0); 3480 } 3481 #undef __FN__ 3482 3483 #define __FN__ "action_destructor" 3484 /*ARGSUSED*/ 3485 static void 3486 action_destructor( 3487 void *buf, 3488 void *cdrarg) 3489 { 3490 ipp_action_t *ap; 3491 3492 ASSERT(buf != NULL); 3493 ap = (ipp_action_t *)buf; 3494 3495 ASSERT(ap->ippa_state == IPP_ASTATE_PROTO); 3496 ASSERT(ap->ippa_ref == NULL); 3497 ASSERT(ap->ippa_refby == NULL); 3498 ASSERT(ap->ippa_packets == 0); 3499 ASSERT(*ap->ippa_name == '\0'); 3500 ASSERT(ap->ippa_destruct_pending); 3501 3502 rw_enter(ipp_action_byid_lock, RW_WRITER); 3503 ASSERT(ap->ippa_hold_count == 0); 3504 3505 /* 3506 * NULL the entry in the array of all action structures. 3507 */ 3508 3509 ipp_action_byid[ap->ippa_id] = NULL; 3510 3511 /* 3512 * Clean up any remnants of the action structure as the buffer is 3513 * about to disappear. 3514 */ 3515 3516 CONFIG_LOCK_FINI(ap->ippa_config_lock); 3517 rw_destroy(ap->ippa_lock); 3518 3519 rw_exit(ipp_action_byid_lock); 3520 } 3521 #undef __FN__ 3522 3523 #define __FN__ "packet_constructor" 3524 /*ARGSUSED*/ 3525 static int 3526 packet_constructor( 3527 void *buf, 3528 void *cdrarg, 3529 int kmflags) 3530 { 3531 ipp_packet_t *pp; 3532 ipp_class_t *cp; 3533 3534 ASSERT(buf != NULL); 3535 bzero(buf, sizeof (ipp_packet_t)); 3536 pp = (ipp_packet_t *)buf; 3537 3538 if ((cp = kmem_alloc(ipp_packet_classes * sizeof (ipp_class_t), 3539 KM_NOSLEEP)) == NULL) 3540 return (ENOMEM); 3541 3542 pp->ippp_class_array = cp; 3543 pp->ippp_class_windex = 0; 3544 pp->ippp_class_rindex = 0; 3545 pp->ippp_class_limit = ipp_packet_classes - 1; 3546 3547 return (0); 3548 } 3549 #undef __FN__ 3550 3551 #define __FN__ "packet_destructor" 3552 /*ARGSUSED*/ 3553 static void 3554 packet_destructor( 3555 void *buf, 3556 void *cdrarg) 3557 { 3558 ipp_packet_t *pp; 3559 3560 ASSERT(buf != NULL); 3561 pp = (ipp_packet_t *)buf; 3562 3563 ASSERT(pp->ippp_data == NULL); 3564 ASSERT(pp->ippp_class_windex == 0); 3565 ASSERT(pp->ippp_class_rindex == 0); 3566 ASSERT(pp->ippp_private == NULL); 3567 ASSERT(pp->ippp_private_free == NULL); 3568 3569 kmem_free(pp->ippp_class_array, 3570 (pp->ippp_class_limit + 1) * sizeof (ipp_class_t)); 3571 3572 if (pp->ippp_log != NULL) { 3573 kmem_free(pp->ippp_log, 3574 (pp->ippp_log_limit + 1) * sizeof (ipp_log_t)); 3575 } 3576 } 3577 #undef __FN__ 3578 3579 /* 3580 * Debug message printout code. 3581 */ 3582 3583 #ifdef IPP_DBG 3584 static void 3585 ipp_debug( 3586 uint64_t type, 3587 const char *fn, 3588 char *fmt, 3589 ...) 3590 { 3591 char buf[255]; 3592 va_list adx; 3593 3594 if ((type & ipp_debug_flags) == 0) 3595 return; 3596 3597 mutex_enter(debug_mutex); 3598 va_start(adx, fmt); 3599 (void) vsnprintf(buf, 255, fmt, adx); 3600 va_end(adx); 3601 3602 printf("(%llx) %s: %s", (unsigned long long)curthread->t_did, fn, 3603 buf); 3604 mutex_exit(debug_mutex); 3605 } 3606 #endif /* IPP_DBG */ 3607