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 * $FreeBSD$ 36dd84a43cSPoul-Henning Kamp */ 37dd84a43cSPoul-Henning Kamp 38dd84a43cSPoul-Henning Kamp /* 39dd84a43cSPoul-Henning Kamp * XXX: How do we in general know that objects referenced in events 40dd84a43cSPoul-Henning Kamp * have not been destroyed before we get around to handle the event ? 41dd84a43cSPoul-Henning Kamp */ 42dd84a43cSPoul-Henning Kamp 43dd84a43cSPoul-Henning Kamp #include <sys/param.h> 44dd84a43cSPoul-Henning Kamp #ifndef _KERNEL 45dd84a43cSPoul-Henning Kamp #include <stdio.h> 46dd84a43cSPoul-Henning Kamp #include <unistd.h> 47dd84a43cSPoul-Henning Kamp #include <string.h> 48dd84a43cSPoul-Henning Kamp #include <stdlib.h> 49dd84a43cSPoul-Henning Kamp #include <signal.h> 50dd84a43cSPoul-Henning Kamp #include <err.h> 51dd84a43cSPoul-Henning Kamp #else 52dd84a43cSPoul-Henning Kamp #include <sys/malloc.h> 53dd84a43cSPoul-Henning Kamp #include <sys/systm.h> 54dd84a43cSPoul-Henning Kamp #include <sys/kernel.h> 55dd84a43cSPoul-Henning Kamp #include <sys/lock.h> 56dd84a43cSPoul-Henning Kamp #include <sys/mutex.h> 57ed0ff8e5SPoul-Henning Kamp #include <sys/eventhandler.h> 58dd84a43cSPoul-Henning Kamp #endif 59dd84a43cSPoul-Henning Kamp #include <sys/errno.h> 60dd84a43cSPoul-Henning Kamp #include <sys/time.h> 61dd84a43cSPoul-Henning Kamp #include <geom/geom.h> 62b1876192SPoul-Henning Kamp #include <geom/geom_int.h> 63dd84a43cSPoul-Henning Kamp 64dd84a43cSPoul-Henning Kamp static struct event_tailq_head g_events = TAILQ_HEAD_INITIALIZER(g_events); 65dd84a43cSPoul-Henning Kamp static u_int g_pending_events, g_silence_events; 66b1876192SPoul-Henning Kamp static void g_do_event(struct g_event *ep); 67dd84a43cSPoul-Henning Kamp static TAILQ_HEAD(,g_provider) g_doorstep = TAILQ_HEAD_INITIALIZER(g_doorstep); 68903e43feSPoul-Henning Kamp static struct mtx g_eventlock; 69ed0ff8e5SPoul-Henning Kamp static int g_shutdown; 70dd84a43cSPoul-Henning Kamp 71dd84a43cSPoul-Henning Kamp void 72dd84a43cSPoul-Henning Kamp g_silence(void) 73dd84a43cSPoul-Henning Kamp { 74dd84a43cSPoul-Henning Kamp 75dd84a43cSPoul-Henning Kamp g_silence_events = 1; 76dd84a43cSPoul-Henning Kamp } 77dd84a43cSPoul-Henning Kamp 78dd84a43cSPoul-Henning Kamp void 79503abe45SPoul-Henning Kamp g_waitidle(void) 80dd84a43cSPoul-Henning Kamp { 81dd84a43cSPoul-Henning Kamp 82dd84a43cSPoul-Henning Kamp g_silence_events = 0; 83dd84a43cSPoul-Henning Kamp mtx_lock(&Giant); 84dd84a43cSPoul-Henning Kamp wakeup(&g_silence_events); 85dd84a43cSPoul-Henning Kamp while (g_pending_events) 86503abe45SPoul-Henning Kamp tsleep(&g_pending_events, PPAUSE, "g_waitidle", hz/5); 87dd84a43cSPoul-Henning Kamp mtx_unlock(&Giant); 88dd84a43cSPoul-Henning Kamp } 89dd84a43cSPoul-Henning Kamp 90dd84a43cSPoul-Henning Kamp void 91dd84a43cSPoul-Henning Kamp g_orphan_provider(struct g_provider *pp, int error) 92dd84a43cSPoul-Henning Kamp { 93dd84a43cSPoul-Henning Kamp 94dd84a43cSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "g_orphan_provider(%p(%s), %d)", 95dd84a43cSPoul-Henning Kamp pp, pp->name, error); 96dd84a43cSPoul-Henning Kamp KASSERT(error != 0, 97dd84a43cSPoul-Henning Kamp ("g_orphan_provider(%p(%s), 0) error must be non-zero\n", 98dd84a43cSPoul-Henning Kamp pp, pp->name)); 99dd84a43cSPoul-Henning Kamp pp->error = error; 100903e43feSPoul-Henning Kamp mtx_lock(&g_eventlock); 101dd84a43cSPoul-Henning Kamp TAILQ_INSERT_TAIL(&g_doorstep, pp, orphan); 102903e43feSPoul-Henning Kamp mtx_unlock(&g_eventlock); 103dd84a43cSPoul-Henning Kamp wakeup(&g_wait_event); 104dd84a43cSPoul-Henning Kamp } 105dd84a43cSPoul-Henning Kamp 106dd84a43cSPoul-Henning Kamp /* 107dd84a43cSPoul-Henning Kamp * This function is called once on each provider which the event handler 108dd84a43cSPoul-Henning Kamp * finds on its g_doorstep. 109dd84a43cSPoul-Henning Kamp */ 110dd84a43cSPoul-Henning Kamp 111dd84a43cSPoul-Henning Kamp static void 112b1876192SPoul-Henning Kamp g_orphan_register(struct g_provider *pp) 113dd84a43cSPoul-Henning Kamp { 114dd84a43cSPoul-Henning Kamp struct g_consumer *cp, *cp2; 115dd84a43cSPoul-Henning Kamp 116dd84a43cSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "g_orphan_register(%s)", pp->name); 117dd84a43cSPoul-Henning Kamp g_topology_assert(); 118dd84a43cSPoul-Henning Kamp 119dd84a43cSPoul-Henning Kamp /* 120dd84a43cSPoul-Henning Kamp * Tell all consumers the bad news. 121dd84a43cSPoul-Henning Kamp * Don't get surprised if they self-destruct. 122dd84a43cSPoul-Henning Kamp */ 123dd84a43cSPoul-Henning Kamp cp = LIST_FIRST(&pp->consumers); 124dd84a43cSPoul-Henning Kamp while (cp != NULL) { 125dd84a43cSPoul-Henning Kamp cp2 = LIST_NEXT(cp, consumers); 12607d77fc6SPoul-Henning Kamp KASSERT(cp->geom->orphan != NULL, 12707d77fc6SPoul-Henning Kamp ("geom %s has no orphan, class %s", 12807d77fc6SPoul-Henning Kamp cp->geom->name, cp->geom->class->name)); 12907d77fc6SPoul-Henning Kamp cp->geom->orphan(cp); 130dd84a43cSPoul-Henning Kamp cp = cp2; 131dd84a43cSPoul-Henning Kamp } 132dd84a43cSPoul-Henning Kamp } 133dd84a43cSPoul-Henning Kamp 134dd84a43cSPoul-Henning Kamp static void 135dd84a43cSPoul-Henning Kamp g_destroy_event(struct g_event *ep) 136dd84a43cSPoul-Henning Kamp { 137dd84a43cSPoul-Henning Kamp 138dd84a43cSPoul-Henning Kamp g_free(ep); 139dd84a43cSPoul-Henning Kamp } 140dd84a43cSPoul-Henning Kamp 141dd84a43cSPoul-Henning Kamp static void 142b1876192SPoul-Henning Kamp g_do_event(struct g_event *ep) 143dd84a43cSPoul-Henning Kamp { 144e805e8f0SPoul-Henning Kamp struct g_class *mp, *mp2; 145dd84a43cSPoul-Henning Kamp struct g_geom *gp; 146dd84a43cSPoul-Henning Kamp struct g_consumer *cp, *cp2; 147dd84a43cSPoul-Henning Kamp struct g_provider *pp; 148dd84a43cSPoul-Henning Kamp int i; 149dd84a43cSPoul-Henning Kamp 150dd84a43cSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "g_do_event(%p) %d m:%p g:%p p:%p c:%p - ", 151e805e8f0SPoul-Henning Kamp ep, ep->event, ep->class, ep->geom, ep->provider, ep->consumer); 152dd84a43cSPoul-Henning Kamp g_topology_assert(); 153dd84a43cSPoul-Henning Kamp switch (ep->event) { 154346cd5feSPoul-Henning Kamp case EV_CALL_ME: 155346cd5feSPoul-Henning Kamp ep->func(ep->arg); 156346cd5feSPoul-Henning Kamp break; 157e805e8f0SPoul-Henning Kamp case EV_NEW_CLASS: 158e805e8f0SPoul-Henning Kamp mp2 = ep->class; 159346cd5feSPoul-Henning Kamp if (g_shutdown) 160346cd5feSPoul-Henning Kamp break; 161dd84a43cSPoul-Henning Kamp if (mp2->taste == NULL) 162dd84a43cSPoul-Henning Kamp break; 163e615b0fdSPoul-Henning Kamp if (g_shutdown) 164e615b0fdSPoul-Henning Kamp break; 1652654e1fcSPoul-Henning Kamp LIST_FOREACH(mp, &g_classes, class) { 166dd84a43cSPoul-Henning Kamp if (mp2 == mp) 167dd84a43cSPoul-Henning Kamp continue; 168dd84a43cSPoul-Henning Kamp LIST_FOREACH(gp, &mp->geom, geom) { 169dd84a43cSPoul-Henning Kamp LIST_FOREACH(pp, &gp->provider, provider) { 170b1876192SPoul-Henning Kamp mp2->taste(ep->class, pp, 0); 171dd84a43cSPoul-Henning Kamp g_topology_assert(); 172dd84a43cSPoul-Henning Kamp } 173dd84a43cSPoul-Henning Kamp } 174dd84a43cSPoul-Henning Kamp } 175dd84a43cSPoul-Henning Kamp break; 176dd84a43cSPoul-Henning Kamp case EV_NEW_PROVIDER: 177e615b0fdSPoul-Henning Kamp if (g_shutdown) 178e615b0fdSPoul-Henning Kamp break; 179dd84a43cSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "EV_NEW_PROVIDER(%s)", 180dd84a43cSPoul-Henning Kamp ep->provider->name); 1812654e1fcSPoul-Henning Kamp LIST_FOREACH(mp, &g_classes, class) { 182dd84a43cSPoul-Henning Kamp if (mp->taste == NULL) 183dd84a43cSPoul-Henning Kamp continue; 184dd84a43cSPoul-Henning Kamp i = 1; 185dd84a43cSPoul-Henning Kamp LIST_FOREACH(cp, &ep->provider->consumers, consumers) 186e805e8f0SPoul-Henning Kamp if(cp->geom->class == mp) 187dd84a43cSPoul-Henning Kamp i = 0; 188dd84a43cSPoul-Henning Kamp if (i) { 189b1876192SPoul-Henning Kamp mp->taste(mp, ep->provider, 0); 190dd84a43cSPoul-Henning Kamp g_topology_assert(); 191dd84a43cSPoul-Henning Kamp } 192dd84a43cSPoul-Henning Kamp } 193dd84a43cSPoul-Henning Kamp break; 194dd84a43cSPoul-Henning Kamp case EV_SPOILED: 195dd84a43cSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "EV_SPOILED(%p(%s),%p)", 196dd84a43cSPoul-Henning Kamp ep->provider, ep->provider->name, ep->consumer); 197dd84a43cSPoul-Henning Kamp cp = LIST_FIRST(&ep->provider->consumers); 198dd84a43cSPoul-Henning Kamp while (cp != NULL) { 199dd84a43cSPoul-Henning Kamp cp2 = LIST_NEXT(cp, consumers); 200dd84a43cSPoul-Henning Kamp if (cp->spoiled) { 201dd84a43cSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "spoiling %p (%s) (%p)", 202dd84a43cSPoul-Henning Kamp cp, cp->geom->name, cp->geom->spoiled); 203dd84a43cSPoul-Henning Kamp if (cp->geom->spoiled != NULL) 204dd84a43cSPoul-Henning Kamp cp->geom->spoiled(cp); 205855f8b26SPoul-Henning Kamp else 206dd84a43cSPoul-Henning Kamp cp->spoiled = 0; 207dd84a43cSPoul-Henning Kamp } 208dd84a43cSPoul-Henning Kamp cp = cp2; 209dd84a43cSPoul-Henning Kamp } 210dd84a43cSPoul-Henning Kamp break; 211dd84a43cSPoul-Henning Kamp case EV_LAST: 212dd84a43cSPoul-Henning Kamp default: 213dd84a43cSPoul-Henning Kamp KASSERT(1 == 0, ("Unknown event %d", ep->event)); 214dd84a43cSPoul-Henning Kamp } 215dd84a43cSPoul-Henning Kamp } 216dd84a43cSPoul-Henning Kamp 217dd84a43cSPoul-Henning Kamp static int 218b1876192SPoul-Henning Kamp one_event(void) 219dd84a43cSPoul-Henning Kamp { 220dd84a43cSPoul-Henning Kamp struct g_event *ep; 221dd84a43cSPoul-Henning Kamp struct g_provider *pp; 222dd84a43cSPoul-Henning Kamp 223dd84a43cSPoul-Henning Kamp g_topology_lock(); 224dd84a43cSPoul-Henning Kamp for (;;) { 225903e43feSPoul-Henning Kamp mtx_lock(&g_eventlock); 226dd84a43cSPoul-Henning Kamp pp = TAILQ_FIRST(&g_doorstep); 227dd84a43cSPoul-Henning Kamp if (pp != NULL) 228dd84a43cSPoul-Henning Kamp TAILQ_REMOVE(&g_doorstep, pp, orphan); 229903e43feSPoul-Henning Kamp mtx_unlock(&g_eventlock); 230dd84a43cSPoul-Henning Kamp if (pp == NULL) 231dd84a43cSPoul-Henning Kamp break; 232b1876192SPoul-Henning Kamp g_orphan_register(pp); 233dd84a43cSPoul-Henning Kamp } 234346cd5feSPoul-Henning Kamp mtx_lock(&g_eventlock); 235dd84a43cSPoul-Henning Kamp ep = TAILQ_FIRST(&g_events); 236dd84a43cSPoul-Henning Kamp if (ep == NULL) { 237346cd5feSPoul-Henning Kamp mtx_unlock(&g_eventlock); 238dd84a43cSPoul-Henning Kamp g_topology_unlock(); 239dd84a43cSPoul-Henning Kamp return (0); 240dd84a43cSPoul-Henning Kamp } 241dd84a43cSPoul-Henning Kamp TAILQ_REMOVE(&g_events, ep, events); 242346cd5feSPoul-Henning Kamp mtx_unlock(&g_eventlock); 243e805e8f0SPoul-Henning Kamp if (ep->class != NULL) 244e805e8f0SPoul-Henning Kamp ep->class->event = NULL; 245dd84a43cSPoul-Henning Kamp if (ep->geom != NULL) 246dd84a43cSPoul-Henning Kamp ep->geom->event = NULL; 247dd84a43cSPoul-Henning Kamp if (ep->provider != NULL) 248dd84a43cSPoul-Henning Kamp ep->provider->event = NULL; 249dd84a43cSPoul-Henning Kamp if (ep->consumer != NULL) 250dd84a43cSPoul-Henning Kamp ep->consumer->event = NULL; 251b1876192SPoul-Henning Kamp g_do_event(ep); 252dd84a43cSPoul-Henning Kamp g_pending_events--; 253dd84a43cSPoul-Henning Kamp if (g_pending_events == 0) { 254dd84a43cSPoul-Henning Kamp wakeup(&g_pending_events); 255dd84a43cSPoul-Henning Kamp } 256dd84a43cSPoul-Henning Kamp g_topology_unlock(); 257dd84a43cSPoul-Henning Kamp g_destroy_event(ep); 258dd84a43cSPoul-Henning Kamp return (1); 259dd84a43cSPoul-Henning Kamp } 260dd84a43cSPoul-Henning Kamp 261dd84a43cSPoul-Henning Kamp void 262b1876192SPoul-Henning Kamp g_run_events() 263dd84a43cSPoul-Henning Kamp { 264dd84a43cSPoul-Henning Kamp 265b1876192SPoul-Henning Kamp while (one_event()) 266dd84a43cSPoul-Henning Kamp ; 267dd84a43cSPoul-Henning Kamp } 268dd84a43cSPoul-Henning Kamp 269dd84a43cSPoul-Henning Kamp void 270e805e8f0SPoul-Henning Kamp g_post_event(enum g_events ev, struct g_class *mp, struct g_geom *gp, struct g_provider *pp, struct g_consumer *cp) 271dd84a43cSPoul-Henning Kamp { 272dd84a43cSPoul-Henning Kamp struct g_event *ep; 273dd84a43cSPoul-Henning Kamp 274dd84a43cSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "g_post_event(%d, %p, %p, %p, %p)", 275dd84a43cSPoul-Henning Kamp ev, mp, gp, pp, cp); 276dd84a43cSPoul-Henning Kamp g_topology_assert(); 277dd84a43cSPoul-Henning Kamp ep = g_malloc(sizeof *ep, M_WAITOK | M_ZERO); 278dd84a43cSPoul-Henning Kamp ep->event = ev; 279dd84a43cSPoul-Henning Kamp if (mp != NULL) { 280e805e8f0SPoul-Henning Kamp ep->class = mp; 281e805e8f0SPoul-Henning Kamp KASSERT(mp->event == NULL, ("Double event on class")); 282dd84a43cSPoul-Henning Kamp mp->event = ep; 283dd84a43cSPoul-Henning Kamp } 284dd84a43cSPoul-Henning Kamp if (gp != NULL) { 285dd84a43cSPoul-Henning Kamp ep->geom = gp; 286dd84a43cSPoul-Henning Kamp KASSERT(gp->event == NULL, ("Double event on geom")); 287dd84a43cSPoul-Henning Kamp gp->event = ep; 288dd84a43cSPoul-Henning Kamp } 289dd84a43cSPoul-Henning Kamp if (pp != NULL) { 290dd84a43cSPoul-Henning Kamp ep->provider = pp; 291dd84a43cSPoul-Henning Kamp KASSERT(pp->event == NULL, ("Double event on provider")); 292dd84a43cSPoul-Henning Kamp pp->event = ep; 293dd84a43cSPoul-Henning Kamp } 294dd84a43cSPoul-Henning Kamp if (cp != NULL) { 295dd84a43cSPoul-Henning Kamp ep->consumer = cp; 296dd84a43cSPoul-Henning Kamp KASSERT(cp->event == NULL, ("Double event on consumer")); 297dd84a43cSPoul-Henning Kamp cp->event = ep; 298dd84a43cSPoul-Henning Kamp } 299346cd5feSPoul-Henning Kamp mtx_lock(&g_eventlock); 300dd84a43cSPoul-Henning Kamp g_pending_events++; 301dd84a43cSPoul-Henning Kamp TAILQ_INSERT_TAIL(&g_events, ep, events); 302346cd5feSPoul-Henning Kamp mtx_unlock(&g_eventlock); 303dd84a43cSPoul-Henning Kamp wakeup(&g_wait_event); 304dd84a43cSPoul-Henning Kamp } 305dd84a43cSPoul-Henning Kamp 306346cd5feSPoul-Henning Kamp int 307346cd5feSPoul-Henning Kamp g_call_me(g_call_me_t *func, void *arg) 308346cd5feSPoul-Henning Kamp { 309346cd5feSPoul-Henning Kamp struct g_event *ep; 310346cd5feSPoul-Henning Kamp 311346cd5feSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "g_call_me(%p, %p", func, arg); 312346cd5feSPoul-Henning Kamp ep = g_malloc(sizeof *ep, M_NOWAIT | M_ZERO); 313346cd5feSPoul-Henning Kamp if (ep == NULL) 314346cd5feSPoul-Henning Kamp return (ENOMEM); 315346cd5feSPoul-Henning Kamp ep->event = EV_CALL_ME; 316346cd5feSPoul-Henning Kamp ep->func = func; 317346cd5feSPoul-Henning Kamp ep->arg = arg; 318346cd5feSPoul-Henning Kamp mtx_lock(&g_eventlock); 319346cd5feSPoul-Henning Kamp g_pending_events++; 320346cd5feSPoul-Henning Kamp TAILQ_INSERT_TAIL(&g_events, ep, events); 321346cd5feSPoul-Henning Kamp mtx_unlock(&g_eventlock); 322346cd5feSPoul-Henning Kamp wakeup(&g_wait_event); 323346cd5feSPoul-Henning Kamp return (0); 324346cd5feSPoul-Henning Kamp } 325346cd5feSPoul-Henning Kamp 326ed0ff8e5SPoul-Henning Kamp #ifdef _KERNEL 327ed0ff8e5SPoul-Henning Kamp static void 328ed0ff8e5SPoul-Henning Kamp geom_shutdown(void *foo __unused) 329ed0ff8e5SPoul-Henning Kamp { 330ed0ff8e5SPoul-Henning Kamp 331ed0ff8e5SPoul-Henning Kamp g_shutdown = 1; 332ed0ff8e5SPoul-Henning Kamp } 333ed0ff8e5SPoul-Henning Kamp #endif 334ed0ff8e5SPoul-Henning Kamp 335dd84a43cSPoul-Henning Kamp void 336dd84a43cSPoul-Henning Kamp g_event_init() 337dd84a43cSPoul-Henning Kamp { 338dd84a43cSPoul-Henning Kamp 339ed0ff8e5SPoul-Henning Kamp #ifdef _KERNEL 340ed0ff8e5SPoul-Henning Kamp 341ed0ff8e5SPoul-Henning Kamp EVENTHANDLER_REGISTER(shutdown_pre_sync, geom_shutdown, NULL, 342ed0ff8e5SPoul-Henning Kamp SHUTDOWN_PRI_FIRST); 343ed0ff8e5SPoul-Henning Kamp #endif 344903e43feSPoul-Henning Kamp mtx_init(&g_eventlock, "GEOM orphanage", NULL, MTX_DEF); 345dd84a43cSPoul-Henning Kamp } 346