git: 419d406e4ee0 - main - geom_vfs: Pre-allocate event for g_vfs_destroy.

John Baldwin jhb at FreeBSD.org
Fri Jul 30 00:09:58 UTC 2021


The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=419d406e4ee068644218fb881bc80f79f8191970

commit 419d406e4ee068644218fb881bc80f79f8191970
Author:     John Baldwin <jhb at FreeBSD.org>
AuthorDate: 2021-07-30 00:09:23 +0000
Commit:     John Baldwin <jhb at FreeBSD.org>
CommitDate: 2021-07-30 00:09:23 +0000

    geom_vfs: Pre-allocate event for g_vfs_destroy.
    
    When an active g_vfs is orphaned due to an underlying disk going away
    the destroy is deferred until the filesystem is unmounted in
    g_vfs_done().  However, g_vfs_done() is invoked from a non-sleepable
    context and cannot use M_WAITOK to allocate the event.  Instead,
    allocate the event in g_vfs_orphan() and save it in the softc to be
    retrieved by the last call to g_vfs_done().
    
    Reported by:    Jithesh Arakkan @ Chelsio
    Reviewed by:    imp
    Sponsored by:   Chelsio Communications
    Differential Revision:  https://reviews.freebsd.org/D31354
---
 sys/geom/geom_vfs.c | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/sys/geom/geom_vfs.c b/sys/geom/geom_vfs.c
index f01765b8ee30..592062b8b12a 100644
--- a/sys/geom/geom_vfs.c
+++ b/sys/geom/geom_vfs.c
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
 struct g_vfs_softc {
 	struct mtx	 sc_mtx;
 	struct bufobj	*sc_bo;
+	struct g_event	*sc_event;
 	int		 sc_active;
 	int		 sc_orphaned;
 	int		 sc_enxio_active;
@@ -96,6 +97,7 @@ static void
 g_vfs_done(struct bio *bip)
 {
 	struct g_consumer *cp;
+	struct g_event *event;
 	struct g_vfs_softc *sc;
 	struct buf *bp;
 	int destroy;
@@ -157,9 +159,14 @@ g_vfs_done(struct bio *bip)
 
 	mtx_lock(&sc->sc_mtx);
 	destroy = ((--sc->sc_active) == 0 && sc->sc_orphaned);
+	if (destroy) {
+		event = sc->sc_event;
+		sc->sc_event = NULL;
+	} else
+		event = NULL;
 	mtx_unlock(&sc->sc_mtx);
 	if (destroy)
-		g_post_event(g_vfs_destroy, cp, M_WAITOK, NULL);
+		g_post_event_ep(g_vfs_destroy, cp, event, NULL);
 
 	bufdone(bp);
 }
@@ -212,6 +219,7 @@ static void
 g_vfs_orphan(struct g_consumer *cp)
 {
 	struct g_geom *gp;
+	struct g_event *event;
 	struct g_vfs_softc *sc;
 	int destroy;
 
@@ -222,12 +230,20 @@ g_vfs_orphan(struct g_consumer *cp)
 	sc = gp->softc;
 	if (sc == NULL)
 		return;
+	event = g_alloc_event(M_WAITOK);
 	mtx_lock(&sc->sc_mtx);
+	KASSERT(sc->sc_event == NULL, ("g_vfs %p already has an event", sc));
 	sc->sc_orphaned = 1;
 	destroy = (sc->sc_active == 0);
+	if (!destroy) {
+		sc->sc_event = event;
+		event = NULL;
+	}
 	mtx_unlock(&sc->sc_mtx);
-	if (destroy)
+	if (destroy) {
+		g_free(event);
 		g_vfs_destroy(cp, 0);
+	}
 
 	/*
 	 * Do not destroy the geom.  Filesystem will do that during unmount.
@@ -297,5 +313,6 @@ g_vfs_close(struct g_consumer *cp)
 	mtx_destroy(&sc->sc_mtx);
 	if (!sc->sc_orphaned || cp->provider == NULL)
 		g_wither_geom_close(gp, ENXIO);
+	KASSERT(sc->sc_event == NULL, ("g_vfs %p event is non-NULL", sc));
 	g_free(sc);
 }


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