Print this page
6659 nvlist_free(NULL) is a no-op
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/os/damap.c
+++ new/usr/src/uts/common/os/damap.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
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 /*
23 23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 26 #include <sys/note.h>
27 27 #include <sys/types.h>
28 28 #include <sys/param.h>
29 29 #include <sys/systm.h>
30 30 #include <sys/buf.h>
31 31 #include <sys/kmem.h>
32 32 #include <sys/cmn_err.h>
33 33 #include <sys/debug.h>
34 34 #include <sys/sunndi.h>
35 35 #include <sys/kstat.h>
36 36 #include <sys/conf.h>
37 37 #include <sys/ddi_periodic.h>
38 38 #include <sys/devctl.h>
39 39 #include <sys/callb.h>
40 40 #include <sys/sysevent.h>
41 41 #include <sys/taskq.h>
42 42 #include <sys/ddi.h>
43 43 #include <sys/bitset.h>
44 44 #include <sys/damap.h>
45 45 #include <sys/damap_impl.h>
46 46
47 47 #ifdef DEBUG
48 48 static int damap_debug = 0;
49 49 #endif /* DEBUG */
50 50
51 51 extern taskq_t *system_taskq;
52 52
53 53 static void dam_addrset_activate(dam_t *, bitset_t *);
54 54 static void dam_addrset_deactivate(dam_t *, bitset_t *);
55 55 static void dam_stabilize_map(void *);
56 56 static void dam_addr_stable_cb(void *);
57 57 static void dam_addrset_stable_cb(void *);
58 58 static void dam_sched_timeout(void (*timeout_cb)(), dam_t *, clock_t);
59 59 static void dam_addr_report(dam_t *, dam_da_t *, id_t, int);
60 60 static void dam_addr_release(dam_t *, id_t);
61 61 static void dam_addr_report_release(dam_t *, id_t);
62 62 static void dam_addr_deactivate(dam_t *, id_t);
63 63 static void dam_deact_cleanup(dam_t *, id_t, char *, damap_deact_rsn_t);
64 64 static id_t dam_get_addrid(dam_t *, char *);
65 65 static int dam_kstat_create(dam_t *);
66 66 static int dam_map_alloc(dam_t *);
67 67
68 68 #define DAM_INCR_STAT(mapp, stat) \
69 69 if ((mapp)->dam_kstatsp) { \
70 70 struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data; \
71 71 stp->stat.value.ui32++; \
72 72 }
73 73
74 74 #define DAM_SET_STAT(mapp, stat, val) \
75 75 if ((mapp)->dam_kstatsp) { \
76 76 struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data; \
77 77 stp->stat.value.ui32 = (val); \
78 78 }
79 79
80 80
81 81 /*
82 82 * increase damap size by 64 entries at a time
83 83 */
84 84 #define DAM_SIZE_BUMP 64
85 85
86 86 int damap_taskq_dispatch_retry_usec = 1000;
87 87
88 88 /*
89 89 * config/unconfig taskq data
90 90 */
91 91 typedef struct {
92 92 dam_t *tqd_mapp;
93 93 id_t tqd_id;
94 94 } cfg_tqd_t;
95 95
96 96 extern pri_t maxclsyspri;
97 97
98 98 /*
99 99 * Create new device address map
100 100 *
101 101 * name: map name (kstat unique)
102 102 * size: max # of map entries
103 103 * mode: style of address reports: per-address or fullset
104 104 * stable_usec: # of quiescent microseconds before report/map is stable
105 105 *
106 106 * activate_arg: address provider activation-callout private
107 107 * activate_cb: address provider activation callback handler
108 108 * deactivate_cb: address provider deactivation callback handler
109 109 *
110 110 * config_arg: configuration-callout private
111 111 * config_cb: class configuration callout
112 112 * unconfig_cb: class unconfiguration callout
113 113 *
114 114 * damapp: pointer to map handle (return)
115 115 *
116 116 * Returns: DAM_SUCCESS
117 117 * DAM_EINVAL Invalid argument(s)
118 118 * DAM_FAILURE General failure
119 119 */
120 120 int
121 121 damap_create(char *name, damap_rptmode_t mode, int map_opts,
122 122 int stable_usec, void *activate_arg, damap_activate_cb_t activate_cb,
123 123 damap_deactivate_cb_t deactivate_cb,
124 124 void *config_arg, damap_configure_cb_t configure_cb,
125 125 damap_unconfig_cb_t unconfig_cb,
126 126 damap_t **damapp)
127 127 {
128 128 dam_t *mapp;
129 129
130 130 if (configure_cb == NULL || unconfig_cb == NULL || name == NULL)
131 131 return (DAM_EINVAL);
132 132
133 133 mapp = kmem_zalloc(sizeof (*mapp), KM_SLEEP);
134 134 mapp->dam_options = map_opts;
135 135 mapp->dam_stable_ticks = drv_usectohz(stable_usec);
136 136 mapp->dam_size = 0;
137 137 mapp->dam_rptmode = mode;
138 138 mapp->dam_activate_arg = activate_arg;
139 139 mapp->dam_activate_cb = (activate_cb_t)activate_cb;
140 140 mapp->dam_deactivate_cb = (deactivate_cb_t)deactivate_cb;
141 141 mapp->dam_config_arg = config_arg;
142 142 mapp->dam_configure_cb = (configure_cb_t)configure_cb;
143 143 mapp->dam_unconfig_cb = (unconfig_cb_t)unconfig_cb;
144 144 mapp->dam_name = i_ddi_strdup(name, KM_SLEEP);
145 145 mutex_init(&mapp->dam_lock, NULL, MUTEX_DRIVER, NULL);
146 146 cv_init(&mapp->dam_sync_cv, NULL, CV_DRIVER, NULL);
147 147 bitset_init(&mapp->dam_active_set);
148 148 bitset_init(&mapp->dam_stable_set);
149 149 bitset_init(&mapp->dam_report_set);
150 150 *damapp = (damap_t *)mapp;
151 151
152 152 DTRACE_PROBE5(damap__create,
153 153 char *, mapp->dam_name, damap_t *, mapp,
154 154 damap_rptmode_t, mode, int, map_opts, int, stable_usec);
155 155
156 156 return (DAM_SUCCESS);
157 157 }
158 158
159 159 /*
160 160 * Allocate backing resources
161 161 *
162 162 * DAMs are lightly backed on create - major allocations occur
163 163 * at the time a report is made to the map, and are extended on
164 164 * a demand basis.
165 165 */
166 166 static int
167 167 dam_map_alloc(dam_t *mapp)
168 168 {
169 169 void *softstate_p;
170 170
171 171 ASSERT(mutex_owned(&mapp->dam_lock));
172 172 if (mapp->dam_flags & DAM_DESTROYPEND)
173 173 return (DAM_FAILURE);
174 174
175 175 /*
176 176 * dam_high > 0 signals map allocation complete
177 177 */
178 178 if (mapp->dam_high)
179 179 return (DAM_SUCCESS);
180 180
181 181 mapp->dam_size = DAM_SIZE_BUMP;
182 182 if (ddi_soft_state_init(&softstate_p, sizeof (dam_da_t),
183 183 mapp->dam_size) != DDI_SUCCESS)
184 184 return (DAM_FAILURE);
185 185
186 186 if (ddi_strid_init(&mapp->dam_addr_hash, mapp->dam_size) !=
187 187 DDI_SUCCESS) {
188 188 ddi_soft_state_fini(softstate_p);
189 189 return (DAM_FAILURE);
190 190 }
191 191 if (dam_kstat_create(mapp) != DDI_SUCCESS) {
192 192 ddi_soft_state_fini(softstate_p);
193 193 ddi_strid_fini(&mapp->dam_addr_hash);
194 194 return (DAM_FAILURE);
195 195 }
196 196 mapp->dam_da = softstate_p;
197 197 mapp->dam_high = 1;
198 198 bitset_resize(&mapp->dam_active_set, mapp->dam_size);
199 199 bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
200 200 bitset_resize(&mapp->dam_report_set, mapp->dam_size);
201 201 return (DAM_SUCCESS);
202 202 }
203 203
204 204 /*
205 205 * Destroy address map
206 206 *
207 207 * damapp: address map
208 208 *
209 209 * Returns: DAM_SUCCESS
210 210 * DAM_EINVAL Invalid argument(s)
211 211 * DAM_FAILURE General failure
212 212 */
213 213 void
214 214 damap_destroy(damap_t *damapp)
215 215 {
216 216 int i;
217 217 dam_t *mapp = (dam_t *)damapp;
218 218
219 219 ASSERT(mapp);
220 220
221 221 DTRACE_PROBE2(damap__destroy,
222 222 char *, mapp->dam_name, damap_t *, mapp);
223 223
224 224 mutex_enter(&mapp->dam_lock);
225 225
226 226 /*
227 227 * prevent new reports from being added to the map
228 228 */
229 229 mapp->dam_flags |= DAM_DESTROYPEND;
230 230
231 231 if (mapp->dam_high) {
232 232 mutex_exit(&mapp->dam_lock);
233 233 /*
234 234 * wait for outstanding reports to stabilize and cancel
235 235 * the timer for this map
236 236 */
237 237 (void) damap_sync(damapp, 0);
238 238 mutex_enter(&mapp->dam_lock);
239 239 dam_sched_timeout(NULL, mapp, 0);
240 240
241 241 /*
242 242 * map is at full stop
243 243 * release the contents of the map, invoking the
244 244 * detactivation protocol as addresses are released
245 245 */
246 246 mutex_exit(&mapp->dam_lock);
247 247 for (i = 1; i < mapp->dam_high; i++) {
248 248 if (ddi_get_soft_state(mapp->dam_da, i) == NULL)
249 249 continue;
250 250
251 251 ASSERT(DAM_IN_REPORT(mapp, i) == 0);
252 252
253 253 if (DAM_IS_STABLE(mapp, i)) {
254 254 dam_addr_deactivate(mapp, i);
255 255 } else {
256 256 ddi_strid_free(mapp->dam_addr_hash, i);
257 257 ddi_soft_state_free(mapp->dam_da, i);
258 258 }
259 259 }
260 260 ddi_strid_fini(&mapp->dam_addr_hash);
261 261 ddi_soft_state_fini(&mapp->dam_da);
262 262 kstat_delete(mapp->dam_kstatsp);
263 263 } else
264 264 mutex_exit(&mapp->dam_lock);
265 265
266 266 bitset_fini(&mapp->dam_active_set);
267 267 bitset_fini(&mapp->dam_stable_set);
268 268 bitset_fini(&mapp->dam_report_set);
269 269 mutex_destroy(&mapp->dam_lock);
270 270 cv_destroy(&mapp->dam_sync_cv);
271 271 if (mapp->dam_name)
272 272 kmem_free(mapp->dam_name, strlen(mapp->dam_name) + 1);
273 273 kmem_free(mapp, sizeof (*mapp));
274 274 }
275 275
276 276 /*
277 277 * Wait for map stability. If sync was successfull then return 1.
278 278 * If called with a non-zero sync_usec, then a return value of 0 means a
279 279 * timeout occurred prior to sync completion. NOTE: if sync_usec is
280 280 * non-zero, it should be much longer than dam_stable_ticks.
281 281 *
282 282 * damapp: address map
283 283 * sync_usec: micorseconds until we give up on sync completion.
284 284 */
285 285 #define WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND)
286 286 int
287 287 damap_sync(damap_t *damapp, int sync_usec)
288 288 {
289 289 dam_t *mapp = (dam_t *)damapp;
290 290 int rv;
291 291
292 292 ASSERT(mapp);
293 293 DTRACE_PROBE3(damap__map__sync__start,
294 294 char *, mapp->dam_name, dam_t *, mapp,
295 295 int, sync_usec);
296 296
297 297 /*
298 298 * Block when waiting for
299 299 * a) stabilization pending or a fullset update pending
300 300 * b) the report set to finalize (bitset is null)
301 301 * c) any scheduled timeouts to fire
302 302 */
303 303 rv = 1; /* return synced */
304 304 mutex_enter(&mapp->dam_lock);
305 305 again: while ((mapp->dam_flags & WAITFOR_FLAGS) ||
306 306 (!bitset_is_null(&mapp->dam_report_set)) ||
307 307 (mapp->dam_tid != 0)) {
308 308 DTRACE_PROBE2(damap__map__sync__waiting,
309 309 char *, mapp->dam_name, dam_t *, mapp);
310 310
311 311 /* Wait for condition relayed via timeout */
312 312 if (sync_usec) {
313 313 if (cv_reltimedwait(&mapp->dam_sync_cv, &mapp->dam_lock,
314 314 drv_usectohz(sync_usec), TR_MICROSEC) == -1) {
315 315 mapp->dam_sync_to_cnt++;
316 316 rv = 0; /* return timeout */
317 317 break;
318 318 }
319 319 } else
320 320 cv_wait(&mapp->dam_sync_cv, &mapp->dam_lock);
321 321 }
322 322
323 323 if (rv) {
324 324 /*
325 325 * Delay one stabilization time after the apparent sync above
326 326 * and verify accuracy - resync if not accurate.
327 327 */
328 328 (void) cv_reltimedwait(&mapp->dam_sync_cv, &mapp->dam_lock,
329 329 mapp->dam_stable_ticks, TR_MICROSEC);
330 330 if (rv && ((mapp->dam_flags & WAITFOR_FLAGS) ||
331 331 (!bitset_is_null(&mapp->dam_report_set)) ||
332 332 (mapp->dam_tid != 0)))
333 333 goto again;
334 334 }
335 335 mutex_exit(&mapp->dam_lock);
336 336
337 337 DTRACE_PROBE3(damap__map__sync__end,
338 338 char *, mapp->dam_name, dam_t *, mapp,
339 339 int, rv);
340 340 return (rv);
341 341 }
342 342
343 343 /*
344 344 * Return 1 if active set is empty
345 345 */
346 346 int
347 347 damap_is_empty(damap_t *damapp)
348 348 {
349 349 dam_t *mapp = (dam_t *)damapp;
350 350 int rv;
351 351
352 352 mutex_enter(&mapp->dam_lock);
353 353 rv = bitset_is_null(&mapp->dam_active_set);
354 354 mutex_exit(&mapp->dam_lock);
355 355 return (rv);
356 356 }
357 357
358 358 /*
359 359 * Get the name of a device address map
360 360 *
361 361 * damapp: address map
362 362 *
363 363 * Returns: name
364 364 */
365 365 char *
366 366 damap_name(damap_t *damapp)
367 367 {
368 368 dam_t *mapp = (dam_t *)damapp;
369 369
370 370 return (mapp ? mapp->dam_name : "UNKNOWN_damap");
371 371 }
372 372
373 373 /*
374 374 * Get the current size of the device address map
375 375 *
376 376 * damapp: address map
377 377 *
378 378 * Returns: size
379 379 */
380 380 int
381 381 damap_size(damap_t *damapp)
382 382 {
383 383 dam_t *mapp = (dam_t *)damapp;
384 384
385 385 return (mapp->dam_size);
386 386 }
387 387
388 388 /*
389 389 * Report an address to per-address report
390 390 *
391 391 * damapp: address map handle
392 392 * address: address in ascii string representation
393 393 * addridp: address ID
394 394 * nvl: optional nvlist of configuration-private data
395 395 * addr_priv: optional provider-private (passed to activate/deactivate cb)
396 396 *
397 397 * Returns: DAM_SUCCESS
398 398 * DAM_EINVAL Invalid argument(s)
399 399 * DAM_MAPFULL address map exhausted
400 400 */
401 401 int
402 402 damap_addr_add(damap_t *damapp, char *address, damap_id_t *addridp,
403 403 nvlist_t *nvl, void *addr_priv)
404 404 {
405 405 dam_t *mapp = (dam_t *)damapp;
406 406 id_t addrid;
407 407 dam_da_t *passp;
408 408
409 409 if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
410 410 return (DAM_EINVAL);
411 411
412 412 DTRACE_PROBE3(damap__addr__add,
413 413 char *, mapp->dam_name, dam_t *, mapp,
414 414 char *, address);
415 415
416 416 mutex_enter(&mapp->dam_lock);
417 417 if ((dam_map_alloc(mapp) != DAM_SUCCESS) ||
418 418 ((addrid = dam_get_addrid(mapp, address)) == 0)) {
419 419 mutex_exit(&mapp->dam_lock);
420 420 return (DAM_MAPFULL);
421 421 }
422 422
423 423 passp = ddi_get_soft_state(mapp->dam_da, addrid);
424 424 ASSERT(passp != NULL);
425 425
426 426 /*
427 427 * If re-reporting the same address (add or remove) clear
428 428 * the existing report
429 429 */
430 430 if (DAM_IN_REPORT(mapp, addrid)) {
431 431 DTRACE_PROBE3(damap__addr__add__jitter,
432 432 char *, mapp->dam_name, dam_t *, mapp,
433 433 char *, address);
434 434 DAM_INCR_STAT(mapp, dam_jitter);
435 435 dam_addr_report_release(mapp, addrid);
436 436 passp->da_jitter++;
437 437 }
438 438 passp->da_ppriv_rpt = addr_priv;
439 439 if (nvl)
440 440 (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
441 441
442 442 dam_addr_report(mapp, passp, addrid, RPT_ADDR_ADD);
443 443 if (addridp != NULL)
444 444 *addridp = (damap_id_t)addrid;
445 445 mutex_exit(&mapp->dam_lock);
446 446 return (DAM_SUCCESS);
447 447 }
448 448
449 449 /*
450 450 * Report removal of address from per-address report
451 451 *
452 452 * damapp: address map
453 453 * address: address in ascii string representation
454 454 *
455 455 * Returns: DAM_SUCCESS
456 456 * DAM_EINVAL Invalid argument(s)
457 457 * DAM_FAILURE General failure
458 458 */
459 459 int
460 460 damap_addr_del(damap_t *damapp, char *address)
461 461 {
462 462 dam_t *mapp = (dam_t *)damapp;
463 463 id_t addrid;
464 464 dam_da_t *passp;
465 465
466 466 if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
467 467 return (DAM_EINVAL);
468 468
469 469 DTRACE_PROBE3(damap__addr__del,
470 470 char *, mapp->dam_name, dam_t *, mapp,
471 471 char *, address);
472 472 mutex_enter(&mapp->dam_lock);
473 473 if (dam_map_alloc(mapp) != DAM_SUCCESS) {
474 474 mutex_exit(&mapp->dam_lock);
475 475 return (DAM_MAPFULL);
476 476 }
477 477
478 478 /*
479 479 * if reporting the removal of an address which is not in the map
480 480 * return success
481 481 */
482 482 if (!(addrid = ddi_strid_str2id(mapp->dam_addr_hash, address))) {
483 483 mutex_exit(&mapp->dam_lock);
484 484 return (DAM_SUCCESS);
485 485 }
486 486 passp = ddi_get_soft_state(mapp->dam_da, addrid);
487 487 ASSERT(passp);
488 488 if (DAM_IN_REPORT(mapp, addrid)) {
489 489 DTRACE_PROBE3(damap__addr__del__jitter,
490 490 char *, mapp->dam_name, dam_t *, mapp,
491 491 char *, address);
492 492 DAM_INCR_STAT(mapp, dam_jitter);
493 493 dam_addr_report_release(mapp, addrid);
494 494 passp->da_jitter++;
495 495 }
496 496 dam_addr_report(mapp, passp, addrid, RPT_ADDR_DEL);
497 497 mutex_exit(&mapp->dam_lock);
498 498 return (DAM_SUCCESS);
499 499 }
500 500
501 501 static int
502 502 damap_addrset_flush_locked(damap_t *damapp)
503 503 {
504 504 dam_t *mapp = (dam_t *)damapp;
505 505 int idx;
506 506
507 507 ASSERT(mapp);
508 508 ASSERT(mutex_owned(&mapp->dam_lock));
509 509 if (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) {
510 510 return (DAM_EINVAL);
511 511 }
512 512
513 513 DTRACE_PROBE2(damap__addrset__flush__locked__enter,
514 514 char *, mapp->dam_name, dam_t *, mapp);
515 515 if (mapp->dam_flags & DAM_SETADD) {
516 516 DTRACE_PROBE2(damap__addrset__flush__locked__reset,
517 517 char *, mapp->dam_name, dam_t *, mapp);
518 518
519 519 /*
520 520 * cancel stabilization timeout
521 521 */
522 522 dam_sched_timeout(NULL, mapp, 0);
523 523 DAM_INCR_STAT(mapp, dam_jitter);
524 524
525 525 /*
526 526 * clear pending reports
527 527 */
528 528 for (idx = 1; idx < mapp->dam_high; idx++) {
529 529 if (DAM_IN_REPORT(mapp, idx)) {
530 530 dam_addr_report_release(mapp, idx);
531 531 }
532 532 }
533 533
534 534 bitset_zero(&mapp->dam_report_set);
535 535 mapp->dam_flags &= ~DAM_SETADD;
536 536 cv_signal(&mapp->dam_sync_cv);
537 537 }
538 538
539 539 return (DAM_SUCCESS);
540 540 }
541 541
542 542 /*
543 543 * Initiate full-set report
544 544 *
545 545 * damapp: address map
546 546 *
547 547 * Returns: DAM_SUCCESS
548 548 * DAM_EINVAL Invalid argument(s)
549 549 */
550 550 int
551 551 damap_addrset_begin(damap_t *damapp)
552 552 {
553 553 dam_t *mapp = (dam_t *)damapp;
554 554 int rv;
555 555
556 556 if (mapp == NULL) {
557 557 return (DAM_EINVAL);
558 558 }
559 559
560 560 DTRACE_PROBE2(damap__addrset__begin,
561 561 char *, mapp->dam_name, dam_t *, mapp);
562 562
563 563 mutex_enter(&mapp->dam_lock);
564 564 if (dam_map_alloc(mapp) != DAM_SUCCESS) {
565 565 mutex_exit(&mapp->dam_lock);
566 566
567 567 return (DAM_MAPFULL);
568 568 }
569 569
570 570 rv = damap_addrset_flush_locked(damapp);
571 571 if (rv == DAM_SUCCESS) {
572 572 mapp->dam_flags |= DAM_SETADD;
573 573 }
574 574 mutex_exit(&mapp->dam_lock);
575 575
576 576 return (rv);
577 577 }
578 578
579 579 /*
580 580 * Cancel full-set report
581 581 *
582 582 * damapp: address map
583 583 *
584 584 * Returns: DAM_SUCCESS
585 585 * DAM_EINVAL Invalid argument(s)
586 586 */
587 587 int
588 588 damap_addrset_flush(damap_t *damapp)
589 589 {
590 590 int rv;
591 591 dam_t *mapp = (dam_t *)damapp;
592 592
593 593 if (mapp == NULL) {
594 594 return (DAM_EINVAL);
595 595 }
596 596
597 597 DTRACE_PROBE2(damap__addrset__flush,
598 598 char *, mapp->dam_name, dam_t *, mapp);
599 599
600 600 mutex_enter(&mapp->dam_lock);
601 601 rv = damap_addrset_flush_locked(damapp);
602 602 mutex_exit(&mapp->dam_lock);
603 603
604 604 return (rv);
605 605 }
606 606
607 607 /*
608 608 * Report address to full-set report
609 609 *
610 610 * damapp: address map handle
611 611 * address: address in ascii string representation
612 612 * rindx: index if address stabilizes
613 613 * nvl: optional nvlist of configuration-private data
614 614 * addr_priv: optional provider-private data (passed to activate/release cb)
615 615 *
616 616 * Returns: DAM_SUCCESS
617 617 * DAM_EINVAL Invalid argument(s)
618 618 * DAM_MAPFULL address map exhausted
619 619 * DAM_FAILURE General failure
620 620 */
621 621 int
622 622 damap_addrset_add(damap_t *damapp, char *address, damap_id_t *ridx,
623 623 nvlist_t *nvl, void *addr_priv)
624 624 {
625 625 dam_t *mapp = (dam_t *)damapp;
626 626 id_t addrid;
627 627 dam_da_t *passp;
628 628
629 629 if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
630 630 return (DAM_EINVAL);
631 631
632 632 DTRACE_PROBE3(damap__addrset__add,
633 633 char *, mapp->dam_name, dam_t *, mapp, char *, address);
634 634
635 635 mutex_enter(&mapp->dam_lock);
636 636 if (!(mapp->dam_flags & DAM_SETADD)) {
637 637 mutex_exit(&mapp->dam_lock);
638 638 return (DAM_FAILURE);
639 639 }
640 640
641 641 if ((addrid = dam_get_addrid(mapp, address)) == 0) {
642 642 mutex_exit(&mapp->dam_lock);
643 643 return (DAM_MAPFULL);
644 644 }
645 645
646 646 passp = ddi_get_soft_state(mapp->dam_da, addrid);
647 647 ASSERT(passp);
648 648 if (DAM_IN_REPORT(mapp, addrid)) {
649 649 DTRACE_PROBE3(damap__addrset__add__jitter,
650 650 char *, mapp->dam_name, dam_t *, mapp,
651 651 char *, address);
652 652 dam_addr_report_release(mapp, addrid);
653 653 passp->da_jitter++;
654 654 }
655 655 passp->da_ppriv_rpt = addr_priv;
656 656 if (nvl)
657 657 (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
658 658 bitset_add(&mapp->dam_report_set, addrid);
659 659 if (ridx)
660 660 *ridx = (damap_id_t)addrid;
661 661 mutex_exit(&mapp->dam_lock);
662 662 return (DAM_SUCCESS);
663 663 }
664 664
665 665 /*
666 666 * Commit full-set report for stabilization
667 667 *
668 668 * damapp: address map handle
669 669 * flags: (currently 0)
670 670 *
671 671 * Returns: DAM_SUCCESS
672 672 * DAM_EINVAL Invalid argument(s)
673 673 * DAM_FAILURE General failure
674 674 */
675 675 int
676 676 damap_addrset_end(damap_t *damapp, int flags)
677 677 {
678 678 dam_t *mapp = (dam_t *)damapp;
679 679 int i;
680 680
681 681 if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
682 682 return (DAM_EINVAL);
683 683
684 684 DTRACE_PROBE2(damap__addrset__end,
685 685 char *, mapp->dam_name, dam_t *, mapp);
686 686
687 687 mutex_enter(&mapp->dam_lock);
688 688 if (!(mapp->dam_flags & DAM_SETADD)) {
689 689 mutex_exit(&mapp->dam_lock);
690 690 return (DAM_FAILURE);
691 691 }
692 692
693 693 if (flags & DAMAP_END_RESET) {
694 694 DTRACE_PROBE2(damap__addrset__end__reset,
695 695 char *, mapp->dam_name, dam_t *, mapp);
696 696 dam_sched_timeout(NULL, mapp, 0);
697 697 for (i = 1; i < mapp->dam_high; i++)
698 698 if (DAM_IN_REPORT(mapp, i))
699 699 dam_addr_report_release(mapp, i);
700 700 } else {
701 701 mapp->dam_last_update = gethrtime();
702 702 dam_sched_timeout(dam_addrset_stable_cb, mapp,
703 703 mapp->dam_stable_ticks);
704 704 }
705 705 mutex_exit(&mapp->dam_lock);
706 706 return (DAM_SUCCESS);
707 707 }
708 708
709 709 /*
710 710 * Return nvlist registered with reported address
711 711 *
712 712 * damapp: address map handle
713 713 * addrid: address ID
714 714 *
715 715 * Returns: nvlist_t * provider supplied via damap_addr{set}_add())
716 716 * NULL
717 717 */
718 718 nvlist_t *
719 719 damap_id2nvlist(damap_t *damapp, damap_id_t addrid)
720 720 {
721 721 dam_t *mapp = (dam_t *)damapp;
722 722 dam_da_t *pass;
723 723
724 724 if (mapp->dam_high && ddi_strid_id2str(mapp->dam_addr_hash, addrid)) {
725 725 if (pass = ddi_get_soft_state(mapp->dam_da, addrid))
726 726 return (pass->da_nvl);
727 727 }
728 728 return (NULL);
729 729 }
730 730
731 731 /*
732 732 * Return address string
733 733 *
734 734 * damapp: address map handle
735 735 * addrid: address ID
736 736 *
737 737 * Returns: char * Address string
738 738 * NULL
739 739 */
740 740 char *
741 741 damap_id2addr(damap_t *damapp, damap_id_t addrid)
742 742 {
743 743 dam_t *mapp = (dam_t *)damapp;
744 744
745 745 if (mapp->dam_high)
746 746 return (ddi_strid_id2str(mapp->dam_addr_hash, addrid));
747 747 else
748 748 return (NULL);
749 749 }
750 750
751 751 /*
752 752 * Release address reference in map
753 753 *
754 754 * damapp: address map handle
755 755 * addrid: address ID
756 756 */
757 757 void
758 758 damap_id_rele(damap_t *damapp, damap_id_t addrid)
759 759 {
760 760 dam_t *mapp = (dam_t *)damapp;
761 761 dam_da_t *passp;
762 762 char *addr;
763 763
764 764 passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
765 765 ASSERT(passp);
766 766
767 767 addr = damap_id2addr(damapp, addrid);
768 768 DTRACE_PROBE4(damap__id__rele,
769 769 char *, mapp->dam_name, dam_t *, mapp,
770 770 char *, addr, int, passp->da_ref);
771 771
772 772 mutex_enter(&mapp->dam_lock);
773 773
774 774 /*
775 775 * teardown address if last outstanding reference
776 776 */
777 777 if (--passp->da_ref == 0)
778 778 dam_addr_release(mapp, (id_t)addrid);
779 779
780 780 mutex_exit(&mapp->dam_lock);
781 781 }
782 782
783 783 /*
784 784 * Return current reference count on address reference in map
785 785 *
786 786 * damapp: address map handle
787 787 * addrid: address ID
788 788 *
789 789 * Returns: DAM_SUCCESS
790 790 * DAM_FAILURE
791 791 */
792 792 int
793 793 damap_id_ref(damap_t *damapp, damap_id_t addrid)
794 794 {
795 795 dam_t *mapp = (dam_t *)damapp;
796 796 dam_da_t *passp;
797 797 int ref = -1;
798 798
799 799 passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
800 800 if (passp)
801 801 ref = passp->da_ref;
802 802
803 803 return (ref);
804 804 }
805 805
806 806 /*
807 807 * Return next address ID in list
808 808 *
809 809 * damapp: address map handle
810 810 * damap_list: address ID list passed to config|unconfig
811 811 * returned by look by lookup_all
812 812 * last: last ID returned, 0 is start of list
813 813 *
814 814 * Returns: addrid Next ID from the list
815 815 * 0 End of the list
816 816 */
817 817 damap_id_t
818 818 damap_id_next(damap_t *damapp, damap_id_list_t damap_list, damap_id_t last)
819 819 {
820 820 int i, start;
821 821 dam_t *mapp = (dam_t *)damapp;
822 822 bitset_t *dam_list = (bitset_t *)damap_list;
823 823
824 824 if (!mapp || !dam_list)
825 825 return ((damap_id_t)0);
826 826
827 827 start = (int)last + 1;
828 828 for (i = start; i < mapp->dam_high; i++) {
829 829 if (bitset_in_set(dam_list, i)) {
830 830 return ((damap_id_t)i);
831 831 }
832 832 }
833 833 return ((damap_id_t)0);
834 834 }
835 835
836 836 /*
837 837 * Set config private data
838 838 *
839 839 * damapp: address map handle
840 840 * addrid: address ID
841 841 * cfg_priv: configuration private data
842 842 *
843 843 */
844 844 void
845 845 damap_id_priv_set(damap_t *damapp, damap_id_t addrid, void *cfg_priv)
846 846 {
847 847 dam_t *mapp = (dam_t *)damapp;
848 848 dam_da_t *passp;
849 849
850 850 mutex_enter(&mapp->dam_lock);
851 851 passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
852 852 if (!passp) {
853 853 mutex_exit(&mapp->dam_lock);
854 854 return;
855 855 }
856 856 passp->da_cfg_priv = cfg_priv;
857 857 mutex_exit(&mapp->dam_lock);
858 858 }
859 859
860 860 /*
861 861 * Get config private data
862 862 *
863 863 * damapp: address map handle
864 864 * addrid: address ID
865 865 *
866 866 * Returns: configuration private data
867 867 */
868 868 void *
869 869 damap_id_priv_get(damap_t *damapp, damap_id_t addrid)
870 870 {
871 871 dam_t *mapp = (dam_t *)damapp;
872 872 dam_da_t *passp;
873 873 void *rv;
874 874
875 875 mutex_enter(&mapp->dam_lock);
876 876 passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
877 877 if (!passp) {
878 878 mutex_exit(&mapp->dam_lock);
879 879 return (NULL);
880 880 }
881 881 rv = passp->da_cfg_priv;
882 882 mutex_exit(&mapp->dam_lock);
883 883 return (rv);
884 884 }
885 885
886 886 /*
887 887 * Lookup a single address in the active address map
888 888 *
889 889 * damapp: address map handle
890 890 * address: address string
891 891 *
892 892 * Returns: ID of active/stable address
893 893 * 0 Address not in stable set
894 894 *
895 895 * Future: Allow the caller to wait for stabilize before returning not found.
896 896 */
897 897 damap_id_t
898 898 damap_lookup(damap_t *damapp, char *address)
899 899 {
900 900 dam_t *mapp = (dam_t *)damapp;
901 901 id_t addrid = 0;
902 902 dam_da_t *passp = NULL;
903 903
904 904 DTRACE_PROBE3(damap__lookup,
905 905 char *, mapp->dam_name, dam_t *, mapp,
906 906 char *, address);
907 907 mutex_enter(&mapp->dam_lock);
908 908 if (!mapp->dam_high)
909 909 addrid = 0;
910 910 else
911 911 addrid = ddi_strid_str2id(mapp->dam_addr_hash, address);
912 912 if (addrid) {
913 913 if (DAM_IS_STABLE(mapp, addrid)) {
914 914 passp = ddi_get_soft_state(mapp->dam_da, addrid);
915 915 ASSERT(passp);
916 916 if (passp) {
917 917 passp->da_ref++;
918 918 } else {
919 919 addrid = 0;
920 920 }
921 921 } else {
922 922 addrid = 0;
923 923 }
924 924 }
925 925 mutex_exit(&mapp->dam_lock);
926 926 DTRACE_PROBE4(damap__lookup__return,
927 927 char *, mapp->dam_name, dam_t *, mapp,
928 928 char *, address, int, addrid);
929 929 return ((damap_id_t)addrid);
930 930 }
931 931
932 932
933 933 /*
934 934 * Return the list of stable addresses in the map
935 935 *
936 936 * damapp: address map handle
937 937 * id_listp: pointer to list of address IDs in stable map (returned)
938 938 *
939 939 * Returns: # of entries returned in alist
940 940 */
941 941 int
942 942 damap_lookup_all(damap_t *damapp, damap_id_list_t *id_listp)
943 943 {
944 944 dam_t *mapp = (dam_t *)damapp;
945 945 int mapsz = mapp->dam_size;
946 946 int n_ids, i;
947 947 bitset_t *bsp;
948 948 char *addrp;
949 949 dam_da_t *passp;
950 950
951 951 DTRACE_PROBE2(damap__lookup__all,
952 952 char *, mapp->dam_name, dam_t *, mapp);
953 953 mutex_enter(&mapp->dam_lock);
954 954 if (!mapp->dam_high) {
955 955 *id_listp = (damap_id_list_t)NULL;
956 956 mutex_exit(&mapp->dam_lock);
957 957 DTRACE_PROBE2(damap__lookup__all__nomap,
958 958 char *, mapp->dam_name, dam_t *, mapp);
959 959 return (0);
960 960 }
961 961 bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP);
962 962 bitset_init(bsp);
963 963 bitset_resize(bsp, mapsz);
964 964 bitset_copy(&mapp->dam_active_set, bsp);
965 965 for (n_ids = 0, i = 1; i < mapsz; i++) {
966 966 if (bitset_in_set(bsp, i)) {
967 967 passp = ddi_get_soft_state(mapp->dam_da, i);
968 968 ASSERT(passp);
969 969 if (passp) {
970 970 addrp = damap_id2addr(damapp, i);
971 971 DTRACE_PROBE3(damap__lookup__all__item,
972 972 char *, mapp->dam_name, dam_t *, mapp,
973 973 char *, addrp);
974 974 passp->da_ref++;
975 975 n_ids++;
976 976 }
977 977 }
978 978 }
979 979 if (n_ids) {
980 980 *id_listp = (damap_id_list_t)bsp;
981 981 mutex_exit(&mapp->dam_lock);
982 982 return (n_ids);
983 983 } else {
984 984 *id_listp = (damap_id_list_t)NULL;
985 985 bitset_fini(bsp);
986 986 kmem_free(bsp, sizeof (*bsp));
987 987 mutex_exit(&mapp->dam_lock);
988 988 return (0);
989 989 }
990 990 }
991 991
992 992 /*
993 993 * Release the address list returned by damap_lookup_all()
994 994 *
995 995 * mapp: address map handle
996 996 * id_list: list of address IDs returned in damap_lookup_all()
997 997 */
998 998 void
999 999 damap_id_list_rele(damap_t *damapp, damap_id_list_t id_list)
1000 1000 {
1001 1001 dam_t *mapp = (dam_t *)damapp;
1002 1002 int i;
1003 1003
1004 1004 if (id_list == NULL)
1005 1005 return;
1006 1006
1007 1007 mutex_enter(&mapp->dam_lock);
1008 1008 for (i = 1; i < mapp->dam_high; i++) {
1009 1009 if (bitset_in_set((bitset_t *)id_list, i))
1010 1010 (void) dam_addr_release(mapp, i);
1011 1011 }
1012 1012 mutex_exit(&mapp->dam_lock);
1013 1013 bitset_fini((bitset_t *)id_list);
1014 1014 kmem_free((void *)id_list, sizeof (bitset_t));
1015 1015 }
1016 1016
1017 1017 /*
1018 1018 * activate an address that has passed the stabilization interval
1019 1019 */
1020 1020 static void
1021 1021 dam_addr_activate(dam_t *mapp, id_t addrid)
1022 1022 {
1023 1023 dam_da_t *passp;
1024 1024 int config_rv;
1025 1025 char *addrstr;
1026 1026
1027 1027 mutex_enter(&mapp->dam_lock);
1028 1028 bitset_add(&mapp->dam_active_set, addrid);
1029 1029 passp = ddi_get_soft_state(mapp->dam_da, addrid);
1030 1030 ASSERT(passp);
1031 1031
1032 1032 /*
1033 1033 * copy the reported nvlist and provider private data
1034 1034 */
1035 1035 addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1036 1036 DTRACE_PROBE3(damap__addr__activate__start,
1037 1037 char *, mapp->dam_name, dam_t *, mapp,
1038 1038 char *, addrstr);
1039 1039 passp->da_nvl = passp->da_nvl_rpt;
1040 1040 passp->da_ppriv = passp->da_ppriv_rpt;
1041 1041 passp->da_ppriv_rpt = NULL;
1042 1042 passp->da_nvl_rpt = NULL;
1043 1043 passp->da_last_stable = gethrtime();
1044 1044 passp->da_stable_cnt++;
1045 1045 mutex_exit(&mapp->dam_lock);
1046 1046 if (mapp->dam_activate_cb) {
1047 1047 (*mapp->dam_activate_cb)(mapp->dam_activate_arg, addrstr,
1048 1048 addrid, &passp->da_ppriv_rpt);
1049 1049 }
1050 1050
1051 1051 /*
1052 1052 * call the address-specific configuration action as part of
1053 1053 * activation.
1054 1054 */
1055 1055 config_rv = (*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp,
1056 1056 addrid);
1057 1057 if (config_rv != DAM_SUCCESS) {
1058 1058 mutex_enter(&mapp->dam_lock);
1059 1059 passp->da_flags |= DA_FAILED_CONFIG;
1060 1060 mutex_exit(&mapp->dam_lock);
1061 1061 DTRACE_PROBE3(damap__addr__activate__config__failure,
1062 1062 char *, mapp->dam_name, dam_t *, mapp,
1063 1063 char *, addrstr);
1064 1064 dam_deact_cleanup(mapp, addrid, addrstr,
1065 1065 DAMAP_DEACT_RSN_CFG_FAIL);
1066 1066 } else {
1067 1067 DTRACE_PROBE3(damap__addr__activate__end,
1068 1068 char *, mapp->dam_name, dam_t *, mapp,
1069 1069 char *, addrstr);
1070 1070 }
1071 1071 }
1072 1072
1073 1073 /*
1074 1074 * deactivate a previously stable address
1075 1075 */
1076 1076 static void
1077 1077 dam_addr_deactivate(dam_t *mapp, id_t addrid)
1078 1078 {
1079 1079 char *addrstr;
1080 1080
1081 1081 addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1082 1082 DTRACE_PROBE3(damap__addr__deactivate__start,
1083 1083 char *, mapp->dam_name, dam_t *, mapp,
1084 1084 char *, addrstr);
1085 1085
1086 1086 /*
1087 1087 * call the unconfiguration callback
1088 1088 */
1089 1089 (*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, addrid);
1090 1090 dam_deact_cleanup(mapp, addrid, addrstr, DAMAP_DEACT_RSN_GONE);
1091 1091 }
1092 1092
1093 1093 static void
1094 1094 dam_deact_cleanup(dam_t *mapp, id_t addrid, char *addrstr,
1095 1095 damap_deact_rsn_t deact_rsn)
1096 1096 {
1097 1097 dam_da_t *passp;
1098 1098
1099 1099 passp = ddi_get_soft_state(mapp->dam_da, addrid);
1100 1100 ASSERT(passp);
1101 1101 if (mapp->dam_deactivate_cb)
1102 1102 (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
↓ open down ↓ |
1102 lines elided |
↑ open up ↑ |
1103 1103 ddi_strid_id2str(mapp->dam_addr_hash, addrid),
1104 1104 addrid, passp->da_ppriv, deact_rsn);
1105 1105
1106 1106 /*
1107 1107 * clear the active bit and free the backing info for
1108 1108 * this address
1109 1109 */
1110 1110 mutex_enter(&mapp->dam_lock);
1111 1111 bitset_del(&mapp->dam_active_set, addrid);
1112 1112 passp->da_ppriv = NULL;
1113 - if (passp->da_nvl)
1114 - nvlist_free(passp->da_nvl);
1113 + nvlist_free(passp->da_nvl);
1115 1114 passp->da_nvl = NULL;
1116 1115 passp->da_ppriv_rpt = NULL;
1117 - if (passp->da_nvl_rpt)
1118 - nvlist_free(passp->da_nvl_rpt);
1116 + nvlist_free(passp->da_nvl_rpt);
1119 1117 passp->da_nvl_rpt = NULL;
1120 1118
1121 1119 DTRACE_PROBE3(damap__addr__deactivate__end,
1122 1120 char *, mapp->dam_name, dam_t *, mapp,
1123 1121 char *, addrstr);
1124 1122
1125 1123 (void) dam_addr_release(mapp, addrid);
1126 1124 mutex_exit(&mapp->dam_lock);
1127 1125 }
1128 1126
1129 1127 /*
1130 1128 * taskq callback for multi-thread activation
1131 1129 */
1132 1130 static void
1133 1131 dam_tq_config(void *arg)
1134 1132 {
1135 1133 cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
1136 1134
1137 1135 dam_addr_activate(tqd->tqd_mapp, tqd->tqd_id);
1138 1136 kmem_free(tqd, sizeof (*tqd));
1139 1137 }
1140 1138
1141 1139 /*
1142 1140 * taskq callback for multi-thread deactivation
1143 1141 */
1144 1142 static void
1145 1143 dam_tq_unconfig(void *arg)
1146 1144 {
1147 1145 cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
1148 1146
1149 1147 dam_addr_deactivate(tqd->tqd_mapp, tqd->tqd_id);
1150 1148 kmem_free(tqd, sizeof (*tqd));
1151 1149 }
1152 1150
1153 1151 /*
1154 1152 * Activate a set of stabilized addresses
1155 1153 */
1156 1154 static void
1157 1155 dam_addrset_activate(dam_t *mapp, bitset_t *activate)
1158 1156 {
1159 1157
1160 1158 int i, nset;
1161 1159 taskq_t *tqp = NULL;
1162 1160 cfg_tqd_t *tqd = NULL;
1163 1161 char tqn[TASKQ_NAMELEN];
1164 1162 extern pri_t maxclsyspri;
1165 1163
1166 1164 if (mapp->dam_options & DAMAP_MTCONFIG) {
1167 1165 /*
1168 1166 * calculate the # of taskq threads to create
1169 1167 */
1170 1168 for (i = 1, nset = 0; i < mapp->dam_high; i++)
1171 1169 if (bitset_in_set(activate, i))
1172 1170 nset++;
1173 1171 ASSERT(nset);
1174 1172 (void) snprintf(tqn, sizeof (tqn), "actv-%s", mapp->dam_name);
1175 1173 tqp = taskq_create(tqn, nset, maxclsyspri, 1,
1176 1174 INT_MAX, TASKQ_PREPOPULATE);
1177 1175 }
1178 1176 for (i = 1; i < mapp->dam_high; i++) {
1179 1177 if (bitset_in_set(activate, i)) {
1180 1178 if (!tqp)
1181 1179 dam_addr_activate(mapp, i);
1182 1180 else {
1183 1181 /*
1184 1182 * multi-threaded activation
1185 1183 */
1186 1184 tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
1187 1185 tqd->tqd_mapp = mapp;
1188 1186 tqd->tqd_id = i;
1189 1187 (void) taskq_dispatch(tqp, dam_tq_config,
1190 1188 tqd, TQ_SLEEP);
1191 1189 }
1192 1190 }
1193 1191 }
1194 1192 if (tqp) {
1195 1193 taskq_wait(tqp);
1196 1194 taskq_destroy(tqp);
1197 1195 }
1198 1196 }
1199 1197
1200 1198 /*
1201 1199 * Deactivate a set of stabilized addresses
1202 1200 */
1203 1201 static void
1204 1202 dam_addrset_deactivate(dam_t *mapp, bitset_t *deactivate)
1205 1203 {
1206 1204 int i, nset;
1207 1205 taskq_t *tqp = NULL;
1208 1206 cfg_tqd_t *tqd = NULL;
1209 1207 char tqn[TASKQ_NAMELEN];
1210 1208
1211 1209 DTRACE_PROBE2(damap__addrset__deactivate,
1212 1210 char *, mapp->dam_name, dam_t *, mapp);
1213 1211
1214 1212 if (mapp->dam_options & DAMAP_MTCONFIG) {
1215 1213 /*
1216 1214 * compute the # of taskq threads to dispatch
1217 1215 */
1218 1216 for (i = 1, nset = 0; i < mapp->dam_high; i++)
1219 1217 if (bitset_in_set(deactivate, i))
1220 1218 nset++;
1221 1219 (void) snprintf(tqn, sizeof (tqn), "deactv-%s",
1222 1220 mapp->dam_name);
1223 1221 tqp = taskq_create(tqn, nset, maxclsyspri, 1,
1224 1222 INT_MAX, TASKQ_PREPOPULATE);
1225 1223 }
1226 1224 for (i = 1; i < mapp->dam_high; i++) {
1227 1225 if (bitset_in_set(deactivate, i)) {
1228 1226 if (!tqp) {
1229 1227 dam_addr_deactivate(mapp, i);
1230 1228 } else {
1231 1229 tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
1232 1230 tqd->tqd_mapp = mapp;
1233 1231 tqd->tqd_id = i;
1234 1232 (void) taskq_dispatch(tqp,
1235 1233 dam_tq_unconfig, tqd, TQ_SLEEP);
1236 1234 }
1237 1235 }
1238 1236 }
1239 1237
1240 1238 if (tqp) {
1241 1239 taskq_wait(tqp);
1242 1240 taskq_destroy(tqp);
1243 1241 }
1244 1242 }
1245 1243
1246 1244 /*
1247 1245 * Release a previously activated address
1248 1246 */
1249 1247 static void
1250 1248 dam_addr_release(dam_t *mapp, id_t addrid)
1251 1249 {
1252 1250 dam_da_t *passp;
1253 1251 char *addrstr;
1254 1252
1255 1253
1256 1254 ASSERT(mutex_owned(&mapp->dam_lock));
1257 1255 passp = ddi_get_soft_state(mapp->dam_da, addrid);
1258 1256 ASSERT(passp);
1259 1257
1260 1258 addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1261 1259 DTRACE_PROBE3(damap__addr__release,
1262 1260 char *, mapp->dam_name, dam_t *, mapp,
1263 1261 char *, addrstr);
1264 1262
1265 1263 /*
1266 1264 * defer releasing the address until outstanding references
1267 1265 * are released
1268 1266 */
1269 1267 if (passp->da_ref > 1) {
1270 1268 DTRACE_PROBE4(damap__addr__release__outstanding__refs,
1271 1269 char *, mapp->dam_name, dam_t *, mapp,
1272 1270 char *, addrstr, int, passp->da_ref);
1273 1271 return;
1274 1272 }
1275 1273
1276 1274 /*
1277 1275 * allow pending reports to stabilize
1278 1276 */
1279 1277 if (DAM_IN_REPORT(mapp, addrid)) {
1280 1278 DTRACE_PROBE3(damap__addr__release__report__pending,
1281 1279 char *, mapp->dam_name, dam_t *, mapp,
1282 1280 char *, addrstr);
1283 1281 return;
1284 1282 }
1285 1283
1286 1284 ddi_strid_free(mapp->dam_addr_hash, addrid);
1287 1285 ddi_soft_state_free(mapp->dam_da, addrid);
1288 1286 }
1289 1287
1290 1288 /*
1291 1289 * process stabilized address reports
1292 1290 */
1293 1291 static void
1294 1292 dam_stabilize_map(void *arg)
1295 1293 {
1296 1294 dam_t *mapp = (dam_t *)arg;
1297 1295 bitset_t delta;
1298 1296 bitset_t cfg;
1299 1297 bitset_t uncfg;
1300 1298 int has_cfg, has_uncfg;
1301 1299 uint32_t i, n_active;
1302 1300
1303 1301 DTRACE_PROBE2(damap__stabilize__map,
1304 1302 char *, mapp->dam_name, dam_t *, mapp);
1305 1303
1306 1304 bitset_init(&delta);
1307 1305 bitset_resize(&delta, mapp->dam_size);
1308 1306 bitset_init(&cfg);
1309 1307 bitset_resize(&cfg, mapp->dam_size);
1310 1308 bitset_init(&uncfg);
1311 1309 bitset_resize(&uncfg, mapp->dam_size);
1312 1310
1313 1311 /*
1314 1312 * determine which addresses have changed during
1315 1313 * this stabilization cycle
1316 1314 */
1317 1315 mutex_enter(&mapp->dam_lock);
1318 1316 ASSERT(mapp->dam_flags & DAM_SPEND);
1319 1317 if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set,
1320 1318 &delta)) {
1321 1319 /*
1322 1320 * no difference
1323 1321 */
1324 1322 bitset_zero(&mapp->dam_stable_set);
1325 1323 mapp->dam_flags &= ~DAM_SPEND;
1326 1324 cv_signal(&mapp->dam_sync_cv);
1327 1325 mutex_exit(&mapp->dam_lock);
1328 1326
1329 1327 bitset_fini(&uncfg);
1330 1328 bitset_fini(&cfg);
1331 1329 bitset_fini(&delta);
1332 1330 DTRACE_PROBE2(damap__stabilize__map__nochange,
1333 1331 char *, mapp->dam_name, dam_t *, mapp);
1334 1332 return;
1335 1333 }
1336 1334
1337 1335 /*
1338 1336 * compute the sets of addresses to be activated and deactivated
1339 1337 */
1340 1338 has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg);
1341 1339 has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg);
1342 1340
1343 1341 /*
1344 1342 * drop map lock while invoking callouts
1345 1343 */
1346 1344 mutex_exit(&mapp->dam_lock);
1347 1345
1348 1346 /*
1349 1347 * activate all newly stable addresss
1350 1348 */
1351 1349 if (has_cfg)
1352 1350 dam_addrset_activate(mapp, &cfg);
1353 1351
1354 1352 /*
1355 1353 * deactivate addresss which are no longer in the map
1356 1354 */
1357 1355 if (has_uncfg)
1358 1356 dam_addrset_deactivate(mapp, &uncfg);
1359 1357
1360 1358
1361 1359 /*
1362 1360 * timestamp the last stable time and increment the kstat keeping
1363 1361 * the # of of stable cycles for the map
1364 1362 */
1365 1363 mutex_enter(&mapp->dam_lock);
1366 1364 bitset_zero(&mapp->dam_stable_set);
1367 1365 mapp->dam_last_stable = gethrtime();
1368 1366 mapp->dam_stable_cnt++;
1369 1367 DAM_INCR_STAT(mapp, dam_cycles);
1370 1368
1371 1369 /*
1372 1370 * determine the number of stable addresses
1373 1371 * and update the n_active kstat for this map
1374 1372 */
1375 1373 for (i = 1, n_active = 0; i < mapp->dam_high; i++)
1376 1374 if (bitset_in_set(&mapp->dam_active_set, i))
1377 1375 n_active++;
1378 1376 DAM_SET_STAT(mapp, dam_active, n_active);
1379 1377
1380 1378 DTRACE_PROBE3(damap__map__stable__end,
1381 1379 char *, mapp->dam_name, dam_t *, mapp,
1382 1380 int, n_active);
1383 1381
1384 1382 mapp->dam_flags &= ~DAM_SPEND;
1385 1383 cv_signal(&mapp->dam_sync_cv);
1386 1384 mutex_exit(&mapp->dam_lock);
1387 1385
1388 1386 bitset_fini(&uncfg);
1389 1387 bitset_fini(&cfg);
1390 1388 bitset_fini(&delta);
1391 1389 }
1392 1390
1393 1391 /*
1394 1392 * per-address stabilization timeout
1395 1393 */
1396 1394 static void
1397 1395 dam_addr_stable_cb(void *arg)
1398 1396 {
1399 1397 dam_t *mapp = (dam_t *)arg;
1400 1398 int i;
1401 1399 dam_da_t *passp;
1402 1400 int spend = 0;
1403 1401 int tpend = 0;
1404 1402 int64_t ts, next_ticks, delta_ticks;
1405 1403
1406 1404 mutex_enter(&mapp->dam_lock);
1407 1405 if (mapp->dam_tid == 0) {
1408 1406 DTRACE_PROBE2(damap__map__addr__stable__cancelled,
1409 1407 char *, mapp->dam_name, dam_t *, mapp);
1410 1408 mutex_exit(&mapp->dam_lock);
1411 1409 return;
1412 1410 }
1413 1411 mapp->dam_tid = 0;
1414 1412
1415 1413 /*
1416 1414 * If still under stabilization, reschedule timeout,
1417 1415 * otherwise dispatch the task to activate and deactivate the
1418 1416 * new stable address
1419 1417 */
1420 1418 if (mapp->dam_flags & DAM_SPEND) {
1421 1419 DAM_INCR_STAT(mapp, dam_overrun);
1422 1420 mapp->dam_stable_overrun++;
1423 1421 DTRACE_PROBE2(damap__map__addr__stable__overrun,
1424 1422 char *, mapp->dam_name, dam_t *, mapp);
1425 1423 dam_sched_timeout(dam_addr_stable_cb, mapp,
1426 1424 mapp->dam_stable_ticks);
1427 1425 mutex_exit(&mapp->dam_lock);
1428 1426 return;
1429 1427 }
1430 1428
1431 1429 DAM_SET_STAT(mapp, dam_overrun, 0);
1432 1430 mapp->dam_stable_overrun = 0;
1433 1431
1434 1432 /* See if any reports stabalized and compute next timeout. */
1435 1433 ts = ddi_get_lbolt64();
1436 1434 next_ticks = mapp->dam_stable_ticks;
1437 1435 for (i = 1; i < mapp->dam_high; i++) {
1438 1436 if (bitset_in_set(&mapp->dam_report_set, i)) {
1439 1437 passp = ddi_get_soft_state(mapp->dam_da, i);
1440 1438 ASSERT(passp);
1441 1439
1442 1440 if (passp->da_deadline <= ts)
1443 1441 spend++; /* report has stabilized */
1444 1442 else {
1445 1443 /* not stabilized, determine next map timeout */
1446 1444 tpend++;
1447 1445 delta_ticks = passp->da_deadline - ts;
1448 1446 if (delta_ticks < next_ticks)
1449 1447 next_ticks = delta_ticks;
1450 1448 }
1451 1449 }
1452 1450 }
1453 1451
1454 1452 /*
1455 1453 * schedule system_taskq activation of stabilized reports
1456 1454 */
1457 1455 if (spend) {
1458 1456 if (taskq_dispatch(system_taskq, dam_stabilize_map,
1459 1457 mapp, TQ_NOSLEEP | TQ_NOQUEUE)) {
1460 1458 DTRACE_PROBE2(damap__map__addr__stable__start,
1461 1459 char *, mapp->dam_name, dam_t *, mapp);
1462 1460
1463 1461 /*
1464 1462 * The stable_set we compute below stays pending until
1465 1463 * processed by dam_stabilize_map. We can't set
1466 1464 * DAM_SPEND (or bitset_del things from the
1467 1465 * report_set) until we *know* that we can handoff the
1468 1466 * result to dam_stabilize_map. If dam_stabilize_map
1469 1467 * starts executing before we are complete, it will
1470 1468 * block on the dam_lock mutex until we are ready.
1471 1469 */
1472 1470 mapp->dam_flags |= DAM_SPEND;
1473 1471
1474 1472 /*
1475 1473 * Copy the current active_set to the stable_set, then
1476 1474 * add or remove stabilized report_set address from
1477 1475 * the stable set (and delete them from the report_set).
1478 1476 */
1479 1477 bitset_copy(&mapp->dam_active_set,
1480 1478 &mapp->dam_stable_set);
1481 1479 for (i = 1; i < mapp->dam_high; i++) {
1482 1480 if (!bitset_in_set(&mapp->dam_report_set, i))
1483 1481 continue;
1484 1482
1485 1483 passp = ddi_get_soft_state(mapp->dam_da, i);
1486 1484 if (passp->da_deadline > ts)
1487 1485 continue; /* report not stabilized */
1488 1486
1489 1487 /* report has stabilized */
1490 1488 if (passp->da_flags & DA_RELE)
1491 1489 bitset_del(&mapp->dam_stable_set, i);
1492 1490 else
1493 1491 bitset_add(&mapp->dam_stable_set, i);
1494 1492
1495 1493 bitset_del(&mapp->dam_report_set, i);
1496 1494 }
1497 1495 } else {
1498 1496 DTRACE_PROBE2(damap__map__addr__stable__spendfail,
1499 1497 char *, mapp->dam_name, dam_t *, mapp);
1500 1498
1501 1499 /*
1502 1500 * Avoid waiting the entire stabalization
1503 1501 * time again if taskq_diskpatch fails.
1504 1502 */
1505 1503 tpend++;
1506 1504 delta_ticks = drv_usectohz(
1507 1505 damap_taskq_dispatch_retry_usec);
1508 1506 if (delta_ticks < next_ticks)
1509 1507 next_ticks = delta_ticks;
1510 1508 }
1511 1509 }
1512 1510
1513 1511 /*
1514 1512 * reschedule the stabilization timer if there are reports
1515 1513 * still pending
1516 1514 */
1517 1515 if (tpend) {
1518 1516 DTRACE_PROBE2(damap__map__addr__stable__tpend, char *,
1519 1517 mapp->dam_name, dam_t *, mapp);
1520 1518 dam_sched_timeout(dam_addr_stable_cb, mapp,
1521 1519 (clock_t)next_ticks);
1522 1520 }
1523 1521
1524 1522 mutex_exit(&mapp->dam_lock);
1525 1523 }
1526 1524
1527 1525 /*
1528 1526 * fullset stabilization timeout callback
1529 1527 */
1530 1528 static void
1531 1529 dam_addrset_stable_cb(void *arg)
1532 1530 {
1533 1531 dam_t *mapp = (dam_t *)arg;
1534 1532
1535 1533 mutex_enter(&mapp->dam_lock);
1536 1534 if (mapp->dam_tid == 0) {
1537 1535 mutex_exit(&mapp->dam_lock);
1538 1536 DTRACE_PROBE2(damap__map__addrset__stable__cancelled,
1539 1537 char *, mapp->dam_name, dam_t *, mapp);
1540 1538 return;
1541 1539 }
1542 1540 mapp->dam_tid = 0;
1543 1541
1544 1542 /*
1545 1543 * If map still underoing stabilization reschedule timeout,
1546 1544 * else dispatch the task to configure the new stable set of
1547 1545 * addresses.
1548 1546 */
1549 1547 if ((mapp->dam_flags & DAM_SPEND) ||
1550 1548 (taskq_dispatch(system_taskq, dam_stabilize_map, mapp,
1551 1549 TQ_NOSLEEP | TQ_NOQUEUE) == NULL)) {
1552 1550 DAM_INCR_STAT(mapp, dam_overrun);
1553 1551 mapp->dam_stable_overrun++;
1554 1552 dam_sched_timeout(dam_addrset_stable_cb, mapp,
1555 1553 drv_usectohz(damap_taskq_dispatch_retry_usec));
1556 1554
1557 1555 DTRACE_PROBE2(damap__map__addrset__stable__overrun,
1558 1556 char *, mapp->dam_name, dam_t *, mapp);
1559 1557 mutex_exit(&mapp->dam_lock);
1560 1558 return;
1561 1559 }
1562 1560
1563 1561 DAM_SET_STAT(mapp, dam_overrun, 0);
1564 1562 mapp->dam_stable_overrun = 0;
1565 1563 bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set);
1566 1564 bitset_zero(&mapp->dam_report_set);
1567 1565 mapp->dam_flags |= DAM_SPEND;
1568 1566 mapp->dam_flags &= ~DAM_SETADD;
1569 1567 /* NOTE: don't need cv_signal since DAM_SPEND is still set */
1570 1568
1571 1569 DTRACE_PROBE2(damap__map__addrset__stable__start,
1572 1570 char *, mapp->dam_name, dam_t *, mapp);
1573 1571 mutex_exit(&mapp->dam_lock);
1574 1572 }
1575 1573
1576 1574 /*
1577 1575 * schedule map timeout in 'ticks' ticks
1578 1576 * if map timer is currently running, cancel if ticks == 0
1579 1577 */
1580 1578 static void
1581 1579 dam_sched_timeout(void (*timeout_cb)(), dam_t *mapp, clock_t ticks)
1582 1580 {
1583 1581 timeout_id_t tid;
1584 1582
1585 1583 DTRACE_PROBE4(damap__sched__timeout,
1586 1584 char *, mapp->dam_name, dam_t *, mapp,
1587 1585 int, ticks, timeout_id_t, mapp->dam_tid);
1588 1586
1589 1587 ASSERT(mutex_owned(&mapp->dam_lock));
1590 1588 if ((tid = mapp->dam_tid) != 0) {
1591 1589 if (ticks == 0) {
1592 1590 mapp->dam_tid = 0;
1593 1591 mutex_exit(&mapp->dam_lock);
1594 1592 (void) untimeout(tid);
1595 1593 mutex_enter(&mapp->dam_lock);
1596 1594 }
1597 1595 } else {
1598 1596 if (timeout_cb && (ticks != 0))
1599 1597 mapp->dam_tid = timeout(timeout_cb, mapp, ticks);
1600 1598 }
1601 1599 }
1602 1600
1603 1601 /*
1604 1602 * report addition or removal of an address
1605 1603 */
1606 1604 static void
1607 1605 dam_addr_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int rpt_type)
1608 1606 {
1609 1607 char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
1610 1608
1611 1609 DTRACE_PROBE4(damap__addr__report,
1612 1610 char *, mapp->dam_name, dam_t *, mapp,
1613 1611 char *, addrstr, int, rpt_type);
1614 1612
1615 1613 ASSERT(mutex_owned(&mapp->dam_lock));
1616 1614 ASSERT(!DAM_IN_REPORT(mapp, addrid));
1617 1615 passp->da_last_report = gethrtime();
1618 1616 mapp->dam_last_update = gethrtime();
1619 1617 passp->da_report_cnt++;
1620 1618 passp->da_deadline = ddi_get_lbolt64() + mapp->dam_stable_ticks;
1621 1619 if (rpt_type == RPT_ADDR_DEL)
1622 1620 passp->da_flags |= DA_RELE;
1623 1621 else if (rpt_type == RPT_ADDR_ADD)
1624 1622 passp->da_flags &= ~DA_RELE;
1625 1623 bitset_add(&mapp->dam_report_set, addrid);
1626 1624 dam_sched_timeout(dam_addr_stable_cb, mapp, mapp->dam_stable_ticks);
1627 1625 }
1628 1626
1629 1627 /*
1630 1628 * release an address report
1631 1629 */
1632 1630 static void
1633 1631 dam_addr_report_release(dam_t *mapp, id_t addrid)
1634 1632 {
1635 1633 dam_da_t *passp;
1636 1634 char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
1637 1635
1638 1636 DTRACE_PROBE3(damap__addr__report__release,
1639 1637 char *, mapp->dam_name, dam_t *, mapp,
1640 1638 char *, addrstr);
1641 1639
1642 1640 ASSERT(mutex_owned(&mapp->dam_lock));
1643 1641 passp = ddi_get_soft_state(mapp->dam_da, addrid);
1644 1642 ASSERT(passp);
1645 1643 /*
1646 1644 * clear the report bit
1647 1645 * if the address has a registered deactivation handler and
1648 1646 * we are holding a private data pointer and the address has not
1649 1647 * stabilized, deactivate the address (private data).
1650 1648 */
↓ open down ↓ |
522 lines elided |
↑ open up ↑ |
1651 1649 bitset_del(&mapp->dam_report_set, addrid);
1652 1650 if (!DAM_IS_STABLE(mapp, addrid) && mapp->dam_deactivate_cb &&
1653 1651 passp->da_ppriv_rpt) {
1654 1652 mutex_exit(&mapp->dam_lock);
1655 1653 (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
1656 1654 ddi_strid_id2str(mapp->dam_addr_hash, addrid),
1657 1655 addrid, passp->da_ppriv_rpt, DAMAP_DEACT_RSN_UNSTBL);
1658 1656 mutex_enter(&mapp->dam_lock);
1659 1657 }
1660 1658 passp->da_ppriv_rpt = NULL;
1661 - if (passp->da_nvl_rpt)
1662 - nvlist_free(passp->da_nvl_rpt);
1659 + nvlist_free(passp->da_nvl_rpt);
1663 1660 }
1664 1661
1665 1662 /*
1666 1663 * return the map ID of an address
1667 1664 */
1668 1665 static id_t
1669 1666 dam_get_addrid(dam_t *mapp, char *address)
1670 1667 {
1671 1668 damap_id_t addrid;
1672 1669 dam_da_t *passp;
1673 1670
1674 1671 ASSERT(mutex_owned(&mapp->dam_lock));
1675 1672 if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) {
1676 1673 if ((addrid = ddi_strid_alloc(mapp->dam_addr_hash,
1677 1674 address)) == (damap_id_t)0) {
1678 1675 return (0);
1679 1676 }
1680 1677 if (ddi_soft_state_zalloc(mapp->dam_da, addrid) !=
1681 1678 DDI_SUCCESS) {
1682 1679 ddi_strid_free(mapp->dam_addr_hash, addrid);
1683 1680 return (0);
1684 1681 }
1685 1682
1686 1683 if (addrid >= mapp->dam_high)
1687 1684 mapp->dam_high = addrid + 1;
1688 1685
1689 1686 /*
1690 1687 * expand bitmaps if ID has outgrown old map size
1691 1688 */
1692 1689 if (mapp->dam_high > mapp->dam_size) {
1693 1690 mapp->dam_size = mapp->dam_size + DAM_SIZE_BUMP;
1694 1691 bitset_resize(&mapp->dam_active_set, mapp->dam_size);
1695 1692 bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
1696 1693 bitset_resize(&mapp->dam_report_set, mapp->dam_size);
1697 1694 }
1698 1695
1699 1696 passp = ddi_get_soft_state(mapp->dam_da, addrid);
1700 1697 passp->da_ref = 1;
1701 1698 passp->da_addr = ddi_strid_id2str(mapp->dam_addr_hash,
1702 1699 addrid); /* for mdb */
1703 1700 }
1704 1701 return (addrid);
1705 1702 }
1706 1703
1707 1704 /*
1708 1705 * create and install map statistics
1709 1706 */
1710 1707 static int
1711 1708 dam_kstat_create(dam_t *mapp)
1712 1709 {
1713 1710 kstat_t *mapsp;
1714 1711 struct dam_kstats *statsp;
1715 1712
1716 1713 mapsp = kstat_create("dam", 0, mapp->dam_name, "damap",
1717 1714 KSTAT_TYPE_NAMED,
1718 1715 sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0);
1719 1716
1720 1717 if (mapsp == NULL)
1721 1718 return (DDI_FAILURE);
1722 1719
1723 1720 statsp = (struct dam_kstats *)mapsp->ks_data;
1724 1721 kstat_named_init(&statsp->dam_cycles, "cycles", KSTAT_DATA_UINT32);
1725 1722 kstat_named_init(&statsp->dam_overrun, "overrun", KSTAT_DATA_UINT32);
1726 1723 kstat_named_init(&statsp->dam_jitter, "jitter", KSTAT_DATA_UINT32);
1727 1724 kstat_named_init(&statsp->dam_active, "active", KSTAT_DATA_UINT32);
1728 1725 kstat_install(mapsp);
1729 1726 mapp->dam_kstatsp = mapsp;
1730 1727 return (DDI_SUCCESS);
1731 1728 }
↓ open down ↓ |
59 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX