xref: /freebsd/sys/geom/geom_event.c (revision 59ccfe81)
1dd84a43cSPoul-Henning Kamp /*-
2dd84a43cSPoul-Henning Kamp  * Copyright (c) 2002 Poul-Henning Kamp
3dd84a43cSPoul-Henning Kamp  * Copyright (c) 2002 Networks Associates Technology, Inc.
4dd84a43cSPoul-Henning Kamp  * All rights reserved.
5dd84a43cSPoul-Henning Kamp  *
6dd84a43cSPoul-Henning Kamp  * This software was developed for the FreeBSD Project by Poul-Henning Kamp
7dd84a43cSPoul-Henning Kamp  * and NAI Labs, the Security Research Division of Network Associates, Inc.
8dd84a43cSPoul-Henning Kamp  * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
9dd84a43cSPoul-Henning Kamp  * DARPA CHATS research program.
10dd84a43cSPoul-Henning Kamp  *
11dd84a43cSPoul-Henning Kamp  * Redistribution and use in source and binary forms, with or without
12dd84a43cSPoul-Henning Kamp  * modification, are permitted provided that the following conditions
13dd84a43cSPoul-Henning Kamp  * are met:
14dd84a43cSPoul-Henning Kamp  * 1. Redistributions of source code must retain the above copyright
15dd84a43cSPoul-Henning Kamp  *    notice, this list of conditions and the following disclaimer.
16dd84a43cSPoul-Henning Kamp  * 2. Redistributions in binary form must reproduce the above copyright
17dd84a43cSPoul-Henning Kamp  *    notice, this list of conditions and the following disclaimer in the
18dd84a43cSPoul-Henning Kamp  *    documentation and/or other materials provided with the distribution.
19dd84a43cSPoul-Henning Kamp  * 3. The names of the authors may not be used to endorse or promote
20dd84a43cSPoul-Henning Kamp  *    products derived from this software without specific prior written
21dd84a43cSPoul-Henning Kamp  *    permission.
22dd84a43cSPoul-Henning Kamp  *
23dd84a43cSPoul-Henning Kamp  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24dd84a43cSPoul-Henning Kamp  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25dd84a43cSPoul-Henning Kamp  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26dd84a43cSPoul-Henning Kamp  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27dd84a43cSPoul-Henning Kamp  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28dd84a43cSPoul-Henning Kamp  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29dd84a43cSPoul-Henning Kamp  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30dd84a43cSPoul-Henning Kamp  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31dd84a43cSPoul-Henning Kamp  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32dd84a43cSPoul-Henning Kamp  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33dd84a43cSPoul-Henning Kamp  * SUCH DAMAGE.
34dd84a43cSPoul-Henning Kamp  */
35dd84a43cSPoul-Henning Kamp 
36dd84a43cSPoul-Henning Kamp /*
37dd84a43cSPoul-Henning Kamp  * XXX: How do we in general know that objects referenced in events
38dd84a43cSPoul-Henning Kamp  * have not been destroyed before we get around to handle the event ?
39dd84a43cSPoul-Henning Kamp  */
40dd84a43cSPoul-Henning Kamp 
4150b1faefSDavid E. O'Brien #include <sys/cdefs.h>
4250b1faefSDavid E. O'Brien __FBSDID("$FreeBSD$");
4350b1faefSDavid E. O'Brien 
44dd84a43cSPoul-Henning Kamp #include <sys/param.h>
45dd84a43cSPoul-Henning Kamp #include <sys/malloc.h>
46dd84a43cSPoul-Henning Kamp #include <sys/systm.h>
47dd84a43cSPoul-Henning Kamp #include <sys/kernel.h>
48dd84a43cSPoul-Henning Kamp #include <sys/lock.h>
49dd84a43cSPoul-Henning Kamp #include <sys/mutex.h>
509197ce2eSPoul-Henning Kamp #include <sys/proc.h>
51dd84a43cSPoul-Henning Kamp #include <sys/errno.h>
52dd84a43cSPoul-Henning Kamp #include <sys/time.h>
53dd84a43cSPoul-Henning Kamp #include <geom/geom.h>
54b1876192SPoul-Henning Kamp #include <geom/geom_int.h>
55dd84a43cSPoul-Henning Kamp 
569197ce2eSPoul-Henning Kamp #include <machine/stdarg.h>
579197ce2eSPoul-Henning Kamp 
58a974614bSPoul-Henning Kamp TAILQ_HEAD(event_tailq_head, g_event);
59a974614bSPoul-Henning Kamp 
60dd84a43cSPoul-Henning Kamp static struct event_tailq_head g_events = TAILQ_HEAD_INITIALIZER(g_events);
61abb50a48SPoul-Henning Kamp static u_int g_pending_events;
62dd84a43cSPoul-Henning Kamp static TAILQ_HEAD(,g_provider) g_doorstep = TAILQ_HEAD_INITIALIZER(g_doorstep);
63903e43feSPoul-Henning Kamp static struct mtx g_eventlock;
641b464bd8SPoul-Henning Kamp static int g_wither_work;
65dd84a43cSPoul-Henning Kamp 
66a974614bSPoul-Henning Kamp #define G_N_EVENTREFS		20
67a974614bSPoul-Henning Kamp 
68a974614bSPoul-Henning Kamp struct g_event {
69a974614bSPoul-Henning Kamp 	TAILQ_ENTRY(g_event)	events;
70a974614bSPoul-Henning Kamp 	g_event_t		*func;
710a9c130cSPoul-Henning Kamp 	void			*arg;
720a9c130cSPoul-Henning Kamp 	int			flag;
73a974614bSPoul-Henning Kamp 	void			*ref[G_N_EVENTREFS];
74a974614bSPoul-Henning Kamp };
75a974614bSPoul-Henning Kamp 
760a9c130cSPoul-Henning Kamp #define EV_DONE		0x80000
770a9c130cSPoul-Henning Kamp #define EV_WAKEUP	0x40000
78c8589ad1SPoul-Henning Kamp #define EV_CANCELED	0x20000
7959ccfe81SMatt Jacob #define EV_INPROGRESS	0x10000
800a9c130cSPoul-Henning Kamp 
81dd84a43cSPoul-Henning Kamp void
82503abe45SPoul-Henning Kamp g_waitidle(void)
83dd84a43cSPoul-Henning Kamp {
84dd84a43cSPoul-Henning Kamp 
859197ce2eSPoul-Henning Kamp 	g_topology_assert_not();
869197ce2eSPoul-Henning Kamp 	mtx_assert(&Giant, MA_NOTOWNED);
879197ce2eSPoul-Henning Kamp 
88e4da09c0SPoul-Henning Kamp 	mtx_lock(&g_eventlock);
89e4da09c0SPoul-Henning Kamp 	while (!TAILQ_EMPTY(&g_events))
90e4da09c0SPoul-Henning Kamp 		msleep(&g_pending_events, &g_eventlock, PPAUSE,
91e4da09c0SPoul-Henning Kamp 		    "g_waitidle", hz/5);
92e4da09c0SPoul-Henning Kamp 	mtx_unlock(&g_eventlock);
939197ce2eSPoul-Henning Kamp 	curthread->td_pflags &= ~TDP_GEOM;
94dd84a43cSPoul-Henning Kamp }
95dd84a43cSPoul-Henning Kamp 
96e4da09c0SPoul-Henning Kamp #if 0
97dd84a43cSPoul-Henning Kamp void
98b8005b9bSPawel Jakub Dawidek g_waitidlelock(void)
99b8005b9bSPawel Jakub Dawidek {
100b8005b9bSPawel Jakub Dawidek 
101b8005b9bSPawel Jakub Dawidek 	g_topology_assert();
102e4da09c0SPoul-Henning Kamp 	mtx_lock(&g_eventlock);
103e4da09c0SPoul-Henning Kamp 	while (!TAILQ_EMPTY(&g_events)) {
104b8005b9bSPawel Jakub Dawidek 		g_topology_unlock();
105e4da09c0SPoul-Henning Kamp 		msleep(&g_pending_events, &g_eventlock, PPAUSE,
106e4da09c0SPoul-Henning Kamp 		    "g_waitidlel", hz/5);
107b8005b9bSPawel Jakub Dawidek 		g_topology_lock();
108b8005b9bSPawel Jakub Dawidek 	}
109e4da09c0SPoul-Henning Kamp 	mtx_unlock(&g_eventlock);
110b8005b9bSPawel Jakub Dawidek }
111e4da09c0SPoul-Henning Kamp #endif
112b8005b9bSPawel Jakub Dawidek 
113b8005b9bSPawel Jakub Dawidek void
114dd84a43cSPoul-Henning Kamp g_orphan_provider(struct g_provider *pp, int error)
115dd84a43cSPoul-Henning Kamp {
116dd84a43cSPoul-Henning Kamp 
1173d1d5bc3SPoul-Henning Kamp 	/* G_VALID_PROVIDER(pp)  We likely lack topology lock */
118dd84a43cSPoul-Henning Kamp 	g_trace(G_T_TOPOLOGY, "g_orphan_provider(%p(%s), %d)",
119dd84a43cSPoul-Henning Kamp 	    pp, pp->name, error);
120dd84a43cSPoul-Henning Kamp 	KASSERT(error != 0,
121dd84a43cSPoul-Henning Kamp 	    ("g_orphan_provider(%p(%s), 0) error must be non-zero\n",
122dd84a43cSPoul-Henning Kamp 	     pp, pp->name));
123d0265773SPoul-Henning Kamp 
124dd84a43cSPoul-Henning Kamp 	pp->error = error;
125903e43feSPoul-Henning Kamp 	mtx_lock(&g_eventlock);
126d0265773SPoul-Henning Kamp 	KASSERT(!(pp->flags & G_PF_ORPHAN),
127d0265773SPoul-Henning Kamp 	    ("g_orphan_provider(%p(%s)), already an orphan", pp, pp->name));
128d0265773SPoul-Henning Kamp 	pp->flags |= G_PF_ORPHAN;
129dd84a43cSPoul-Henning Kamp 	TAILQ_INSERT_TAIL(&g_doorstep, pp, orphan);
130903e43feSPoul-Henning Kamp 	mtx_unlock(&g_eventlock);
131dd84a43cSPoul-Henning Kamp 	wakeup(&g_wait_event);
132dd84a43cSPoul-Henning Kamp }
133dd84a43cSPoul-Henning Kamp 
134dd84a43cSPoul-Henning Kamp /*
135dd84a43cSPoul-Henning Kamp  * This function is called once on each provider which the event handler
136dd84a43cSPoul-Henning Kamp  * finds on its g_doorstep.
137dd84a43cSPoul-Henning Kamp  */
138dd84a43cSPoul-Henning Kamp 
139dd84a43cSPoul-Henning Kamp static void
140b1876192SPoul-Henning Kamp g_orphan_register(struct g_provider *pp)
141dd84a43cSPoul-Henning Kamp {
142dd84a43cSPoul-Henning Kamp 	struct g_consumer *cp, *cp2;
1438592d7a7SPoul-Henning Kamp 	int wf;
144dd84a43cSPoul-Henning Kamp 
145dd84a43cSPoul-Henning Kamp 	g_topology_assert();
1463d1d5bc3SPoul-Henning Kamp 	G_VALID_PROVIDER(pp);
1473d1d5bc3SPoul-Henning Kamp 	g_trace(G_T_TOPOLOGY, "g_orphan_register(%s)", pp->name);
148dd84a43cSPoul-Henning Kamp 
1493ea5d7ecSPawel Jakub Dawidek 	g_cancel_event(pp);
1503ea5d7ecSPawel Jakub Dawidek 
1518592d7a7SPoul-Henning Kamp 	wf = pp->flags & G_PF_WITHER;
1528592d7a7SPoul-Henning Kamp 	pp->flags &= ~G_PF_WITHER;
1538592d7a7SPoul-Henning Kamp 
154dd84a43cSPoul-Henning Kamp 	/*
155dd84a43cSPoul-Henning Kamp 	 * Tell all consumers the bad news.
156f48b8819SPoul-Henning Kamp 	 * Don't be surprised if they self-destruct.
157dd84a43cSPoul-Henning Kamp 	 */
158dd84a43cSPoul-Henning Kamp 	cp = LIST_FIRST(&pp->consumers);
159dd84a43cSPoul-Henning Kamp 	while (cp != NULL) {
160dd84a43cSPoul-Henning Kamp 		cp2 = LIST_NEXT(cp, consumers);
16107d77fc6SPoul-Henning Kamp 		KASSERT(cp->geom->orphan != NULL,
16207d77fc6SPoul-Henning Kamp 		    ("geom %s has no orphan, class %s",
16307d77fc6SPoul-Henning Kamp 		    cp->geom->name, cp->geom->class->name));
16407d77fc6SPoul-Henning Kamp 		cp->geom->orphan(cp);
165dd84a43cSPoul-Henning Kamp 		cp = cp2;
166dd84a43cSPoul-Henning Kamp 	}
1678592d7a7SPoul-Henning Kamp 	if (LIST_EMPTY(&pp->consumers) && wf)
168b144e6ffSPoul-Henning Kamp 		g_destroy_provider(pp);
1698592d7a7SPoul-Henning Kamp 	else
1708592d7a7SPoul-Henning Kamp 		pp->flags |= wf;
17120d2026bSPoul-Henning Kamp #ifdef notyet
172e5829909SPoul-Henning Kamp 	cp = LIST_FIRST(&pp->consumers);
173e5829909SPoul-Henning Kamp 	if (cp != NULL)
174e5829909SPoul-Henning Kamp 		return;
175e5829909SPoul-Henning Kamp 	if (pp->geom->flags & G_GEOM_WITHER)
176e5829909SPoul-Henning Kamp 		g_destroy_provider(pp);
17720d2026bSPoul-Henning Kamp #endif
178dd84a43cSPoul-Henning Kamp }
179dd84a43cSPoul-Henning Kamp 
180dd84a43cSPoul-Henning Kamp static int
181b1876192SPoul-Henning Kamp one_event(void)
182dd84a43cSPoul-Henning Kamp {
183dd84a43cSPoul-Henning Kamp 	struct g_event *ep;
184dd84a43cSPoul-Henning Kamp 	struct g_provider *pp;
185dd84a43cSPoul-Henning Kamp 
186dd84a43cSPoul-Henning Kamp 	g_topology_lock();
187dd84a43cSPoul-Henning Kamp 	for (;;) {
188903e43feSPoul-Henning Kamp 		mtx_lock(&g_eventlock);
189d6b910d2SPawel Jakub Dawidek 		TAILQ_FOREACH(pp, &g_doorstep, orphan) {
190d6b910d2SPawel Jakub Dawidek 			if (pp->nstart == pp->nend)
191d6b910d2SPawel Jakub Dawidek 				break;
192d6b910d2SPawel Jakub Dawidek 		}
1933d1d5bc3SPoul-Henning Kamp 		if (pp != NULL) {
1943d1d5bc3SPoul-Henning Kamp 			G_VALID_PROVIDER(pp);
195dd84a43cSPoul-Henning Kamp 			TAILQ_REMOVE(&g_doorstep, pp, orphan);
1963d1d5bc3SPoul-Henning Kamp 		}
197903e43feSPoul-Henning Kamp 		mtx_unlock(&g_eventlock);
198dd84a43cSPoul-Henning Kamp 		if (pp == NULL)
199dd84a43cSPoul-Henning Kamp 			break;
200b1876192SPoul-Henning Kamp 		g_orphan_register(pp);
201dd84a43cSPoul-Henning Kamp 	}
202346cd5feSPoul-Henning Kamp 	mtx_lock(&g_eventlock);
203dd84a43cSPoul-Henning Kamp 	ep = TAILQ_FIRST(&g_events);
204dd84a43cSPoul-Henning Kamp 	if (ep == NULL) {
205e4da09c0SPoul-Henning Kamp 		wakeup(&g_pending_events);
206346cd5feSPoul-Henning Kamp 		mtx_unlock(&g_eventlock);
207dd84a43cSPoul-Henning Kamp 		g_topology_unlock();
208dd84a43cSPoul-Henning Kamp 		return (0);
209dd84a43cSPoul-Henning Kamp 	}
21059ccfe81SMatt Jacob 	if (ep->flag & EV_INPROGRESS) {
21159ccfe81SMatt Jacob 		mtx_unlock(&g_eventlock);
21259ccfe81SMatt Jacob 		g_topology_unlock();
21359ccfe81SMatt Jacob 		return (1);
21459ccfe81SMatt Jacob 	}
21559ccfe81SMatt Jacob 	ep->flag |= EV_INPROGRESS;
216346cd5feSPoul-Henning Kamp 	mtx_unlock(&g_eventlock);
217d98777f8SPoul-Henning Kamp 	g_topology_assert();
218d98777f8SPoul-Henning Kamp 	ep->func(ep->arg, 0);
219d98777f8SPoul-Henning Kamp 	g_topology_assert();
220e4da09c0SPoul-Henning Kamp 	mtx_lock(&g_eventlock);
221e4da09c0SPoul-Henning Kamp 	TAILQ_REMOVE(&g_events, ep, events);
22259ccfe81SMatt Jacob 	ep->flag &= ~EV_INPROGRESS;
223e4da09c0SPoul-Henning Kamp 	mtx_unlock(&g_eventlock);
2240a9c130cSPoul-Henning Kamp 	if (ep->flag & EV_WAKEUP) {
2250a9c130cSPoul-Henning Kamp 		ep->flag |= EV_DONE;
2260a9c130cSPoul-Henning Kamp 		wakeup(ep);
2270a9c130cSPoul-Henning Kamp 	} else {
2289dfffbc9SPoul-Henning Kamp 		g_free(ep);
2290a9c130cSPoul-Henning Kamp 	}
230a9ed5e11SPoul-Henning Kamp 	g_topology_unlock();
231dd84a43cSPoul-Henning Kamp 	return (1);
232dd84a43cSPoul-Henning Kamp }
233dd84a43cSPoul-Henning Kamp 
234dd84a43cSPoul-Henning Kamp void
235b1876192SPoul-Henning Kamp g_run_events()
236dd84a43cSPoul-Henning Kamp {
2371b464bd8SPoul-Henning Kamp 	int i;
238dd84a43cSPoul-Henning Kamp 
239b1876192SPoul-Henning Kamp 	while (one_event())
240dd84a43cSPoul-Henning Kamp 		;
2411b464bd8SPoul-Henning Kamp 	g_topology_lock();
2421b464bd8SPoul-Henning Kamp 	i = g_wither_work;
2431b464bd8SPoul-Henning Kamp 	while (i) {
2441b464bd8SPoul-Henning Kamp 		i = g_wither_washer();
2451b464bd8SPoul-Henning Kamp 		g_wither_work = i & 1;
2461b464bd8SPoul-Henning Kamp 		i &= 2;
2471b464bd8SPoul-Henning Kamp 	}
2481b464bd8SPoul-Henning Kamp 	g_topology_unlock();
249dd84a43cSPoul-Henning Kamp }
250dd84a43cSPoul-Henning Kamp 
251dd84a43cSPoul-Henning Kamp void
252afcbcfaeSPoul-Henning Kamp g_cancel_event(void *ref)
253dddc28bfSPoul-Henning Kamp {
254dddc28bfSPoul-Henning Kamp 	struct g_event *ep, *epn;
2552ab31b05SPoul-Henning Kamp 	struct g_provider *pp;
256afcbcfaeSPoul-Henning Kamp 	u_int n;
257dddc28bfSPoul-Henning Kamp 
258dddc28bfSPoul-Henning Kamp 	mtx_lock(&g_eventlock);
2592ab31b05SPoul-Henning Kamp 	TAILQ_FOREACH(pp, &g_doorstep, orphan) {
2602ab31b05SPoul-Henning Kamp 		if (pp != ref)
2612ab31b05SPoul-Henning Kamp 			continue;
2622ab31b05SPoul-Henning Kamp 		TAILQ_REMOVE(&g_doorstep, pp, orphan);
2632ab31b05SPoul-Henning Kamp 		break;
2642ab31b05SPoul-Henning Kamp 	}
265e4da09c0SPoul-Henning Kamp 	TAILQ_FOREACH_SAFE(ep, &g_events, events, epn) {
26659ccfe81SMatt Jacob 		if (ep->flag & EV_INPROGRESS)
26759ccfe81SMatt Jacob 			continue;
268afcbcfaeSPoul-Henning Kamp 		for (n = 0; n < G_N_EVENTREFS; n++) {
269afcbcfaeSPoul-Henning Kamp 			if (ep->ref[n] == NULL)
270afcbcfaeSPoul-Henning Kamp 				break;
271e4da09c0SPoul-Henning Kamp 			if (ep->ref[n] != ref)
272e4da09c0SPoul-Henning Kamp 				continue;
273dddc28bfSPoul-Henning Kamp 			TAILQ_REMOVE(&g_events, ep, events);
274316aed03SPoul-Henning Kamp 			ep->func(ep->arg, EV_CANCEL);
275e4da09c0SPoul-Henning Kamp 			mtx_assert(&g_eventlock, MA_OWNED);
2760a9c130cSPoul-Henning Kamp 			if (ep->flag & EV_WAKEUP) {
277e4da09c0SPoul-Henning Kamp 				ep->flag |= (EV_DONE|EV_CANCELED);
2780a9c130cSPoul-Henning Kamp 				wakeup(ep);
2790a9c130cSPoul-Henning Kamp 			} else {
2809dfffbc9SPoul-Henning Kamp 				g_free(ep);
2810a9c130cSPoul-Henning Kamp 			}
282afcbcfaeSPoul-Henning Kamp 			break;
283dddc28bfSPoul-Henning Kamp 		}
284afcbcfaeSPoul-Henning Kamp 	}
285e4da09c0SPoul-Henning Kamp 	if (TAILQ_EMPTY(&g_events))
286e4da09c0SPoul-Henning Kamp 		wakeup(&g_pending_events);
287dddc28bfSPoul-Henning Kamp 	mtx_unlock(&g_eventlock);
288dddc28bfSPoul-Henning Kamp }
289dddc28bfSPoul-Henning Kamp 
2900a9c130cSPoul-Henning Kamp static int
291793ffa8eSPoul-Henning Kamp g_post_event_x(g_event_t *func, void *arg, int flag, int wuflag, struct g_event **epp, va_list ap)
292346cd5feSPoul-Henning Kamp {
293346cd5feSPoul-Henning Kamp 	struct g_event *ep;
294afcbcfaeSPoul-Henning Kamp 	void *p;
295afcbcfaeSPoul-Henning Kamp 	u_int n;
296346cd5feSPoul-Henning Kamp 
297793ffa8eSPoul-Henning Kamp 	g_trace(G_T_TOPOLOGY, "g_post_event_x(%p, %p, %d, %d)",
298d246aa55SPawel Jakub Dawidek 	    func, arg, flag, wuflag);
299793ffa8eSPoul-Henning Kamp 	KASSERT(wuflag == 0 || wuflag == EV_WAKEUP,
300793ffa8eSPoul-Henning Kamp 	    ("Wrong wuflag in g_post_event_x(0x%x)", wuflag));
3018cd1535aSPoul-Henning Kamp 	ep = g_malloc(sizeof *ep, flag | M_ZERO);
302346cd5feSPoul-Henning Kamp 	if (ep == NULL)
303346cd5feSPoul-Henning Kamp 		return (ENOMEM);
304793ffa8eSPoul-Henning Kamp 	ep->flag = wuflag;
305afcbcfaeSPoul-Henning Kamp 	for (n = 0; n < G_N_EVENTREFS; n++) {
306afcbcfaeSPoul-Henning Kamp 		p = va_arg(ap, void *);
307afcbcfaeSPoul-Henning Kamp 		if (p == NULL)
308afcbcfaeSPoul-Henning Kamp 			break;
309afcbcfaeSPoul-Henning Kamp 		g_trace(G_T_TOPOLOGY, "  ref %p", p);
310e0d617c1SPoul-Henning Kamp 		ep->ref[n] = p;
311afcbcfaeSPoul-Henning Kamp 	}
312afcbcfaeSPoul-Henning Kamp 	KASSERT(p == NULL, ("Too many references to event"));
313346cd5feSPoul-Henning Kamp 	ep->func = func;
314346cd5feSPoul-Henning Kamp 	ep->arg = arg;
315346cd5feSPoul-Henning Kamp 	mtx_lock(&g_eventlock);
316346cd5feSPoul-Henning Kamp 	TAILQ_INSERT_TAIL(&g_events, ep, events);
317346cd5feSPoul-Henning Kamp 	mtx_unlock(&g_eventlock);
318346cd5feSPoul-Henning Kamp 	wakeup(&g_wait_event);
3190a9c130cSPoul-Henning Kamp 	if (epp != NULL)
3200a9c130cSPoul-Henning Kamp 		*epp = ep;
3219197ce2eSPoul-Henning Kamp 	curthread->td_pflags |= TDP_GEOM;
3220a9c130cSPoul-Henning Kamp 	return (0);
3230a9c130cSPoul-Henning Kamp }
3240a9c130cSPoul-Henning Kamp 
3250a9c130cSPoul-Henning Kamp int
3260a9c130cSPoul-Henning Kamp g_post_event(g_event_t *func, void *arg, int flag, ...)
3270a9c130cSPoul-Henning Kamp {
3280a9c130cSPoul-Henning Kamp 	va_list ap;
329a1a9b445SPoul-Henning Kamp 	int i;
3300a9c130cSPoul-Henning Kamp 
3310a9c130cSPoul-Henning Kamp 	KASSERT(flag == M_WAITOK || flag == M_NOWAIT,
3320a9c130cSPoul-Henning Kamp 	    ("Wrong flag to g_post_event"));
333a1a9b445SPoul-Henning Kamp 	va_start(ap, flag);
334793ffa8eSPoul-Henning Kamp 	i = g_post_event_x(func, arg, flag, 0, NULL, ap);
335a1a9b445SPoul-Henning Kamp 	va_end(ap);
336a1a9b445SPoul-Henning Kamp 	return (i);
3370a9c130cSPoul-Henning Kamp }
3380a9c130cSPoul-Henning Kamp 
3391b464bd8SPoul-Henning Kamp void
3401b464bd8SPoul-Henning Kamp g_do_wither() {
3411b464bd8SPoul-Henning Kamp 
3421b464bd8SPoul-Henning Kamp 	g_wither_work = 1;
3431b464bd8SPoul-Henning Kamp 	wakeup(&g_wait_event);
3441b464bd8SPoul-Henning Kamp }
3450a9c130cSPoul-Henning Kamp 
3460a9c130cSPoul-Henning Kamp /*
3470a9c130cSPoul-Henning Kamp  * XXX: It might actually be useful to call this function with topology held.
3480a9c130cSPoul-Henning Kamp  * XXX: This would ensure that the event gets created before anything else
3490a9c130cSPoul-Henning Kamp  * XXX: changes.  At present all users have a handle on things in some other
3500a9c130cSPoul-Henning Kamp  * XXX: way, so this remains an XXX for now.
3510a9c130cSPoul-Henning Kamp  */
3520a9c130cSPoul-Henning Kamp 
3530a9c130cSPoul-Henning Kamp int
3540a9c130cSPoul-Henning Kamp g_waitfor_event(g_event_t *func, void *arg, int flag, ...)
3550a9c130cSPoul-Henning Kamp {
3560a9c130cSPoul-Henning Kamp 	va_list ap;
3570a9c130cSPoul-Henning Kamp 	struct g_event *ep;
3580a9c130cSPoul-Henning Kamp 	int error;
3590a9c130cSPoul-Henning Kamp 
36018e88d82SPawel Jakub Dawidek 	g_topology_assert_not();
3610a9c130cSPoul-Henning Kamp 	KASSERT(flag == M_WAITOK || flag == M_NOWAIT,
3620a9c130cSPoul-Henning Kamp 	    ("Wrong flag to g_post_event"));
363a1a9b445SPoul-Henning Kamp 	va_start(ap, flag);
364793ffa8eSPoul-Henning Kamp 	error = g_post_event_x(func, arg, flag, EV_WAKEUP, &ep, ap);
365a1a9b445SPoul-Henning Kamp 	va_end(ap);
3660a9c130cSPoul-Henning Kamp 	if (error)
3670a9c130cSPoul-Henning Kamp 		return (error);
3680a9c130cSPoul-Henning Kamp 	do
3690a9c130cSPoul-Henning Kamp 		tsleep(ep, PRIBIO, "g_waitfor_event", hz);
3700a9c130cSPoul-Henning Kamp 	while (!(ep->flag & EV_DONE));
371c8589ad1SPoul-Henning Kamp 	if (ep->flag & EV_CANCELED)
372c8589ad1SPoul-Henning Kamp 		error = EAGAIN;
3739dfffbc9SPoul-Henning Kamp 	g_free(ep);
374c8589ad1SPoul-Henning Kamp 	return (error);
375346cd5feSPoul-Henning Kamp }
376346cd5feSPoul-Henning Kamp 
377dd84a43cSPoul-Henning Kamp void
378dd84a43cSPoul-Henning Kamp g_event_init()
379dd84a43cSPoul-Henning Kamp {
380dd84a43cSPoul-Henning Kamp 
381903e43feSPoul-Henning Kamp 	mtx_init(&g_eventlock, "GEOM orphanage", NULL, MTX_DEF);
382dd84a43cSPoul-Henning Kamp }
383