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 *
dm_get_event(int * errp)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
dm_init_event_queue(void (* cb)(nvlist_t *,int),int * errp)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
events_new_event(char * name,int dtype,char * etype)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
events_new_slice_event(char * dev,char * type)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
events_start_event_watcher()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
add_event_to_queue(nvlist_t * event)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
cb_watch_events()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
event_handler(sysevent_t * ev)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
print_nvlist(char * prefix,nvlist_t * list)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
walk_devtree()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
walker(void * arg)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