Print this page
10114 fmev_proxy_cb() doesn't need inval checks
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/fm/libfmevent/common/fmev_subscribe.c
+++ new/usr/src/lib/fm/libfmevent/common/fmev_subscribe.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
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
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 /*
27 + * Copyright (c) 2018, Joyent, Inc.
28 + */
29 +
30 +/*
27 31 * FMA event subscription interfaces - subscribe to FMA protocol
28 32 * from outside the fault manager.
29 33 */
30 34
31 35 #include <sys/types.h>
32 36 #include <atomic.h>
33 37 #include <libsysevent.h>
34 38 #include <libuutil.h>
35 39 #include <pthread.h>
36 40 #include <stdarg.h>
37 41 #include <stdlib.h>
38 42 #include <string.h>
39 43 #include <strings.h>
40 44 #include <unistd.h>
41 45 #include <fm/libtopo.h>
42 46
43 47 #include <fm/libfmevent.h>
44 48
45 49 #include "fmev_impl.h"
46 50
47 51 static topo_hdl_t *g_topohdl;
48 52
49 53 typedef struct {
50 54 struct fmev_hdl_cmn sh_cmn;
51 55 evchan_t *sh_binding;
52 56 uu_avl_pool_t *sh_pool;
53 57 uu_avl_t *sh_avl;
54 58 uint32_t sh_subcnt;
55 59 uint32_t sh_flags;
56 60 sysevent_subattr_t *sh_attr;
57 61 pthread_mutex_t sh_lock;
58 62 pthread_mutex_t sh_srlz_lock;
59 63 } fmev_shdl_impl_t;
60 64
61 65 #define HDL2IHDL(hdl) ((fmev_shdl_impl_t *)(hdl))
62 66 #define IHDL2HDL(ihdl) ((fmev_shdl_t)(ihdl))
63 67
64 68 #define _FMEV_SHMAGIC 0x5368446c /* ShDl */
65 69 #define FMEV_SHDL_VALID(ihdl) ((ihdl)->sh_cmn.hc_magic == _FMEV_SHMAGIC)
66 70
67 71 #define SHDL_FL_SERIALIZE 0x1
68 72
69 73 #define FMEV_API_ENTER(hdl, v) \
70 74 fmev_api_enter(&HDL2IHDL(hdl)->sh_cmn, LIBFMEVENT_VERSION_##v)
71 75
72 76 /*
73 77 * For each subscription on a handle we add a node to an avl tree
74 78 * to track subscriptions.
75 79 */
76 80
77 81 #define FMEV_SID_SZ (16 + 1) /* Matches MAX_SUBID_LEN */
78 82
79 83 struct fmev_subinfo {
80 84 uu_avl_node_t si_node;
81 85 fmev_shdl_impl_t *si_ihdl;
82 86 char si_pat[FMEV_MAX_CLASS];
83 87 char si_sid[FMEV_SID_SZ];
84 88 fmev_cbfunc_t *si_cb;
85 89 void *si_cbarg;
86 90 };
87 91
88 92 struct fmev_hdl_cmn *
89 93 fmev_shdl_cmn(fmev_shdl_t hdl)
90 94 {
91 95 return (&HDL2IHDL(hdl)->sh_cmn);
92 96 }
93 97
94 98 static int
95 99 shdlctl_start(fmev_shdl_impl_t *ihdl)
96 100 {
97 101 (void) pthread_mutex_lock(&ihdl->sh_lock);
98 102
99 103 if (ihdl->sh_subcnt == 0) {
100 104 return (1); /* lock still held */
101 105 } else {
102 106 (void) pthread_mutex_unlock(&ihdl->sh_lock);
103 107 return (0);
104 108 }
105 109 }
106 110
107 111 static void
108 112 shdlctl_end(fmev_shdl_impl_t *ihdl)
109 113 {
110 114 (void) pthread_mutex_unlock(&ihdl->sh_lock);
111 115 }
112 116
113 117 fmev_err_t
114 118 fmev_shdlctl_serialize(fmev_shdl_t hdl)
115 119 {
116 120 fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
117 121
118 122 if (!FMEV_API_ENTER(hdl, 1))
119 123 return (fmev_errno);
120 124
121 125 if (!shdlctl_start(ihdl))
122 126 return (fmev_seterr(FMEVERR_BUSY));
123 127
124 128 if (!(ihdl->sh_flags & SHDL_FL_SERIALIZE)) {
125 129 (void) pthread_mutex_init(&ihdl->sh_srlz_lock, NULL);
126 130 ihdl->sh_flags |= SHDL_FL_SERIALIZE;
127 131 }
128 132
129 133 shdlctl_end(ihdl);
130 134 return (fmev_seterr(FMEV_SUCCESS));
131 135 }
132 136
133 137 fmev_err_t
134 138 fmev_shdlctl_thrattr(fmev_shdl_t hdl, pthread_attr_t *attr)
135 139 {
136 140 fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
137 141
138 142 if (!FMEV_API_ENTER(hdl, 1))
139 143 return (fmev_errno);
140 144
141 145 if (!shdlctl_start(ihdl))
142 146 return (fmev_seterr(FMEVERR_BUSY));
143 147
144 148 sysevent_subattr_thrattr(ihdl->sh_attr, attr);
145 149
146 150 shdlctl_end(ihdl);
147 151 return (fmev_seterr(FMEV_SUCCESS));
148 152 }
149 153
150 154 fmev_err_t
151 155 fmev_shdlctl_sigmask(fmev_shdl_t hdl, sigset_t *set)
152 156 {
153 157 fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
154 158
155 159 if (!FMEV_API_ENTER(hdl, 1))
156 160 return (fmev_errno);
157 161
158 162 if (!shdlctl_start(ihdl))
159 163 return (fmev_seterr(FMEVERR_BUSY));
160 164
161 165 sysevent_subattr_sigmask(ihdl->sh_attr, set);
162 166
163 167 shdlctl_end(ihdl);
164 168 return (fmev_seterr(FMEV_SUCCESS));
165 169 }
166 170
167 171 fmev_err_t
168 172 fmev_shdlctl_thrsetup(fmev_shdl_t hdl, door_xcreate_thrsetup_func_t *func,
169 173 void *cookie)
170 174 {
171 175 fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
172 176
173 177 if (!FMEV_API_ENTER(hdl, 1))
174 178 return (fmev_errno);
175 179
176 180 if (!shdlctl_start(ihdl))
177 181 return (fmev_seterr(FMEVERR_BUSY));
178 182
179 183 sysevent_subattr_thrsetup(ihdl->sh_attr, func, cookie);
180 184
181 185 shdlctl_end(ihdl);
182 186 return (fmev_seterr(FMEV_SUCCESS));
183 187 }
184 188
185 189 fmev_err_t
186 190 fmev_shdlctl_thrcreate(fmev_shdl_t hdl, door_xcreate_server_func_t *func,
187 191 void *cookie)
188 192 {
189 193 fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
190 194
191 195 if (!FMEV_API_ENTER(hdl, 1))
192 196 return (fmev_errno);
193 197
194 198 if (!shdlctl_start(ihdl))
195 199 return (fmev_seterr(FMEVERR_BUSY));
196 200
197 201 sysevent_subattr_thrcreate(ihdl->sh_attr, func, cookie);
↓ open down ↓ |
161 lines elided |
↑ open up ↑ |
198 202
199 203 shdlctl_end(ihdl);
200 204 return (fmev_seterr(FMEV_SUCCESS));
201 205 }
202 206
203 207 /*
204 208 * Our door service function. We return 0 regardless so that the kernel
205 209 * does not keep either retrying (EAGAIN) or bleat to cmn_err.
206 210 */
207 211
208 -uint64_t fmev_proxy_cb_inval;
209 212 uint64_t fmev_proxy_cb_enomem;
210 213
211 214 int
212 215 fmev_proxy_cb(sysevent_t *sep, void *arg)
213 216 {
214 217 struct fmev_subinfo *sip = arg;
215 218 fmev_shdl_impl_t *ihdl = sip->si_ihdl;
216 219 nvlist_t *nvl;
217 220 char *class;
218 221 fmev_t ev;
219 222
220 - if (sip == NULL || sip->si_cb == NULL) {
221 - fmev_proxy_cb_inval++;
222 - return (0);
223 - }
224 -
225 223 if ((ev = fmev_sysev2fmev(IHDL2HDL(ihdl), sep, &class, &nvl)) == NULL) {
226 224 fmev_proxy_cb_enomem++;
227 225 return (0);
228 226 }
229 227
230 228 if (ihdl->sh_flags & SHDL_FL_SERIALIZE)
231 229 (void) pthread_mutex_lock(&ihdl->sh_srlz_lock);
232 230
233 231 sip->si_cb(ev, class, nvl, sip->si_cbarg);
234 232
235 233 if (ihdl->sh_flags & SHDL_FL_SERIALIZE)
236 234 (void) pthread_mutex_unlock(&ihdl->sh_srlz_lock);
237 235
238 236 fmev_rele(ev); /* release hold obtained in fmev_sysev2fmev */
239 237
240 238 return (0);
241 239 }
242 240
243 241 static volatile uint32_t fmev_subid;
244 242
245 243 fmev_err_t
246 244 fmev_shdl_subscribe(fmev_shdl_t hdl, const char *pat, fmev_cbfunc_t func,
247 245 void *funcarg)
248 246 {
249 247 fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
250 248 struct fmev_subinfo *sip;
251 249 uu_avl_index_t idx;
252 250 uint64_t nsid;
253 251 int serr;
254 252
255 253 if (!FMEV_API_ENTER(hdl, 1))
256 254 return (fmev_errno);
257 255
258 256 if (pat == NULL || func == NULL)
259 257 return (fmev_seterr(FMEVERR_API));
260 258
261 259 /*
262 260 * Empty class patterns are illegal, as is the sysevent magic for
263 261 * all classes. Also validate class length.
264 262 */
265 263 if (*pat == '\0' || strncmp(pat, EC_ALL, sizeof (EC_ALL)) == 0 ||
266 264 strncmp(pat, EC_SUB_ALL, sizeof (EC_SUB_ALL)) == 0 ||
267 265 strnlen(pat, FMEV_MAX_CLASS) == FMEV_MAX_CLASS)
268 266 return (fmev_seterr(FMEVERR_BADCLASS));
269 267
270 268 if ((sip = fmev_shdl_zalloc(hdl, sizeof (*sip))) == NULL)
271 269 return (fmev_seterr(FMEVERR_ALLOC));
272 270
273 271 (void) strncpy(sip->si_pat, pat, sizeof (sip->si_pat));
274 272
275 273 uu_avl_node_init(sip, &sip->si_node, ihdl->sh_pool);
276 274
277 275 (void) pthread_mutex_lock(&ihdl->sh_lock);
278 276
279 277 if (uu_avl_find(ihdl->sh_avl, sip, NULL, &idx) != NULL) {
280 278 (void) pthread_mutex_unlock(&ihdl->sh_lock);
281 279 fmev_shdl_free(hdl, sip, sizeof (*sip));
282 280 return (fmev_seterr(FMEVERR_DUPLICATE));
283 281 }
284 282
285 283 /*
286 284 * Generate a subscriber id for GPEC that is unique to this
287 285 * subscription. There is no provision for persistent
288 286 * subscribers. The subscriber id must be unique within
289 287 * this zone.
290 288 */
291 289 nsid = (uint64_t)getpid() << 32 | atomic_inc_32_nv(&fmev_subid);
292 290 (void) snprintf(sip->si_sid, sizeof (sip->si_sid), "%llx", nsid);
293 291
294 292 sip->si_ihdl = ihdl;
295 293 sip->si_cb = func;
296 294 sip->si_cbarg = funcarg;
297 295
298 296 if ((serr = sysevent_evc_xsubscribe(ihdl->sh_binding, sip->si_sid,
299 297 sip->si_pat, fmev_proxy_cb, sip, 0, ihdl->sh_attr)) != 0) {
300 298 fmev_err_t err;
301 299
302 300 (void) pthread_mutex_unlock(&ihdl->sh_lock);
303 301 fmev_shdl_free(hdl, sip, sizeof (*sip));
304 302
305 303 switch (serr) {
306 304 case ENOMEM:
307 305 err = FMEVERR_MAX_SUBSCRIBERS;
308 306 break;
309 307
310 308 default:
311 309 err = FMEVERR_INTERNAL;
312 310 break;
313 311 }
314 312
315 313 return (fmev_seterr(err));
316 314 }
317 315
318 316 uu_avl_insert(ihdl->sh_avl, sip, idx);
319 317 ihdl->sh_subcnt++;
320 318
321 319 (void) pthread_mutex_unlock(&ihdl->sh_lock);
322 320
323 321 return (fmev_seterr(FMEV_SUCCESS));
324 322 }
325 323
326 324 static int
327 325 fmev_subinfo_fini(fmev_shdl_impl_t *ihdl, struct fmev_subinfo *sip,
328 326 boolean_t doavl)
329 327 {
330 328 int err;
331 329
332 330 ASSERT(sip->si_ihdl == ihdl);
333 331
334 332 err = sysevent_evc_unsubscribe(ihdl->sh_binding, sip->si_sid);
335 333
336 334 if (err == 0) {
337 335 if (doavl) {
338 336 uu_avl_remove(ihdl->sh_avl, sip);
339 337 uu_avl_node_fini(sip, &sip->si_node, ihdl->sh_pool);
340 338 }
341 339 fmev_shdl_free(IHDL2HDL(ihdl), sip, sizeof (*sip));
342 340 ihdl->sh_subcnt--;
343 341 }
344 342
345 343 return (err);
346 344 }
347 345
348 346 fmev_err_t
349 347 fmev_shdl_unsubscribe(fmev_shdl_t hdl, const char *pat)
350 348 {
351 349 fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
352 350 fmev_err_t rv = FMEVERR_NOMATCH;
353 351 struct fmev_subinfo *sip;
354 352 struct fmev_subinfo si;
355 353 int err;
356 354
357 355 if (!FMEV_API_ENTER(hdl, 1))
358 356 return (fmev_errno);
359 357
360 358 if (pat == NULL)
361 359 return (fmev_seterr(FMEVERR_API));
362 360
363 361 if (*pat == '\0' || strncmp(pat, EVCH_ALLSUB, sizeof (EC_ALL)) == 0 ||
364 362 strnlen(pat, FMEV_MAX_CLASS) == FMEV_MAX_CLASS)
365 363 return (fmev_seterr(FMEVERR_BADCLASS));
366 364
367 365 (void) strncpy(si.si_pat, pat, sizeof (si.si_pat));
368 366
369 367 (void) pthread_mutex_lock(&ihdl->sh_lock);
370 368
371 369 if ((sip = uu_avl_find(ihdl->sh_avl, &si, NULL, NULL)) != NULL) {
372 370 if ((err = fmev_subinfo_fini(ihdl, sip, B_TRUE)) == 0) {
373 371 rv = FMEV_SUCCESS;
374 372 } else {
375 373 /*
376 374 * Return an API error if the unsubscribe was
377 375 * attempted from within a door callback invocation;
378 376 * other errors should not happen.
379 377 */
380 378 rv = (err == EDEADLK) ? FMEVERR_API : FMEVERR_INTERNAL;
381 379 }
382 380 }
383 381
384 382 (void) pthread_mutex_unlock(&ihdl->sh_lock);
385 383
386 384 return (fmev_seterr(rv));
387 385 }
388 386
389 387 void *
390 388 fmev_shdl_alloc(fmev_shdl_t hdl, size_t sz)
391 389 {
392 390 fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
393 391
394 392 if (!FMEV_API_ENTER(hdl, 1))
395 393 return (NULL);
396 394
397 395 return (ihdl->sh_cmn.hc_alloc(sz));
398 396 }
399 397
400 398 void *
401 399 fmev_shdl_zalloc(fmev_shdl_t hdl, size_t sz)
402 400 {
403 401 fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
404 402
405 403 if (!FMEV_API_ENTER(hdl, 1))
406 404 return (NULL);
407 405
408 406 return (ihdl->sh_cmn.hc_zalloc(sz));
409 407 }
410 408
411 409 void
412 410 fmev_shdl_free(fmev_shdl_t hdl, void *buf, size_t sz)
413 411 {
414 412 fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
415 413
416 414 if (!FMEV_API_ENTER(hdl, 1))
417 415 return;
418 416
419 417 ihdl->sh_cmn.hc_free(buf, sz);
420 418 }
421 419
422 420 char *
423 421 fmev_shdl_strdup(fmev_shdl_t hdl, char *src)
424 422 {
425 423 fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
426 424 size_t srclen;
427 425 char *dst;
428 426
429 427 if (!FMEV_API_ENTER(hdl, 2))
430 428 return (NULL);
431 429
432 430 srclen = strlen(src);
433 431
434 432 if ((dst = ihdl->sh_cmn.hc_alloc(srclen + 1)) == NULL) {
435 433 (void) fmev_seterr(FMEVERR_ALLOC);
436 434 return (NULL);
437 435 }
438 436
439 437 (void) strncpy(dst, src, srclen);
440 438 dst[srclen] = '\0';
441 439 return (dst);
442 440 }
443 441
444 442 void
445 443 fmev_shdl_strfree(fmev_shdl_t hdl, char *buf)
446 444 {
447 445 fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
448 446
449 447 (void) FMEV_API_ENTER(hdl, 2);
450 448
451 449 ihdl->sh_cmn.hc_free(buf, strlen(buf) + 1);
452 450 }
453 451
454 452 int
455 453 fmev_shdl_valid(fmev_shdl_t hdl)
456 454 {
457 455 return (FMEV_SHDL_VALID(HDL2IHDL(hdl)));
458 456 }
459 457
460 458 /*ARGSUSED*/
461 459 static int
462 460 fmev_keycmp(const void *l, const void *r, void *arg)
463 461 {
464 462 struct fmev_subinfo *left = (struct fmev_subinfo *)l;
465 463 struct fmev_subinfo *right = (struct fmev_subinfo *)r;
466 464
467 465 return (strncmp(left->si_pat, right->si_pat, FMEV_MAX_CLASS));
468 466 }
469 467
470 468 fmev_shdl_t
471 469 fmev_shdl_init(uint32_t caller_version, void *(*hdlalloc)(size_t),
472 470 void *(*hdlzalloc)(size_t), void (*hdlfree)(void *, size_t))
473 471 {
474 472 fmev_shdl_impl_t *ihdl;
475 473 struct fmev_hdl_cmn hc;
476 474 const char *chan_name;
477 475 int err;
478 476
479 477 hc.hc_magic = _FMEV_SHMAGIC;
480 478 hc.hc_api_vers = caller_version;
481 479 hc.hc_alloc = hdlalloc ? hdlalloc : dflt_alloc;
482 480 hc.hc_zalloc = hdlzalloc ? hdlzalloc : dflt_zalloc;
483 481 hc.hc_free = hdlfree ? hdlfree : dflt_free;
484 482
485 483 if (!fmev_api_init(&hc))
486 484 return (NULL); /* error type set */
487 485
488 486 if (!((hdlalloc == NULL && hdlzalloc == NULL && hdlfree == NULL) ||
489 487 (hdlalloc != NULL && hdlzalloc != NULL && hdlfree != NULL))) {
490 488 (void) fmev_seterr(FMEVERR_API);
491 489 return (NULL);
492 490 }
493 491
494 492 if (hdlzalloc == NULL)
495 493 ihdl = dflt_zalloc(sizeof (*ihdl));
496 494 else
497 495 ihdl = hdlzalloc(sizeof (*ihdl));
498 496
499 497 if (ihdl == NULL) {
500 498 (void) fmev_seterr(FMEVERR_ALLOC);
501 499 return (NULL);
502 500 }
503 501
504 502 ihdl->sh_cmn = hc;
505 503
506 504 if ((ihdl->sh_attr = sysevent_subattr_alloc()) == NULL) {
507 505 err = FMEVERR_ALLOC;
508 506 goto error;
509 507 }
510 508
511 509 (void) pthread_mutex_init(&ihdl->sh_lock, NULL);
512 510
513 511 /*
514 512 * For simulation purposes we allow an environment variable
515 513 * to provide a different channel name.
516 514 */
517 515 if ((chan_name = getenv("FMD_SNOOP_CHANNEL")) == NULL)
518 516 chan_name = FMD_SNOOP_CHANNEL;
519 517
520 518 /*
521 519 * Try to bind to the event channel. If it's not already present,
522 520 * attempt to create the channel so that we can startup before
523 521 * the event producer (who will also apply choices such as
524 522 * channel depth when they bind to the channel).
525 523 */
526 524 if (sysevent_evc_bind(chan_name, &ihdl->sh_binding,
527 525 EVCH_CREAT | EVCH_HOLD_PEND_INDEF) != 0) {
528 526 switch (errno) {
529 527 case EINVAL:
530 528 default:
531 529 err = FMEVERR_INTERNAL;
532 530 break;
533 531 case ENOMEM:
534 532 err = FMEVERR_ALLOC;
535 533 break;
536 534 case EPERM:
537 535 err = FMEVERR_NOPRIV;
538 536 break;
539 537 }
540 538 goto error;
541 539 }
542 540
543 541 if ((ihdl->sh_pool = uu_avl_pool_create("subinfo_pool",
544 542 sizeof (struct fmev_subinfo),
545 543 offsetof(struct fmev_subinfo, si_node), fmev_keycmp,
546 544 UU_AVL_POOL_DEBUG)) == NULL) {
547 545 err = FMEVERR_INTERNAL;
548 546 goto error;
549 547 }
550 548
551 549 if ((ihdl->sh_avl = uu_avl_create(ihdl->sh_pool, NULL,
552 550 UU_DEFAULT)) == NULL) {
553 551 err = FMEVERR_INTERNAL;
554 552 goto error;
555 553 }
556 554
557 555 return (IHDL2HDL(ihdl));
558 556
559 557 error:
560 558 (void) fmev_shdl_fini(IHDL2HDL(ihdl));
561 559 (void) fmev_seterr(err);
562 560 return (NULL);
563 561 }
564 562
565 563 fmev_err_t
566 564 fmev_shdl_getauthority(fmev_shdl_t hdl, nvlist_t **nvlp)
567 565 {
568 566 fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
569 567 nvlist_t *propnvl;
570 568 fmev_err_t rc;
571 569
572 570 if (!FMEV_API_ENTER(hdl, 2))
573 571 return (fmev_errno);
574 572
575 573 (void) pthread_mutex_lock(&ihdl->sh_lock);
576 574
577 575 if (sysevent_evc_getpropnvl(ihdl->sh_binding, &propnvl) != 0) {
578 576 *nvlp = NULL;
579 577 (void) pthread_mutex_unlock(&ihdl->sh_lock);
580 578 return (fmev_seterr(FMEVERR_UNKNOWN));
581 579 }
582 580
583 581 if (propnvl == NULL) {
584 582 rc = FMEVERR_BUSY; /* Other end has not bound */
585 583 } else {
586 584 nvlist_t *auth;
587 585
588 586 if (nvlist_lookup_nvlist(propnvl, "fmdauth", &auth) == 0) {
589 587 rc = (nvlist_dup(auth, nvlp, 0) == 0) ? FMEV_SUCCESS :
590 588 FMEVERR_ALLOC;
591 589 } else {
592 590 rc = FMEVERR_INTERNAL;
593 591 }
594 592 nvlist_free(propnvl);
595 593 }
596 594
597 595 (void) pthread_mutex_unlock(&ihdl->sh_lock);
598 596
599 597 if (rc != FMEV_SUCCESS) {
600 598 *nvlp = NULL;
601 599 (void) fmev_seterr(rc);
602 600 }
603 601
604 602 return (rc);
605 603 }
606 604
607 605 char *
608 606 fmev_shdl_nvl2str(fmev_shdl_t hdl, nvlist_t *nvl)
609 607 {
610 608 fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
611 609 char *fmri, *fmricp;
612 610 fmev_err_t err;
613 611 int topoerr;
614 612
615 613 if (!FMEV_API_ENTER(hdl, 2))
616 614 return (NULL);
617 615
618 616 if (g_topohdl == NULL) {
619 617 (void) pthread_mutex_lock(&ihdl->sh_lock);
620 618 if (g_topohdl == NULL)
621 619 g_topohdl = topo_open(TOPO_VERSION, NULL, &topoerr);
622 620 (void) pthread_mutex_unlock(&ihdl->sh_lock);
623 621
624 622 if (g_topohdl == NULL) {
625 623 (void) fmev_seterr(FMEVERR_INTERNAL);
626 624 return (NULL);
627 625 }
628 626 }
629 627
630 628 if (topo_fmri_nvl2str(g_topohdl, nvl, &fmri, &topoerr) == 0) {
631 629 fmricp = fmev_shdl_strdup(hdl, fmri);
632 630 topo_hdl_strfree(g_topohdl, fmri);
633 631 return (fmricp); /* fmev_errno set if strdup failed */
634 632 }
635 633
636 634 switch (topoerr) {
637 635 case ETOPO_FMRI_NOMEM:
638 636 err = FMEVERR_ALLOC;
639 637 break;
640 638
641 639 case ETOPO_FMRI_MALFORM:
642 640 case ETOPO_METHOD_NOTSUP:
643 641 case ETOPO_METHOD_INVAL:
644 642 default:
645 643 err = FMEVERR_INVALIDARG;
646 644 break;
647 645 }
648 646
649 647 (void) fmev_seterr(err);
650 648 return (NULL);
651 649 }
652 650
653 651 fmev_err_t
654 652 fmev_shdl_fini(fmev_shdl_t hdl)
655 653 {
656 654 fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
657 655
658 656 if (!FMEV_API_ENTER(hdl, 1))
659 657 return (fmev_errno);
660 658
661 659 (void) pthread_mutex_lock(&ihdl->sh_lock);
662 660
663 661 /*
664 662 * Verify that we are not in callback context - return an API
665 663 * error if we are.
666 664 */
667 665 if (sysevent_evc_unsubscribe(ihdl->sh_binding, "invalidsid") ==
668 666 EDEADLK) {
669 667 (void) pthread_mutex_unlock(&ihdl->sh_lock);
670 668 return (fmev_seterr(FMEVERR_API));
671 669 }
672 670
673 671 if (ihdl->sh_avl) {
674 672 void *cookie = NULL;
675 673 struct fmev_subinfo *sip;
676 674
677 675 while ((sip = uu_avl_teardown(ihdl->sh_avl, &cookie)) != NULL)
678 676 (void) fmev_subinfo_fini(ihdl, sip, B_FALSE);
679 677
680 678 uu_avl_destroy(ihdl->sh_avl);
681 679 ihdl->sh_avl = NULL;
682 680 }
683 681
684 682 ASSERT(ihdl->sh_subcnt == 0);
685 683
686 684 if (ihdl->sh_binding) {
687 685 (void) sysevent_evc_unbind(ihdl->sh_binding);
688 686 ihdl->sh_binding = NULL;
689 687 }
690 688
691 689 if (ihdl->sh_pool) {
692 690 uu_avl_pool_destroy(ihdl->sh_pool);
693 691 ihdl->sh_pool = NULL;
694 692 }
695 693
696 694 if (ihdl->sh_attr) {
697 695 sysevent_subattr_free(ihdl->sh_attr);
698 696 ihdl->sh_attr = NULL;
699 697 }
700 698
701 699 ihdl->sh_cmn.hc_magic = 0;
702 700
703 701 if (g_topohdl) {
704 702 topo_close(g_topohdl);
705 703 g_topohdl = NULL;
706 704 }
707 705
708 706 (void) pthread_mutex_unlock(&ihdl->sh_lock);
709 707 (void) pthread_mutex_destroy(&ihdl->sh_lock);
710 708
711 709 fmev_shdl_free(hdl, hdl, sizeof (*ihdl));
712 710
713 711 fmev_api_freetsd();
714 712
715 713 return (fmev_seterr(FMEV_SUCCESS));
716 714 }
↓ open down ↓ |
482 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX