sdev_comm.c revision 3c5e027b0f15017d4b6afff01915ea70ae476223
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* routines to invoke user level name lookup services
*/
#include <sys/sysmacros.h>
#include <sys/pathname.h>
/* default timeout to wait for devfsadm response in seconds */
/* atomic bitset for devfsadm status */
volatile uint_t devfsadm_state;
static kmutex_t devfsadm_lock;
static kcondvar_t devfsadm_cv;
static int dev_node_wait_timeout = DEV_NODE_WAIT_TIMEOUT;
static int dev_devfsadm_startup = DEV_DEVFSADM_STARTUP;
/*
* Door used to communicate with devfsadmd
*/
static char *sdev_door_upcall_filename = NULL;
static int sdev_upcall_door_revoked = 0;
static int sdev_door_upcall_filename_size;
static int sdev_devfsadm_revoked(void);
void
sdev_devfsadm_lockinit(void)
{
}
void
{
}
/*
* Wait for node to be created
*/
int
{
/* tick value at which wait expires */
expire = ddi_get_lbolt() +
sdcmn_err6(("wait4lookup %s %s, %ld %d\n",
if (SDEV_IS_LGWAITING(dv)) {
/* devfsadm nodes */
while (DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state) &&
!sdev_devfsadm_revoked()) {
/* wait 2 sec and check devfsadm completion */
/* was this node constructed ? */
rval = 0;
}
sdcmn_err6(("%s: wait done, %screated %d\n",
dv->sdev_state));
break;
} else if (rv == 0) {
/* interrupted */
sdcmn_err6(("%s: wait interrupted\n",
break;
} else if ((rv == -1) &&
(ddi_get_lbolt() >= expire)) {
sdcmn_err6(("%s: wait time is up\n",
break;
}
sdcmn_err6(("%s: wait "
"rv %ld state 0x%x expire %ld\n",
expire - ddi_get_lbolt()));
}
} else {
/*
* for the nodes created by
* devname_lookup_func callback
* or plug-in modules
*/
}
rval = 0;
}
sdcmn_err6(("wait4lookup unblocking %s state 0x%x %d\n",
if (is_lookup) {
} else {
}
return (rval);
}
void
{
if (SDEV_IS_LGWAITING(dv)) {
}
}
/*
* In the case devfsadmd is down, it is re-started by syseventd
* upon receiving an event subscribed to by devfsadmd.
*/
static int
{
int se_err = 0;
sysevent_t *ev;
switch (se_err) {
case SE_NO_TRANSPORT:
"syseventd may not be responding\n");
break;
default:
"sysevent error %d\n", se_err);
break;
}
}
return (se_err);
}
static int
{
int error;
/* tick value at which wait expires */
expire = ddi_get_lbolt() +
if (sdev_door_upcall_filename == NULL) {
if ((error = sdev_start_devfsadmd()) != 0) {
return (error);
}
/* wait for devfsadmd start */
while (sdev_door_upcall_filename == NULL) {
sdcmn_err6(("waiting for dev_door creation, %ld\n",
expire - ddi_get_lbolt()));
expire);
if (rv <= 0) {
sdcmn_err6(("devfsadmd startup error\n"));
return (EBADF);
}
}
sdcmn_err6(("devfsadmd is ready\n"));
}
&sdev_upcall_door)) != 0) {
sdcmn_err6(("upcall_lookup: door open error %d\n",
error));
return (error);
}
return (0);
}
static void
{
if (sdev_upcall_door) {
}
if (sdev_door_upcall_filename) {
}
}
static int
{
int error;
int retry;
if (((sdev_upcall_door == NULL) &&
((error = sdev_open_upcall_door()) != 0)) ||
sdcmn_err6(("call_devfsadm: upcall lookup error\n"));
return (error);
}
sdcmn_err6(("call devfsadm: upcall lookup ok\n"));
break;
}
/*
* handle door call errors
*/
if (sdev_devfsadm_revoked()) {
sdcmn_err6(("upcall lookup door revoked, "
"error %d\n", error));
return (error);
}
switch (error) {
case EINTR:
/* return error here? */
sdcmn_err6(("sdev_ki_call_devfsadm: EINTR\n"));
break;
case EAGAIN:
sdcmn_err6(("sdev_ki_call_devfsadm: EAGAIN\n"));
break;
case EBADF:
if (retry > 4) {
sdcmn_err6(("sdev_ki_call_devfsadm: EBADF\n"));
return (EBADF);
}
"sdev_ki_call_devfsadm: EBADF, re-binding\n"));
if (error != 0) {
sdcmn_err6(("sdev_ki_call_devfsadm: "
"EBADF lookup error %d\n", error));
if (!sdev_devfsadm_revoked())
"?unable to invoke devfsadm - "
"please run manually\n");
return (EBADF);
}
break;
case EINVAL:
default:
"?sdev: door_ki_upcall unexpected result %d\n",
error);
return (error);
}
}
if (!error) {
if (resultp->devfsadm_error != 0) {
sdcmn_err6(("sdev_ki_call_devfsadmd: result %d\n",
}
} else {
}
return (error);
}
static int
sdev_devfsadm_revoked(void)
{
int rv;
extern int sys_shutdown;
if (sys_shutdown) {
sdcmn_err6(("dev: shutdown observed\n"));
return (1);
}
if (sdev_upcall_door && !sdev_upcall_door_revoked) {
sdcmn_err6(("lookup door: revoked\n"));
}
}
return (sdev_upcall_door_revoked);
}
/*ARGSUSED*/
static void
{
if (!error) {
sdcmn_err6(("devfsadm result error: %d\n",
if (!result.devfsadm_error) {
} else {
}
} else {
}
done:
sdcmn_err6(("sdev_config_all_thread: stopping, devfsadm state 0x%x\n",
thread_exit();
}
/*
* launch an asynchronous thread to do the devfsadm dev_config_all
*/
/*ARGSUSED*/
void
{
}
int
devname_filename_register(char *name)
{
int error = 0;
char *strbuf;
char *namep;
int n;
sdcmn_err6(("error copyin \n"));
} else {
/* handling the daemon re-start situations */
sdcmn_err6(("size %d file name %s\n",
}
return (error);
}