summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2008-03-23 01:23:35 +0000
committermarcel <marcel@FreeBSD.org>2008-03-23 01:23:35 +0000
commit31a163ef068a0fe80f68c1244f8fada5bed392f9 (patch)
tree2ff31a93e84cc181a680dc031cae27d30b7baf43 /sys
parent4d5f668fc2cd6a638546067e461737ff770579f2 (diff)
downloadFreeBSD-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.h1
-rw-r--r--sys/geom/geom_subr.c60
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, ...)
{
OpenPOWER on IntegriCloud