diff options
author | marcel <marcel@FreeBSD.org> | 2008-03-23 01:23:35 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2008-03-23 01:23:35 +0000 |
commit | 31a163ef068a0fe80f68c1244f8fada5bed392f9 (patch) | |
tree | 2ff31a93e84cc181a680dc031cae27d30b7baf43 /sys | |
parent | 4d5f668fc2cd6a638546067e461737ff770579f2 (diff) | |
download | FreeBSD-src-31a163ef068a0fe80f68c1244f8fada5bed392f9.zip FreeBSD-src-31a163ef068a0fe80f68c1244f8fada5bed392f9.tar.gz |
Add g_retaste(), which given a class will present all non-open providers
to it for tasting. This is useful when the class, through means outside
the scope of GEOM, can claim providers previously unclaimed.
The g_retaste() function posts an event which is handled by the
g_retaste_event().
Event suggested by: phk
Diffstat (limited to 'sys')
-rw-r--r-- | sys/geom/geom.h | 1 | ||||
-rw-r--r-- | sys/geom/geom_subr.c | 60 |
2 files changed, 61 insertions, 0 deletions
diff --git a/sys/geom/geom.h b/sys/geom/geom.h index dea2272..8bf9439 100644 --- a/sys/geom/geom.h +++ b/sys/geom/geom.h @@ -234,6 +234,7 @@ int g_handleattr_str(struct bio *bp, const char *attribute, char *str); struct g_consumer * g_new_consumer(struct g_geom *gp); struct g_geom * g_new_geomf(struct g_class *mp, const char *fmt, ...); struct g_provider * g_new_providerf(struct g_geom *gp, const char *fmt, ...); +int g_retaste(struct g_class *mp); void g_spoil(struct g_provider *pp, struct g_consumer *cp); int g_std_access(struct g_provider *pp, int dr, int dw, int de); void g_std_done(struct bio *bp); diff --git a/sys/geom/geom_subr.c b/sys/geom/geom_subr.c index 1c0b3a4..08f1ce3 100644 --- a/sys/geom/geom_subr.c +++ b/sys/geom/geom_subr.c @@ -249,6 +249,66 @@ g_modevent(module_t mod, int type, void *data) return (error); } +static void +g_retaste_event(void *arg, int flag) +{ + struct g_class *cp, *mp; + struct g_geom *gp; + struct g_hh00 *hh; + struct g_provider *pp; + + g_topology_assert(); + if (flag == EV_CANCEL) /* XXX: can't happen ? */ + return; + if (g_shutdown) + return; + + hh = arg; + mp = hh->mp; + hh->error = 0; + if (hh->post) { + g_free(hh); + hh = NULL; + } + g_trace(G_T_TOPOLOGY, "g_retaste(%s)", mp->name); + + LIST_FOREACH(cp, &g_classes, class) { + LIST_FOREACH(gp, &cp->geom, geom) { + LIST_FOREACH(pp, &gp->provider, provider) { + if (pp->acr || pp->acw || pp->ace) + continue; + mp->taste(mp, pp, 0); + g_topology_assert(); + } + } + } +} + +int +g_retaste(struct g_class *mp) +{ + struct g_hh00 *hh; + int error; + + if (mp->taste == NULL) + return (EINVAL); + + hh = g_malloc(sizeof *hh, M_WAITOK | M_ZERO); + hh->mp = mp; + + if (cold) { + hh->post = 1; + error = g_post_event(g_retaste_event, hh, M_WAITOK, NULL); + } else { + error = g_waitfor_event(g_retaste_event, hh, M_WAITOK, NULL); + if (error == 0) + error = hh->error; + g_free(hh); + } + + return (error); +} + struct g_geom * g_new_geomf(struct g_class *mp, const char *fmt, ...) { |