1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 #include <sys/errno.h> 31 #include <sys/stropts.h> 32 #include <sys/debug.h> 33 #include <sys/ddi.h> 34 #include <sys/sunddi.h> 35 #include <sys/vmem.h> 36 #include <sys/cmn_err.h> 37 #include <sys/callb.h> 38 #include <sys/sysevent.h> 39 #include <sys/sysevent_impl.h> 40 #include <sys/modctl.h> 41 #include <sys/sysmacros.h> 42 #include <sys/disp.h> 43 #include <sys/autoconf.h> 44 #include <sys/atomic.h> 45 46 /* for doors */ 47 #include <sys/pathname.h> 48 #include <sys/door.h> 49 #include <sys/kmem.h> 50 #include <sys/cpuvar.h> 51 #include <sys/fs/snode.h> 52 53 /* 54 * log_sysevent.c - Provides the interfaces for kernel event publication 55 * to the sysevent event daemon (syseventd). 56 */ 57 58 /* 59 * Debug stuff 60 */ 61 static int log_event_debug = 0; 62 #define LOG_DEBUG(args) if (log_event_debug) cmn_err args 63 #ifdef DEBUG 64 #define LOG_DEBUG1(args) if (log_event_debug > 1) cmn_err args 65 #else 66 #define LOG_DEBUG1(args) 67 #endif 68 69 /* 70 * Local static vars 71 */ 72 /* queue of event buffers sent to syseventd */ 73 static log_eventq_t *log_eventq_sent = NULL; 74 75 /* 76 * Count of event buffers in the queue 77 */ 78 int log_eventq_cnt = 0; 79 80 /* queue of event buffers awaiting delivery to syseventd */ 81 static log_eventq_t *log_eventq_head = NULL; 82 static log_eventq_t *log_eventq_tail = NULL; 83 static uint64_t kernel_event_id = 0; 84 static int encoding = NV_ENCODE_NATIVE; 85 86 /* log event delivery flag */ 87 #define LOGEVENT_DELIVERY_OK 0 /* OK to deliver event buffers */ 88 #define LOGEVENT_DELIVERY_CONT 1 /* Continue to deliver event buffers */ 89 #define LOGEVENT_DELIVERY_HOLD 2 /* Hold delivering of event buffers */ 90 91 /* 92 * Tunable maximum event buffer queue size. Size depends on how many events 93 * the queue must hold when syseventd is not available, for example during 94 * system startup. Experience showed that more than 2000 events could be posted 95 * due to correctable memory errors. 96 */ 97 int logevent_max_q_sz = 5000; 98 99 100 static int log_event_delivery = LOGEVENT_DELIVERY_HOLD; 101 static char *logevent_door_upcall_filename = NULL; 102 static int logevent_door_upcall_filename_size; 103 104 static door_handle_t event_door = NULL; /* Door for upcalls */ 105 106 /* 107 * async thread-related variables 108 * 109 * eventq_head_mutex - synchronizes access to the kernel event queue 110 * 111 * eventq_sent_mutex - synchronizes access to the queue of event sents to 112 * userlevel 113 * 114 * log_event_cv - condition variable signaled when an event has arrived or 115 * userlevel ready to process event buffers 116 * 117 * async_thread - asynchronous event delivery thread to userlevel daemon. 118 * 119 * sysevent_upcall_status - status of the door upcall link 120 */ 121 static kmutex_t eventq_head_mutex; 122 static kmutex_t eventq_sent_mutex; 123 static kcondvar_t log_event_cv; 124 static kthread_id_t async_thread = NULL; 125 126 static kmutex_t event_qfull_mutex; 127 static kcondvar_t event_qfull_cv; 128 static int event_qfull_blocked = 0; 129 130 static int sysevent_upcall_status = -1; 131 static kmutex_t registered_channel_mutex; 132 133 /* 134 * Indicates the syseventd daemon has begun taking events 135 */ 136 int sysevent_daemon_init = 0; 137 138 /* 139 * Back-off delay when door_ki_upcall returns EAGAIN. Typically 140 * caused by the server process doing a forkall(). Since all threads 141 * but the thread actually doing the forkall() need to be quiesced, 142 * the fork may take some time. The min/max pause are in units 143 * of clock ticks. 144 */ 145 #define LOG_EVENT_MIN_PAUSE 8 146 #define LOG_EVENT_MAX_PAUSE 128 147 148 static kmutex_t event_pause_mutex; 149 static kcondvar_t event_pause_cv; 150 static int event_pause_state = 0; 151 152 /* 153 * log_event_upcall_lookup - Establish door connection with user event 154 * daemon (syseventd) 155 */ 156 static int 157 log_event_upcall_lookup() 158 { 159 int error; 160 161 if (event_door) { /* Release our previous hold (if any) */ 162 door_ki_rele(event_door); 163 } 164 165 event_door = NULL; 166 167 /* 168 * Locate the door used for upcalls 169 */ 170 if ((error = 171 door_ki_open(logevent_door_upcall_filename, &event_door)) != 0) { 172 return (error); 173 } 174 175 return (0); 176 } 177 178 179 /*ARGSUSED*/ 180 static void 181 log_event_busy_timeout(void *arg) 182 { 183 mutex_enter(&event_pause_mutex); 184 event_pause_state = 0; 185 cv_signal(&event_pause_cv); 186 mutex_exit(&event_pause_mutex); 187 } 188 189 static void 190 log_event_pause(int nticks) 191 { 192 timeout_id_t id; 193 194 /* 195 * Only one use of log_event_pause at a time 196 */ 197 ASSERT(event_pause_state == 0); 198 199 event_pause_state = 1; 200 id = timeout(log_event_busy_timeout, NULL, nticks); 201 if (id != 0) { 202 mutex_enter(&event_pause_mutex); 203 while (event_pause_state) 204 cv_wait(&event_pause_cv, &event_pause_mutex); 205 mutex_exit(&event_pause_mutex); 206 } 207 event_pause_state = 0; 208 } 209 210 211 /* 212 * log_event_upcall - Perform the upcall to syseventd for event buffer delivery. 213 * Check for rebinding errors 214 * This buffer is reused to by the syseventd door_return 215 * to hold the result code 216 */ 217 static int 218 log_event_upcall(log_event_upcall_arg_t *arg) 219 { 220 int error; 221 size_t size; 222 sysevent_t *ev; 223 door_arg_t darg, save_arg; 224 int retry; 225 int neagain = 0; 226 int neintr = 0; 227 int nticks = LOG_EVENT_MIN_PAUSE; 228 229 /* Initialize door args */ 230 ev = (sysevent_t *)&arg->buf; 231 size = sizeof (log_event_upcall_arg_t) + SE_PAYLOAD_SZ(ev); 232 233 darg.rbuf = (char *)arg; 234 darg.data_ptr = (char *)arg; 235 darg.rsize = size; 236 darg.data_size = size; 237 darg.desc_ptr = NULL; 238 darg.desc_num = 0; 239 240 if ((event_door == NULL) && 241 ((error = log_event_upcall_lookup()) != 0)) { 242 LOG_DEBUG((CE_CONT, 243 "log_event_upcall: event_door error (%d)\n", error)); 244 245 return (error); 246 } 247 248 LOG_DEBUG1((CE_CONT, "log_event_upcall: 0x%llx\n", 249 (longlong_t)SE_SEQ((sysevent_t *)&arg->buf))); 250 251 save_arg = darg; 252 for (retry = 0; ; retry++) { 253 if ((error = door_ki_upcall(event_door, &darg)) == 0) { 254 break; 255 } 256 switch (error) { 257 case EINTR: 258 neintr++; 259 log_event_pause(2); 260 darg = save_arg; 261 break; 262 case EAGAIN: 263 /* cannot deliver upcall - process may be forking */ 264 neagain++; 265 log_event_pause(nticks); 266 nticks <<= 1; 267 if (nticks > LOG_EVENT_MAX_PAUSE) 268 nticks = LOG_EVENT_MAX_PAUSE; 269 darg = save_arg; 270 break; 271 case EBADF: 272 LOG_DEBUG((CE_CONT, "log_event_upcall: rebinding\n")); 273 /* Server may have died. Try rebinding */ 274 if ((error = log_event_upcall_lookup()) != 0) { 275 LOG_DEBUG((CE_CONT, 276 "log_event_upcall: lookup error %d\n", 277 error)); 278 return (EBADF); 279 } 280 if (retry > 4) { 281 LOG_DEBUG((CE_CONT, 282 "log_event_upcall: ebadf\n")); 283 return (EBADF); 284 } 285 LOG_DEBUG((CE_CONT, "log_event_upcall: " 286 "retrying upcall after lookup\n")); 287 darg = save_arg; 288 break; 289 default: 290 cmn_err(CE_CONT, 291 "log_event_upcall: door_ki_upcall error %d\n", 292 error); 293 return (error); 294 } 295 } 296 297 if (neagain > 0 || neintr > 0) { 298 LOG_DEBUG((CE_CONT, "upcall: eagain=%d eintr=%d nticks=%d\n", 299 neagain, neintr, nticks)); 300 } 301 302 LOG_DEBUG1((CE_CONT, "log_event_upcall:\n\t" 303 "error=%d rptr1=%p rptr2=%p dptr2=%p ret1=%x ret2=%x\n", 304 error, (void *)arg, (void *)darg.rbuf, 305 (void *)darg.data_ptr, 306 *((int *)(darg.rbuf)), *((int *)(darg.data_ptr)))); 307 308 if (!error) { 309 /* 310 * upcall was successfully executed. Check return code. 311 */ 312 error = *((int *)(darg.rbuf)); 313 } 314 315 return (error); 316 } 317 318 /* 319 * log_event_deliver - event delivery thread 320 * Deliver all events on the event queue to syseventd. 321 * If the daemon can not process events, stop event 322 * delivery and wait for an indication from the 323 * daemon to resume delivery. 324 * 325 * Once all event buffers have been delivered, wait 326 * until there are more to deliver. 327 */ 328 static void 329 log_event_deliver() 330 { 331 log_eventq_t *q; 332 int upcall_err; 333 callb_cpr_t cprinfo; 334 335 CALLB_CPR_INIT(&cprinfo, &eventq_head_mutex, callb_generic_cpr, 336 "logevent"); 337 338 /* 339 * eventq_head_mutex is exited (released) when there are no more 340 * events to process from the eventq in cv_wait(). 341 */ 342 mutex_enter(&eventq_head_mutex); 343 344 for (;;) { 345 LOG_DEBUG1((CE_CONT, "log_event_deliver: head = %p\n", 346 (void *)log_eventq_head)); 347 348 upcall_err = 0; 349 q = log_eventq_head; 350 351 while (q) { 352 log_eventq_t *next; 353 354 /* 355 * Release event queue lock during upcall to 356 * syseventd 357 */ 358 if (log_event_delivery == LOGEVENT_DELIVERY_HOLD) { 359 upcall_err = EAGAIN; 360 break; 361 } 362 363 mutex_exit(&eventq_head_mutex); 364 if ((upcall_err = log_event_upcall(&q->arg)) != 0) { 365 mutex_enter(&eventq_head_mutex); 366 break; 367 } 368 369 /* 370 * We may be able to add entries to 371 * the queue now. 372 */ 373 if (event_qfull_blocked > 0 && 374 log_eventq_cnt < logevent_max_q_sz) { 375 mutex_enter(&event_qfull_mutex); 376 if (event_qfull_blocked > 0) { 377 cv_signal(&event_qfull_cv); 378 } 379 mutex_exit(&event_qfull_mutex); 380 } 381 382 mutex_enter(&eventq_head_mutex); 383 384 /* 385 * Daemon restart can cause entries to be moved from 386 * the sent queue and put back on the event queue. 387 * If this has occurred, replay event queue 388 * processing from the new queue head. 389 */ 390 if (q != log_eventq_head) { 391 q = log_eventq_head; 392 LOG_DEBUG((CE_CONT, "log_event_deliver: " 393 "door upcall/daemon restart race\n")); 394 } else { 395 /* 396 * Move the event to the sent queue when a 397 * successful delivery has been made. 398 */ 399 mutex_enter(&eventq_sent_mutex); 400 next = q->next; 401 q->next = log_eventq_sent; 402 log_eventq_sent = q; 403 q = next; 404 log_eventq_head = q; 405 log_eventq_cnt--; 406 if (q == NULL) { 407 ASSERT(log_eventq_cnt == 0); 408 log_eventq_tail = NULL; 409 } 410 mutex_exit(&eventq_sent_mutex); 411 } 412 } 413 414 switch (upcall_err) { 415 case 0: 416 /* 417 * Success. The queue is empty. 418 */ 419 sysevent_upcall_status = 0; 420 break; 421 case EAGAIN: 422 /* 423 * Delivery is on hold (but functional). 424 */ 425 sysevent_upcall_status = 0; 426 /* 427 * If the user has already signaled for delivery 428 * resumption, continue. Otherwise, we wait until 429 * we are signaled to continue. 430 */ 431 if (log_event_delivery == LOGEVENT_DELIVERY_CONT) { 432 log_event_delivery = LOGEVENT_DELIVERY_OK; 433 continue; 434 } else { 435 log_event_delivery = LOGEVENT_DELIVERY_HOLD; 436 } 437 438 LOG_DEBUG1((CE_CONT, "log_event_deliver: EAGAIN\n")); 439 break; 440 default: 441 LOG_DEBUG((CE_CONT, "log_event_deliver: " 442 "upcall err %d\n", upcall_err)); 443 sysevent_upcall_status = upcall_err; 444 /* 445 * Signal everyone waiting that transport is down 446 */ 447 if (event_qfull_blocked > 0) { 448 mutex_enter(&event_qfull_mutex); 449 if (event_qfull_blocked > 0) { 450 cv_broadcast(&event_qfull_cv); 451 } 452 mutex_exit(&event_qfull_mutex); 453 } 454 break; 455 } 456 457 CALLB_CPR_SAFE_BEGIN(&cprinfo); 458 cv_wait(&log_event_cv, &eventq_head_mutex); 459 CALLB_CPR_SAFE_END(&cprinfo, &eventq_head_mutex); 460 } 461 /* NOTREACHED */ 462 } 463 464 /* 465 * log_event_init - Allocate and initialize log_event data structures. 466 */ 467 void 468 log_event_init() 469 { 470 mutex_init(&eventq_head_mutex, NULL, MUTEX_DEFAULT, NULL); 471 mutex_init(&eventq_sent_mutex, NULL, MUTEX_DEFAULT, NULL); 472 cv_init(&log_event_cv, NULL, CV_DEFAULT, NULL); 473 474 mutex_init(&event_qfull_mutex, NULL, MUTEX_DEFAULT, NULL); 475 cv_init(&event_qfull_cv, NULL, CV_DEFAULT, NULL); 476 477 mutex_init(&event_pause_mutex, NULL, MUTEX_DEFAULT, NULL); 478 cv_init(&event_pause_cv, NULL, CV_DEFAULT, NULL); 479 480 mutex_init(®istered_channel_mutex, NULL, MUTEX_DEFAULT, NULL); 481 sysevent_evc_init(); 482 } 483 484 /* 485 * The following routines are used by kernel event publishers to 486 * allocate, append and free event buffers 487 */ 488 /* 489 * sysevent_alloc - Allocate new eventq struct. This element contains 490 * an event buffer that will be used in a subsequent 491 * call to log_sysevent. 492 */ 493 sysevent_t * 494 sysevent_alloc(char *class, char *subclass, char *pub, int flag) 495 { 496 int payload_sz; 497 int class_sz, subclass_sz, pub_sz; 498 int aligned_class_sz, aligned_subclass_sz, aligned_pub_sz; 499 sysevent_t *ev; 500 log_eventq_t *q; 501 502 ASSERT(class != NULL); 503 ASSERT(subclass != NULL); 504 ASSERT(pub != NULL); 505 506 /* 507 * Calculate and reserve space for the class, subclass and 508 * publisher strings in the event buffer 509 */ 510 class_sz = strlen(class) + 1; 511 subclass_sz = strlen(subclass) + 1; 512 pub_sz = strlen(pub) + 1; 513 514 ASSERT((class_sz <= MAX_CLASS_LEN) && (subclass_sz 515 <= MAX_SUBCLASS_LEN) && (pub_sz <= MAX_PUB_LEN)); 516 517 /* String sizes must be 64-bit aligned in the event buffer */ 518 aligned_class_sz = SE_ALIGN(class_sz); 519 aligned_subclass_sz = SE_ALIGN(subclass_sz); 520 aligned_pub_sz = SE_ALIGN(pub_sz); 521 522 payload_sz = (aligned_class_sz - sizeof (uint64_t)) + 523 (aligned_subclass_sz - sizeof (uint64_t)) + 524 (aligned_pub_sz - sizeof (uint64_t)) - sizeof (uint64_t); 525 526 /* 527 * Allocate event buffer plus additional sysevent queue 528 * and payload overhead. 529 */ 530 q = kmem_zalloc(sizeof (log_eventq_t) + payload_sz, flag); 531 if (q == NULL) { 532 return (NULL); 533 } 534 535 /* Initialize the event buffer data */ 536 ev = (sysevent_t *)&q->arg.buf; 537 SE_VERSION(ev) = SYS_EVENT_VERSION; 538 bcopy(class, SE_CLASS_NAME(ev), class_sz); 539 540 SE_SUBCLASS_OFF(ev) = SE_ALIGN(offsetof(sysevent_impl_t, se_class_name)) 541 + aligned_class_sz; 542 bcopy(subclass, SE_SUBCLASS_NAME(ev), subclass_sz); 543 544 SE_PUB_OFF(ev) = SE_SUBCLASS_OFF(ev) + aligned_subclass_sz; 545 bcopy(pub, SE_PUB_NAME(ev), pub_sz); 546 547 SE_ATTR_PTR(ev) = UINT64_C(0); 548 SE_PAYLOAD_SZ(ev) = payload_sz; 549 550 return (ev); 551 } 552 553 /* 554 * sysevent_free - Free event buffer and any attribute data. 555 */ 556 void 557 sysevent_free(sysevent_t *ev) 558 { 559 log_eventq_t *q; 560 nvlist_t *nvl; 561 562 ASSERT(ev != NULL); 563 q = (log_eventq_t *)((caddr_t)ev - offsetof(log_eventq_t, arg.buf)); 564 nvl = (nvlist_t *)(uintptr_t)SE_ATTR_PTR(ev); 565 566 if (nvl != NULL) { 567 size_t size = 0; 568 (void) nvlist_size(nvl, &size, encoding); 569 SE_PAYLOAD_SZ(ev) -= size; 570 nvlist_free(nvl); 571 } 572 kmem_free(q, sizeof (log_eventq_t) + SE_PAYLOAD_SZ(ev)); 573 } 574 575 /* 576 * free_packed_event - Free packed event buffer 577 */ 578 static void 579 free_packed_event(sysevent_t *ev) 580 { 581 log_eventq_t *q; 582 583 ASSERT(ev != NULL); 584 q = (log_eventq_t *)((caddr_t)ev - offsetof(log_eventq_t, arg.buf)); 585 586 kmem_free(q, sizeof (log_eventq_t) + SE_PAYLOAD_SZ(ev)); 587 } 588 589 /* 590 * sysevent_add_attr - Add new attribute element to an event attribute list 591 * If attribute list is NULL, start a new list. 592 */ 593 int 594 sysevent_add_attr(sysevent_attr_list_t **ev_attr_list, char *name, 595 sysevent_value_t *se_value, int flag) 596 { 597 int error; 598 nvlist_t **nvlp = (nvlist_t **)ev_attr_list; 599 600 if (nvlp == NULL || se_value == NULL) { 601 return (SE_EINVAL); 602 } 603 604 /* 605 * attr_sz is composed of the value data size + the name data size + 606 * any header data. 64-bit aligned. 607 */ 608 if (strlen(name) >= MAX_ATTR_NAME) { 609 return (SE_EINVAL); 610 } 611 612 /* 613 * Allocate nvlist 614 */ 615 if ((*nvlp == NULL) && 616 (nvlist_alloc(nvlp, NV_UNIQUE_NAME_TYPE, flag) != 0)) 617 return (SE_ENOMEM); 618 619 /* add the attribute */ 620 switch (se_value->value_type) { 621 case SE_DATA_TYPE_BYTE: 622 error = nvlist_add_byte(*ev_attr_list, name, 623 se_value->value.sv_byte); 624 break; 625 case SE_DATA_TYPE_INT16: 626 error = nvlist_add_int16(*ev_attr_list, name, 627 se_value->value.sv_int16); 628 break; 629 case SE_DATA_TYPE_UINT16: 630 error = nvlist_add_uint16(*ev_attr_list, name, 631 se_value->value.sv_uint16); 632 break; 633 case SE_DATA_TYPE_INT32: 634 error = nvlist_add_int32(*ev_attr_list, name, 635 se_value->value.sv_int32); 636 break; 637 case SE_DATA_TYPE_UINT32: 638 error = nvlist_add_uint32(*ev_attr_list, name, 639 se_value->value.sv_uint32); 640 break; 641 case SE_DATA_TYPE_INT64: 642 error = nvlist_add_int64(*ev_attr_list, name, 643 se_value->value.sv_int64); 644 break; 645 case SE_DATA_TYPE_UINT64: 646 error = nvlist_add_uint64(*ev_attr_list, name, 647 se_value->value.sv_uint64); 648 break; 649 case SE_DATA_TYPE_STRING: 650 if (strlen((char *)se_value->value.sv_string) >= MAX_STRING_SZ) 651 return (SE_EINVAL); 652 error = nvlist_add_string(*ev_attr_list, name, 653 se_value->value.sv_string); 654 break; 655 case SE_DATA_TYPE_BYTES: 656 if (se_value->value.sv_bytes.size > MAX_BYTE_ARRAY) 657 return (SE_EINVAL); 658 error = nvlist_add_byte_array(*ev_attr_list, name, 659 se_value->value.sv_bytes.data, 660 se_value->value.sv_bytes.size); 661 break; 662 case SE_DATA_TYPE_TIME: 663 error = nvlist_add_hrtime(*ev_attr_list, name, 664 se_value->value.sv_time); 665 break; 666 default: 667 return (SE_EINVAL); 668 } 669 670 return (error ? SE_ENOMEM : 0); 671 } 672 673 /* 674 * sysevent_free_attr - Free an attribute list not associated with an 675 * event buffer. 676 */ 677 void 678 sysevent_free_attr(sysevent_attr_list_t *ev_attr_list) 679 { 680 nvlist_free((nvlist_t *)ev_attr_list); 681 } 682 683 /* 684 * sysevent_attach_attributes - Attach an attribute list to an event buffer. 685 * 686 * This data will be re-packed into contiguous memory when the event 687 * buffer is posted to log_sysevent. 688 */ 689 int 690 sysevent_attach_attributes(sysevent_t *ev, sysevent_attr_list_t *ev_attr_list) 691 { 692 size_t size = 0; 693 694 if (SE_ATTR_PTR(ev) != UINT64_C(0)) { 695 return (SE_EINVAL); 696 } 697 698 SE_ATTR_PTR(ev) = (uintptr_t)ev_attr_list; 699 (void) nvlist_size((nvlist_t *)ev_attr_list, &size, encoding); 700 SE_PAYLOAD_SZ(ev) += size; 701 SE_FLAG(ev) = 0; 702 703 return (0); 704 } 705 706 /* 707 * sysevent_detach_attributes - Detach but don't free attribute list from the 708 * event buffer. 709 */ 710 void 711 sysevent_detach_attributes(sysevent_t *ev) 712 { 713 size_t size = 0; 714 nvlist_t *nvl; 715 716 if ((nvl = (nvlist_t *)(uintptr_t)SE_ATTR_PTR(ev)) == NULL) { 717 return; 718 } 719 720 SE_ATTR_PTR(ev) = UINT64_C(0); 721 (void) nvlist_size(nvl, &size, encoding); 722 SE_PAYLOAD_SZ(ev) -= size; 723 ASSERT(SE_PAYLOAD_SZ(ev) >= 0); 724 } 725 726 /* 727 * sysevent_attr_name - Get name of attribute 728 */ 729 char * 730 sysevent_attr_name(sysevent_attr_t *attr) 731 { 732 if (attr == NULL) { 733 return (NULL); 734 } 735 736 return (nvpair_name(attr)); 737 } 738 739 /* 740 * sysevent_attr_type - Get type of attribute 741 */ 742 int 743 sysevent_attr_type(sysevent_attr_t *attr) 744 { 745 /* 746 * The SE_DATA_TYPE_* are typedef'ed to be the 747 * same value as DATA_TYPE_* 748 */ 749 return (nvpair_type((nvpair_t *)attr)); 750 } 751 752 /* 753 * Repack event buffer into contiguous memory 754 */ 755 static sysevent_t * 756 se_repack(sysevent_t *ev, int flag) 757 { 758 size_t copy_len; 759 caddr_t attr; 760 size_t size; 761 uint64_t attr_offset; 762 sysevent_t *copy; 763 log_eventq_t *qcopy; 764 sysevent_attr_list_t *nvl; 765 766 copy_len = sizeof (log_eventq_t) + SE_PAYLOAD_SZ(ev); 767 qcopy = kmem_zalloc(copy_len, flag); 768 if (qcopy == NULL) { 769 return (NULL); 770 } 771 copy = (sysevent_t *)&qcopy->arg.buf; 772 773 /* 774 * Copy event header, class, subclass and publisher names 775 * Set the attribute offset (in number of bytes) to contiguous 776 * memory after the header. 777 */ 778 779 attr_offset = SE_ATTR_OFF(ev); 780 781 ASSERT((caddr_t)copy + attr_offset <= (caddr_t)copy + copy_len); 782 783 bcopy(ev, copy, attr_offset); 784 785 /* Check if attribute list exists */ 786 if ((nvl = (nvlist_t *)(uintptr_t)SE_ATTR_PTR(ev)) == NULL) { 787 return (copy); 788 } 789 790 /* 791 * Copy attribute data to contiguous memory 792 */ 793 attr = (char *)copy + attr_offset; 794 (void) nvlist_size(nvl, &size, encoding); 795 if (nvlist_pack(nvl, &attr, &size, encoding, flag) != 0) { 796 kmem_free(qcopy, copy_len); 797 return (NULL); 798 } 799 SE_ATTR_PTR(copy) = UINT64_C(0); 800 SE_FLAG(copy) = SE_PACKED_BUF; 801 802 return (copy); 803 } 804 805 /* 806 * The sysevent registration provides a persistent and reliable database 807 * for channel information for sysevent channel publishers and 808 * subscribers. 809 * 810 * A channel is created and maintained by the kernel upon the first 811 * SE_OPEN_REGISTRATION operation to log_sysevent_register(). Channel 812 * event subscription information is updated as publishers or subscribers 813 * perform subsequent operations (SE_BIND_REGISTRATION, SE_REGISTER, 814 * SE_UNREGISTER and SE_UNBIND_REGISTRATION). 815 * 816 * For consistency, id's are assigned for every publisher or subscriber 817 * bound to a particular channel. The id's are used to constrain resources 818 * and perform subscription lookup. 819 * 820 * Associated with each channel is a hashed list of the current subscriptions 821 * based upon event class and subclasses. A subscription contains a class name, 822 * list of possible subclasses and an array of subscriber ids. Subscriptions 823 * are updated for every SE_REGISTER or SE_UNREGISTER operation. 824 * 825 * Channels are closed once the last subscriber or publisher performs a 826 * SE_CLOSE_REGISTRATION operation. All resources associated with the named 827 * channel are freed upon last close. 828 * 829 * Locking: 830 * Every operation to log_sysevent() is protected by a single lock, 831 * registered_channel_mutex. It is expected that the granularity of 832 * a single lock is sufficient given the frequency that updates will 833 * occur. 834 * 835 * If this locking strategy proves to be too contentious, a per-hash 836 * or per-channel locking strategy may be implemented. 837 */ 838 839 840 #define CHANN_HASH(channel_name) (hash_func(channel_name) \ 841 % CHAN_HASH_SZ) 842 843 sysevent_channel_descriptor_t *registered_channels[CHAN_HASH_SZ]; 844 static int channel_cnt; 845 static void remove_all_class(sysevent_channel_descriptor_t *chan, 846 uint32_t sub_id); 847 848 static uint32_t 849 hash_func(const char *s) 850 { 851 uint32_t result = 0; 852 uint_t g; 853 854 while (*s != '\0') { 855 result <<= 4; 856 result += (uint32_t)*s++; 857 g = result & 0xf0000000; 858 if (g != 0) { 859 result ^= g >> 24; 860 result ^= g; 861 } 862 } 863 864 return (result); 865 } 866 867 static sysevent_channel_descriptor_t * 868 get_channel(char *channel_name) 869 { 870 int hash_index; 871 sysevent_channel_descriptor_t *chan_list; 872 873 if (channel_name == NULL) 874 return (NULL); 875 876 /* Find channel descriptor */ 877 hash_index = CHANN_HASH(channel_name); 878 chan_list = registered_channels[hash_index]; 879 while (chan_list != NULL) { 880 if (strcmp(chan_list->scd_channel_name, channel_name) == 0) { 881 break; 882 } else { 883 chan_list = chan_list->scd_next; 884 } 885 } 886 887 return (chan_list); 888 } 889 890 static class_lst_t * 891 create_channel_registration(sysevent_channel_descriptor_t *chan, 892 char *event_class, int index) 893 { 894 size_t class_len; 895 class_lst_t *c_list; 896 897 class_len = strlen(event_class) + 1; 898 c_list = kmem_zalloc(sizeof (class_lst_t), KM_SLEEP); 899 c_list->cl_name = kmem_zalloc(class_len, KM_SLEEP); 900 bcopy(event_class, c_list->cl_name, class_len); 901 902 c_list->cl_subclass_list = 903 kmem_zalloc(sizeof (subclass_lst_t), KM_SLEEP); 904 c_list->cl_subclass_list->sl_name = 905 kmem_zalloc(sizeof (EC_SUB_ALL), KM_SLEEP); 906 bcopy(EC_SUB_ALL, c_list->cl_subclass_list->sl_name, 907 sizeof (EC_SUB_ALL)); 908 909 c_list->cl_next = chan->scd_class_list_tbl[index]; 910 chan->scd_class_list_tbl[index] = c_list; 911 912 return (c_list); 913 } 914 915 static void 916 free_channel_registration(sysevent_channel_descriptor_t *chan) 917 { 918 int i; 919 class_lst_t *clist, *next_clist; 920 subclass_lst_t *sclist, *next_sc; 921 922 for (i = 0; i <= CLASS_HASH_SZ; ++i) { 923 924 clist = chan->scd_class_list_tbl[i]; 925 while (clist != NULL) { 926 sclist = clist->cl_subclass_list; 927 while (sclist != NULL) { 928 kmem_free(sclist->sl_name, 929 strlen(sclist->sl_name) + 1); 930 next_sc = sclist->sl_next; 931 kmem_free(sclist, sizeof (subclass_lst_t)); 932 sclist = next_sc; 933 } 934 kmem_free(clist->cl_name, 935 strlen(clist->cl_name) + 1); 936 next_clist = clist->cl_next; 937 kmem_free(clist, sizeof (class_lst_t)); 938 clist = next_clist; 939 } 940 } 941 chan->scd_class_list_tbl[0] = NULL; 942 } 943 944 static int 945 open_channel(char *channel_name) 946 { 947 int hash_index; 948 sysevent_channel_descriptor_t *chan, *chan_list; 949 950 951 if (channel_cnt > MAX_CHAN) { 952 return (-1); 953 } 954 955 /* Find channel descriptor */ 956 hash_index = CHANN_HASH(channel_name); 957 chan_list = registered_channels[hash_index]; 958 while (chan_list != NULL) { 959 if (strcmp(chan_list->scd_channel_name, channel_name) == 0) { 960 chan_list->scd_ref_cnt++; 961 kmem_free(channel_name, strlen(channel_name) + 1); 962 return (0); 963 } else { 964 chan_list = chan_list->scd_next; 965 } 966 } 967 968 969 /* New channel descriptor */ 970 chan = kmem_zalloc(sizeof (sysevent_channel_descriptor_t), KM_SLEEP); 971 chan->scd_channel_name = channel_name; 972 973 /* 974 * Create subscriber ids in the range [1, MAX_SUBSCRIBERS). 975 * Subscriber id 0 is never allocated, but is used as a reserved id 976 * by libsysevent 977 */ 978 if ((chan->scd_subscriber_cache = vmem_create(channel_name, (void *)1, 979 MAX_SUBSCRIBERS + 1, 1, NULL, NULL, NULL, 0, 980 VM_NOSLEEP | VMC_IDENTIFIER)) == NULL) { 981 kmem_free(chan, sizeof (sysevent_channel_descriptor_t)); 982 return (-1); 983 } 984 if ((chan->scd_publisher_cache = vmem_create(channel_name, (void *)1, 985 MAX_PUBLISHERS + 1, 1, NULL, NULL, NULL, 0, 986 VM_NOSLEEP | VMC_IDENTIFIER)) == NULL) { 987 vmem_destroy(chan->scd_subscriber_cache); 988 kmem_free(chan, sizeof (sysevent_channel_descriptor_t)); 989 return (-1); 990 } 991 992 chan->scd_ref_cnt = 1; 993 994 (void) create_channel_registration(chan, EC_ALL, 0); 995 996 if (registered_channels[hash_index] != NULL) 997 chan->scd_next = registered_channels[hash_index]; 998 999 registered_channels[hash_index] = chan; 1000 1001 ++channel_cnt; 1002 1003 return (0); 1004 } 1005 1006 static void 1007 close_channel(char *channel_name) 1008 { 1009 int hash_index; 1010 sysevent_channel_descriptor_t *chan, *prev_chan; 1011 1012 /* Find channel descriptor */ 1013 hash_index = CHANN_HASH(channel_name); 1014 prev_chan = chan = registered_channels[hash_index]; 1015 1016 while (chan != NULL) { 1017 if (strcmp(chan->scd_channel_name, channel_name) == 0) { 1018 break; 1019 } else { 1020 prev_chan = chan; 1021 chan = chan->scd_next; 1022 } 1023 } 1024 1025 if (chan == NULL) 1026 return; 1027 1028 chan->scd_ref_cnt--; 1029 if (chan->scd_ref_cnt > 0) 1030 return; 1031 1032 free_channel_registration(chan); 1033 vmem_destroy(chan->scd_subscriber_cache); 1034 vmem_destroy(chan->scd_publisher_cache); 1035 kmem_free(chan->scd_channel_name, 1036 strlen(chan->scd_channel_name) + 1); 1037 if (registered_channels[hash_index] == chan) 1038 registered_channels[hash_index] = chan->scd_next; 1039 else 1040 prev_chan->scd_next = chan->scd_next; 1041 kmem_free(chan, sizeof (sysevent_channel_descriptor_t)); 1042 --channel_cnt; 1043 } 1044 1045 static id_t 1046 bind_common(sysevent_channel_descriptor_t *chan, int type) 1047 { 1048 id_t id; 1049 1050 if (type == SUBSCRIBER) { 1051 id = (id_t)(uintptr_t)vmem_alloc(chan->scd_subscriber_cache, 1, 1052 VM_NOSLEEP | VM_NEXTFIT); 1053 if (id <= 0 || id > MAX_SUBSCRIBERS) 1054 return (0); 1055 chan->scd_subscriber_ids[id] = 1; 1056 } else { 1057 id = (id_t)(uintptr_t)vmem_alloc(chan->scd_publisher_cache, 1, 1058 VM_NOSLEEP | VM_NEXTFIT); 1059 if (id <= 0 || id > MAX_PUBLISHERS) 1060 return (0); 1061 chan->scd_publisher_ids[id] = 1; 1062 } 1063 1064 return (id); 1065 } 1066 1067 static int 1068 unbind_common(sysevent_channel_descriptor_t *chan, int type, id_t id) 1069 { 1070 if (type == SUBSCRIBER) { 1071 if (id <= 0 || id > MAX_SUBSCRIBERS) 1072 return (0); 1073 if (chan->scd_subscriber_ids[id] == 0) 1074 return (0); 1075 (void) remove_all_class(chan, id); 1076 chan->scd_subscriber_ids[id] = 0; 1077 vmem_free(chan->scd_subscriber_cache, (void *)(uintptr_t)id, 1); 1078 } else { 1079 if (id <= 0 || id > MAX_PUBLISHERS) 1080 return (0); 1081 if (chan->scd_publisher_ids[id] == 0) 1082 return (0); 1083 chan->scd_publisher_ids[id] = 0; 1084 vmem_free(chan->scd_publisher_cache, (void *)(uintptr_t)id, 1); 1085 } 1086 1087 return (1); 1088 } 1089 1090 static void 1091 release_id(sysevent_channel_descriptor_t *chan, int type, id_t id) 1092 { 1093 if (unbind_common(chan, type, id)) 1094 close_channel(chan->scd_channel_name); 1095 } 1096 1097 static subclass_lst_t * 1098 find_subclass(class_lst_t *c_list, char *subclass) 1099 { 1100 subclass_lst_t *sc_list; 1101 1102 if (c_list == NULL) 1103 return (NULL); 1104 1105 sc_list = c_list->cl_subclass_list; 1106 1107 while (sc_list != NULL) { 1108 if (strcmp(sc_list->sl_name, subclass) == 0) { 1109 return (sc_list); 1110 } 1111 sc_list = sc_list->sl_next; 1112 } 1113 1114 return (NULL); 1115 } 1116 1117 static void 1118 insert_subclass(class_lst_t *c_list, char **subclass_names, 1119 int subclass_num, uint32_t sub_id) 1120 { 1121 int i, subclass_sz; 1122 subclass_lst_t *sc_list; 1123 1124 for (i = 0; i < subclass_num; ++i) { 1125 if ((sc_list = find_subclass(c_list, subclass_names[i])) 1126 != NULL) { 1127 sc_list->sl_num[sub_id] = 1; 1128 } else { 1129 1130 sc_list = kmem_zalloc(sizeof (subclass_lst_t), 1131 KM_SLEEP); 1132 subclass_sz = strlen(subclass_names[i]) + 1; 1133 sc_list->sl_name = kmem_zalloc(subclass_sz, KM_SLEEP); 1134 bcopy(subclass_names[i], sc_list->sl_name, 1135 subclass_sz); 1136 1137 sc_list->sl_num[sub_id] = 1; 1138 1139 sc_list->sl_next = c_list->cl_subclass_list; 1140 c_list->cl_subclass_list = sc_list; 1141 } 1142 } 1143 } 1144 1145 static class_lst_t * 1146 find_class(sysevent_channel_descriptor_t *chan, char *class_name) 1147 { 1148 class_lst_t *c_list; 1149 1150 c_list = chan->scd_class_list_tbl[CLASS_HASH(class_name)]; 1151 while (c_list != NULL) { 1152 if (strcmp(class_name, c_list->cl_name) == 0) 1153 break; 1154 c_list = c_list->cl_next; 1155 } 1156 1157 return (c_list); 1158 } 1159 1160 static void 1161 remove_all_class(sysevent_channel_descriptor_t *chan, uint32_t sub_id) 1162 { 1163 int i; 1164 class_lst_t *c_list; 1165 subclass_lst_t *sc_list; 1166 1167 for (i = 0; i <= CLASS_HASH_SZ; ++i) { 1168 1169 c_list = chan->scd_class_list_tbl[i]; 1170 while (c_list != NULL) { 1171 sc_list = c_list->cl_subclass_list; 1172 while (sc_list != NULL) { 1173 sc_list->sl_num[sub_id] = 0; 1174 sc_list = sc_list->sl_next; 1175 } 1176 c_list = c_list->cl_next; 1177 } 1178 } 1179 } 1180 1181 static void 1182 remove_class(sysevent_channel_descriptor_t *chan, uint32_t sub_id, 1183 char *class_name) 1184 { 1185 class_lst_t *c_list; 1186 subclass_lst_t *sc_list; 1187 1188 if (strcmp(class_name, EC_ALL) == 0) { 1189 remove_all_class(chan, sub_id); 1190 return; 1191 } 1192 1193 if ((c_list = find_class(chan, class_name)) == NULL) { 1194 return; 1195 } 1196 1197 sc_list = c_list->cl_subclass_list; 1198 while (sc_list != NULL) { 1199 sc_list->sl_num[sub_id] = 0; 1200 sc_list = sc_list->sl_next; 1201 } 1202 } 1203 1204 static int 1205 insert_class(sysevent_channel_descriptor_t *chan, char *event_class, 1206 char **event_subclass_lst, int subclass_num, uint32_t sub_id) 1207 { 1208 class_lst_t *c_list; 1209 1210 if (strcmp(event_class, EC_ALL) == 0) { 1211 insert_subclass(chan->scd_class_list_tbl[0], 1212 event_subclass_lst, 1, sub_id); 1213 return (0); 1214 } 1215 1216 if (strlen(event_class) + 1 > MAX_CLASS_LEN) 1217 return (-1); 1218 1219 /* New class, add to the registration cache */ 1220 if ((c_list = find_class(chan, event_class)) == NULL) { 1221 c_list = create_channel_registration(chan, event_class, 1222 CLASS_HASH(event_class)); 1223 } 1224 1225 /* Update the subclass list */ 1226 insert_subclass(c_list, event_subclass_lst, subclass_num, sub_id); 1227 1228 return (0); 1229 } 1230 1231 static int 1232 add_registration(sysevent_channel_descriptor_t *chan, uint32_t sub_id, 1233 char *nvlbuf, size_t nvlsize) 1234 { 1235 uint_t num_elem; 1236 char *event_class; 1237 char **event_list; 1238 nvlist_t *nvl; 1239 nvpair_t *nvpair = NULL; 1240 1241 if (nvlist_unpack(nvlbuf, nvlsize, &nvl, KM_SLEEP) != 0) 1242 return (-1); 1243 1244 if ((nvpair = nvlist_next_nvpair(nvl, nvpair)) == NULL) { 1245 nvlist_free(nvl); 1246 return (-1); 1247 } 1248 1249 if ((event_class = nvpair_name(nvpair)) == NULL) { 1250 nvlist_free(nvl); 1251 return (-1); 1252 } 1253 if (nvpair_value_string_array(nvpair, &event_list, 1254 &num_elem) != 0) { 1255 nvlist_free(nvl); 1256 return (-1); 1257 } 1258 1259 if (insert_class(chan, event_class, event_list, num_elem, sub_id) < 0) { 1260 nvlist_free(nvl); 1261 return (-1); 1262 } 1263 1264 nvlist_free(nvl); 1265 1266 return (0); 1267 } 1268 1269 /* 1270 * get_registration - Return the requested class hash chain 1271 */ 1272 static int 1273 get_registration(sysevent_channel_descriptor_t *chan, char *databuf, 1274 uint32_t *bufsz, uint32_t class_index) 1275 { 1276 int num_classes = 0; 1277 char *nvlbuf = NULL; 1278 size_t nvlsize; 1279 nvlist_t *nvl; 1280 class_lst_t *clist; 1281 subclass_lst_t *sc_list; 1282 1283 if (class_index < 0 || class_index > CLASS_HASH_SZ) 1284 return (EINVAL); 1285 1286 if ((clist = chan->scd_class_list_tbl[class_index]) == NULL) { 1287 return (ENOENT); 1288 } 1289 1290 if (nvlist_alloc(&nvl, 0, 0) != 0) { 1291 return (EFAULT); 1292 } 1293 1294 while (clist != NULL) { 1295 if (nvlist_add_string(nvl, CLASS_NAME, clist->cl_name) 1296 != 0) { 1297 nvlist_free(nvl); 1298 return (EFAULT); 1299 } 1300 1301 sc_list = clist->cl_subclass_list; 1302 while (sc_list != NULL) { 1303 if (nvlist_add_byte_array(nvl, sc_list->sl_name, 1304 sc_list->sl_num, MAX_SUBSCRIBERS) != 0) { 1305 nvlist_free(nvl); 1306 return (EFAULT); 1307 } 1308 sc_list = sc_list->sl_next; 1309 } 1310 num_classes++; 1311 clist = clist->cl_next; 1312 } 1313 1314 if (num_classes == 0) { 1315 nvlist_free(nvl); 1316 return (ENOENT); 1317 } 1318 1319 if (nvlist_pack(nvl, &nvlbuf, &nvlsize, NV_ENCODE_NATIVE, 1320 KM_SLEEP) 1321 != 0) { 1322 nvlist_free(nvl); 1323 return (EFAULT); 1324 } 1325 1326 nvlist_free(nvl); 1327 1328 if (nvlsize > *bufsz) { 1329 kmem_free(nvlbuf, nvlsize); 1330 *bufsz = nvlsize; 1331 return (EAGAIN); 1332 } 1333 1334 bcopy(nvlbuf, databuf, nvlsize); 1335 kmem_free(nvlbuf, nvlsize); 1336 1337 return (0); 1338 } 1339 1340 /* 1341 * log_sysevent_register - Register event subscriber for a particular 1342 * event channel. 1343 */ 1344 int 1345 log_sysevent_register(char *channel_name, char *udatabuf, se_pubsub_t *udata) 1346 { 1347 int error = 0; 1348 char *kchannel, *databuf = NULL; 1349 size_t bufsz; 1350 se_pubsub_t kdata; 1351 sysevent_channel_descriptor_t *chan; 1352 1353 if (copyin(udata, &kdata, sizeof (se_pubsub_t)) == -1) { 1354 return (EFAULT); 1355 } 1356 if (kdata.ps_channel_name_len == 0) { 1357 return (EINVAL); 1358 } 1359 kchannel = kmem_alloc(kdata.ps_channel_name_len, KM_SLEEP); 1360 if (copyin(channel_name, kchannel, kdata.ps_channel_name_len) == -1) { 1361 kmem_free(kchannel, kdata.ps_channel_name_len); 1362 return (EFAULT); 1363 } 1364 bufsz = kdata.ps_buflen; 1365 if (bufsz > 0) { 1366 databuf = kmem_alloc(bufsz, KM_SLEEP); 1367 if (copyin(udatabuf, databuf, bufsz) == -1) { 1368 kmem_free(kchannel, kdata.ps_channel_name_len); 1369 kmem_free(databuf, bufsz); 1370 return (EFAULT); 1371 } 1372 } 1373 1374 mutex_enter(®istered_channel_mutex); 1375 if (kdata.ps_op != SE_OPEN_REGISTRATION && 1376 kdata.ps_op != SE_CLOSE_REGISTRATION) { 1377 chan = get_channel(kchannel); 1378 if (chan == NULL) { 1379 mutex_exit(®istered_channel_mutex); 1380 kmem_free(kchannel, kdata.ps_channel_name_len); 1381 if (bufsz > 0) 1382 kmem_free(databuf, bufsz); 1383 return (ENOENT); 1384 } 1385 } 1386 1387 switch (kdata.ps_op) { 1388 case SE_OPEN_REGISTRATION: 1389 if (open_channel(kchannel) != 0) { 1390 error = ENOMEM; 1391 if (bufsz > 0) 1392 kmem_free(databuf, bufsz); 1393 kmem_free(kchannel, kdata.ps_channel_name_len); 1394 } 1395 1396 mutex_exit(®istered_channel_mutex); 1397 return (error); 1398 case SE_CLOSE_REGISTRATION: 1399 close_channel(kchannel); 1400 break; 1401 case SE_BIND_REGISTRATION: 1402 if ((kdata.ps_id = bind_common(chan, kdata.ps_type)) <= 0) 1403 error = EBUSY; 1404 break; 1405 case SE_UNBIND_REGISTRATION: 1406 (void) unbind_common(chan, kdata.ps_type, (id_t)kdata.ps_id); 1407 break; 1408 case SE_REGISTER: 1409 if (bufsz == 0) { 1410 error = EINVAL; 1411 break; 1412 } 1413 if (add_registration(chan, kdata.ps_id, databuf, bufsz) == -1) 1414 error = EINVAL; 1415 break; 1416 case SE_UNREGISTER: 1417 if (bufsz == 0) { 1418 error = EINVAL; 1419 break; 1420 } 1421 remove_class(chan, kdata.ps_id, databuf); 1422 break; 1423 case SE_CLEANUP: 1424 /* Cleanup the indicated subscriber or publisher */ 1425 release_id(chan, kdata.ps_type, kdata.ps_id); 1426 break; 1427 case SE_GET_REGISTRATION: 1428 error = get_registration(chan, databuf, 1429 &kdata.ps_buflen, kdata.ps_id); 1430 break; 1431 default: 1432 error = ENOTSUP; 1433 } 1434 1435 mutex_exit(®istered_channel_mutex); 1436 1437 kmem_free(kchannel, kdata.ps_channel_name_len); 1438 1439 if (bufsz > 0) { 1440 if (copyout(databuf, udatabuf, bufsz) == -1) 1441 error = EFAULT; 1442 kmem_free(databuf, bufsz); 1443 } 1444 1445 if (copyout(&kdata, udata, sizeof (se_pubsub_t)) == -1) 1446 return (EFAULT); 1447 1448 return (error); 1449 } 1450 1451 /* 1452 * log_sysevent_copyout_data - Copyout event data to userland. 1453 * This is called from modctl(MODEVENTS, MODEVENTS_GETDATA) 1454 * The buffer size is always sufficient. 1455 */ 1456 int 1457 log_sysevent_copyout_data(sysevent_id_t *eid, size_t ubuflen, caddr_t ubuf) 1458 { 1459 int error = ENOENT; 1460 log_eventq_t *q; 1461 sysevent_t *ev; 1462 sysevent_id_t eid_copy; 1463 1464 /* 1465 * Copy eid 1466 */ 1467 if (copyin(eid, &eid_copy, sizeof (sysevent_id_t)) == -1) { 1468 return (EFAULT); 1469 } 1470 1471 mutex_enter(&eventq_sent_mutex); 1472 q = log_eventq_sent; 1473 1474 /* 1475 * Search for event buffer on the sent queue with matching 1476 * event identifier 1477 */ 1478 while (q) { 1479 ev = (sysevent_t *)&q->arg.buf; 1480 1481 if (SE_TIME(ev) != eid_copy.eid_ts || 1482 SE_SEQ(ev) != eid_copy.eid_seq) { 1483 q = q->next; 1484 continue; 1485 } 1486 1487 if (ubuflen < SE_SIZE(ev)) { 1488 error = EFAULT; 1489 break; 1490 } 1491 if (copyout(ev, ubuf, SE_SIZE(ev)) != 0) { 1492 error = EFAULT; 1493 LOG_DEBUG((CE_NOTE, "Unable to retrieve system event " 1494 "0x%" PRIx64 " from queue: EFAULT\n", 1495 eid->eid_seq)); 1496 } else { 1497 error = 0; 1498 } 1499 break; 1500 } 1501 1502 mutex_exit(&eventq_sent_mutex); 1503 1504 return (error); 1505 } 1506 1507 /* 1508 * log_sysevent_free_data - Free kernel copy of the event buffer identified 1509 * by eid (must have already been sent). Called from 1510 * modctl(MODEVENTS, MODEVENTS_FREEDATA). 1511 */ 1512 int 1513 log_sysevent_free_data(sysevent_id_t *eid) 1514 { 1515 int error = ENOENT; 1516 sysevent_t *ev; 1517 log_eventq_t *q, *prev = NULL; 1518 sysevent_id_t eid_copy; 1519 1520 /* 1521 * Copy eid 1522 */ 1523 if (copyin(eid, &eid_copy, sizeof (sysevent_id_t)) == -1) { 1524 return (EFAULT); 1525 } 1526 1527 mutex_enter(&eventq_sent_mutex); 1528 q = log_eventq_sent; 1529 1530 /* 1531 * Look for the event to be freed on the sent queue. Due to delayed 1532 * processing of the event, it may not be on the sent queue yet. 1533 * It is up to the user to retry the free operation to ensure that the 1534 * event is properly freed. 1535 */ 1536 while (q) { 1537 ev = (sysevent_t *)&q->arg.buf; 1538 1539 if (SE_TIME(ev) != eid_copy.eid_ts || 1540 SE_SEQ(ev) != eid_copy.eid_seq) { 1541 prev = q; 1542 q = q->next; 1543 continue; 1544 } 1545 /* 1546 * Take it out of log_eventq_sent and free it 1547 */ 1548 if (prev) { 1549 prev->next = q->next; 1550 } else { 1551 log_eventq_sent = q->next; 1552 } 1553 free_packed_event(ev); 1554 error = 0; 1555 break; 1556 } 1557 1558 mutex_exit(&eventq_sent_mutex); 1559 1560 return (error); 1561 } 1562 1563 /* 1564 * log_sysevent_flushq - Begin or resume event buffer delivery. If neccessary, 1565 * create log_event_deliver thread or wake it up 1566 */ 1567 /*ARGSUSED*/ 1568 void 1569 log_sysevent_flushq(int cmd, uint_t flag) 1570 { 1571 mutex_enter(&eventq_head_mutex); 1572 1573 /* 1574 * Start the event delivery thread 1575 * Mark the upcall status as active since we should 1576 * now be able to begin emptying the queue normally. 1577 */ 1578 if (!async_thread) { 1579 sysevent_upcall_status = 0; 1580 sysevent_daemon_init = 1; 1581 setup_ddi_poststartup(); 1582 async_thread = thread_create(NULL, 0, log_event_deliver, 1583 NULL, 0, &p0, TS_RUN, minclsyspri); 1584 } 1585 1586 log_event_delivery = LOGEVENT_DELIVERY_CONT; 1587 cv_signal(&log_event_cv); 1588 mutex_exit(&eventq_head_mutex); 1589 } 1590 1591 /* 1592 * log_sysevent_filename - Called by syseventd via 1593 * modctl(MODEVENTS, MODEVENTS_SET_DOOR_UPCALL_FILENAME) 1594 * to subsequently bind the event_door. 1595 * 1596 * This routine is called everytime syseventd (re)starts 1597 * and must therefore replay any events buffers that have 1598 * been sent but not freed. 1599 * 1600 * Event buffer delivery begins after a call to 1601 * log_sysevent_flushq(). 1602 */ 1603 int 1604 log_sysevent_filename(char *file) 1605 { 1606 /* 1607 * Called serially by syseventd init code, no need to protect door 1608 * data. 1609 */ 1610 /* Unbind old event door */ 1611 if (logevent_door_upcall_filename) { 1612 kmem_free(logevent_door_upcall_filename, 1613 logevent_door_upcall_filename_size); 1614 if (event_door) { 1615 door_ki_rele(event_door); 1616 event_door = NULL; 1617 } 1618 } 1619 logevent_door_upcall_filename_size = strlen(file) + 1; 1620 logevent_door_upcall_filename = kmem_alloc( 1621 logevent_door_upcall_filename_size, KM_SLEEP); 1622 (void) strcpy(logevent_door_upcall_filename, file); 1623 1624 /* 1625 * We are called when syseventd restarts. Move all sent, but 1626 * not committed events from log_eventq_sent to log_eventq_head. 1627 * Do it in proper order to maintain increasing event id. 1628 */ 1629 mutex_enter(&eventq_head_mutex); 1630 1631 mutex_enter(&eventq_sent_mutex); 1632 while (log_eventq_sent) { 1633 log_eventq_t *tmp = log_eventq_sent->next; 1634 log_eventq_sent->next = log_eventq_head; 1635 if (log_eventq_head == NULL) { 1636 ASSERT(log_eventq_cnt == 0); 1637 log_eventq_tail = log_eventq_sent; 1638 log_eventq_tail->next = NULL; 1639 } else if (log_eventq_head == log_eventq_tail) { 1640 ASSERT(log_eventq_cnt == 1); 1641 ASSERT(log_eventq_head->next == NULL); 1642 ASSERT(log_eventq_tail->next == NULL); 1643 } 1644 log_eventq_head = log_eventq_sent; 1645 log_eventq_sent = tmp; 1646 log_eventq_cnt++; 1647 } 1648 mutex_exit(&eventq_sent_mutex); 1649 mutex_exit(&eventq_head_mutex); 1650 1651 return (0); 1652 } 1653 1654 /* 1655 * queue_sysevent - queue an event buffer 1656 */ 1657 static int 1658 queue_sysevent(sysevent_t *ev, sysevent_id_t *eid, int flag) 1659 { 1660 log_eventq_t *q; 1661 1662 ASSERT(flag == SE_SLEEP || flag == SE_NOSLEEP); 1663 1664 restart: 1665 1666 /* Max Q size exceeded */ 1667 mutex_enter(&event_qfull_mutex); 1668 if (sysevent_daemon_init && log_eventq_cnt >= logevent_max_q_sz) { 1669 /* 1670 * If queue full and transport down, return no transport 1671 */ 1672 if (sysevent_upcall_status != 0) { 1673 mutex_exit(&event_qfull_mutex); 1674 free_packed_event(ev); 1675 eid->eid_seq = UINT64_C(0); 1676 eid->eid_ts = INT64_C(0); 1677 return (SE_NO_TRANSPORT); 1678 } 1679 if (flag == SE_NOSLEEP) { 1680 mutex_exit(&event_qfull_mutex); 1681 free_packed_event(ev); 1682 eid->eid_seq = UINT64_C(0); 1683 eid->eid_ts = INT64_C(0); 1684 return (SE_EQSIZE); 1685 } 1686 event_qfull_blocked++; 1687 cv_wait(&event_qfull_cv, &event_qfull_mutex); 1688 event_qfull_blocked--; 1689 mutex_exit(&event_qfull_mutex); 1690 goto restart; 1691 } 1692 mutex_exit(&event_qfull_mutex); 1693 1694 mutex_enter(&eventq_head_mutex); 1695 1696 /* Time stamp and assign ID */ 1697 SE_SEQ(ev) = eid->eid_seq = atomic_add_64_nv(&kernel_event_id, 1698 (uint64_t)1); 1699 SE_TIME(ev) = eid->eid_ts = gethrtime(); 1700 1701 LOG_DEBUG1((CE_CONT, "log_sysevent: class=%d type=%d id=0x%llx\n", 1702 SE_CLASS(ev), SE_SUBCLASS(ev), (longlong_t)SE_SEQ(ev))); 1703 1704 /* 1705 * Put event on eventq 1706 */ 1707 q = (log_eventq_t *)((caddr_t)ev - offsetof(log_eventq_t, arg.buf)); 1708 q->next = NULL; 1709 if (log_eventq_head == NULL) { 1710 ASSERT(log_eventq_cnt == 0); 1711 log_eventq_head = q; 1712 log_eventq_tail = q; 1713 } else { 1714 if (log_eventq_head == log_eventq_tail) { 1715 ASSERT(log_eventq_cnt == 1); 1716 ASSERT(log_eventq_head->next == NULL); 1717 ASSERT(log_eventq_tail->next == NULL); 1718 } 1719 log_eventq_tail->next = q; 1720 log_eventq_tail = q; 1721 } 1722 log_eventq_cnt++; 1723 1724 /* Signal event delivery thread */ 1725 if (log_eventq_cnt == 1) { 1726 cv_signal(&log_event_cv); 1727 } 1728 mutex_exit(&eventq_head_mutex); 1729 1730 return (0); 1731 } 1732 1733 /* 1734 * log_sysevent - kernel system event logger. 1735 * 1736 * Returns SE_ENOMEM if buf allocation failed or SE_EQSIZE if the 1737 * maximum event queue size will be exceeded 1738 * Returns 0 for successfully queued event buffer 1739 */ 1740 int 1741 log_sysevent(sysevent_t *ev, int flag, sysevent_id_t *eid) 1742 { 1743 sysevent_t *ev_copy; 1744 int rval; 1745 1746 ASSERT(flag == SE_SLEEP || flag == SE_NOSLEEP); 1747 ASSERT(!(flag == SE_SLEEP && servicing_interrupt())); 1748 1749 ev_copy = se_repack(ev, flag); 1750 if (ev_copy == NULL) { 1751 ASSERT(flag == SE_NOSLEEP); 1752 return (SE_ENOMEM); 1753 } 1754 rval = queue_sysevent(ev_copy, eid, flag); 1755 ASSERT(rval == 0 || rval == SE_ENOMEM || rval == SE_EQSIZE || 1756 rval == SE_NO_TRANSPORT); 1757 ASSERT(!(flag == SE_SLEEP && (rval == SE_EQSIZE || rval == SE_ENOMEM))); 1758 return (rval); 1759 } 1760 1761 /* 1762 * log_usr_sysevent - user system event logger 1763 * Private to devfsadm and accessible only via 1764 * modctl(MODEVENTS, MODEVENTS_POST_EVENT) 1765 */ 1766 int 1767 log_usr_sysevent(sysevent_t *ev, int ev_size, sysevent_id_t *eid) 1768 { 1769 int ret, copy_sz; 1770 sysevent_t *ev_copy; 1771 sysevent_id_t new_eid; 1772 log_eventq_t *qcopy; 1773 1774 copy_sz = ev_size + offsetof(log_eventq_t, arg) + 1775 offsetof(log_event_upcall_arg_t, buf); 1776 qcopy = kmem_zalloc(copy_sz, KM_SLEEP); 1777 ev_copy = (sysevent_t *)&qcopy->arg.buf; 1778 1779 /* 1780 * Copy event 1781 */ 1782 if (copyin(ev, ev_copy, ev_size) == -1) { 1783 kmem_free(qcopy, copy_sz); 1784 return (EFAULT); 1785 } 1786 1787 if ((ret = queue_sysevent(ev_copy, &new_eid, SE_NOSLEEP)) != 0) { 1788 if (ret == SE_ENOMEM || ret == SE_EQSIZE) 1789 return (EAGAIN); 1790 else 1791 return (EIO); 1792 } 1793 1794 if (copyout(&new_eid, eid, sizeof (sysevent_id_t)) == -1) { 1795 return (EFAULT); 1796 } 1797 1798 return (0); 1799 } 1800 1801 1802 1803 int 1804 ddi_log_sysevent( 1805 dev_info_t *dip, 1806 char *vendor, 1807 char *class, 1808 char *subclass, 1809 nvlist_t *attr_list, 1810 sysevent_id_t *eidp, 1811 int sleep_flag) 1812 { 1813 sysevent_attr_list_t *list = (sysevent_attr_list_t *)attr_list; 1814 char pubstr[32]; 1815 sysevent_t *event; 1816 sysevent_id_t eid; 1817 const char *drvname; 1818 char *publisher; 1819 int se_flag; 1820 int rval; 1821 int n; 1822 1823 if (sleep_flag == DDI_SLEEP && servicing_interrupt()) { 1824 cmn_err(CE_NOTE, "!ddi_log_syevent: driver %s%d - cannot queue " 1825 "event from interrupt context with sleep semantics\n", 1826 ddi_driver_name(dip), ddi_get_instance(dip)); 1827 return (DDI_ECONTEXT); 1828 } 1829 1830 drvname = ddi_driver_name(dip); 1831 n = strlen(vendor) + strlen(drvname) + 7; 1832 if (n < sizeof (pubstr)) { 1833 publisher = pubstr; 1834 } else { 1835 publisher = kmem_alloc(n, 1836 (sleep_flag == DDI_SLEEP) ? KM_SLEEP : KM_NOSLEEP); 1837 if (publisher == NULL) { 1838 return (DDI_ENOMEM); 1839 } 1840 } 1841 (void) strcpy(publisher, vendor); 1842 (void) strcat(publisher, ":kern:"); 1843 (void) strcat(publisher, drvname); 1844 1845 se_flag = (sleep_flag == DDI_SLEEP) ? SE_SLEEP : SE_NOSLEEP; 1846 event = sysevent_alloc(class, subclass, publisher, se_flag); 1847 1848 if (publisher != pubstr) { 1849 kmem_free(publisher, n); 1850 } 1851 1852 if (event == NULL) { 1853 return (DDI_ENOMEM); 1854 } 1855 1856 if (list) { 1857 (void) sysevent_attach_attributes(event, list); 1858 } 1859 1860 rval = log_sysevent(event, se_flag, &eid); 1861 if (list) { 1862 sysevent_detach_attributes(event); 1863 } 1864 sysevent_free(event); 1865 if (rval == 0) { 1866 if (eidp) { 1867 eidp->eid_seq = eid.eid_seq; 1868 eidp->eid_ts = eid.eid_ts; 1869 } 1870 return (DDI_SUCCESS); 1871 } 1872 if (rval == SE_NO_TRANSPORT) 1873 return (DDI_ETRANSPORT); 1874 1875 ASSERT(rval == SE_ENOMEM || rval == SE_EQSIZE); 1876 return ((rval == SE_ENOMEM) ? DDI_ENOMEM : DDI_EBUSY); 1877 } 1878 1879 uint64_t 1880 log_sysevent_new_id() 1881 { 1882 return (atomic_add_64_nv(&kernel_event_id, (uint64_t)1)); 1883 } 1884