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