summaryrefslogtreecommitdiffstats
path: root/sys/geom
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2013-09-02 10:44:54 +0000
committermav <mav@FreeBSD.org>2013-09-02 10:44:54 +0000
commit8324fc34800d49750576a82222607f14c9136ebc (patch)
tree0ac5a9836067a976daa9efc81a814260de25e465 /sys/geom
parent8159278dbd8e0197c9ca41a8e8a49b78c13ef17f (diff)
downloadFreeBSD-src-8324fc34800d49750576a82222607f14c9136ebc.zip
FreeBSD-src-8324fc34800d49750576a82222607f14c9136ebc.tar.gz
Make ELI destruction (including orphanization) less aggressive, making it
always wait for provider close. Old algorithm was reported to cause NULL dereference panic on attempt to close provider after softc destruction. If not global workaroung in GEOM, that could even cause destruction with requests still in flight.
Diffstat (limited to 'sys/geom')
-rw-r--r--sys/geom/eli/g_eli.c22
1 files changed, 12 insertions, 10 deletions
diff --git a/sys/geom/eli/g_eli.c b/sys/geom/eli/g_eli.c
index 6819fcc..18e3cc4 100644
--- a/sys/geom/eli/g_eli.c
+++ b/sys/geom/eli/g_eli.c
@@ -621,21 +621,19 @@ end:
* to close it when this situation occur.
*/
static void
-g_eli_last_close(struct g_eli_softc *sc)
+g_eli_last_close(void *arg, int flags __unused)
{
struct g_geom *gp;
- struct g_provider *pp;
- char ppname[64];
+ char gpname[64];
int error;
g_topology_assert();
- gp = sc->sc_geom;
- pp = LIST_FIRST(&gp->provider);
- strlcpy(ppname, pp->name, sizeof(ppname));
- error = g_eli_destroy(sc, TRUE);
+ gp = arg;
+ strlcpy(gpname, gp->name, sizeof(gpname));
+ error = g_eli_destroy(gp->softc, TRUE);
KASSERT(error == 0, ("Cannot detach %s on last close (error=%d).",
- ppname, error));
- G_ELI_DEBUG(0, "Detached %s on last close.", ppname);
+ gpname, error));
+ G_ELI_DEBUG(0, "Detached %s on last close.", gpname);
}
int
@@ -665,7 +663,7 @@ g_eli_access(struct g_provider *pp, int dr, int dw, int de)
*/
if ((sc->sc_flags & G_ELI_FLAG_RW_DETACH) ||
(sc->sc_flags & G_ELI_FLAG_WOPEN)) {
- g_eli_last_close(sc);
+ g_post_event(g_eli_last_close, gp, M_WAITOK, NULL);
}
return (0);
}
@@ -916,6 +914,10 @@ g_eli_destroy(struct g_eli_softc *sc, boolean_t force)
if (force) {
G_ELI_DEBUG(1, "Device %s is still open, so it "
"cannot be definitely removed.", pp->name);
+ sc->sc_flags |= G_ELI_FLAG_RW_DETACH;
+ gp->access = g_eli_access;
+ g_wither_provider(pp, ENXIO);
+ return (EBUSY);
} else {
G_ELI_DEBUG(1,
"Device %s is still open (r%dw%de%d).", pp->name,
OpenPOWER on IntegriCloud