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