/* * log_event_upcall - Perform the upcall to syseventd for event buffer delivery. * Check for rebinding errors * This buffer is reused to by the syseventd door_return * to hold the result code */ static int log_event_upcall(log_event_upcall_arg_t *arg) { int error; size_t size; sysevent_t *ev; door_arg_t darg, save_arg; int retry; int neagain = 0; int neintr = 0; int nticks = LOG_EVENT_MIN_PAUSE; /* Initialize door args */ ev = (sysevent_t *)&arg->buf; size = sizeof (log_event_upcall_arg_t) + SE_PAYLOAD_SZ(ev); darg.rbuf = (char *)arg; darg.data_ptr = (char *)arg; darg.rsize = size; darg.data_size = size; darg.desc_ptr = NULL; darg.desc_num = 0; if ((event_door == NULL) && ((error = log_event_upcall_lookup()) != 0)) { LOG_DEBUG((CE_CONT, "log_event_upcall: event_door error (%d)\n", error)); return (error); } LOG_DEBUG1((CE_CONT, "log_event_upcall: 0x%llx\n", (longlong_t)SE_SEQ((sysevent_t *)&arg->buf))); save_arg = darg; for (retry = 0; ; retry++) { if ((error = door_ki_upcall_limited(event_door, &darg, NULL, SIZE_MAX, 0)) == 0) { break; } switch (error) { case EINTR: neintr++; log_event_pause(2); darg = save_arg; break; case EAGAIN: /* cannot deliver upcall - process may be forking */ neagain++; log_event_pause(nticks); nticks <<= 1; if (nticks > LOG_EVENT_MAX_PAUSE) nticks = LOG_EVENT_MAX_PAUSE; darg = save_arg; break; case EBADF: LOG_DEBUG((CE_CONT, "log_event_upcall: rebinding\n")); /* Server may have died. Try rebinding */ if ((error = log_event_upcall_lookup()) != 0) { LOG_DEBUG((CE_CONT, "log_event_upcall: lookup error %d\n", error)); return (EBADF); } if (retry > 4) { LOG_DEBUG((CE_CONT, "log_event_upcall: ebadf\n")); return (EBADF); } LOG_DEBUG((CE_CONT, "log_event_upcall: " "retrying upcall after lookup\n")); darg = save_arg; break; default: cmn_err(CE_CONT, "log_event_upcall: door_ki_upcall error %d\n", error); return (error); } } if (neagain > 0 || neintr > 0) { LOG_DEBUG((CE_CONT, "upcall: eagain=%d eintr=%d nticks=%d\n", neagain, neintr, nticks)); } LOG_DEBUG1((CE_CONT, "log_event_upcall:\n\t" "error=%d rptr1=%p rptr2=%p dptr2=%p ret1=%x ret2=%x\n", error, (void *)arg, (void *)darg.rbuf, (void *)darg.data_ptr, *((int *)(darg.rbuf)), *((int *)(darg.data_ptr)))); if (!error) { /* * upcall was successfully executed. Check return code. */ error = *((int *)(darg.rbuf)); } return (error); }
/* * log_event_upcall - Perform the upcall to syseventd for event buffer delivery. * Check for rebinding errors * This buffer is reused to by the syseventd door_return * to hold the result code */ static int log_event_upcall(log_event_upcall_arg_t *arg) { int error; size_t size; sysevent_t *ev; door_arg_t darg, save_arg; int retry; int neagain = 0; int neintr = 0; int nticks = LOG_EVENT_MIN_PAUSE; /* Initialize door args */ ev = (sysevent_t *)&arg->buf; size = sizeof (log_event_upcall_arg_t) + SE_PAYLOAD_SZ(ev); darg.rbuf = (char *)arg; darg.data_ptr = (char *)arg; darg.rsize = size; darg.data_size = size; darg.desc_ptr = NULL; darg.desc_num = 0; LOG_DEBUG1((CE_CONT, "log_event_upcall: 0x%llx\n", (longlong_t)SE_SEQ((sysevent_t *)&arg->buf))); save_arg = darg; for (retry = 0; ; retry++) { mutex_enter(&event_door_mutex); if (event_door == NULL) { mutex_exit(&event_door_mutex); return (EBADF); } if ((error = door_ki_upcall_limited(event_door, &darg, NULL, SIZE_MAX, 0)) == 0) { mutex_exit(&event_door_mutex); break; } /* * EBADF is handled outside the switch below because we need to * hold event_door_mutex a bit longer */ if (error == EBADF) { /* Server died */ door_ki_rele(event_door); event_door = NULL; mutex_exit(&event_door_mutex); return (error); } mutex_exit(&event_door_mutex); /* * The EBADF case is already handled above with event_door_mutex * held */ switch (error) { case EINTR: neintr++; log_event_pause(2); darg = save_arg; break; case EAGAIN: /* cannot deliver upcall - process may be forking */ neagain++; log_event_pause(nticks); nticks <<= 1; if (nticks > LOG_EVENT_MAX_PAUSE) nticks = LOG_EVENT_MAX_PAUSE; darg = save_arg; break; default: cmn_err(CE_CONT, "log_event_upcall: door_ki_upcall error %d\n", error); return (error); } } if (neagain > 0 || neintr > 0) { LOG_DEBUG((CE_CONT, "upcall: eagain=%d eintr=%d nticks=%d\n", neagain, neintr, nticks)); } LOG_DEBUG1((CE_CONT, "log_event_upcall:\n\t" "error=%d rptr1=%p rptr2=%p dptr2=%p ret1=%x ret2=%x\n", error, (void *)arg, (void *)darg.rbuf, (void *)darg.data_ptr, *((int *)(darg.rbuf)), *((int *)(darg.data_ptr)))); if (!error) { /* * upcall was successfully executed. Check return code. */ error = *((int *)(darg.rbuf)); } return (error); }