diff --git a/share/man/man9/g_event.9 b/share/man/man9/g_event.9 --- a/share/man/man9/g_event.9 +++ b/share/man/man9/g_event.9 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 16, 2004 +.Dd July 23, 2021 .Dt G_EVENT 9 .Os .Sh NAME @@ -40,6 +40,10 @@ .Fn g_waitfor_event "g_event_t *func" "void *arg" "int flag" ... .Ft void .Fn g_cancel_event "void *ref" +.Ft "struct g_event *" +.Fn g_alloc_event "int flag" +.Ft void +.Fn g_post_event_ep "g_event_t *func" "void *arg" "struct g_event *ep" ... .Sh DESCRIPTION The GEOM framework has its own event queue to inform classes about important events. @@ -80,6 +84,13 @@ It waits until the event is finished or canceled and then returns. .Pp The +.Fn g_post_event_ep +function posts the event with a pre-allocated +.Va struct g_event . +An event may be pre-allocated with +.Fn g_alloc_event . +.Pp +The .Fn g_cancel_event function cancels all event(s) identified by .Fa ref . @@ -123,6 +134,25 @@ function cannot be called from an event, since doing so would result in a deadlock. .El +.Pp +.Fn g_alloc_event : +.Bl -item -offset indent +.It +The argument +.Fa flag +has to be +.Dv M_WAITOK +or +.Dv M_NOWAIT . +.It +The returned +.Va struct g_event * +must be freed with +.Fn g_free +if +.Fn g_post_event_ep +is not called. +.El .Sh RETURN VALUES The .Fn g_post_event diff --git a/sys/geom/geom.h b/sys/geom/geom.h --- a/sys/geom/geom.h +++ b/sys/geom/geom.h @@ -260,6 +260,7 @@ /* geom_event.c */ typedef void g_event_t(void *, int flag); +struct g_event; #define EV_CANCEL 1 int g_post_event(g_event_t *func, void *arg, int flag, ...); int g_waitfor_event(g_event_t *func, void *arg, int flag, ...); @@ -269,6 +270,8 @@ int g_media_gone(struct g_provider *pp, int flag); void g_orphan_provider(struct g_provider *pp, int error); void g_waitidlelock(void); +struct g_event *g_alloc_event(int flag); +void g_post_event_ep(g_event_t *func, void *arg, struct g_event *ep, ...); /* geom_subr.c */ int g_access(struct g_consumer *cp, int nread, int nwrite, int nexcl); diff --git a/sys/geom/geom_event.c b/sys/geom/geom_event.c --- a/sys/geom/geom_event.c +++ b/sys/geom/geom_event.c @@ -341,20 +341,22 @@ 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) +struct g_event * +g_alloc_event(int flag) +{ + 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_ep_va(g_event_t *func, void *arg, int wuflag, + struct g_event *ep, va_list ap) { - struct g_event *ep; 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 +373,38 @@ 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_ep(g_event_t *func, void *arg, struct g_event *ep, ...) +{ + va_list ap; + + va_start(ap, ep); + g_post_event_ep_va(func, arg, 0, ep, 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_ep_va(func, arg, wuflag, ep, ap); return (0); }