git: 380710a5c8c1 - main - geom: create an API to allocate events, and use that storage to send them

Warner Losh imp at FreeBSD.org
Sat Jul 24 00:09:11 UTC 2021


The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=380710a5c8c1fd638ec961351b75b667e91667c9

commit 380710a5c8c1fd638ec961351b75b667e91667c9
Author:     Warner Losh <imp at FreeBSD.org>
AuthorDate: 2021-07-23 21:16:57 +0000
Commit:     Warner Losh <imp at FreeBSD.org>
CommitDate: 2021-07-24 00:08:45 +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
---
 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);
 }
 


More information about the dev-commits-src-all mailing list