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