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