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 27 Jun 2004 17:26:54 -0000 @@ -57,11 +57,28 @@ struct class_list_head g_classes = LIST_ static struct g_tailq_head geoms = TAILQ_HEAD_INITIALIZER(geoms); char *g_wait_event, *g_wait_up, *g_wait_down, *g_wait_sim; +static void g_spoil_event(void *arg, int flag); + struct g_hh00 { struct g_class *mp; int error; }; +static void +g_force_spoil(struct g_provider *pp) +{ + struct g_consumer *cp, *cp2; + struct g_geom *gp; + + gp = pp->geom; + LIST_FOREACH_SAFE(cp, &gp->consumer, consumer, cp2) { + if (cp->provider != NULL && cp->spoiled) { + g_cancel_event(&cp->provider->consumers); + g_spoil_event(cp->provider, 0); + } + } +} + /* * This event offers a new class a chance to taste all preexisting providers. */ @@ -71,7 +88,7 @@ g_load_class(void *arg, int flag) struct g_hh00 *hh; struct g_class *mp2, *mp; struct g_geom *gp; - struct g_provider *pp; + struct g_provider *pp, *pp2; g_topology_assert(); if (flag == EV_CANCEL) /* XXX: can't happen ? */ @@ -102,6 +119,14 @@ g_load_class(void *arg, int flag) if (mp == mp2) continue; LIST_FOREACH(gp, &mp2->geom, geom) { + LIST_FOREACH_SAFE(pp, &gp->provider, provider, pp2) { + /* + * If any of consumers, that belong to this geom + * are marked as beeing spoiled, call spoil + * event before we give this provider for taste. + */ + g_force_spoil(pp); + } LIST_FOREACH(pp, &gp->provider, provider) { mp->taste(mp, pp, 0); g_topology_assert(); @@ -289,7 +314,8 @@ g_wither_geom(struct g_geom *gp, int err cp2 = LIST_NEXT(cp, consumer); if (cp->acr || cp->acw || cp->ace) continue; - g_detach(cp); + if (cp->provider != NULL) + g_detach(cp); g_destroy_consumer(cp); } if (LIST_EMPTY(&gp->provider) && LIST_EMPTY(&gp->consumer)) @@ -364,6 +390,13 @@ g_new_provider_event(void *arg, int flag i = 0; if (!i) continue; + /* + * If any of consumers, that belong to this provider's geom + * are marked as beeing spoiled, call spoil event before we + * give this provider for taste. + */ + g_force_spoil(pp); + G_VALID_PROVIDER(pp); mp->taste(mp, pp, 0); g_topology_assert(); } @@ -440,6 +473,7 @@ g_destroy_provider(struct g_provider *pp g_topology_assert(); G_VALID_PROVIDER(pp); + g_trace(G_T_TOPOLOGY, "g_destroy_provider(%p(%s))", pp, pp->name); KASSERT(LIST_EMPTY(&pp->consumers), ("g_destroy_provider but attached")); KASSERT (pp->acr == 0, ("g_destroy_provider with acr")); @@ -797,7 +831,7 @@ g_spoil(struct g_provider *pp, struct g_ KASSERT(cp2->ace == 0, ("spoiling cp->ace = %d", cp2->ace)); cp2->spoiled++; } - g_post_event(g_spoil_event, pp, M_WAITOK, pp, NULL); + g_post_event(g_spoil_event, pp, M_WAITOK, pp, &pp->consumers, NULL); } int