diff --git a/sys/geom/geom.h b/sys/geom/geom.h index cd1691ce7993..55a11722ee3e 100644 --- a/sys/geom/geom.h +++ b/sys/geom/geom.h @@ -220,8 +220,8 @@ void g_trace(int level, const char *, ...); /* geom_event.c */ -typedef void g_call_me_t(void *); -int g_call_me(g_call_me_t *func, void *arg); +typedef void g_call_me_t(void *, int flag); +int g_call_me(g_call_me_t *func, void *arg, ...); void g_orphan_provider(struct g_provider *pp, int error); void g_waitidle(void); diff --git a/sys/geom/geom_bsd.c b/sys/geom/geom_bsd.c index 6e143330baf5..39f422258d2c 100644 --- a/sys/geom/geom_bsd.c +++ b/sys/geom/geom_bsd.c @@ -479,7 +479,7 @@ g_bsd_try(struct g_geom *gp, struct g_slicer *gsp, struct g_consumer *cp, int se */ static void -g_bsd_ioctl(void *arg) +g_bsd_ioctl(void *arg, int flag __unused) { struct bio *bp; struct g_geom *gp; @@ -608,7 +608,7 @@ g_bsd_diocbsdbb(dev_t dev, u_long cmd __unused, caddr_t data, int fflag __unused * footshooting as best we can. */ static void -g_bsd_hotwrite(void *arg) +g_bsd_hotwrite(void *arg, int flag __unused) { struct bio *bp; struct g_geom *gp; @@ -682,7 +682,7 @@ g_bsd_start(struct bio *bp) /* We do not allow deleting our hot spots */ return (EPERM); case BIO_WRITE: - g_call_me(g_bsd_hotwrite, bp); + g_call_me(g_bsd_hotwrite, bp, gp, NULL); return (EJUSTRETURN); case BIO_GETATTR: if (g_handleattr(bp, "BSD::labelsum", ms->labelsum, @@ -723,7 +723,7 @@ g_bsd_start(struct bio *bp) * some I/O requests. Ask the event-handler to schedule * us in a less restricted environment. */ - error = g_call_me(g_bsd_ioctl, bp); + error = g_call_me(g_bsd_ioctl, bp, gp, NULL); if (error) g_io_deliver(bp, error); /* diff --git a/sys/geom/geom_disk.c b/sys/geom/geom_disk.c index 7d5b6772d632..7ffd4640f012 100644 --- a/sys/geom/geom_disk.c +++ b/sys/geom/geom_disk.c @@ -294,7 +294,7 @@ g_disk_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g } static void -g_disk_create(void *arg) +g_disk_create(void *arg, int flag __unused) { struct g_geom *gp; struct g_provider *pp; @@ -335,7 +335,7 @@ disk_create(int unit, struct disk *dp, int flags, void *unused __unused, void * dp->d_devstat = devstat_new_entry(dp->d_name, dp->d_unit, dp->d_sectorsize, DEVSTAT_ALL_SUPPORTED, DEVSTAT_TYPE_DIRECT, DEVSTAT_PRIORITY_MAX); - g_call_me(g_disk_create, dp); + g_call_me(g_disk_create, dp, dp, NULL); } void @@ -351,7 +351,7 @@ disk_destroy(struct disk *dp) } static void -g_kern_disks(void *p) +g_kern_disks(void *p, int flag __unused) { struct sbuf *sb; struct g_geom *gp; @@ -376,7 +376,7 @@ sysctl_disks(SYSCTL_HANDLER_ARGS) sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); sbuf_clear(sb); - error = g_call_me(g_kern_disks, sb); + error = g_call_me(g_kern_disks, sb, NULL); while (!error && !sbuf_done(sb)) { tsleep(sb, PZERO, "kern.disks", hz); } diff --git a/sys/geom/geom_disk.h b/sys/geom/geom_disk.h index 7cd079e0f946..712e8713df61 100644 --- a/sys/geom/geom_disk.h +++ b/sys/geom/geom_disk.h @@ -40,6 +40,8 @@ #ifdef _KERNEL #include +#include +#include typedef int disk_open_t(struct disk *); typedef int disk_close_t(struct disk *); @@ -60,6 +62,8 @@ struct disk { u_int d_flags; const char *d_name; u_int d_unit; + struct bio_queue_head *d_queue; + struct mtx *d_lock; /* Disk methods */ disk_open_t *d_open; diff --git a/sys/geom/geom_dump.c b/sys/geom/geom_dump.c index b1ea85bad5de..1c39fc2ff329 100644 --- a/sys/geom/geom_dump.c +++ b/sys/geom/geom_dump.c @@ -101,7 +101,7 @@ g_confdot_class(struct sbuf *sb, struct g_class *mp) } void -g_confdot(void *p) +g_confdot(void *p, int flag __unused) { struct g_class *mp; struct sbuf *sb; @@ -143,7 +143,7 @@ g_conftxt_class(struct sbuf *sb, struct g_class *mp) } void -g_conftxt(void *p) +g_conftxt(void *p, int flag __unused) { struct g_class *mp; struct sbuf *sb; @@ -263,7 +263,7 @@ g_conf_specific(struct sbuf *sb, struct g_class *mp, struct g_geom *gp, struct g } void -g_confxml(void *p) +g_confxml(void *p, int flag __unused) { g_topology_assert(); diff --git a/sys/geom/geom_event.c b/sys/geom/geom_event.c index 0af148fdccfa..e0e6deb96fd0 100644 --- a/sys/geom/geom_event.c +++ b/sys/geom/geom_event.c @@ -55,6 +55,7 @@ #include #include #include +#include #endif #include #include @@ -158,28 +159,25 @@ g_do_event(struct g_event *ep) struct g_provider *pp; int i; - g_trace(G_T_TOPOLOGY, "g_do_event(%p) %d m:%p g:%p p:%p c:%p - ", - ep, ep->event, ep->class, ep->geom, ep->provider, ep->consumer); + g_trace(G_T_TOPOLOGY, "g_do_event(%p) %d - ", ep, ep->event); g_topology_assert(); switch (ep->event) { case EV_CALL_ME: - ep->func(ep->arg); + ep->func(ep->arg, 0); g_topology_assert(); break; case EV_NEW_CLASS: - mp2 = ep->class; if (g_shutdown) break; + mp2 = ep->ref[0]; if (mp2->taste == NULL) break; - if (g_shutdown) - break; LIST_FOREACH(mp, &g_classes, class) { if (mp2 == mp) continue; LIST_FOREACH(gp, &mp->geom, geom) { LIST_FOREACH(pp, &gp->provider, provider) { - mp2->taste(ep->class, pp, 0); + mp2->taste(mp2, pp, 0); g_topology_assert(); } } @@ -188,28 +186,26 @@ g_do_event(struct g_event *ep) case EV_NEW_PROVIDER: if (g_shutdown) break; - g_trace(G_T_TOPOLOGY, "EV_NEW_PROVIDER(%s)", - ep->provider->name); + pp = ep->ref[0]; + g_trace(G_T_TOPOLOGY, "EV_NEW_PROVIDER(%s)", pp->name); LIST_FOREACH(mp, &g_classes, class) { if (mp->taste == NULL) continue; - if (!strcmp(ep->provider->name, "geom.ctl") && - strcmp(mp->name, "DEV")) - continue; i = 1; - LIST_FOREACH(cp, &ep->provider->consumers, consumers) + LIST_FOREACH(cp, &pp->consumers, consumers) if(cp->geom->class == mp) i = 0; if (i) { - mp->taste(mp, ep->provider, 0); + mp->taste(mp, pp, 0); g_topology_assert(); } } break; case EV_SPOILED: + pp = ep->ref[0]; g_trace(G_T_TOPOLOGY, "EV_SPOILED(%p(%s),%p)", - ep->provider, ep->provider->name, ep->consumer); - cp = LIST_FIRST(&ep->provider->consumers); + pp, pp->name, ep->ref[1]); + cp = LIST_FIRST(&pp->consumers); while (cp != NULL) { cp2 = LIST_NEXT(cp, consumers); if (cp->spoiled) { @@ -257,14 +253,6 @@ one_event(void) } TAILQ_REMOVE(&g_events, ep, events); mtx_unlock(&g_eventlock); - if (ep->class != NULL) - ep->class->event = NULL; - if (ep->geom != NULL) - ep->geom->event = NULL; - if (ep->provider != NULL) - ep->provider->event = NULL; - if (ep->consumer != NULL) - ep->consumer->event = NULL; g_do_event(ep); g_destroy_event(ep); g_pending_events--; @@ -284,39 +272,27 @@ g_run_events() } void -g_post_event(enum g_events ev, struct g_class *mp, struct g_geom *gp, struct g_provider *pp, struct g_consumer *cp) +g_post_event(enum g_events ev, ...) { struct g_event *ep; + va_list ap; + void *p; + int n; - g_trace(G_T_TOPOLOGY, "g_post_event(%d, %p, %p, %p, %p)", - ev, mp, gp, pp, cp); + g_trace(G_T_TOPOLOGY, "g_post_event(%d)", ev); g_topology_assert(); ep = g_malloc(sizeof *ep, M_WAITOK | M_ZERO); ep->event = ev; - if (mp != NULL) { - ep->class = mp; - KASSERT(mp->event == NULL, ("Double event on class %d %d", - ep->event, mp->event->event)); - mp->event = ep; - } - if (gp != NULL) { - ep->geom = gp; - KASSERT(gp->event == NULL, ("Double event on geom %d %d", - ep->event, gp->event->event)); - gp->event = ep; - } - if (pp != NULL) { - ep->provider = pp; - KASSERT(pp->event == NULL, ("Double event on provider %s %d %d", - pp->name, ep->event, pp->event->event)); - pp->event = ep; - } - if (cp != NULL) { - ep->consumer = cp; - KASSERT(cp->event == NULL, ("Double event on consumer %d %d", - ep->event, cp->event->event)); - cp->event = ep; + va_start(ap, ev); + for (n = 0; n < G_N_EVENTREFS; n++) { + p = va_arg(ap, void *); + if (p == NULL) + break; + g_trace(G_T_TOPOLOGY, " ref %p", p); + ep->ref[n++] = p; } + va_end(ap); + KASSERT(p == NULL, ("Too many references to event")); mtx_lock(&g_eventlock); g_pending_events++; TAILQ_INSERT_TAIL(&g_events, ep, events); @@ -325,36 +301,49 @@ g_post_event(enum g_events ev, struct g_class *mp, struct g_geom *gp, struct g_p } void -g_cancel_event(struct g_class *mp, struct g_geom *gp, struct g_provider *pp, struct g_consumer *cp) +g_cancel_event(void *ref) { struct g_event *ep, *epn; + u_int n; mtx_lock(&g_eventlock); - ep = TAILQ_FIRST(&g_events); - for (;ep != NULL;) { + for (ep = TAILQ_FIRST(&g_events); ep != NULL; ep = epn) { epn = TAILQ_NEXT(ep, events); - if ( - (ep->class != NULL && ep->class == mp) || - (ep->geom != NULL && ep->geom == gp) || - (ep->provider != NULL && ep->provider == pp) || - (ep->consumer != NULL && ep->consumer == cp)) { - TAILQ_REMOVE(&g_events, ep, events); - g_free(ep); + for (n = 0; n < G_N_EVENTREFS; n++) { + if (ep->ref[n] == NULL) + break; + if (ep->ref[n] == ref) { + TAILQ_REMOVE(&g_events, ep, events); + g_free(ep); + break; + } } - ep = epn; } mtx_unlock(&g_eventlock); } int -g_call_me(g_call_me_t *func, void *arg) +g_call_me(g_call_me_t *func, void *arg, ...) { struct g_event *ep; + va_list ap; + void *p; + u_int n; g_trace(G_T_TOPOLOGY, "g_call_me(%p, %p", func, arg); ep = g_malloc(sizeof *ep, M_NOWAIT | M_ZERO); if (ep == NULL) return (ENOMEM); + va_start(ap, arg); + for (n = 0; n < G_N_EVENTREFS; n++) { + p = va_arg(ap, void *); + if (p == NULL) + break; + g_trace(G_T_TOPOLOGY, " ref %p", p); + ep->ref[n++] = p; + } + va_end(ap); + KASSERT(p == NULL, ("Too many references to event")); ep->event = EV_CALL_ME; ep->func = func; ep->arg = arg; diff --git a/sys/geom/geom_int.h b/sys/geom/geom_int.h index f709d736f3d9..aa8877d2f3cd 100644 --- a/sys/geom/geom_int.h +++ b/sys/geom/geom_int.h @@ -66,15 +66,14 @@ enum g_events { EV_LAST }; +#define G_N_EVENTREFS 20 + struct g_event { enum g_events event; TAILQ_ENTRY(g_event) events; - struct g_class *class; - struct g_geom *geom; - struct g_provider *provider; - struct g_consumer *consumer; void *arg; g_call_me_t *func; + void *ref[G_N_EVENTREFS]; }; /* @@ -86,15 +85,15 @@ struct g_event { #define GEOM_MINOR_PROVIDERS 10 /* geom_dump.c */ -void g_confxml(void *); +void g_confxml(void *, int flag); void g_conf_specific(struct sbuf *sb, struct g_class *mp, struct g_geom *gp, struct g_provider *pp, struct g_consumer *cp); -void g_confdot(void *); -void g_conftxt(void *); +void g_confdot(void *, int flag); +void g_conftxt(void *, int flag); /* geom_event.c */ void g_event_init(void); -void g_post_event(enum g_events ev, struct g_class *mp, struct g_geom *gp, struct g_provider *pp, struct g_consumer *cp); -void g_cancel_event(struct g_class *mp, struct g_geom *gp, struct g_provider *pp, struct g_consumer *cp); +void g_post_event(enum g_events ev, ...); +void g_cancel_event(void *ref); void g_run_events(void); void g_stall_events(void); void g_release_events(void); diff --git a/sys/geom/geom_kern.c b/sys/geom/geom_kern.c index 227c6d0ce2a6..0c2029dee4e5 100644 --- a/sys/geom/geom_kern.c +++ b/sys/geom/geom_kern.c @@ -161,7 +161,7 @@ sysctl_kern_geom_conftxt(SYSCTL_HANDLER_ARGS) sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); sbuf_clear(sb); - g_call_me(g_conftxt, sb); + g_call_me(g_conftxt, sb, NULL); do { tsleep(sb, PZERO, "g_conftxt", hz); } while(!sbuf_done(sb)); @@ -178,7 +178,7 @@ sysctl_kern_geom_confdot(SYSCTL_HANDLER_ARGS) sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); sbuf_clear(sb); - g_call_me(g_confdot, sb); + g_call_me(g_confdot, sb, NULL); do { tsleep(sb, PZERO, "g_confdot", hz); } while(!sbuf_done(sb)); @@ -195,7 +195,7 @@ sysctl_kern_geom_confxml(SYSCTL_HANDLER_ARGS) sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); sbuf_clear(sb); - g_call_me(g_confxml, sb); + g_call_me(g_confxml, sb, NULL); do { tsleep(sb, PZERO, "g_confxml", hz); } while(!sbuf_done(sb)); diff --git a/sys/geom/geom_mbr.c b/sys/geom/geom_mbr.c index b60bc22edbe8..5b249383d9a8 100644 --- a/sys/geom/geom_mbr.c +++ b/sys/geom/geom_mbr.c @@ -173,7 +173,7 @@ g_mbr_modify(struct g_geom *gp, struct g_mbr_softc *ms, u_char *sec0) } static void -g_mbr_ioctl(void *arg) +g_mbr_ioctl(void *arg, int flag __unused) { struct bio *bp; struct g_geom *gp; @@ -249,7 +249,7 @@ g_mbr_start(struct bio *bp) * some I/O requests. Ask the event-handler to schedule * us in a less restricted environment. */ - error = g_call_me(g_mbr_ioctl, bp); + error = g_call_me(g_mbr_ioctl, bp, gp, NULL); if (error) g_io_deliver(bp, error); /* diff --git a/sys/geom/geom_pc98.c b/sys/geom/geom_pc98.c index 443d9236f13b..390ac95941df 100644 --- a/sys/geom/geom_pc98.c +++ b/sys/geom/geom_pc98.c @@ -160,7 +160,7 @@ g_pc98_modify(struct g_geom *gp, struct g_pc98_softc *ms, u_char *sec) } static void -g_pc98_ioctl(void *arg) +g_pc98_ioctl(void *arg, int flag __unused) { struct bio *bp; struct g_geom *gp; @@ -234,7 +234,7 @@ g_pc98_start(struct bio *bp) * some I/O requests. Ask the event-handler to schedule * us in a less restricted environment. */ - error = g_call_me(g_pc98_ioctl, bp); + error = g_call_me(g_pc98_ioctl, bp, gp, NULL); if (error) g_io_deliver(bp, error); /* diff --git a/sys/geom/geom_subr.c b/sys/geom/geom_subr.c index f2c43fea281b..9a54da14775e 100644 --- a/sys/geom/geom_subr.c +++ b/sys/geom/geom_subr.c @@ -83,7 +83,7 @@ g_add_class(struct g_class *mp) LIST_INIT(&mp->geom); LIST_INSERT_HEAD(&g_classes, mp, class); if (g_nproviders > 0) - g_post_event(EV_NEW_CLASS, mp, NULL, NULL, NULL); + g_post_event(EV_NEW_CLASS, mp, NULL); g_topology_unlock(); } @@ -126,7 +126,7 @@ g_destroy_geom(struct g_geom *gp) KASSERT(LIST_EMPTY(&gp->provider), ("g_destroy_geom(%s) with provider(s) [%p]", gp->name, LIST_FIRST(&gp->consumer))); - g_cancel_event(NULL, gp, NULL, NULL); + g_cancel_event(gp); LIST_REMOVE(gp, geom); TAILQ_REMOVE(&geoms, gp, geoms); g_free(gp->name); @@ -163,7 +163,7 @@ g_destroy_consumer(struct g_consumer *cp) KASSERT (cp->acr == 0, ("g_destroy_consumer with acr")); KASSERT (cp->acw == 0, ("g_destroy_consumer with acw")); KASSERT (cp->ace == 0, ("g_destroy_consumer with ace")); - g_cancel_event(NULL, NULL, NULL, cp); + g_cancel_event(cp); LIST_REMOVE(cp, consumer); devstat_remove_entry(cp->stat); g_free(cp); @@ -193,7 +193,7 @@ g_new_providerf(struct g_geom *gp, const char *fmt, ...) DEVSTAT_TYPE_DIRECT, DEVSTAT_PRIORITY_MAX); LIST_INSERT_HEAD(&gp->provider, pp, provider); g_nproviders++; - g_post_event(EV_NEW_PROVIDER, NULL, NULL, pp, NULL); + g_post_event(EV_NEW_PROVIDER, pp, NULL); return (pp); } @@ -218,7 +218,7 @@ g_destroy_provider(struct g_provider *pp) KASSERT (pp->acr == 0, ("g_destroy_provider with acr")); KASSERT (pp->acw == 0, ("g_destroy_provider with acw")); KASSERT (pp->acw == 0, ("g_destroy_provider with ace")); - g_cancel_event(NULL, NULL, pp, NULL); + g_cancel_event(pp); g_nproviders--; LIST_REMOVE(pp, provider); gp = pp->geom; @@ -447,7 +447,7 @@ g_access_rel(struct g_consumer *cp, int dcr, int dcw, int dce) g_spoil(pp, cp); else if (pp->acw != 0 && pp->acw == -dcw && !(pp->geom->flags & G_GEOM_WITHER)) - g_post_event(EV_NEW_PROVIDER, NULL, NULL, pp, NULL); + g_post_event(EV_NEW_PROVIDER, pp, NULL); pp->acr += dcr; pp->acw += dcw; @@ -567,7 +567,7 @@ g_spoil(struct g_provider *pp, struct g_consumer *cp) KASSERT(cp2->ace == 0, ("spoiling cp->ace = %d", cp2->ace)); cp2->spoiled++; } - g_post_event(EV_SPOILED, NULL, NULL, pp, cp); + g_post_event(EV_SPOILED, pp, cp, NULL); } int