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); 65abb50a48SPoul-Henning Kamp static u_int g_pending_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 72503abe45SPoul-Henning Kamp g_waitidle(void) 73dd84a43cSPoul-Henning Kamp { 74dd84a43cSPoul-Henning Kamp 75dd84a43cSPoul-Henning Kamp while (g_pending_events) 76503abe45SPoul-Henning Kamp tsleep(&g_pending_events, PPAUSE, "g_waitidle", hz/5); 77dd84a43cSPoul-Henning Kamp } 78dd84a43cSPoul-Henning Kamp 79dd84a43cSPoul-Henning Kamp void 80dd84a43cSPoul-Henning Kamp g_orphan_provider(struct g_provider *pp, int error) 81dd84a43cSPoul-Henning Kamp { 82dd84a43cSPoul-Henning Kamp 83dd84a43cSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "g_orphan_provider(%p(%s), %d)", 84dd84a43cSPoul-Henning Kamp pp, pp->name, error); 85dd84a43cSPoul-Henning Kamp KASSERT(error != 0, 86dd84a43cSPoul-Henning Kamp ("g_orphan_provider(%p(%s), 0) error must be non-zero\n", 87dd84a43cSPoul-Henning Kamp pp, pp->name)); 88dd84a43cSPoul-Henning Kamp pp->error = error; 89903e43feSPoul-Henning Kamp mtx_lock(&g_eventlock); 90dd84a43cSPoul-Henning Kamp TAILQ_INSERT_TAIL(&g_doorstep, pp, orphan); 91903e43feSPoul-Henning Kamp mtx_unlock(&g_eventlock); 92dd84a43cSPoul-Henning Kamp wakeup(&g_wait_event); 93dd84a43cSPoul-Henning Kamp } 94dd84a43cSPoul-Henning Kamp 95dd84a43cSPoul-Henning Kamp /* 96dd84a43cSPoul-Henning Kamp * This function is called once on each provider which the event handler 97dd84a43cSPoul-Henning Kamp * finds on its g_doorstep. 98dd84a43cSPoul-Henning Kamp */ 99dd84a43cSPoul-Henning Kamp 100dd84a43cSPoul-Henning Kamp static void 101b1876192SPoul-Henning Kamp g_orphan_register(struct g_provider *pp) 102dd84a43cSPoul-Henning Kamp { 103dd84a43cSPoul-Henning Kamp struct g_consumer *cp, *cp2; 104dd84a43cSPoul-Henning Kamp 105dd84a43cSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "g_orphan_register(%s)", pp->name); 106dd84a43cSPoul-Henning Kamp g_topology_assert(); 107dd84a43cSPoul-Henning Kamp 108dd84a43cSPoul-Henning Kamp /* 109dd84a43cSPoul-Henning Kamp * Tell all consumers the bad news. 110f48b8819SPoul-Henning Kamp * Don't be surprised if they self-destruct. 111dd84a43cSPoul-Henning Kamp */ 112dd84a43cSPoul-Henning Kamp cp = LIST_FIRST(&pp->consumers); 113dd84a43cSPoul-Henning Kamp while (cp != NULL) { 114dd84a43cSPoul-Henning Kamp cp2 = LIST_NEXT(cp, consumers); 11507d77fc6SPoul-Henning Kamp KASSERT(cp->geom->orphan != NULL, 11607d77fc6SPoul-Henning Kamp ("geom %s has no orphan, class %s", 11707d77fc6SPoul-Henning Kamp cp->geom->name, cp->geom->class->name)); 11807d77fc6SPoul-Henning Kamp cp->geom->orphan(cp); 119dd84a43cSPoul-Henning Kamp cp = cp2; 120dd84a43cSPoul-Henning Kamp } 121e5829909SPoul-Henning Kamp cp = LIST_FIRST(&pp->consumers); 122e5829909SPoul-Henning Kamp if (cp != NULL) 123e5829909SPoul-Henning Kamp return; 124e5829909SPoul-Henning Kamp if (pp->geom->flags & G_GEOM_WITHER) 125e5829909SPoul-Henning Kamp g_destroy_provider(pp); 126dd84a43cSPoul-Henning Kamp } 127dd84a43cSPoul-Henning Kamp 128dd84a43cSPoul-Henning Kamp static void 129dd84a43cSPoul-Henning Kamp g_destroy_event(struct g_event *ep) 130dd84a43cSPoul-Henning Kamp { 131dd84a43cSPoul-Henning Kamp 132dd84a43cSPoul-Henning Kamp g_free(ep); 133dd84a43cSPoul-Henning Kamp } 134dd84a43cSPoul-Henning Kamp 135dd84a43cSPoul-Henning Kamp static void 136b1876192SPoul-Henning Kamp g_do_event(struct g_event *ep) 137dd84a43cSPoul-Henning Kamp { 138e805e8f0SPoul-Henning Kamp struct g_class *mp, *mp2; 139dd84a43cSPoul-Henning Kamp struct g_geom *gp; 140dd84a43cSPoul-Henning Kamp struct g_consumer *cp, *cp2; 141dd84a43cSPoul-Henning Kamp struct g_provider *pp; 142dd84a43cSPoul-Henning Kamp int i; 143dd84a43cSPoul-Henning Kamp 144dd84a43cSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "g_do_event(%p) %d m:%p g:%p p:%p c:%p - ", 145e805e8f0SPoul-Henning Kamp ep, ep->event, ep->class, ep->geom, ep->provider, ep->consumer); 146dd84a43cSPoul-Henning Kamp g_topology_assert(); 147dd84a43cSPoul-Henning Kamp switch (ep->event) { 148346cd5feSPoul-Henning Kamp case EV_CALL_ME: 149346cd5feSPoul-Henning Kamp ep->func(ep->arg); 150cd4f50fbSPoul-Henning Kamp g_topology_assert(); 151346cd5feSPoul-Henning Kamp break; 152e805e8f0SPoul-Henning Kamp case EV_NEW_CLASS: 153e805e8f0SPoul-Henning Kamp mp2 = ep->class; 154346cd5feSPoul-Henning Kamp if (g_shutdown) 155346cd5feSPoul-Henning Kamp break; 156dd84a43cSPoul-Henning Kamp if (mp2->taste == NULL) 157dd84a43cSPoul-Henning Kamp break; 158e615b0fdSPoul-Henning Kamp if (g_shutdown) 159e615b0fdSPoul-Henning Kamp break; 1602654e1fcSPoul-Henning Kamp LIST_FOREACH(mp, &g_classes, class) { 161dd84a43cSPoul-Henning Kamp if (mp2 == mp) 162dd84a43cSPoul-Henning Kamp continue; 163dd84a43cSPoul-Henning Kamp LIST_FOREACH(gp, &mp->geom, geom) { 164dd84a43cSPoul-Henning Kamp LIST_FOREACH(pp, &gp->provider, provider) { 165b1876192SPoul-Henning Kamp mp2->taste(ep->class, pp, 0); 166dd84a43cSPoul-Henning Kamp g_topology_assert(); 167dd84a43cSPoul-Henning Kamp } 168dd84a43cSPoul-Henning Kamp } 169dd84a43cSPoul-Henning Kamp } 170dd84a43cSPoul-Henning Kamp break; 171dd84a43cSPoul-Henning Kamp case EV_NEW_PROVIDER: 172e615b0fdSPoul-Henning Kamp if (g_shutdown) 173e615b0fdSPoul-Henning Kamp break; 174dd84a43cSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "EV_NEW_PROVIDER(%s)", 175dd84a43cSPoul-Henning Kamp ep->provider->name); 1762654e1fcSPoul-Henning Kamp LIST_FOREACH(mp, &g_classes, class) { 177dd84a43cSPoul-Henning Kamp if (mp->taste == NULL) 178dd84a43cSPoul-Henning Kamp continue; 179a9ed5e11SPoul-Henning Kamp if (!strcmp(ep->provider->name, "geom.ctl") && 180a9ed5e11SPoul-Henning Kamp strcmp(mp->name, "DEV")) 181a9ed5e11SPoul-Henning Kamp continue; 182dd84a43cSPoul-Henning Kamp i = 1; 183dd84a43cSPoul-Henning Kamp LIST_FOREACH(cp, &ep->provider->consumers, consumers) 184e805e8f0SPoul-Henning Kamp if(cp->geom->class == mp) 185dd84a43cSPoul-Henning Kamp i = 0; 186dd84a43cSPoul-Henning Kamp if (i) { 187b1876192SPoul-Henning Kamp mp->taste(mp, ep->provider, 0); 188dd84a43cSPoul-Henning Kamp g_topology_assert(); 189dd84a43cSPoul-Henning Kamp } 190dd84a43cSPoul-Henning Kamp } 191dd84a43cSPoul-Henning Kamp break; 192dd84a43cSPoul-Henning Kamp case EV_SPOILED: 193dd84a43cSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "EV_SPOILED(%p(%s),%p)", 194dd84a43cSPoul-Henning Kamp ep->provider, ep->provider->name, ep->consumer); 195dd84a43cSPoul-Henning Kamp cp = LIST_FIRST(&ep->provider->consumers); 196dd84a43cSPoul-Henning Kamp while (cp != NULL) { 197dd84a43cSPoul-Henning Kamp cp2 = LIST_NEXT(cp, consumers); 198dd84a43cSPoul-Henning Kamp if (cp->spoiled) { 199dd84a43cSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "spoiling %p (%s) (%p)", 200dd84a43cSPoul-Henning Kamp cp, cp->geom->name, cp->geom->spoiled); 201dd84a43cSPoul-Henning Kamp if (cp->geom->spoiled != NULL) 202dd84a43cSPoul-Henning Kamp cp->geom->spoiled(cp); 203855f8b26SPoul-Henning Kamp else 204dd84a43cSPoul-Henning Kamp cp->spoiled = 0; 205dd84a43cSPoul-Henning Kamp } 206dd84a43cSPoul-Henning Kamp cp = cp2; 207dd84a43cSPoul-Henning Kamp } 208dd84a43cSPoul-Henning Kamp break; 209dd84a43cSPoul-Henning Kamp case EV_LAST: 210dd84a43cSPoul-Henning Kamp default: 211dd84a43cSPoul-Henning Kamp KASSERT(1 == 0, ("Unknown event %d", ep->event)); 212dd84a43cSPoul-Henning Kamp } 213dd84a43cSPoul-Henning Kamp } 214dd84a43cSPoul-Henning Kamp 215dd84a43cSPoul-Henning Kamp static int 216b1876192SPoul-Henning Kamp one_event(void) 217dd84a43cSPoul-Henning Kamp { 218dd84a43cSPoul-Henning Kamp struct g_event *ep; 219dd84a43cSPoul-Henning Kamp struct g_provider *pp; 220dd84a43cSPoul-Henning Kamp 221dd84a43cSPoul-Henning Kamp g_topology_lock(); 222dd84a43cSPoul-Henning Kamp for (;;) { 223903e43feSPoul-Henning Kamp mtx_lock(&g_eventlock); 224dd84a43cSPoul-Henning Kamp pp = TAILQ_FIRST(&g_doorstep); 225dd84a43cSPoul-Henning Kamp if (pp != NULL) 226dd84a43cSPoul-Henning Kamp TAILQ_REMOVE(&g_doorstep, pp, orphan); 227903e43feSPoul-Henning Kamp mtx_unlock(&g_eventlock); 228dd84a43cSPoul-Henning Kamp if (pp == NULL) 229dd84a43cSPoul-Henning Kamp break; 230b1876192SPoul-Henning Kamp g_orphan_register(pp); 231dd84a43cSPoul-Henning Kamp } 232346cd5feSPoul-Henning Kamp mtx_lock(&g_eventlock); 233dd84a43cSPoul-Henning Kamp ep = TAILQ_FIRST(&g_events); 234dd84a43cSPoul-Henning Kamp if (ep == NULL) { 235346cd5feSPoul-Henning Kamp mtx_unlock(&g_eventlock); 236dd84a43cSPoul-Henning Kamp g_topology_unlock(); 237dd84a43cSPoul-Henning Kamp return (0); 238dd84a43cSPoul-Henning Kamp } 239dd84a43cSPoul-Henning Kamp TAILQ_REMOVE(&g_events, ep, events); 240346cd5feSPoul-Henning Kamp mtx_unlock(&g_eventlock); 241e805e8f0SPoul-Henning Kamp if (ep->class != NULL) 242e805e8f0SPoul-Henning Kamp ep->class->event = NULL; 243dd84a43cSPoul-Henning Kamp if (ep->geom != NULL) 244dd84a43cSPoul-Henning Kamp ep->geom->event = NULL; 245dd84a43cSPoul-Henning Kamp if (ep->provider != NULL) 246dd84a43cSPoul-Henning Kamp ep->provider->event = NULL; 247dd84a43cSPoul-Henning Kamp if (ep->consumer != NULL) 248dd84a43cSPoul-Henning Kamp ep->consumer->event = NULL; 249b1876192SPoul-Henning Kamp g_do_event(ep); 250dd84a43cSPoul-Henning Kamp g_destroy_event(ep); 251a9ed5e11SPoul-Henning Kamp g_pending_events--; 252a9ed5e11SPoul-Henning Kamp if (g_pending_events == 0) 253a9ed5e11SPoul-Henning Kamp wakeup(&g_pending_events); 254a9ed5e11SPoul-Henning Kamp g_topology_unlock(); 255dd84a43cSPoul-Henning Kamp return (1); 256dd84a43cSPoul-Henning Kamp } 257dd84a43cSPoul-Henning Kamp 258dd84a43cSPoul-Henning Kamp void 259b1876192SPoul-Henning Kamp g_run_events() 260dd84a43cSPoul-Henning Kamp { 261dd84a43cSPoul-Henning Kamp 262b1876192SPoul-Henning Kamp while (one_event()) 263dd84a43cSPoul-Henning Kamp ; 264dd84a43cSPoul-Henning Kamp } 265dd84a43cSPoul-Henning Kamp 266dd84a43cSPoul-Henning Kamp void 267e805e8f0SPoul-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) 268dd84a43cSPoul-Henning Kamp { 269dd84a43cSPoul-Henning Kamp struct g_event *ep; 270dd84a43cSPoul-Henning Kamp 271dd84a43cSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "g_post_event(%d, %p, %p, %p, %p)", 272dd84a43cSPoul-Henning Kamp ev, mp, gp, pp, cp); 273dd84a43cSPoul-Henning Kamp g_topology_assert(); 274a163d034SWarner Losh ep = g_malloc(sizeof *ep, M_WAITOK | M_ZERO); 275dd84a43cSPoul-Henning Kamp ep->event = ev; 276dd84a43cSPoul-Henning Kamp if (mp != NULL) { 277e805e8f0SPoul-Henning Kamp ep->class = mp; 278a9ed5e11SPoul-Henning Kamp KASSERT(mp->event == NULL, ("Double event on class %d %d", 279a9ed5e11SPoul-Henning Kamp ep->event, mp->event->event)); 280dd84a43cSPoul-Henning Kamp mp->event = ep; 281dd84a43cSPoul-Henning Kamp } 282dd84a43cSPoul-Henning Kamp if (gp != NULL) { 283dd84a43cSPoul-Henning Kamp ep->geom = gp; 284a9ed5e11SPoul-Henning Kamp KASSERT(gp->event == NULL, ("Double event on geom %d %d", 285a9ed5e11SPoul-Henning Kamp ep->event, gp->event->event)); 286dd84a43cSPoul-Henning Kamp gp->event = ep; 287dd84a43cSPoul-Henning Kamp } 288dd84a43cSPoul-Henning Kamp if (pp != NULL) { 289dd84a43cSPoul-Henning Kamp ep->provider = pp; 290a9ed5e11SPoul-Henning Kamp KASSERT(pp->event == NULL, ("Double event on provider %s %d %d", 291a9ed5e11SPoul-Henning Kamp pp->name, ep->event, pp->event->event)); 292dd84a43cSPoul-Henning Kamp pp->event = ep; 293dd84a43cSPoul-Henning Kamp } 294dd84a43cSPoul-Henning Kamp if (cp != NULL) { 295dd84a43cSPoul-Henning Kamp ep->consumer = cp; 296a9ed5e11SPoul-Henning Kamp KASSERT(cp->event == NULL, ("Double event on consumer %d %d", 297a9ed5e11SPoul-Henning Kamp ep->event, cp->event->event)); 298dd84a43cSPoul-Henning Kamp cp->event = ep; 299dd84a43cSPoul-Henning Kamp } 300346cd5feSPoul-Henning Kamp mtx_lock(&g_eventlock); 301dd84a43cSPoul-Henning Kamp g_pending_events++; 302dd84a43cSPoul-Henning Kamp TAILQ_INSERT_TAIL(&g_events, ep, events); 303346cd5feSPoul-Henning Kamp mtx_unlock(&g_eventlock); 304dd84a43cSPoul-Henning Kamp wakeup(&g_wait_event); 305dd84a43cSPoul-Henning Kamp } 306dd84a43cSPoul-Henning Kamp 307346cd5feSPoul-Henning Kamp int 308346cd5feSPoul-Henning Kamp g_call_me(g_call_me_t *func, void *arg) 309346cd5feSPoul-Henning Kamp { 310346cd5feSPoul-Henning Kamp struct g_event *ep; 311346cd5feSPoul-Henning Kamp 312346cd5feSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "g_call_me(%p, %p", func, arg); 313346cd5feSPoul-Henning Kamp ep = g_malloc(sizeof *ep, M_NOWAIT | M_ZERO); 314346cd5feSPoul-Henning Kamp if (ep == NULL) 315346cd5feSPoul-Henning Kamp return (ENOMEM); 316346cd5feSPoul-Henning Kamp ep->event = EV_CALL_ME; 317346cd5feSPoul-Henning Kamp ep->func = func; 318346cd5feSPoul-Henning Kamp ep->arg = arg; 319346cd5feSPoul-Henning Kamp mtx_lock(&g_eventlock); 320346cd5feSPoul-Henning Kamp g_pending_events++; 321346cd5feSPoul-Henning Kamp TAILQ_INSERT_TAIL(&g_events, ep, events); 322346cd5feSPoul-Henning Kamp mtx_unlock(&g_eventlock); 323346cd5feSPoul-Henning Kamp wakeup(&g_wait_event); 324346cd5feSPoul-Henning Kamp return (0); 325346cd5feSPoul-Henning Kamp } 326346cd5feSPoul-Henning Kamp 327ed0ff8e5SPoul-Henning Kamp #ifdef _KERNEL 328ed0ff8e5SPoul-Henning Kamp static void 329ed0ff8e5SPoul-Henning Kamp geom_shutdown(void *foo __unused) 330ed0ff8e5SPoul-Henning Kamp { 331ed0ff8e5SPoul-Henning Kamp 332ed0ff8e5SPoul-Henning Kamp g_shutdown = 1; 333ed0ff8e5SPoul-Henning Kamp } 334ed0ff8e5SPoul-Henning Kamp #endif 335ed0ff8e5SPoul-Henning Kamp 336dd84a43cSPoul-Henning Kamp void 337dd84a43cSPoul-Henning Kamp g_event_init() 338dd84a43cSPoul-Henning Kamp { 339dd84a43cSPoul-Henning Kamp 340ed0ff8e5SPoul-Henning Kamp #ifdef _KERNEL 341ed0ff8e5SPoul-Henning Kamp 342ed0ff8e5SPoul-Henning Kamp EVENTHANDLER_REGISTER(shutdown_pre_sync, geom_shutdown, NULL, 343ed0ff8e5SPoul-Henning Kamp SHUTDOWN_PRI_FIRST); 344ed0ff8e5SPoul-Henning Kamp #endif 345903e43feSPoul-Henning Kamp mtx_init(&g_eventlock, "GEOM orphanage", NULL, MTX_DEF); 346dd84a43cSPoul-Henning Kamp } 347