devfsadmd_mod.c revision bc9ec910d60a3256c0b6bb68a13afa62e106730a
/*
* 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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <limits.h>
#include <thread.h>
#include <wait.h>
#include <synch.h>
#include <syslog.h>
#include <libintl.h>
#include <libsysevent.h>
#include "sysevent_signal.h"
#include "../devfsadm/devfsadm.h"
/*
* SLM for devfsadmd device configuration daemon
*/
extern char *root_dir;
extern void syseventd_print();
/* Alternate root declarations during install */
static int use_alt_root = 0;
static struct slm_mod_ops devfsadm_mod_ops = {
typedef struct ev_queue {
} ev_queue_t;
static ev_queue_t *eventq_head;
static ev_queue_t *eventq_tail;
(devfsadmd not responding) Run devfsadm")
#define RETRY_MAX 3
static int
{
int status, w;
/* Check the requested command */
if (s == NULL) {
return (-1);
}
/* Check the ability to execute devfsadmd from this process */
return (-1);
}
return (-1);
}
/*
* Block SIGCHLD and set up a default handler for the duration of the
* system1 call.
*/
(void) sigemptyset(&mask);
/* Fork off the child process (using fork1(), because it's MT-safe) */
case -1:
/* Error */
return (-1);
case 0:
/* Set-up an initial signal mask for the child */
(void) sigemptyset(&mask);
closefrom(3);
_exit(-1);
break;
default:
/* Parent */
break;
}
do {
return ((w == -1)? w: status);
}
/*
* devfsadmdeliver_event - called by syseventd to deliver an event buffer.
* The event buffer is subsequently delivered to
* devfsadmd. If devfsadmd, is not responding to the
* delivery attempt, we will try to startup the
* daemon. MT protection is provided by syseventd
* and the client lock. This insures sequential
* event delivery and protection from re-entrance.
*/
/*ARGSUSED*/
static int
{
int ev_size;
/* Not initialized */
if (sysevent_hp == NULL) {
return (0);
}
/* Quick return for uninteresting events */
return (0);
}
/* Queue event for delivery to devfsadmd */
return (EAGAIN);
}
return (EAGAIN);
}
(void) mutex_lock(&evq_lock);
if (eventq_head == NULL) {
} else {
}
(void) cond_signal(&evq_cv);
(void) mutex_unlock(&evq_lock);
return (0);
}
static int cleanup;
void
{
int retry;
(void) mutex_lock(&evq_lock);
for (;;) {
while (eventq_head == NULL) {
(void) cond_signal(&evq_cv);
(void) mutex_unlock(&evq_lock);
return;
}
}
/* Send events on to devfsadmd */
evqp = eventq_head;
while (evqp) {
(void) mutex_unlock(&evq_lock);
retry = 0;
while (sysevent_send_event(sysevent_hp,
/*
* If we are using an alternate root, devfsadm
* is run to handle node creation.
*/
if (use_alt_root == 0) {
/*
* daemon unresponsive -
* restart daemon and retry once more
* if not installing
*/
if (system1(
DEVFSADMD_START) != -1) {
(void) sleep(1);
}
}
++retry;
continue;
} else {
break;
}
} else {
break;
}
}
(void) mutex_lock(&evq_lock);
if (eventq_head != NULL) {
if (eventq_head == NULL)
eventq_tail = NULL;
}
evqp = eventq_head;
}
if (cleanup) {
(void) cond_signal(&evq_cv);
(void) mutex_unlock(&evq_lock);
return;
}
}
/* NOTREACHED */
}
struct slm_mod_ops *
slm_init()
{
char alt_door[MAXPATHLEN];
/* Initialize the private sysevent handle */
} else {
/* Try alternate door during install time */
return (NULL);
use_alt_root = 1;
}
if (sysevent_hp == NULL) {
syseventd_print(0, "Unable to allocate sysevent handle"
" for devfsadm module\n");
return (NULL);
}
if (sysevent_bind_publisher(sysevent_hp) != 0) {
if (sysevent_bind_publisher(sysevent_hp) != 0) {
(void) sysevent_close_channel(sysevent_hp);
return (NULL);
}
}
}
cleanup = 0;
eventq_head = NULL;
eventq_tail = NULL;
(void) mutex_destroy(&evq_lock);
(void) cond_destroy(&evq_cv);
return (NULL);
}
return (&devfsadm_mod_ops);
}
void
slm_fini()
{
/* Wait for all events to be flushed out to devfsadmd */
(void) mutex_lock(&evq_lock);
cleanup = 1;
(void) cond_signal(&evq_cv);
(void) mutex_unlock(&evq_lock);
/* Wait for delivery thread to exit */
(void) mutex_destroy(&evq_lock);
(void) cond_destroy(&evq_cv);
sysevent_hp = NULL;
}