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> 50afcbcfaeSPoul-Henning Kamp #include <machine/stdarg.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 56a974614bSPoul-Henning Kamp TAILQ_HEAD(event_tailq_head, g_event); 57a974614bSPoul-Henning Kamp 58dd84a43cSPoul-Henning Kamp static struct event_tailq_head g_events = TAILQ_HEAD_INITIALIZER(g_events); 59abb50a48SPoul-Henning Kamp static u_int g_pending_events; 60dd84a43cSPoul-Henning Kamp static TAILQ_HEAD(,g_provider) g_doorstep = TAILQ_HEAD_INITIALIZER(g_doorstep); 61903e43feSPoul-Henning Kamp static struct mtx g_eventlock; 62d943f1b0SPoul-Henning Kamp static struct sx g_eventstall; 63dd84a43cSPoul-Henning Kamp 64a974614bSPoul-Henning Kamp #define G_N_EVENTREFS 20 65a974614bSPoul-Henning Kamp 66a974614bSPoul-Henning Kamp struct g_event { 67a974614bSPoul-Henning Kamp TAILQ_ENTRY(g_event) events; 68a974614bSPoul-Henning Kamp g_event_t *func; 690a9c130cSPoul-Henning Kamp void *arg; 700a9c130cSPoul-Henning Kamp int flag; 71a974614bSPoul-Henning Kamp void *ref[G_N_EVENTREFS]; 72a974614bSPoul-Henning Kamp }; 73a974614bSPoul-Henning Kamp 740a9c130cSPoul-Henning Kamp #define EV_DONE 0x80000 750a9c130cSPoul-Henning Kamp #define EV_WAKEUP 0x40000 76c8589ad1SPoul-Henning Kamp #define EV_CANCELED 0x20000 770a9c130cSPoul-Henning Kamp 78dd84a43cSPoul-Henning Kamp void 79503abe45SPoul-Henning Kamp g_waitidle(void) 80dd84a43cSPoul-Henning Kamp { 81dd84a43cSPoul-Henning Kamp 82dd84a43cSPoul-Henning Kamp while (g_pending_events) 83503abe45SPoul-Henning Kamp tsleep(&g_pending_events, PPAUSE, "g_waitidle", hz/5); 84dd84a43cSPoul-Henning Kamp } 85dd84a43cSPoul-Henning Kamp 86dd84a43cSPoul-Henning Kamp void 87d943f1b0SPoul-Henning Kamp g_stall_events(void) 88d943f1b0SPoul-Henning Kamp { 89d943f1b0SPoul-Henning Kamp 90fbf79df3SPoul-Henning Kamp sx_xlock(&g_eventstall); 91d943f1b0SPoul-Henning Kamp } 92d943f1b0SPoul-Henning Kamp 93d943f1b0SPoul-Henning Kamp void 94d943f1b0SPoul-Henning Kamp g_release_events(void) 95d943f1b0SPoul-Henning Kamp { 96d943f1b0SPoul-Henning Kamp 97fbf79df3SPoul-Henning Kamp sx_xunlock(&g_eventstall); 98d943f1b0SPoul-Henning Kamp } 99d943f1b0SPoul-Henning Kamp 100d943f1b0SPoul-Henning Kamp void 101dd84a43cSPoul-Henning Kamp g_orphan_provider(struct g_provider *pp, int error) 102dd84a43cSPoul-Henning Kamp { 103dd84a43cSPoul-Henning Kamp 104dd84a43cSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "g_orphan_provider(%p(%s), %d)", 105dd84a43cSPoul-Henning Kamp pp, pp->name, error); 106dd84a43cSPoul-Henning Kamp KASSERT(error != 0, 107dd84a43cSPoul-Henning Kamp ("g_orphan_provider(%p(%s), 0) error must be non-zero\n", 108dd84a43cSPoul-Henning Kamp pp, pp->name)); 109d0265773SPoul-Henning Kamp 110dd84a43cSPoul-Henning Kamp pp->error = error; 111903e43feSPoul-Henning Kamp mtx_lock(&g_eventlock); 112d0265773SPoul-Henning Kamp KASSERT(!(pp->flags & G_PF_ORPHAN), 113d0265773SPoul-Henning Kamp ("g_orphan_provider(%p(%s)), already an orphan", pp, pp->name)); 114d0265773SPoul-Henning Kamp pp->flags |= G_PF_ORPHAN; 115dd84a43cSPoul-Henning Kamp TAILQ_INSERT_TAIL(&g_doorstep, pp, orphan); 116903e43feSPoul-Henning Kamp mtx_unlock(&g_eventlock); 117dd84a43cSPoul-Henning Kamp wakeup(&g_wait_event); 118dd84a43cSPoul-Henning Kamp } 119dd84a43cSPoul-Henning Kamp 120dd84a43cSPoul-Henning Kamp /* 121dd84a43cSPoul-Henning Kamp * This function is called once on each provider which the event handler 122dd84a43cSPoul-Henning Kamp * finds on its g_doorstep. 123dd84a43cSPoul-Henning Kamp */ 124dd84a43cSPoul-Henning Kamp 125dd84a43cSPoul-Henning Kamp static void 126b1876192SPoul-Henning Kamp g_orphan_register(struct g_provider *pp) 127dd84a43cSPoul-Henning Kamp { 128dd84a43cSPoul-Henning Kamp struct g_consumer *cp, *cp2; 1298592d7a7SPoul-Henning Kamp int wf; 130dd84a43cSPoul-Henning Kamp 131dd84a43cSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "g_orphan_register(%s)", pp->name); 132dd84a43cSPoul-Henning Kamp g_topology_assert(); 133dd84a43cSPoul-Henning Kamp 1348592d7a7SPoul-Henning Kamp wf = pp->flags & G_PF_WITHER; 1358592d7a7SPoul-Henning Kamp pp->flags &= ~G_PF_WITHER; 1368592d7a7SPoul-Henning Kamp 137dd84a43cSPoul-Henning Kamp /* 138dd84a43cSPoul-Henning Kamp * Tell all consumers the bad news. 139f48b8819SPoul-Henning Kamp * Don't be surprised if they self-destruct. 140dd84a43cSPoul-Henning Kamp */ 141dd84a43cSPoul-Henning Kamp cp = LIST_FIRST(&pp->consumers); 142dd84a43cSPoul-Henning Kamp while (cp != NULL) { 143dd84a43cSPoul-Henning Kamp cp2 = LIST_NEXT(cp, consumers); 14407d77fc6SPoul-Henning Kamp KASSERT(cp->geom->orphan != NULL, 14507d77fc6SPoul-Henning Kamp ("geom %s has no orphan, class %s", 14607d77fc6SPoul-Henning Kamp cp->geom->name, cp->geom->class->name)); 14707d77fc6SPoul-Henning Kamp cp->geom->orphan(cp); 148dd84a43cSPoul-Henning Kamp cp = cp2; 149dd84a43cSPoul-Henning Kamp } 1508592d7a7SPoul-Henning Kamp if (LIST_EMPTY(&pp->consumers) && wf) 151b144e6ffSPoul-Henning Kamp g_destroy_provider(pp); 1528592d7a7SPoul-Henning Kamp else 1538592d7a7SPoul-Henning Kamp pp->flags |= wf; 15420d2026bSPoul-Henning Kamp #ifdef notyet 155e5829909SPoul-Henning Kamp cp = LIST_FIRST(&pp->consumers); 156e5829909SPoul-Henning Kamp if (cp != NULL) 157e5829909SPoul-Henning Kamp return; 158e5829909SPoul-Henning Kamp if (pp->geom->flags & G_GEOM_WITHER) 159e5829909SPoul-Henning Kamp g_destroy_provider(pp); 16020d2026bSPoul-Henning Kamp #endif 161dd84a43cSPoul-Henning Kamp } 162dd84a43cSPoul-Henning Kamp 163dd84a43cSPoul-Henning Kamp static int 164b1876192SPoul-Henning Kamp one_event(void) 165dd84a43cSPoul-Henning Kamp { 166dd84a43cSPoul-Henning Kamp struct g_event *ep; 167dd84a43cSPoul-Henning Kamp struct g_provider *pp; 168dd84a43cSPoul-Henning Kamp 169d943f1b0SPoul-Henning Kamp sx_xlock(&g_eventstall); 170dd84a43cSPoul-Henning Kamp g_topology_lock(); 171dd84a43cSPoul-Henning Kamp for (;;) { 172903e43feSPoul-Henning Kamp mtx_lock(&g_eventlock); 173dd84a43cSPoul-Henning Kamp pp = TAILQ_FIRST(&g_doorstep); 174dd84a43cSPoul-Henning Kamp if (pp != NULL) 175dd84a43cSPoul-Henning Kamp TAILQ_REMOVE(&g_doorstep, pp, orphan); 176903e43feSPoul-Henning Kamp mtx_unlock(&g_eventlock); 177dd84a43cSPoul-Henning Kamp if (pp == NULL) 178dd84a43cSPoul-Henning Kamp break; 179b1876192SPoul-Henning Kamp g_orphan_register(pp); 180dd84a43cSPoul-Henning Kamp } 181346cd5feSPoul-Henning Kamp mtx_lock(&g_eventlock); 182dd84a43cSPoul-Henning Kamp ep = TAILQ_FIRST(&g_events); 183dd84a43cSPoul-Henning Kamp if (ep == NULL) { 184346cd5feSPoul-Henning Kamp mtx_unlock(&g_eventlock); 185dd84a43cSPoul-Henning Kamp g_topology_unlock(); 186d943f1b0SPoul-Henning Kamp sx_xunlock(&g_eventstall); 187dd84a43cSPoul-Henning Kamp return (0); 188dd84a43cSPoul-Henning Kamp } 189dd84a43cSPoul-Henning Kamp TAILQ_REMOVE(&g_events, ep, events); 190346cd5feSPoul-Henning Kamp mtx_unlock(&g_eventlock); 191d98777f8SPoul-Henning Kamp g_topology_assert(); 192d98777f8SPoul-Henning Kamp ep->func(ep->arg, 0); 193d98777f8SPoul-Henning Kamp g_topology_assert(); 1940a9c130cSPoul-Henning Kamp if (ep->flag & EV_WAKEUP) { 1950a9c130cSPoul-Henning Kamp ep->flag |= EV_DONE; 1960a9c130cSPoul-Henning Kamp wakeup(ep); 1970a9c130cSPoul-Henning Kamp } else { 1989dfffbc9SPoul-Henning Kamp g_free(ep); 1990a9c130cSPoul-Henning Kamp } 200a9ed5e11SPoul-Henning Kamp g_pending_events--; 201a9ed5e11SPoul-Henning Kamp if (g_pending_events == 0) 202a9ed5e11SPoul-Henning Kamp wakeup(&g_pending_events); 203a9ed5e11SPoul-Henning Kamp g_topology_unlock(); 204d943f1b0SPoul-Henning Kamp sx_xunlock(&g_eventstall); 205dd84a43cSPoul-Henning Kamp return (1); 206dd84a43cSPoul-Henning Kamp } 207dd84a43cSPoul-Henning Kamp 208dd84a43cSPoul-Henning Kamp void 209b1876192SPoul-Henning Kamp g_run_events() 210dd84a43cSPoul-Henning Kamp { 211dd84a43cSPoul-Henning Kamp 212b1876192SPoul-Henning Kamp while (one_event()) 213dd84a43cSPoul-Henning Kamp ; 214dd84a43cSPoul-Henning Kamp } 215dd84a43cSPoul-Henning Kamp 216dd84a43cSPoul-Henning Kamp void 217afcbcfaeSPoul-Henning Kamp g_cancel_event(void *ref) 218dddc28bfSPoul-Henning Kamp { 219dddc28bfSPoul-Henning Kamp struct g_event *ep, *epn; 2202ab31b05SPoul-Henning Kamp struct g_provider *pp; 221afcbcfaeSPoul-Henning Kamp u_int n; 222dddc28bfSPoul-Henning Kamp 223dddc28bfSPoul-Henning Kamp mtx_lock(&g_eventlock); 2242ab31b05SPoul-Henning Kamp TAILQ_FOREACH(pp, &g_doorstep, orphan) { 2252ab31b05SPoul-Henning Kamp if (pp != ref) 2262ab31b05SPoul-Henning Kamp continue; 2272ab31b05SPoul-Henning Kamp TAILQ_REMOVE(&g_doorstep, pp, orphan); 2282ab31b05SPoul-Henning Kamp break; 2292ab31b05SPoul-Henning Kamp } 230afcbcfaeSPoul-Henning Kamp for (ep = TAILQ_FIRST(&g_events); ep != NULL; ep = epn) { 231dddc28bfSPoul-Henning Kamp epn = TAILQ_NEXT(ep, events); 232afcbcfaeSPoul-Henning Kamp for (n = 0; n < G_N_EVENTREFS; n++) { 233afcbcfaeSPoul-Henning Kamp if (ep->ref[n] == NULL) 234afcbcfaeSPoul-Henning Kamp break; 235afcbcfaeSPoul-Henning Kamp if (ep->ref[n] == ref) { 236dddc28bfSPoul-Henning Kamp TAILQ_REMOVE(&g_events, ep, events); 237316aed03SPoul-Henning Kamp ep->func(ep->arg, EV_CANCEL); 2380a9c130cSPoul-Henning Kamp if (ep->flag & EV_WAKEUP) { 2390a9c130cSPoul-Henning Kamp ep->flag |= EV_DONE; 240c8589ad1SPoul-Henning Kamp ep->flag |= EV_CANCELED; 2410a9c130cSPoul-Henning Kamp wakeup(ep); 2420a9c130cSPoul-Henning Kamp } else { 2439dfffbc9SPoul-Henning Kamp g_free(ep); 2440a9c130cSPoul-Henning Kamp } 245afcbcfaeSPoul-Henning Kamp break; 246dddc28bfSPoul-Henning Kamp } 247afcbcfaeSPoul-Henning Kamp } 248dddc28bfSPoul-Henning Kamp } 249dddc28bfSPoul-Henning Kamp mtx_unlock(&g_eventlock); 250dddc28bfSPoul-Henning Kamp } 251dddc28bfSPoul-Henning Kamp 2520a9c130cSPoul-Henning Kamp static int 2530a9c130cSPoul-Henning Kamp g_post_event_x(g_event_t *func, void *arg, int flag, struct g_event **epp, va_list ap) 254346cd5feSPoul-Henning Kamp { 255346cd5feSPoul-Henning Kamp struct g_event *ep; 256afcbcfaeSPoul-Henning Kamp void *p; 257afcbcfaeSPoul-Henning Kamp u_int n; 258346cd5feSPoul-Henning Kamp 259e0d617c1SPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "g_post_event_x(%p, %p, %d)", func, arg, flag); 2608cd1535aSPoul-Henning Kamp ep = g_malloc(sizeof *ep, flag | M_ZERO); 261346cd5feSPoul-Henning Kamp if (ep == NULL) 262346cd5feSPoul-Henning Kamp return (ENOMEM); 2630a9c130cSPoul-Henning Kamp ep->flag = flag; 264afcbcfaeSPoul-Henning Kamp for (n = 0; n < G_N_EVENTREFS; n++) { 265afcbcfaeSPoul-Henning Kamp p = va_arg(ap, void *); 266afcbcfaeSPoul-Henning Kamp if (p == NULL) 267afcbcfaeSPoul-Henning Kamp break; 268afcbcfaeSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, " ref %p", p); 269e0d617c1SPoul-Henning Kamp ep->ref[n] = p; 270afcbcfaeSPoul-Henning Kamp } 271afcbcfaeSPoul-Henning Kamp KASSERT(p == NULL, ("Too many references to event")); 272346cd5feSPoul-Henning Kamp ep->func = func; 273346cd5feSPoul-Henning Kamp ep->arg = arg; 274346cd5feSPoul-Henning Kamp mtx_lock(&g_eventlock); 275346cd5feSPoul-Henning Kamp g_pending_events++; 276346cd5feSPoul-Henning Kamp TAILQ_INSERT_TAIL(&g_events, ep, events); 277346cd5feSPoul-Henning Kamp mtx_unlock(&g_eventlock); 278346cd5feSPoul-Henning Kamp wakeup(&g_wait_event); 2790a9c130cSPoul-Henning Kamp if (epp != NULL) 2800a9c130cSPoul-Henning Kamp *epp = ep; 2810a9c130cSPoul-Henning Kamp return (0); 2820a9c130cSPoul-Henning Kamp } 2830a9c130cSPoul-Henning Kamp 2840a9c130cSPoul-Henning Kamp int 2850a9c130cSPoul-Henning Kamp g_post_event(g_event_t *func, void *arg, int flag, ...) 2860a9c130cSPoul-Henning Kamp { 2870a9c130cSPoul-Henning Kamp va_list ap; 288a1a9b445SPoul-Henning Kamp int i; 2890a9c130cSPoul-Henning Kamp 2900a9c130cSPoul-Henning Kamp KASSERT(flag == M_WAITOK || flag == M_NOWAIT, 2910a9c130cSPoul-Henning Kamp ("Wrong flag to g_post_event")); 292a1a9b445SPoul-Henning Kamp va_start(ap, flag); 293a1a9b445SPoul-Henning Kamp i = g_post_event_x(func, arg, flag, NULL, ap); 294a1a9b445SPoul-Henning Kamp va_end(ap); 295a1a9b445SPoul-Henning Kamp return (i); 2960a9c130cSPoul-Henning Kamp } 2970a9c130cSPoul-Henning Kamp 2980a9c130cSPoul-Henning Kamp 2990a9c130cSPoul-Henning Kamp /* 3000a9c130cSPoul-Henning Kamp * XXX: It might actually be useful to call this function with topology held. 3010a9c130cSPoul-Henning Kamp * XXX: This would ensure that the event gets created before anything else 3020a9c130cSPoul-Henning Kamp * XXX: changes. At present all users have a handle on things in some other 3030a9c130cSPoul-Henning Kamp * XXX: way, so this remains an XXX for now. 3040a9c130cSPoul-Henning Kamp */ 3050a9c130cSPoul-Henning Kamp 3060a9c130cSPoul-Henning Kamp int 3070a9c130cSPoul-Henning Kamp g_waitfor_event(g_event_t *func, void *arg, int flag, ...) 3080a9c130cSPoul-Henning Kamp { 3090a9c130cSPoul-Henning Kamp va_list ap; 3100a9c130cSPoul-Henning Kamp struct g_event *ep; 3110a9c130cSPoul-Henning Kamp int error; 3120a9c130cSPoul-Henning Kamp 3130a9c130cSPoul-Henning Kamp /* g_topology_assert_not(); */ 3140a9c130cSPoul-Henning Kamp KASSERT(flag == M_WAITOK || flag == M_NOWAIT, 3150a9c130cSPoul-Henning Kamp ("Wrong flag to g_post_event")); 316a1a9b445SPoul-Henning Kamp va_start(ap, flag); 3170a9c130cSPoul-Henning Kamp error = g_post_event_x(func, arg, flag | EV_WAKEUP, &ep, ap); 318a1a9b445SPoul-Henning Kamp va_end(ap); 3190a9c130cSPoul-Henning Kamp if (error) 3200a9c130cSPoul-Henning Kamp return (error); 3210a9c130cSPoul-Henning Kamp do 3220a9c130cSPoul-Henning Kamp tsleep(ep, PRIBIO, "g_waitfor_event", hz); 3230a9c130cSPoul-Henning Kamp while (!(ep->flag & EV_DONE)); 324c8589ad1SPoul-Henning Kamp if (ep->flag & EV_CANCELED) 325c8589ad1SPoul-Henning Kamp error = EAGAIN; 3269dfffbc9SPoul-Henning Kamp g_free(ep); 327c8589ad1SPoul-Henning Kamp return (error); 328346cd5feSPoul-Henning Kamp } 329346cd5feSPoul-Henning Kamp 330dd84a43cSPoul-Henning Kamp void 331dd84a43cSPoul-Henning Kamp g_event_init() 332dd84a43cSPoul-Henning Kamp { 333dd84a43cSPoul-Henning Kamp 334903e43feSPoul-Henning Kamp mtx_init(&g_eventlock, "GEOM orphanage", NULL, MTX_DEF); 335d943f1b0SPoul-Henning Kamp sx_init(&g_eventstall, "GEOM event stalling"); 336dd84a43cSPoul-Henning Kamp } 337