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