1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <stdio.h> 30*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 31*7c478bd9Sstevel@tonic-gate #include <stropts.h> 32*7c478bd9Sstevel@tonic-gate #include <synch.h> 33*7c478bd9Sstevel@tonic-gate #include <thread.h> 34*7c478bd9Sstevel@tonic-gate #include <libsysevent.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/sysevent/eventdefs.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/sysevent/dev.h> 37*7c478bd9Sstevel@tonic-gate #include <errno.h> 38*7c478bd9Sstevel@tonic-gate #include <libgen.h> 39*7c478bd9Sstevel@tonic-gate #include <unistd.h> 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate #include "libdiskmgt.h" 42*7c478bd9Sstevel@tonic-gate #include "disks_private.h" 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate struct event_list { 45*7c478bd9Sstevel@tonic-gate struct event_list *next; 46*7c478bd9Sstevel@tonic-gate nvlist_t *event; 47*7c478bd9Sstevel@tonic-gate }; 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate static struct event_list *events = NULL; 50*7c478bd9Sstevel@tonic-gate static int event_error = 0; 51*7c478bd9Sstevel@tonic-gate static int event_break = 0; 52*7c478bd9Sstevel@tonic-gate static mutex_t queue_lock; 53*7c478bd9Sstevel@tonic-gate static sema_t semaphore; 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate /* 56*7c478bd9Sstevel@tonic-gate * When we add a controller we get an add event for each drive on the 57*7c478bd9Sstevel@tonic-gate * controller. We don't want to walk the devtree for each drive since 58*7c478bd9Sstevel@tonic-gate * we will get the same information each time. So, the solution is to 59*7c478bd9Sstevel@tonic-gate * wait for a few seconds for all of the add events to come in and then 60*7c478bd9Sstevel@tonic-gate * do a single walk. If an add event comes in after we start the walk, we 61*7c478bd9Sstevel@tonic-gate * need to do another walk since we might have missed that drive. 62*7c478bd9Sstevel@tonic-gate * 63*7c478bd9Sstevel@tonic-gate * State: 0 - no walker; 1 - walker waiting; 2 - walker running 64*7c478bd9Sstevel@tonic-gate * 0 -> 1; wait a few seconds 65*7c478bd9Sstevel@tonic-gate * 1 -> 2; walking the devtree 66*7c478bd9Sstevel@tonic-gate * 2 -> either 0 or 1 (see below) 67*7c478bd9Sstevel@tonic-gate * While running (state 2), if event comes in, go back to waiting (state 1) 68*7c478bd9Sstevel@tonic-gate * after the walk otherwise go back to none (state 0). 69*7c478bd9Sstevel@tonic-gate * 70*7c478bd9Sstevel@tonic-gate * walker_lock protects walker_state & events_pending 71*7c478bd9Sstevel@tonic-gate */ 72*7c478bd9Sstevel@tonic-gate #define WALK_NONE 0 73*7c478bd9Sstevel@tonic-gate #define WALK_WAITING 1 74*7c478bd9Sstevel@tonic-gate #define WALK_RUNNING 2 75*7c478bd9Sstevel@tonic-gate #define WALK_WAIT_TIME 60 /* wait 60 seconds */ 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate static mutex_t walker_lock; 78*7c478bd9Sstevel@tonic-gate static int walker_state = WALK_NONE; 79*7c478bd9Sstevel@tonic-gate static int events_pending = 0; 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate static int sendevents = 0; 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate static void add_event_to_queue(nvlist_t *event); 84*7c478bd9Sstevel@tonic-gate static void cb_watch_events(); 85*7c478bd9Sstevel@tonic-gate static void event_handler(sysevent_t *ev); 86*7c478bd9Sstevel@tonic-gate static void print_nvlist(char *prefix, nvlist_t *list); 87*7c478bd9Sstevel@tonic-gate static void walk_devtree(); 88*7c478bd9Sstevel@tonic-gate static void walker(void *arg); 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate static void(*callback)(nvlist_t *, int) = NULL; 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate nvlist_t * 93*7c478bd9Sstevel@tonic-gate dm_get_event(int *errp) 94*7c478bd9Sstevel@tonic-gate { 95*7c478bd9Sstevel@tonic-gate nvlist_t *event = NULL; 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate *errp = 0; 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate /* wait until there is an event in the queue */ 100*7c478bd9Sstevel@tonic-gate /*CONSTCOND*/ 101*7c478bd9Sstevel@tonic-gate while (1) { 102*7c478bd9Sstevel@tonic-gate (void) sema_wait(&semaphore); 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate if (event_break) { 105*7c478bd9Sstevel@tonic-gate event_break = 0; 106*7c478bd9Sstevel@tonic-gate *errp = EINTR; 107*7c478bd9Sstevel@tonic-gate break; 108*7c478bd9Sstevel@tonic-gate } 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&queue_lock); 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate /* first see if we ran out of memory since the last call */ 113*7c478bd9Sstevel@tonic-gate if (event_error != 0) { 114*7c478bd9Sstevel@tonic-gate *errp = event_error; 115*7c478bd9Sstevel@tonic-gate event_error = 0; 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate } else if (events != NULL) { 118*7c478bd9Sstevel@tonic-gate struct event_list *tmpp; 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate event = events->event; 121*7c478bd9Sstevel@tonic-gate tmpp = events->next; 122*7c478bd9Sstevel@tonic-gate free(events); 123*7c478bd9Sstevel@tonic-gate events = tmpp; 124*7c478bd9Sstevel@tonic-gate } 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&queue_lock); 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate if (*errp != 0 || event != NULL) { 129*7c478bd9Sstevel@tonic-gate break; 130*7c478bd9Sstevel@tonic-gate } 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate return (event); 134*7c478bd9Sstevel@tonic-gate } 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate void 137*7c478bd9Sstevel@tonic-gate dm_init_event_queue(void (*cb)(nvlist_t *, int), int *errp) 138*7c478bd9Sstevel@tonic-gate { 139*7c478bd9Sstevel@tonic-gate if (sendevents == 1) { 140*7c478bd9Sstevel@tonic-gate /* we were already initialized, see what changes to make */ 141*7c478bd9Sstevel@tonic-gate *errp = 0; 142*7c478bd9Sstevel@tonic-gate if (cb != callback) { 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate callback = cb; 145*7c478bd9Sstevel@tonic-gate if (cb == NULL) { 146*7c478bd9Sstevel@tonic-gate /* clearing the cb so shutdown the internal cb thread */ 147*7c478bd9Sstevel@tonic-gate event_break = 1; 148*7c478bd9Sstevel@tonic-gate (void) sema_post(&semaphore); 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate } else { 151*7c478bd9Sstevel@tonic-gate /* installing a cb; we didn't have one before */ 152*7c478bd9Sstevel@tonic-gate thread_t watch_thread; 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate *errp = thr_create(NULL, NULL, 155*7c478bd9Sstevel@tonic-gate (void *(*)(void *))cb_watch_events, NULL, THR_DAEMON, 156*7c478bd9Sstevel@tonic-gate &watch_thread); 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate } 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate } else { 161*7c478bd9Sstevel@tonic-gate /* first time to initialize */ 162*7c478bd9Sstevel@tonic-gate sendevents = 1; 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate *errp = sema_init(&semaphore, 0, USYNC_THREAD, NULL); 165*7c478bd9Sstevel@tonic-gate if (*errp != 0) { 166*7c478bd9Sstevel@tonic-gate return; 167*7c478bd9Sstevel@tonic-gate } 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate if (cb != NULL) { 170*7c478bd9Sstevel@tonic-gate thread_t watch_thread; 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate callback = cb; 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate *errp = thr_create(NULL, NULL, 175*7c478bd9Sstevel@tonic-gate (void *(*)(void *))cb_watch_events, NULL, THR_DAEMON, 176*7c478bd9Sstevel@tonic-gate &watch_thread); 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate } 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate void 182*7c478bd9Sstevel@tonic-gate events_new_event(char *name, int dtype, char *etype) 183*7c478bd9Sstevel@tonic-gate { 184*7c478bd9Sstevel@tonic-gate nvlist_t *event = NULL; 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate if (!sendevents) { 187*7c478bd9Sstevel@tonic-gate return; 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate if (nvlist_alloc(&event, NVATTRS, 0) != 0) { 191*7c478bd9Sstevel@tonic-gate event = NULL; 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate } else { 194*7c478bd9Sstevel@tonic-gate int error = 0; 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate if (name != NULL && 197*7c478bd9Sstevel@tonic-gate nvlist_add_string(event, DM_EV_NAME, name) != 0) { 198*7c478bd9Sstevel@tonic-gate error = ENOMEM; 199*7c478bd9Sstevel@tonic-gate } 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate if (dtype != -1 && 202*7c478bd9Sstevel@tonic-gate nvlist_add_uint32(event, DM_EV_DTYPE, dtype) != 0) { 203*7c478bd9Sstevel@tonic-gate error = ENOMEM; 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate if (nvlist_add_string(event, DM_EV_TYPE, etype) != 0) { 207*7c478bd9Sstevel@tonic-gate error = ENOMEM; 208*7c478bd9Sstevel@tonic-gate } 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate if (error != 0) { 211*7c478bd9Sstevel@tonic-gate nvlist_free(event); 212*7c478bd9Sstevel@tonic-gate event = NULL; 213*7c478bd9Sstevel@tonic-gate } 214*7c478bd9Sstevel@tonic-gate } 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate add_event_to_queue(event); 217*7c478bd9Sstevel@tonic-gate } 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate void 220*7c478bd9Sstevel@tonic-gate events_new_slice_event(char *dev, char *type) 221*7c478bd9Sstevel@tonic-gate { 222*7c478bd9Sstevel@tonic-gate events_new_event(basename(dev), DM_SLICE, type); 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate int 226*7c478bd9Sstevel@tonic-gate events_start_event_watcher() 227*7c478bd9Sstevel@tonic-gate { 228*7c478bd9Sstevel@tonic-gate sysevent_handle_t *shp; 229*7c478bd9Sstevel@tonic-gate const char *subclass_list[1]; 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate /* Bind event handler and create subscriber handle */ 232*7c478bd9Sstevel@tonic-gate shp = sysevent_bind_handle(event_handler); 233*7c478bd9Sstevel@tonic-gate if (shp == NULL) { 234*7c478bd9Sstevel@tonic-gate if (dm_debug) { 235*7c478bd9Sstevel@tonic-gate /* keep going when we're debugging */ 236*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "ERROR: bind failed %d\n", errno); 237*7c478bd9Sstevel@tonic-gate return (0); 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate return (errno); 240*7c478bd9Sstevel@tonic-gate } 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate subclass_list[0] = ESC_DISK; 243*7c478bd9Sstevel@tonic-gate if (sysevent_subscribe_event(shp, EC_DEV_ADD, subclass_list, 1) != 0) { 244*7c478bd9Sstevel@tonic-gate if (dm_debug) { 245*7c478bd9Sstevel@tonic-gate /* keep going when we're debugging */ 246*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "ERROR: subscribe failed\n"); 247*7c478bd9Sstevel@tonic-gate return (0); 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate return (errno); 250*7c478bd9Sstevel@tonic-gate } 251*7c478bd9Sstevel@tonic-gate if (sysevent_subscribe_event(shp, EC_DEV_REMOVE, subclass_list, 1) 252*7c478bd9Sstevel@tonic-gate != 0) { 253*7c478bd9Sstevel@tonic-gate if (dm_debug) { 254*7c478bd9Sstevel@tonic-gate /* keep going when we're debugging */ 255*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "ERROR: subscribe failed\n"); 256*7c478bd9Sstevel@tonic-gate return (0); 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate return (errno); 259*7c478bd9Sstevel@tonic-gate } 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate return (0); 262*7c478bd9Sstevel@tonic-gate } 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate static void 265*7c478bd9Sstevel@tonic-gate add_event_to_queue(nvlist_t *event) 266*7c478bd9Sstevel@tonic-gate { 267*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&queue_lock); 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate if (event == NULL) { 270*7c478bd9Sstevel@tonic-gate event_error = ENOMEM; 271*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&queue_lock); 272*7c478bd9Sstevel@tonic-gate return; 273*7c478bd9Sstevel@tonic-gate } 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate if (events == NULL) { 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate events = (struct event_list *)malloc(sizeof (struct event_list)); 278*7c478bd9Sstevel@tonic-gate if (events == NULL) { 279*7c478bd9Sstevel@tonic-gate event_error = ENOMEM; 280*7c478bd9Sstevel@tonic-gate nvlist_free(event); 281*7c478bd9Sstevel@tonic-gate } else { 282*7c478bd9Sstevel@tonic-gate events->next = NULL; 283*7c478bd9Sstevel@tonic-gate events->event = event; 284*7c478bd9Sstevel@tonic-gate } 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate } else { 287*7c478bd9Sstevel@tonic-gate /* already have events in the queue */ 288*7c478bd9Sstevel@tonic-gate struct event_list *ep; 289*7c478bd9Sstevel@tonic-gate struct event_list *new_event; 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate /* find the last element in the list */ 292*7c478bd9Sstevel@tonic-gate for (ep = events; ep->next != NULL; ep = ep->next); 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate new_event = (struct event_list *)malloc(sizeof (struct event_list)); 295*7c478bd9Sstevel@tonic-gate if (new_event == NULL) { 296*7c478bd9Sstevel@tonic-gate event_error = ENOMEM; 297*7c478bd9Sstevel@tonic-gate nvlist_free(event); 298*7c478bd9Sstevel@tonic-gate } else { 299*7c478bd9Sstevel@tonic-gate new_event->next = NULL; 300*7c478bd9Sstevel@tonic-gate new_event->event = event; 301*7c478bd9Sstevel@tonic-gate ep->next = new_event; 302*7c478bd9Sstevel@tonic-gate } 303*7c478bd9Sstevel@tonic-gate } 304*7c478bd9Sstevel@tonic-gate 305*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&queue_lock); 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate (void) sema_post(&semaphore); 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate static void 311*7c478bd9Sstevel@tonic-gate cb_watch_events() 312*7c478bd9Sstevel@tonic-gate { 313*7c478bd9Sstevel@tonic-gate nvlist_t *event; 314*7c478bd9Sstevel@tonic-gate int error; 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate /*CONSTCOND*/ 317*7c478bd9Sstevel@tonic-gate while (1) { 318*7c478bd9Sstevel@tonic-gate event = dm_get_event(&error); 319*7c478bd9Sstevel@tonic-gate if (callback == NULL) { 320*7c478bd9Sstevel@tonic-gate /* end the thread */ 321*7c478bd9Sstevel@tonic-gate return; 322*7c478bd9Sstevel@tonic-gate } 323*7c478bd9Sstevel@tonic-gate callback(event, error); 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate } 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate static void 328*7c478bd9Sstevel@tonic-gate event_handler(sysevent_t *ev) 329*7c478bd9Sstevel@tonic-gate { 330*7c478bd9Sstevel@tonic-gate char *class_name; 331*7c478bd9Sstevel@tonic-gate char *pub; 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate class_name = sysevent_get_class_name(ev); 334*7c478bd9Sstevel@tonic-gate if (dm_debug) { 335*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "****EVENT: %s %s ", class_name, 336*7c478bd9Sstevel@tonic-gate sysevent_get_subclass_name(ev)); 337*7c478bd9Sstevel@tonic-gate if ((pub = sysevent_get_pub_name(ev)) != NULL) { 338*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", pub); 339*7c478bd9Sstevel@tonic-gate free(pub); 340*7c478bd9Sstevel@tonic-gate } else { 341*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 342*7c478bd9Sstevel@tonic-gate } 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(class_name, EC_DEV_ADD)) { 346*7c478bd9Sstevel@tonic-gate /* batch up the adds into a single devtree walk */ 347*7c478bd9Sstevel@tonic-gate walk_devtree(); 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate } else if (libdiskmgt_str_eq(class_name, EC_DEV_REMOVE)) { 350*7c478bd9Sstevel@tonic-gate nvlist_t *nvlist = NULL; 351*7c478bd9Sstevel@tonic-gate char *dev_name = NULL; 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate (void) sysevent_get_attr_list(ev, &nvlist); 354*7c478bd9Sstevel@tonic-gate if (nvlist != NULL) { 355*7c478bd9Sstevel@tonic-gate (void) nvlist_lookup_string(nvlist, DEV_NAME, &dev_name); 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate if (dm_debug) { 358*7c478bd9Sstevel@tonic-gate print_nvlist("**** ", nvlist); 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate if (dev_name != NULL) { 363*7c478bd9Sstevel@tonic-gate cache_update(DM_EV_DISK_DELETE, dev_name); 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate if (nvlist != NULL) { 367*7c478bd9Sstevel@tonic-gate nvlist_free(nvlist); 368*7c478bd9Sstevel@tonic-gate } 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate /* 373*7c478bd9Sstevel@tonic-gate * This is a debugging function only. 374*7c478bd9Sstevel@tonic-gate */ 375*7c478bd9Sstevel@tonic-gate static void 376*7c478bd9Sstevel@tonic-gate print_nvlist(char *prefix, nvlist_t *list) 377*7c478bd9Sstevel@tonic-gate { 378*7c478bd9Sstevel@tonic-gate nvpair_t *nvp; 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate nvp = nvlist_next_nvpair(list, NULL); 381*7c478bd9Sstevel@tonic-gate while (nvp != NULL) { 382*7c478bd9Sstevel@tonic-gate char *attrname; 383*7c478bd9Sstevel@tonic-gate char *str; 384*7c478bd9Sstevel@tonic-gate uint32_t ui32; 385*7c478bd9Sstevel@tonic-gate uint64_t ui64; 386*7c478bd9Sstevel@tonic-gate char **str_array; 387*7c478bd9Sstevel@tonic-gate uint_t cnt; 388*7c478bd9Sstevel@tonic-gate int i; 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate attrname = nvpair_name(nvp); 391*7c478bd9Sstevel@tonic-gate switch (nvpair_type(nvp)) { 392*7c478bd9Sstevel@tonic-gate case DATA_TYPE_STRING: 393*7c478bd9Sstevel@tonic-gate (void) nvpair_value_string(nvp, &str); 394*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s%s: %s\n", prefix, attrname, str); 395*7c478bd9Sstevel@tonic-gate break; 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate case DATA_TYPE_STRING_ARRAY: 398*7c478bd9Sstevel@tonic-gate (void) nvpair_value_string_array(nvp, &str_array, &cnt); 399*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s%s:\n", prefix, attrname); 400*7c478bd9Sstevel@tonic-gate for (i = 0; i < cnt; i++) { 401*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s %s\n", prefix, str_array[i]); 402*7c478bd9Sstevel@tonic-gate } 403*7c478bd9Sstevel@tonic-gate break; 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate case DATA_TYPE_UINT32: 406*7c478bd9Sstevel@tonic-gate (void) nvpair_value_uint32(nvp, &ui32); 407*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s%s: %u\n", prefix, attrname, ui32); 408*7c478bd9Sstevel@tonic-gate break; 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate case DATA_TYPE_UINT64: 411*7c478bd9Sstevel@tonic-gate (void) nvpair_value_uint64(nvp, &ui64); 412*7c478bd9Sstevel@tonic-gate #ifdef _LP64 413*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s%s: %lu\n", prefix, attrname, ui64); 414*7c478bd9Sstevel@tonic-gate #else 415*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s%s: %llu\n", prefix, attrname, ui64); 416*7c478bd9Sstevel@tonic-gate #endif 417*7c478bd9Sstevel@tonic-gate break; 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate case DATA_TYPE_BOOLEAN: 421*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s%s: true\n", prefix, attrname); 422*7c478bd9Sstevel@tonic-gate break; 423*7c478bd9Sstevel@tonic-gate 424*7c478bd9Sstevel@tonic-gate default: 425*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s%s: UNSUPPORTED TYPE\n", prefix, 426*7c478bd9Sstevel@tonic-gate attrname); 427*7c478bd9Sstevel@tonic-gate break; 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate nvp = nvlist_next_nvpair(list, nvp); 431*7c478bd9Sstevel@tonic-gate } 432*7c478bd9Sstevel@tonic-gate } 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate /* 435*7c478bd9Sstevel@tonic-gate * Batch up the adds into a single devtree walk. We can get a bunch of 436*7c478bd9Sstevel@tonic-gate * adds when we add a controller since we will get an add event for each 437*7c478bd9Sstevel@tonic-gate * drive. 438*7c478bd9Sstevel@tonic-gate */ 439*7c478bd9Sstevel@tonic-gate static void 440*7c478bd9Sstevel@tonic-gate walk_devtree() 441*7c478bd9Sstevel@tonic-gate { 442*7c478bd9Sstevel@tonic-gate thread_t walk_thread; 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&walker_lock); 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate switch (walker_state) { 447*7c478bd9Sstevel@tonic-gate case WALK_NONE: 448*7c478bd9Sstevel@tonic-gate if (thr_create(NULL, NULL, (void *(*)(void *))walker, NULL, 449*7c478bd9Sstevel@tonic-gate THR_DAEMON, &walk_thread) == 0) { 450*7c478bd9Sstevel@tonic-gate walker_state = WALK_WAITING; 451*7c478bd9Sstevel@tonic-gate } 452*7c478bd9Sstevel@tonic-gate break; 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate case WALK_WAITING: 455*7c478bd9Sstevel@tonic-gate /* absorb the event and do nothing */ 456*7c478bd9Sstevel@tonic-gate break; 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate case WALK_RUNNING: 459*7c478bd9Sstevel@tonic-gate events_pending = 1; 460*7c478bd9Sstevel@tonic-gate break; 461*7c478bd9Sstevel@tonic-gate } 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&walker_lock); 464*7c478bd9Sstevel@tonic-gate } 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 467*7c478bd9Sstevel@tonic-gate static void 468*7c478bd9Sstevel@tonic-gate walker(void *arg) 469*7c478bd9Sstevel@tonic-gate { 470*7c478bd9Sstevel@tonic-gate int walk_again = 0; 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate do { 473*7c478bd9Sstevel@tonic-gate /* start by wating for a few seconds to absorb extra events */ 474*7c478bd9Sstevel@tonic-gate (void) sleep(WALK_WAIT_TIME); 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&walker_lock); 477*7c478bd9Sstevel@tonic-gate walker_state = WALK_RUNNING; 478*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&walker_lock); 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate cache_update(DM_EV_DISK_ADD, NULL); 481*7c478bd9Sstevel@tonic-gate 482*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&walker_lock); 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate if (events_pending) { 485*7c478bd9Sstevel@tonic-gate events_pending = 0; 486*7c478bd9Sstevel@tonic-gate walker_state = WALK_WAITING; 487*7c478bd9Sstevel@tonic-gate walk_again = 1; 488*7c478bd9Sstevel@tonic-gate } else { 489*7c478bd9Sstevel@tonic-gate walker_state = WALK_NONE; 490*7c478bd9Sstevel@tonic-gate walk_again = 0; 491*7c478bd9Sstevel@tonic-gate } 492*7c478bd9Sstevel@tonic-gate 493*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&walker_lock); 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate } while (walk_again); 496*7c478bd9Sstevel@tonic-gate } 497