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 113416494d7SJustin T. Gibbs struct g_attrchanged_args { 114416494d7SJustin T. Gibbs struct g_provider *pp; 115416494d7SJustin T. Gibbs const char *attr; 116416494d7SJustin T. Gibbs }; 117416494d7SJustin T. Gibbs 118416494d7SJustin T. Gibbs static void 119416494d7SJustin T. Gibbs g_attr_changed_event(void *arg, int flag) 120416494d7SJustin T. Gibbs { 121416494d7SJustin T. Gibbs struct g_attrchanged_args *args; 122416494d7SJustin T. Gibbs struct g_provider *pp; 123416494d7SJustin T. Gibbs struct g_consumer *cp; 124416494d7SJustin T. Gibbs struct g_consumer *next_cp; 125416494d7SJustin T. Gibbs 126416494d7SJustin T. Gibbs args = arg; 127416494d7SJustin T. Gibbs pp = args->pp; 128416494d7SJustin T. Gibbs 129416494d7SJustin T. Gibbs g_topology_assert(); 130416494d7SJustin T. Gibbs if (flag != EV_CANCEL && g_shutdown == 0) { 131416494d7SJustin T. Gibbs 132416494d7SJustin T. Gibbs /* 133416494d7SJustin T. Gibbs * Tell all consumers of the change. 134416494d7SJustin T. Gibbs */ 135416494d7SJustin T. Gibbs LIST_FOREACH_SAFE(cp, &pp->consumers, consumers, next_cp) { 136416494d7SJustin T. Gibbs if (cp->geom->attrchanged != NULL) 137416494d7SJustin T. Gibbs cp->geom->attrchanged(cp, args->attr); 138416494d7SJustin T. Gibbs } 139416494d7SJustin T. Gibbs } 140416494d7SJustin T. Gibbs g_free(args); 141416494d7SJustin T. Gibbs } 142416494d7SJustin T. Gibbs 143416494d7SJustin T. Gibbs int 144416494d7SJustin T. Gibbs g_attr_changed(struct g_provider *pp, const char *attr, int flag) 145416494d7SJustin T. Gibbs { 146416494d7SJustin T. Gibbs struct g_attrchanged_args *args; 147416494d7SJustin T. Gibbs int error; 148416494d7SJustin T. Gibbs 149416494d7SJustin T. Gibbs args = g_malloc(sizeof *args, flag); 150416494d7SJustin T. Gibbs if (args == NULL) 151416494d7SJustin T. Gibbs return (ENOMEM); 152416494d7SJustin T. Gibbs args->pp = pp; 153416494d7SJustin T. Gibbs args->attr = attr; 154416494d7SJustin T. Gibbs error = g_post_event(g_attr_changed_event, args, flag, pp, NULL); 155416494d7SJustin T. Gibbs if (error != 0) 156416494d7SJustin T. Gibbs g_free(args); 157416494d7SJustin T. Gibbs return (error); 158416494d7SJustin T. Gibbs } 159416494d7SJustin T. Gibbs 160b8005b9bSPawel Jakub Dawidek void 161dd84a43cSPoul-Henning Kamp g_orphan_provider(struct g_provider *pp, int error) 162dd84a43cSPoul-Henning Kamp { 163dd84a43cSPoul-Henning Kamp 1643d1d5bc3SPoul-Henning Kamp /* G_VALID_PROVIDER(pp) We likely lack topology lock */ 165dd84a43cSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "g_orphan_provider(%p(%s), %d)", 166dd84a43cSPoul-Henning Kamp pp, pp->name, error); 167dd84a43cSPoul-Henning Kamp KASSERT(error != 0, 168dd84a43cSPoul-Henning Kamp ("g_orphan_provider(%p(%s), 0) error must be non-zero\n", 169dd84a43cSPoul-Henning Kamp pp, pp->name)); 170d0265773SPoul-Henning Kamp 171dd84a43cSPoul-Henning Kamp pp->error = error; 172903e43feSPoul-Henning Kamp mtx_lock(&g_eventlock); 173d0265773SPoul-Henning Kamp KASSERT(!(pp->flags & G_PF_ORPHAN), 174d0265773SPoul-Henning Kamp ("g_orphan_provider(%p(%s)), already an orphan", pp, pp->name)); 175d0265773SPoul-Henning Kamp pp->flags |= G_PF_ORPHAN; 176dd84a43cSPoul-Henning Kamp TAILQ_INSERT_TAIL(&g_doorstep, pp, orphan); 177903e43feSPoul-Henning Kamp mtx_unlock(&g_eventlock); 178dd84a43cSPoul-Henning Kamp wakeup(&g_wait_event); 179dd84a43cSPoul-Henning Kamp } 180dd84a43cSPoul-Henning Kamp 181dd84a43cSPoul-Henning Kamp /* 182dd84a43cSPoul-Henning Kamp * This function is called once on each provider which the event handler 183dd84a43cSPoul-Henning Kamp * finds on its g_doorstep. 184dd84a43cSPoul-Henning Kamp */ 185dd84a43cSPoul-Henning Kamp 186dd84a43cSPoul-Henning Kamp static void 187b1876192SPoul-Henning Kamp g_orphan_register(struct g_provider *pp) 188dd84a43cSPoul-Henning Kamp { 189dd84a43cSPoul-Henning Kamp struct g_consumer *cp, *cp2; 1908592d7a7SPoul-Henning Kamp int wf; 191dd84a43cSPoul-Henning Kamp 192dd84a43cSPoul-Henning Kamp g_topology_assert(); 1933d1d5bc3SPoul-Henning Kamp G_VALID_PROVIDER(pp); 1943d1d5bc3SPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "g_orphan_register(%s)", pp->name); 195dd84a43cSPoul-Henning Kamp 1963ea5d7ecSPawel Jakub Dawidek g_cancel_event(pp); 1973ea5d7ecSPawel Jakub Dawidek 1988592d7a7SPoul-Henning Kamp wf = pp->flags & G_PF_WITHER; 1998592d7a7SPoul-Henning Kamp pp->flags &= ~G_PF_WITHER; 2008592d7a7SPoul-Henning Kamp 201dd84a43cSPoul-Henning Kamp /* 202dd84a43cSPoul-Henning Kamp * Tell all consumers the bad news. 203f48b8819SPoul-Henning Kamp * Don't be surprised if they self-destruct. 204dd84a43cSPoul-Henning Kamp */ 2053631c638SAlexander Motin LIST_FOREACH_SAFE(cp, &pp->consumers, consumers, cp2) { 20607d77fc6SPoul-Henning Kamp KASSERT(cp->geom->orphan != NULL, 20707d77fc6SPoul-Henning Kamp ("geom %s has no orphan, class %s", 20807d77fc6SPoul-Henning Kamp cp->geom->name, cp->geom->class->name)); 2093631c638SAlexander Motin cp->flags |= G_CF_ORPHAN; 21007d77fc6SPoul-Henning Kamp cp->geom->orphan(cp); 211dd84a43cSPoul-Henning Kamp } 2128592d7a7SPoul-Henning Kamp if (LIST_EMPTY(&pp->consumers) && wf) 213b144e6ffSPoul-Henning Kamp g_destroy_provider(pp); 2148592d7a7SPoul-Henning Kamp else 2158592d7a7SPoul-Henning Kamp pp->flags |= wf; 21620d2026bSPoul-Henning Kamp #ifdef notyet 217e5829909SPoul-Henning Kamp cp = LIST_FIRST(&pp->consumers); 218e5829909SPoul-Henning Kamp if (cp != NULL) 219e5829909SPoul-Henning Kamp return; 220e5829909SPoul-Henning Kamp if (pp->geom->flags & G_GEOM_WITHER) 221e5829909SPoul-Henning Kamp g_destroy_provider(pp); 22220d2026bSPoul-Henning Kamp #endif 223dd84a43cSPoul-Henning Kamp } 224dd84a43cSPoul-Henning Kamp 225dd84a43cSPoul-Henning Kamp static int 226b1876192SPoul-Henning Kamp one_event(void) 227dd84a43cSPoul-Henning Kamp { 228dd84a43cSPoul-Henning Kamp struct g_event *ep; 229dd84a43cSPoul-Henning Kamp struct g_provider *pp; 230dd84a43cSPoul-Henning Kamp 231f7842e00SJaakko Heinonen g_topology_assert(); 232903e43feSPoul-Henning Kamp mtx_lock(&g_eventlock); 233d6b910d2SPawel Jakub Dawidek TAILQ_FOREACH(pp, &g_doorstep, orphan) { 234d6b910d2SPawel Jakub Dawidek if (pp->nstart == pp->nend) 235d6b910d2SPawel Jakub Dawidek break; 236d6b910d2SPawel Jakub Dawidek } 2373d1d5bc3SPoul-Henning Kamp if (pp != NULL) { 2383d1d5bc3SPoul-Henning Kamp G_VALID_PROVIDER(pp); 239dd84a43cSPoul-Henning Kamp TAILQ_REMOVE(&g_doorstep, pp, orphan); 240903e43feSPoul-Henning Kamp mtx_unlock(&g_eventlock); 241b1876192SPoul-Henning Kamp g_orphan_register(pp); 242f7842e00SJaakko Heinonen return (1); 243dd84a43cSPoul-Henning Kamp } 244f7842e00SJaakko Heinonen 245dd84a43cSPoul-Henning Kamp ep = TAILQ_FIRST(&g_events); 246dd84a43cSPoul-Henning Kamp if (ep == NULL) { 247e4da09c0SPoul-Henning Kamp wakeup(&g_pending_events); 248dd84a43cSPoul-Henning Kamp return (0); 249dd84a43cSPoul-Henning Kamp } 25059ccfe81SMatt Jacob if (ep->flag & EV_INPROGRESS) { 25159ccfe81SMatt Jacob mtx_unlock(&g_eventlock); 25259ccfe81SMatt Jacob return (1); 25359ccfe81SMatt Jacob } 25459ccfe81SMatt Jacob ep->flag |= EV_INPROGRESS; 255346cd5feSPoul-Henning Kamp mtx_unlock(&g_eventlock); 256d98777f8SPoul-Henning Kamp g_topology_assert(); 257d98777f8SPoul-Henning Kamp ep->func(ep->arg, 0); 258d98777f8SPoul-Henning Kamp g_topology_assert(); 259e4da09c0SPoul-Henning Kamp mtx_lock(&g_eventlock); 260e4da09c0SPoul-Henning Kamp TAILQ_REMOVE(&g_events, ep, events); 26159ccfe81SMatt Jacob ep->flag &= ~EV_INPROGRESS; 2620a9c130cSPoul-Henning Kamp if (ep->flag & EV_WAKEUP) { 2630a9c130cSPoul-Henning Kamp ep->flag |= EV_DONE; 2649d142a6eSJaakko Heinonen mtx_unlock(&g_eventlock); 2650a9c130cSPoul-Henning Kamp wakeup(ep); 2660a9c130cSPoul-Henning Kamp } else { 2679d142a6eSJaakko Heinonen mtx_unlock(&g_eventlock); 2689dfffbc9SPoul-Henning Kamp g_free(ep); 2690a9c130cSPoul-Henning Kamp } 270dd84a43cSPoul-Henning Kamp return (1); 271dd84a43cSPoul-Henning Kamp } 272dd84a43cSPoul-Henning Kamp 273dd84a43cSPoul-Henning Kamp void 274b1876192SPoul-Henning Kamp g_run_events() 275dd84a43cSPoul-Henning Kamp { 2761b464bd8SPoul-Henning Kamp int i; 277dd84a43cSPoul-Henning Kamp 278f7842e00SJaakko Heinonen for (;;) { 279f7842e00SJaakko Heinonen g_topology_lock(); 280b1876192SPoul-Henning Kamp while (one_event()) 281dd84a43cSPoul-Henning Kamp ; 282f7842e00SJaakko Heinonen mtx_assert(&g_eventlock, MA_OWNED); 2831b464bd8SPoul-Henning Kamp i = g_wither_work; 284f7842e00SJaakko Heinonen if (i) { 285f7842e00SJaakko Heinonen mtx_unlock(&g_eventlock); 2861b464bd8SPoul-Henning Kamp while (i) { 2871b464bd8SPoul-Henning Kamp i = g_wither_washer(); 2881b464bd8SPoul-Henning Kamp g_wither_work = i & 1; 2891b464bd8SPoul-Henning Kamp i &= 2; 2901b464bd8SPoul-Henning Kamp } 2911b464bd8SPoul-Henning Kamp g_topology_unlock(); 292f7842e00SJaakko Heinonen } else { 293f7842e00SJaakko Heinonen g_topology_unlock(); 294f7842e00SJaakko Heinonen msleep(&g_wait_event, &g_eventlock, PRIBIO | PDROP, 29520a5d5dcSAlexander Motin "-", TAILQ_EMPTY(&g_doorstep) ? 0 : hz / 10); 296f7842e00SJaakko Heinonen } 297f7842e00SJaakko Heinonen } 298f7842e00SJaakko Heinonen /* NOTREACHED */ 299dd84a43cSPoul-Henning Kamp } 300dd84a43cSPoul-Henning Kamp 301dd84a43cSPoul-Henning Kamp void 302afcbcfaeSPoul-Henning Kamp g_cancel_event(void *ref) 303dddc28bfSPoul-Henning Kamp { 304dddc28bfSPoul-Henning Kamp struct g_event *ep, *epn; 3052ab31b05SPoul-Henning Kamp struct g_provider *pp; 306afcbcfaeSPoul-Henning Kamp u_int n; 307dddc28bfSPoul-Henning Kamp 308dddc28bfSPoul-Henning Kamp mtx_lock(&g_eventlock); 3092ab31b05SPoul-Henning Kamp TAILQ_FOREACH(pp, &g_doorstep, orphan) { 3102ab31b05SPoul-Henning Kamp if (pp != ref) 3112ab31b05SPoul-Henning Kamp continue; 3122ab31b05SPoul-Henning Kamp TAILQ_REMOVE(&g_doorstep, pp, orphan); 3132ab31b05SPoul-Henning Kamp break; 3142ab31b05SPoul-Henning Kamp } 315e4da09c0SPoul-Henning Kamp TAILQ_FOREACH_SAFE(ep, &g_events, events, epn) { 31659ccfe81SMatt Jacob if (ep->flag & EV_INPROGRESS) 31759ccfe81SMatt Jacob continue; 318afcbcfaeSPoul-Henning Kamp for (n = 0; n < G_N_EVENTREFS; n++) { 319afcbcfaeSPoul-Henning Kamp if (ep->ref[n] == NULL) 320afcbcfaeSPoul-Henning Kamp break; 321e4da09c0SPoul-Henning Kamp if (ep->ref[n] != ref) 322e4da09c0SPoul-Henning Kamp continue; 323dddc28bfSPoul-Henning Kamp TAILQ_REMOVE(&g_events, ep, events); 324316aed03SPoul-Henning Kamp ep->func(ep->arg, EV_CANCEL); 325e4da09c0SPoul-Henning Kamp mtx_assert(&g_eventlock, MA_OWNED); 3260a9c130cSPoul-Henning Kamp if (ep->flag & EV_WAKEUP) { 327e4da09c0SPoul-Henning Kamp ep->flag |= (EV_DONE|EV_CANCELED); 3280a9c130cSPoul-Henning Kamp wakeup(ep); 3290a9c130cSPoul-Henning Kamp } else { 3309dfffbc9SPoul-Henning Kamp g_free(ep); 3310a9c130cSPoul-Henning Kamp } 332afcbcfaeSPoul-Henning Kamp break; 333dddc28bfSPoul-Henning Kamp } 334afcbcfaeSPoul-Henning Kamp } 335e4da09c0SPoul-Henning Kamp if (TAILQ_EMPTY(&g_events)) 336e4da09c0SPoul-Henning Kamp wakeup(&g_pending_events); 337dddc28bfSPoul-Henning Kamp mtx_unlock(&g_eventlock); 338dddc28bfSPoul-Henning Kamp } 339dddc28bfSPoul-Henning Kamp 3400a9c130cSPoul-Henning Kamp static int 341793ffa8eSPoul-Henning Kamp g_post_event_x(g_event_t *func, void *arg, int flag, int wuflag, struct g_event **epp, va_list ap) 342346cd5feSPoul-Henning Kamp { 343346cd5feSPoul-Henning Kamp struct g_event *ep; 344afcbcfaeSPoul-Henning Kamp void *p; 345afcbcfaeSPoul-Henning Kamp u_int n; 346346cd5feSPoul-Henning Kamp 347793ffa8eSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, "g_post_event_x(%p, %p, %d, %d)", 348d246aa55SPawel Jakub Dawidek func, arg, flag, wuflag); 349793ffa8eSPoul-Henning Kamp KASSERT(wuflag == 0 || wuflag == EV_WAKEUP, 350793ffa8eSPoul-Henning Kamp ("Wrong wuflag in g_post_event_x(0x%x)", wuflag)); 3518cd1535aSPoul-Henning Kamp ep = g_malloc(sizeof *ep, flag | M_ZERO); 352346cd5feSPoul-Henning Kamp if (ep == NULL) 353346cd5feSPoul-Henning Kamp return (ENOMEM); 354793ffa8eSPoul-Henning Kamp ep->flag = wuflag; 355afcbcfaeSPoul-Henning Kamp for (n = 0; n < G_N_EVENTREFS; n++) { 356afcbcfaeSPoul-Henning Kamp p = va_arg(ap, void *); 357afcbcfaeSPoul-Henning Kamp if (p == NULL) 358afcbcfaeSPoul-Henning Kamp break; 359afcbcfaeSPoul-Henning Kamp g_trace(G_T_TOPOLOGY, " ref %p", p); 360e0d617c1SPoul-Henning Kamp ep->ref[n] = p; 361afcbcfaeSPoul-Henning Kamp } 362afcbcfaeSPoul-Henning Kamp KASSERT(p == NULL, ("Too many references to event")); 363346cd5feSPoul-Henning Kamp ep->func = func; 364346cd5feSPoul-Henning Kamp ep->arg = arg; 365346cd5feSPoul-Henning Kamp mtx_lock(&g_eventlock); 366346cd5feSPoul-Henning Kamp TAILQ_INSERT_TAIL(&g_events, ep, events); 367346cd5feSPoul-Henning Kamp mtx_unlock(&g_eventlock); 368346cd5feSPoul-Henning Kamp wakeup(&g_wait_event); 3690a9c130cSPoul-Henning Kamp if (epp != NULL) 3700a9c130cSPoul-Henning Kamp *epp = ep; 3719197ce2eSPoul-Henning Kamp curthread->td_pflags |= TDP_GEOM; 3720a9c130cSPoul-Henning Kamp return (0); 3730a9c130cSPoul-Henning Kamp } 3740a9c130cSPoul-Henning Kamp 3750a9c130cSPoul-Henning Kamp int 3760a9c130cSPoul-Henning Kamp g_post_event(g_event_t *func, void *arg, int flag, ...) 3770a9c130cSPoul-Henning Kamp { 3780a9c130cSPoul-Henning Kamp va_list ap; 379a1a9b445SPoul-Henning Kamp int i; 3800a9c130cSPoul-Henning Kamp 3810a9c130cSPoul-Henning Kamp KASSERT(flag == M_WAITOK || flag == M_NOWAIT, 3820a9c130cSPoul-Henning Kamp ("Wrong flag to g_post_event")); 383a1a9b445SPoul-Henning Kamp va_start(ap, flag); 384793ffa8eSPoul-Henning Kamp i = g_post_event_x(func, arg, flag, 0, NULL, ap); 385a1a9b445SPoul-Henning Kamp va_end(ap); 386a1a9b445SPoul-Henning Kamp return (i); 3870a9c130cSPoul-Henning Kamp } 3880a9c130cSPoul-Henning Kamp 3891b464bd8SPoul-Henning Kamp void 390f7842e00SJaakko Heinonen g_do_wither() 391f7842e00SJaakko Heinonen { 3921b464bd8SPoul-Henning Kamp 393f7842e00SJaakko Heinonen mtx_lock(&g_eventlock); 3941b464bd8SPoul-Henning Kamp g_wither_work = 1; 395f7842e00SJaakko Heinonen mtx_unlock(&g_eventlock); 3961b464bd8SPoul-Henning Kamp wakeup(&g_wait_event); 3971b464bd8SPoul-Henning Kamp } 3980a9c130cSPoul-Henning Kamp 3990a9c130cSPoul-Henning Kamp /* 4000a9c130cSPoul-Henning Kamp * XXX: It might actually be useful to call this function with topology held. 4010a9c130cSPoul-Henning Kamp * XXX: This would ensure that the event gets created before anything else 4020a9c130cSPoul-Henning Kamp * XXX: changes. At present all users have a handle on things in some other 4030a9c130cSPoul-Henning Kamp * XXX: way, so this remains an XXX for now. 4040a9c130cSPoul-Henning Kamp */ 4050a9c130cSPoul-Henning Kamp 4060a9c130cSPoul-Henning Kamp int 4070a9c130cSPoul-Henning Kamp g_waitfor_event(g_event_t *func, void *arg, int flag, ...) 4080a9c130cSPoul-Henning Kamp { 4090a9c130cSPoul-Henning Kamp va_list ap; 4100a9c130cSPoul-Henning Kamp struct g_event *ep; 4110a9c130cSPoul-Henning Kamp int error; 4120a9c130cSPoul-Henning Kamp 41318e88d82SPawel Jakub Dawidek g_topology_assert_not(); 4140a9c130cSPoul-Henning Kamp KASSERT(flag == M_WAITOK || flag == M_NOWAIT, 4150a9c130cSPoul-Henning Kamp ("Wrong flag to g_post_event")); 416a1a9b445SPoul-Henning Kamp va_start(ap, flag); 417793ffa8eSPoul-Henning Kamp error = g_post_event_x(func, arg, flag, EV_WAKEUP, &ep, ap); 418a1a9b445SPoul-Henning Kamp va_end(ap); 4190a9c130cSPoul-Henning Kamp if (error) 4200a9c130cSPoul-Henning Kamp return (error); 4219d142a6eSJaakko Heinonen 4229d142a6eSJaakko Heinonen mtx_lock(&g_eventlock); 4239d142a6eSJaakko Heinonen while (!(ep->flag & EV_DONE)) 4249d142a6eSJaakko Heinonen msleep(ep, &g_eventlock, PRIBIO, "g_waitfor_event", hz); 425c8589ad1SPoul-Henning Kamp if (ep->flag & EV_CANCELED) 426c8589ad1SPoul-Henning Kamp error = EAGAIN; 4279d142a6eSJaakko Heinonen mtx_unlock(&g_eventlock); 4289d142a6eSJaakko Heinonen 4299dfffbc9SPoul-Henning Kamp g_free(ep); 430c8589ad1SPoul-Henning Kamp return (error); 431346cd5feSPoul-Henning Kamp } 432346cd5feSPoul-Henning Kamp 433dd84a43cSPoul-Henning Kamp void 434dd84a43cSPoul-Henning Kamp g_event_init() 435dd84a43cSPoul-Henning Kamp { 436dd84a43cSPoul-Henning Kamp 437903e43feSPoul-Henning Kamp mtx_init(&g_eventlock, "GEOM orphanage", NULL, MTX_DEF); 438dd84a43cSPoul-Henning Kamp } 439