diff -ruP geom.orig/geom.h geom/geom.h --- geom.orig/geom.h Mon Dec 8 11:52:22 2003 +++ geom/geom.h Mon Jan 12 10:34:31 2004 @@ -64,6 +64,11 @@ typedef int g_ctl_config_geom_t (struct gctl_req *, struct g_geom *gp, const char *verb); typedef void g_init_t (struct g_class *mp); typedef void g_fini_t (struct g_class *mp); +#define G_TA_TASTE 0x0001 +#define G_TA_RETASTE 0x0002 +#define G_TA_FIRST 0x0004 +#define G_TA_LAST 0x0008 +#define G_TA_ALLMASK 0x000f typedef struct g_geom * g_taste_t (struct g_class *, struct g_provider *, int flags); typedef int g_ioctl_t(struct g_provider *pp, u_long cmd, void *data, struct thread *td); #define G_TF_NORMAL 0 diff -ruP geom.orig/geom_subr.c geom/geom_subr.c --- geom.orig/geom_subr.c Sun Jan 11 15:50:11 2004 +++ geom/geom_subr.c Mon Jan 12 16:46:48 2004 @@ -59,10 +59,14 @@ static int g_valid_obj(void const *ptr); -struct g_hh00 { +struct g_hh00_class { struct g_class *mp; int error; }; +struct g_hh00_provider { + struct g_provider *provider; + int flags; +}; /* * This event offers a new class a chance to taste all preexisting providers. @@ -70,10 +74,11 @@ static void g_load_class(void *arg, int flag) { - struct g_hh00 *hh; + struct g_hh00_class *hh; struct g_class *mp2, *mp; struct g_geom *gp; - struct g_provider *pp; + struct g_provider *pp, *pp2; + int tflags; g_topology_assert(); if (flag == EV_CANCEL) /* XXX: can't happen ? */ @@ -98,22 +103,34 @@ mp->init(mp); if (mp->taste == NULL) return; + pp = NULL; + tflags = G_TA_TASTE | G_TA_FIRST; LIST_FOREACH(mp2, &g_classes, class) { if (mp == mp2) continue; LIST_FOREACH(gp, &mp2->geom, geom) { - LIST_FOREACH(pp, &gp->provider, provider) { - mp->taste(mp, pp, 0); - g_topology_assert(); + LIST_FOREACH(pp2, &gp->provider, provider) { + if (pp != NULL) { + mp->taste(mp, pp, tflags); + g_topology_assert(); + if ((tflags & G_TA_FIRST) != 0) + tflags &= ~G_TA_FIRST; + } + pp = pp2; } } } + if (pp != NULL) { + tflags |= G_TA_LAST; + mp->taste(mp, pp, tflags); + g_topology_assert(); + } } static void g_unload_class(void *arg, int flag) { - struct g_hh00 *hh; + struct g_hh00_class *hh; struct g_class *mp; struct g_geom *gp; struct g_provider *pp; @@ -165,7 +182,7 @@ int g_modevent(module_t mod, int type, void *data) { - struct g_hh00 *hh; + struct g_hh00_class *hh; int error; static int g_ignition; @@ -323,17 +340,28 @@ static void g_new_provider_event(void *arg, int flag) { + struct g_hh00_provider *hh; struct g_class *mp; struct g_provider *pp; struct g_consumer *cp; - int i; + int i, tflags; g_topology_assert(); if (flag == EV_CANCEL) return; if (g_shutdown) return; - pp = arg; + hh = arg; + pp = hh->provider; + tflags = hh->flags; + g_free(hh); + KASSERT((tflags & ~G_TA_ALLMASK) == 0, ("Wrong flags for taste event")); + KASSERT(tflags != 0, ("Wrong flags for taste event")); +/* We need logical XOR operation for a moment. */ +#define LXOR(a, b) (!(a) != !(b)) + KASSERT(LXOR((tflags & G_TA_TASTE) != 0, (tflags & G_TA_RETASTE) != 0), + ("Wrong flags for taste event")); +#undef LXOR LIST_FOREACH(mp, &g_classes, class) { if (mp->taste == NULL) continue; @@ -343,7 +371,7 @@ i = 0; if (!i) continue; - mp->taste(mp, pp, 0); + mp->taste(mp, pp, tflags); g_topology_assert(); /* * XXX: Bandaid for 5.2-RELEASE @@ -360,6 +388,7 @@ struct g_provider * g_new_providerf(struct g_geom *gp, const char *fmt, ...) { + struct g_hh00_provider *hh; struct g_provider *pp; struct sbuf *sb; va_list ap; @@ -380,7 +409,10 @@ pp->stat = devstat_new_entry(pp, -1, 0, DEVSTAT_ALL_SUPPORTED, DEVSTAT_TYPE_DIRECT, DEVSTAT_PRIORITY_MAX); LIST_INSERT_HEAD(&gp->provider, pp, provider); - g_post_event(g_new_provider_event, pp, M_WAITOK, pp, NULL); + hh = g_malloc(sizeof *hh, M_WAITOK | M_ZERO); + hh->provider = pp; + hh->flags = G_TA_TASTE | G_TA_FIRST | G_TA_LAST; + g_post_event(g_new_provider_event, hh, M_WAITOK, hh, NULL); return (pp); } @@ -633,9 +665,15 @@ if (pp->acw == 0 && dcw != 0) g_spoil(pp, cp); else if (pp->acw != 0 && pp->acw == -dcw && - !(pp->geom->flags & G_GEOM_WITHER)) - g_post_event(g_new_provider_event, pp, M_WAITOK, - pp, NULL); + !(pp->geom->flags & G_GEOM_WITHER)) { + struct g_hh00_provider *hh; + + hh = g_malloc(sizeof *hh, M_WAITOK | M_ZERO); + hh->provider = pp; + hh->flags = G_TA_RETASTE | G_TA_FIRST | G_TA_LAST; + g_post_event(g_new_provider_event, hh, M_WAITOK, + hh, NULL); + } pp->acr += dcr; pp->acw += dcw;