Index: geom_int.h =================================================================== RCS file: /private/FreeBSD/src/sys/geom/geom_int.h,v retrieving revision 1.28 diff -u -p -r1.28 geom_int.h --- geom_int.h 8 Jul 2004 16:17:14 -0000 1.28 +++ geom_int.h 29 Jul 2004 11:54:53 -0000 @@ -68,7 +68,6 @@ void g_conftxt(void *, int flag); /* geom_event.c */ void g_event_init(void); void g_run_events(void); -void g_do_wither(void); /* geom_subr.c */ extern struct class_list_head g_classes; Index: geom_event.c =================================================================== RCS file: /private/FreeBSD/src/sys/geom/geom_event.c,v retrieving revision 1.50 diff -u -p -r1.50 geom_event.c --- geom_event.c 8 Jul 2004 16:17:14 -0000 1.50 +++ geom_event.c 29 Jul 2004 12:15:17 -0000 @@ -59,7 +59,6 @@ static struct event_tailq_head g_events static u_int g_pending_events; static TAILQ_HEAD(,g_provider) g_doorstep = TAILQ_HEAD_INITIALIZER(g_doorstep); static struct mtx g_eventlock; -static int g_wither_work; #define G_N_EVENTREFS 20 @@ -195,18 +194,13 @@ one_event(void) void g_run_events() { - int i; - while (one_event()) - ; - g_topology_lock(); - i = g_wither_work; - while (i) { - i = g_wither_washer(); - g_wither_work = i & 1; - i &= 2; - } - g_topology_unlock(); + do { + g_topology_lock(); + while (g_wither_washer()) + ; + g_topology_unlock(); + } while (one_event()); } void @@ -296,13 +290,6 @@ g_post_event(g_event_t *func, void *arg, return (i); } -void -g_do_wither() { - - g_wither_work = 1; - wakeup(&g_wait_event); -} - /* * XXX: It might actually be useful to call this function with topology held. * XXX: This would ensure that the event gets created before anything else Index: geom_subr.c =================================================================== RCS file: /private/FreeBSD/src/sys/geom/geom_subr.c,v retrieving revision 1.78 diff -u -p -r1.78 geom_subr.c --- geom_subr.c 9 Jul 2004 14:06:17 -0000 1.78 +++ geom_subr.c 29 Jul 2004 12:08:56 -0000 @@ -57,6 +57,8 @@ 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 int g_wither_work; + struct g_hh00 { struct g_class *mp; int error; @@ -159,8 +161,11 @@ g_unload_class(void *arg, int flag) if (gp == NULL) break; error = mp->destroy_geom(NULL, mp, gp); + g_topology_assert(); if (error != 0) break; + while (g_wither_washer()) + ; } if (error == 0) { if (mp->fini != NULL) @@ -210,6 +215,14 @@ g_modevent(module_t mod, int type, void return (error); } +static void +g_do_wither(void) +{ + + g_wither_work = 1; + wakeup(&g_wait_event); +} + struct g_geom * g_new_geomf(struct g_class *mp, const char *fmt, ...) { @@ -279,9 +292,7 @@ g_wither_geom(struct g_geom *gp, int err /* * This function is called (repeatedly) until we cant wash away more - * withered bits at present. Return value contains two bits. Bit 0 - * set means "withering stuff we can't wash now", bit 1 means "call - * me again, there may be stuff I didn't get the first time around. + * withered bits at present. If it returns 1, it should be called again. */ int g_wither_washer() @@ -290,10 +301,12 @@ g_wither_washer() struct g_geom *gp, *gp2; struct g_provider *pp, *pp2; struct g_consumer *cp, *cp2; - int result; + int again; - result = 0; g_topology_assert(); + if (!g_wither_work) + return (0); + again = g_wither_work = 0; LIST_FOREACH(mp, &g_classes, class) { LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) { LIST_FOREACH_SAFE(pp, &gp->provider, provider, pp2) { @@ -302,7 +315,7 @@ g_wither_washer() if (LIST_EMPTY(&pp->consumers)) g_destroy_provider(pp); else - result |= 1; + g_wither_work = 1; } if (!(gp->flags & G_GEOM_WITHER)) continue; @@ -310,26 +323,26 @@ g_wither_washer() if (LIST_EMPTY(&pp->consumers)) g_destroy_provider(pp); else - result |= 1; + g_wither_work = 1; } LIST_FOREACH_SAFE(cp, &gp->consumer, consumer, cp2) { if (cp->acr || cp->acw || cp->ace) { - result |= 1; + g_wither_work = 1; continue; } if (cp->provider != NULL) g_detach(cp); g_destroy_consumer(cp); - result |= 2; + again = 1; } if (LIST_EMPTY(&gp->provider) && LIST_EMPTY(&gp->consumer)) g_destroy_geom(gp); else - result |= 1; + g_wither_work = 1; } } - return (result); + return (again); } struct g_consumer *