Index: sys/geom/geom.h =================================================================== --- sys/geom/geom.h +++ sys/geom/geom.h @@ -269,6 +269,9 @@ int g_media_gone(struct g_provider *pp, int flag); void g_orphan_provider(struct g_provider *pp, int error); void g_waitidlelock(void); +void *g_alloc_event(int flag); +void g_post_event_storage(g_event_t *func, void *arg, int wuflag, + void *ep, ...); /* geom_subr.c */ int g_access(struct g_consumer *cp, int nread, int nwrite, int nexcl); Index: sys/geom/geom_disk.h =================================================================== --- sys/geom/geom_disk.h +++ sys/geom/geom_disk.h @@ -125,6 +125,7 @@ /* Fields private to geom_disk, to be moved on next version bump */ LIST_HEAD(,disk_alias) d_aliases; + void *d_event; }; #define DISKFLAG_RESERVED 0x0001 /* Was NEEDSGIANT */ Index: sys/geom/geom_disk.c =================================================================== --- sys/geom/geom_disk.c +++ sys/geom/geom_disk.c @@ -885,6 +885,7 @@ dp->d_sectorsize, DEVSTAT_ALL_SUPPORTED, DEVSTAT_TYPE_DIRECT, DEVSTAT_PRIORITY_MAX); dp->d_geom = NULL; + dp->d_event = g_alloc_event(M_WAITOK); dp->d_init_level = DISK_INIT_NONE; @@ -901,7 +902,7 @@ g_cancel_event(dp); if (dp->d_devstat != NULL) devstat_remove_entry(dp->d_devstat); - g_post_event(g_disk_destroy, dp, M_WAITOK, NULL); + g_post_event_storage(g_disk_destroy, dp, 0, dp->d_event, NULL); } void Index: sys/geom/geom_event.c =================================================================== --- sys/geom/geom_event.c +++ sys/geom/geom_event.c @@ -341,20 +341,23 @@ mtx_unlock(&g_eventlock); } -static int -g_post_event_x(g_event_t *func, void *arg, int flag, int wuflag, struct g_event **epp, va_list ap) +void * +g_alloc_event(int flag) { - struct g_event *ep; + KASSERT(flag == M_WAITOK || flag == M_NOWAIT, + ("Wrong flag to g_alloc_event")); + + return (g_malloc(sizeof(struct g_event), flag | M_ZERO)); +} + +static void +g_post_event_storage_va(g_event_t *func, void *arg, int wuflag, + void *xep, va_list ap) +{ + struct g_event *ep = xep; void *p; u_int n; - g_trace(G_T_TOPOLOGY, "g_post_event_x(%p, %p, %d, %d)", - func, arg, flag, wuflag); - KASSERT(wuflag == 0 || wuflag == EV_WAKEUP, - ("Wrong wuflag in g_post_event_x(0x%x)", wuflag)); - ep = g_malloc(sizeof *ep, flag | M_ZERO); - if (ep == NULL) - return (ENOMEM); ep->flag = wuflag; for (n = 0; n < G_N_EVENTREFS; n++) { p = va_arg(ap, void *); @@ -371,12 +374,39 @@ TAILQ_INSERT_TAIL(&g_events, ep, events); mtx_unlock(&g_eventlock); wakeup(&g_wait_event); - if (epp != NULL) - *epp = ep; curthread->td_pflags |= TDP_GEOM; thread_lock(curthread); curthread->td_flags |= TDF_ASTPENDING; thread_unlock(curthread); +} + +void +g_post_event_storage(g_event_t *func, void *arg, int wuflag, + void *xep, ...) +{ + va_list ap; + + va_start(ap, xep); + g_post_event_storage_va(func, arg, wuflag, xep, ap); + va_end(ap); +} + + +static int +g_post_event_x(g_event_t *func, void *arg, int flag, int wuflag, struct g_event **epp, va_list ap) +{ + struct g_event *ep; + + g_trace(G_T_TOPOLOGY, "g_post_event_x(%p, %p, %d, %d)", + func, arg, flag, wuflag); + KASSERT(wuflag == 0 || wuflag == EV_WAKEUP, + ("Wrong wuflag in g_post_event_x(0x%x)", wuflag)); + ep = g_alloc_event(flag); + if (ep == NULL) + return (ENOMEM); + if (epp != NULL) + *epp = ep; + g_post_event_storage(func, arg, wuflag, ep, ap); return (0); }