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);
 }