/*
* 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
*/
/*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stropts.h>
#include <synch.h>
#include <thread.h>
#include <libsysevent.h>
#include <errno.h>
#include <libgen.h>
#include <unistd.h>
#include "libdiskmgt.h"
#include "disks_private.h"
struct event_list {
};
static int event_error = 0;
static int event_break = 0;
/*
* When we add a controller we get an add event for each drive on the
* controller. We don't want to walk the devtree for each drive since
* we will get the same information each time. So, the solution is to
* wait for a few seconds for all of the add events to come in and then
* do a single walk. If an add event comes in after we start the walk, we
* need to do another walk since we might have missed that drive.
*
* State: 0 - no walker; 1 - walker waiting; 2 - walker running
* 0 -> 1; wait a few seconds
* 1 -> 2; walking the devtree
* 2 -> either 0 or 1 (see below)
* While running (state 2), if event comes in, go back to waiting (state 1)
* after the walk otherwise go back to none (state 0).
*
* walker_lock protects walker_state & events_pending
*/
#define WALK_NONE 0
static int events_pending = 0;
static int sendevents = 0;
static void cb_watch_events();
static void walk_devtree();
nvlist_t *
{
*errp = 0;
/* wait until there is an event in the queue */
/*CONSTCOND*/
while (1) {
if (event_break) {
event_break = 0;
break;
}
(void) mutex_lock(&queue_lock);
/* first see if we ran out of memory since the last call */
if (event_error != 0) {
*errp = event_error;
event_error = 0;
}
(void) mutex_unlock(&queue_lock);
break;
}
}
return (event);
}
void
{
if (sendevents == 1) {
/* we were already initialized, see what changes to make */
*errp = 0;
/* clearing the cb so shutdown the internal cb thread */
event_break = 1;
} else {
/* installing a cb; we didn't have one before */
&watch_thread);
}
}
} else {
/* first time to initialize */
sendevents = 1;
if (*errp != 0) {
return;
}
&watch_thread);
}
}
}
void
{
if (!sendevents) {
return;
}
} else {
int error = 0;
}
if (dtype != -1 &&
}
}
if (error != 0) {
}
}
}
void
{
}
int
{
/* Bind event handler and create subscriber handle */
if (dm_debug) {
/* keep going when we're debugging */
return (0);
}
return (errno);
}
subclass_list[0] = ESC_DISK;
if (dm_debug) {
/* keep going when we're debugging */
return (0);
}
return (errno);
}
!= 0) {
if (dm_debug) {
/* keep going when we're debugging */
return (0);
}
return (errno);
}
return (0);
}
static void
{
(void) mutex_lock(&queue_lock);
(void) mutex_unlock(&queue_lock);
return;
}
} else {
}
} else {
/* already have events in the queue */
/* find the last element in the list */
} else {
}
}
(void) mutex_unlock(&queue_lock);
}
static void
{
int error;
/*CONSTCOND*/
while (1) {
/* end the thread */
return;
}
}
}
static void
{
char *class_name;
char *pub;
if (dm_debug) {
} else {
}
}
/* batch up the adds into a single devtree walk */
walk_devtree();
if (dm_debug) {
}
}
}
}
}
}
/*
* This is a debugging function only.
*/
static void
{
char *attrname;
char *str;
char **str_array;
int i;
switch (nvpair_type(nvp)) {
case DATA_TYPE_STRING:
break;
case DATA_TYPE_STRING_ARRAY:
for (i = 0; i < cnt; i++) {
}
break;
case DATA_TYPE_UINT32:
break;
case DATA_TYPE_UINT64:
#ifdef _LP64
#else
#endif
break;
case DATA_TYPE_BOOLEAN:
break;
default:
attrname);
break;
}
}
}
/*
* Batch up the adds into a single devtree walk. We can get a bunch of
* adds when we add a controller since we will get an add event for each
* drive.
*/
static void
{
(void) mutex_lock(&walker_lock);
switch (walker_state) {
case WALK_NONE:
THR_DAEMON, &walk_thread) == 0)
break;
case WALK_WAITING:
case WALK_RUNNING:
/* Absorb the event */
break;
}
(void) mutex_unlock(&walker_lock);
}
/*ARGSUSED*/
static void
{
for (;;) {
(void) mutex_lock(&walker_lock);
(void) mutex_unlock(&walker_lock);
(void) mutex_lock(&walker_lock);
/*
* We get per disk event. Make sure to collect all the newly
* added disks into the cache.
*/
if (events_pending > 0) {
(void) mutex_unlock(&walker_lock);
continue;
}
(void) mutex_unlock(&walker_lock);
/*
* Wait for a few seconds to absorb extra events before
* exiting.
*/
(void) sleep(WALK_WAIT_TIME);
(void) mutex_lock(&walker_lock);
if (events_pending > 0) {
(void) mutex_unlock(&walker_lock);
continue;
}
(void) mutex_unlock(&walker_lock);
break;
}
}