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