Date: Sun, 12 Sep 2021 16:35:18 GMT From: Warner Losh <imp@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: 55f527816ddb - stable/13 - geom: create an API to allocate events, and use that storage to send them Message-ID: <202109121635.18CGZIef073939@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=55f527816ddbacb9fcce7b95d5be20fb0617d5c2 commit 55f527816ddbacb9fcce7b95d5be20fb0617d5c2 Author: Warner Losh <imp@FreeBSD.org> AuthorDate: 2021-07-23 21:16:57 +0000 Commit: Warner Losh <imp@FreeBSD.org> CommitDate: 2021-09-12 15:56:13 +0000 geom: create an API to allocate events, and use that storage to send them g_alloc_event will allocate storage for an opaque event. g_post_event_ep can use memory returned by g_alloc_event to send an event from a context that might not be able to allocate the event. Occasionally, we can alloate memory when we create an object, but not while we're destroy it. This allows one to allocate at creation time memory to use when destorying the object. Reviewed by: jhb Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D30544 (cherry picked from commit 380710a5c8c1fd638ec961351b75b667e91667c9) --- share/man/man9/g_event.9 | 32 ++++++++++++++++++++++++++++- sys/geom/geom.h | 3 +++ sys/geom/geom_event.c | 52 +++++++++++++++++++++++++++++++++++++----------- 3 files changed, 74 insertions(+), 13 deletions(-) diff --git a/share/man/man9/g_event.9 b/share/man/man9/g_event.9 index 0bdd0ab6688b..32c4703100d8 100644 --- 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 @@ function. 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 @@ The 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 index cb294e2c7451..1aba1f46d6d5 100644 --- a/sys/geom/geom.h +++ b/sys/geom/geom.h @@ -260,6 +260,7 @@ extern int g_debugflags; /* 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_changed(struct g_provider *pp, int flag); 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 index b829d2ef637c..f9a1d445d36a 100644 --- a/sys/geom/geom_event.c +++ b/sys/geom/geom_event.c @@ -341,20 +341,22 @@ g_cancel_event(void *ref) 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 @@ g_post_event_x(g_event_t *func, void *arg, int flag, int wuflag, struct g_event 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); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202109121635.18CGZIef073939>