Exemplo n.º 1
0
/*
 * 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);
}
Exemplo n.º 2
0
/*
 * 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);
}