Index: geom_subr.c =================================================================== RCS file: /private/FreeBSD/src/sys/geom/geom_subr.c,v retrieving revision 1.75 diff -u -p -r1.75 geom_subr.c --- geom_subr.c 18 Mar 2004 07:17:10 -0000 1.75 +++ geom_subr.c 19 May 2004 16:08:44 -0000 @@ -110,19 +110,15 @@ g_load_class(void *arg, int flag) } } -static void -g_unload_class(void *arg, int flag) +static int +g_unload_class(struct g_class *mp) { - struct g_hh00 *hh; - struct g_class *mp; struct g_geom *gp; struct g_provider *pp; struct g_consumer *cp; int error; g_topology_assert(); - hh = arg; - mp = hh->mp; G_VALID_CLASS(mp); g_trace(G_T_TOPOLOGY, "g_unload_class(%s)", mp->name); @@ -130,23 +126,19 @@ g_unload_class(void *arg, int flag) * We allow unloading if we have no geoms, or a class * method we can use to get rid of them. */ - if (!LIST_EMPTY(&mp->geom) && mp->destroy_geom == NULL) { - hh->error = EOPNOTSUPP; - return; - } + if (!LIST_EMPTY(&mp->geom) && mp->destroy_geom == NULL) + return (EOPNOTSUPP); /* We refuse to unload if anything is open */ LIST_FOREACH(gp, &mp->geom, geom) { - LIST_FOREACH(pp, &gp->provider, provider) - if (pp->acr || pp->acw || pp->ace) { - hh->error = EBUSY; - return; - } - LIST_FOREACH(cp, &gp->consumer, consumer) - if (cp->acr || cp->acw || cp->ace) { - hh->error = EBUSY; - return; - } + LIST_FOREACH(pp, &gp->provider, provider) { + if (pp->acr || pp->acw || pp->ace) + return (EBUSY); + } + LIST_FOREACH(cp, &gp->consumer, consumer) { + if (cp->acr || cp->acw || cp->ace) + return (EBUSY); + } } /* Bar new entries */ @@ -161,52 +153,56 @@ g_unload_class(void *arg, int flag) error = mp->destroy_geom(NULL, mp, gp); if (error != 0) break; + g_topology_unlock(); + g_waitidle(); + g_topology_lock(); } if (error == 0) { if (mp->fini != NULL) mp->fini(mp); LIST_REMOVE(mp, class); } - hh->error = error; - return; + return (error); } int g_modevent(module_t mod, int type, void *data) { + struct g_class *mp; struct g_hh00 *hh; int error; static int g_ignition; + DROP_GIANT(); if (!g_ignition) { g_ignition++; g_init(); } - hh = g_malloc(sizeof *hh, M_WAITOK | M_ZERO); - hh->mp = data; error = EOPNOTSUPP; + mp = data; switch (type) { case MOD_LOAD: - g_trace(G_T_TOPOLOGY, "g_modevent(%s, LOAD)", hh->mp->name); + g_trace(G_T_TOPOLOGY, "g_modevent(%s, LOAD)", mp->name); + hh = g_malloc(sizeof *hh, M_WAITOK | M_ZERO); + hh->mp = mp; g_post_event(g_load_class, hh, M_WAITOK, NULL); error = 0; break; case MOD_UNLOAD: - g_trace(G_T_TOPOLOGY, "g_modevent(%s, UNLOAD)", hh->mp->name); - error = g_waitfor_event(g_unload_class, hh, M_WAITOK, NULL); - if (error == 0) - error = hh->error; + g_trace(G_T_TOPOLOGY, "g_modevent(%s, UNLOAD)", mp->name); + g_topology_lock(); + error = g_unload_class(data); + g_topology_unlock(); if (error == 0) { g_waitidle(); - KASSERT(LIST_EMPTY(&hh->mp->geom), - ("Unloaded class (%s) still has geom", hh->mp->name)); + KASSERT(LIST_EMPTY(&mp->geom), + ("Unloaded class (%s) still has geom", mp->name)); } - g_free(hh); break; default: - g_free(hh); break; } + PICKUP_GIANT(); return (error); }