summaryrefslogtreecommitdiffstats
path: root/sys/geom
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2008-03-23 01:31:59 +0000
committermarcel <marcel@FreeBSD.org>2008-03-23 01:31:59 +0000
commitc184f6ced2d94b18defce564aa19ac904e701381 (patch)
tree990452ef2aa40dcdf7acbf8963fada5059b37e6b /sys/geom
parent31a163ef068a0fe80f68c1244f8fada5bed392f9 (diff)
downloadFreeBSD-src-c184f6ced2d94b18defce564aa19ac904e701381.zip
FreeBSD-src-c184f6ced2d94b18defce564aa19ac904e701381.tar.gz
Redefine G_PART_SCHEME_DECLARE() from populating a private linker set
to declaring a proper module. The module event handler is part of the gpart core and will add the scheme to an internal list on module load and will remove the scheme from the internal list on module unload. This makes it possible to dynamically load and unload partitioning schemes.
Diffstat (limited to 'sys/geom')
-rw-r--r--sys/geom/part/g_part.c129
-rw-r--r--sys/geom/part/g_part.h16
-rw-r--r--sys/geom/part/g_part_apm.c2
-rw-r--r--sys/geom/part/g_part_bsd.c2
-rw-r--r--sys/geom/part/g_part_gpt.c2
-rw-r--r--sys/geom/part/g_part_mbr.c2
-rw-r--r--sys/geom/part/g_part_vtoc8.c2
7 files changed, 128 insertions, 27 deletions
diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c
index 2a6c342..0b715ac 100644
--- a/sys/geom/part/g_part.c
+++ b/sys/geom/part/g_part.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/uuid.h>
#include <geom/geom.h>
#include <geom/geom_ctl.h>
+#include <geom/geom_int.h>
#include <geom/part/g_part.h>
#include "g_part_if.h"
@@ -52,13 +53,13 @@ static kobj_method_t g_part_null_methods[] = {
};
static struct g_part_scheme g_part_null_scheme = {
- "n/a",
+ "(none)",
g_part_null_methods,
sizeof(struct g_part_table),
};
-G_PART_SCHEME_DECLARE(g_part_null_scheme);
-SET_DECLARE(g_part_scheme_set, struct g_part_scheme);
+TAILQ_HEAD(, g_part_scheme) g_part_schemes =
+ TAILQ_HEAD_INITIALIZER(g_part_schemes);
struct g_part_alias_list {
const char *lexeme;
@@ -79,6 +80,8 @@ struct g_part_alias_list {
*/
static g_ctl_req_t g_part_ctlreq;
static g_ctl_destroy_geom_t g_part_destroy_geom;
+static g_fini_t g_part_fini;
+static g_init_t g_part_init;
static g_taste_t g_part_taste;
static g_access_t g_part_access;
@@ -93,6 +96,8 @@ static struct g_class g_part_class = {
/* Class methods. */
.ctlreq = g_part_ctlreq,
.destroy_geom = g_part_destroy_geom,
+ .fini = g_part_fini,
+ .init = g_part_init,
.taste = g_part_taste,
/* Geom methods. */
.access = g_part_access,
@@ -317,16 +322,13 @@ g_part_parm_quad(const char *p, quad_t *v)
static int
g_part_parm_scheme(const char *p, struct g_part_scheme **v)
{
- struct g_part_scheme **iter, *s;
+ struct g_part_scheme *s;
- s = NULL;
- SET_FOREACH(iter, g_part_scheme_set) {
- if ((*iter)->name == NULL)
+ TAILQ_FOREACH(s, &g_part_schemes, scheme_list) {
+ if (s == &g_part_null_scheme)
continue;
- if (!strcasecmp((*iter)->name, p)) {
- s = *iter;
+ if (!strcasecmp(s->name, p))
break;
- }
}
if (s == NULL)
return (EINVAL);
@@ -360,33 +362,32 @@ g_part_parm_uint(const char *p, u_int *v)
static int
g_part_probe(struct g_geom *gp, struct g_consumer *cp, int depth)
{
- struct g_part_scheme **iter, *scheme;
+ struct g_part_scheme *iter, *scheme;
struct g_part_table *table;
int pri, probe;
table = gp->softc;
- scheme = (table != NULL) ? table->gpt_scheme : &g_part_null_scheme;
- pri = (scheme != &g_part_null_scheme) ? G_PART_PROBE(table, cp) :
- INT_MIN;
+ scheme = (table != NULL) ? table->gpt_scheme : NULL;
+ pri = (scheme != NULL) ? G_PART_PROBE(table, cp) : INT_MIN;
if (pri == 0)
goto done;
if (pri > 0) { /* error */
- scheme = &g_part_null_scheme;
+ scheme = NULL;
pri = INT_MIN;
}
- SET_FOREACH(iter, g_part_scheme_set) {
- if ((*iter) == &g_part_null_scheme)
+ TAILQ_FOREACH(iter, &g_part_schemes, scheme_list) {
+ if (iter == &g_part_null_scheme)
continue;
- table = (void *)kobj_create((kobj_class_t)(*iter), M_GEOM,
+ table = (void *)kobj_create((kobj_class_t)iter, M_GEOM,
M_WAITOK);
table->gpt_gp = gp;
- table->gpt_scheme = *iter;
+ table->gpt_scheme = iter;
table->gpt_depth = depth;
probe = G_PART_PROBE(table, cp);
if (probe <= 0 && probe > pri) {
pri = probe;
- scheme = *iter;
+ scheme = iter;
if (gp->softc != NULL)
kobj_delete((kobj_t)gp->softc, M_GEOM);
gp->softc = table;
@@ -397,7 +398,7 @@ g_part_probe(struct g_geom *gp, struct g_consumer *cp, int depth)
}
done:
- return ((scheme == &g_part_null_scheme) ? ENXIO : 0);
+ return ((scheme == NULL) ? ENXIO : 0);
}
/*
@@ -1572,3 +1573,89 @@ g_part_start(struct bio *bp)
bp2->bio_done = g_std_done;
g_io_request(bp2, cp);
}
+
+static void
+g_part_init(struct g_class *mp)
+{
+
+ TAILQ_INSERT_TAIL(&g_part_schemes, &g_part_null_scheme, scheme_list);
+}
+
+static void
+g_part_fini(struct g_class *mp)
+{
+
+ TAILQ_REMOVE(&g_part_schemes, &g_part_null_scheme, scheme_list);
+}
+
+static void
+g_part_unload_event(void *arg, int flag)
+{
+ struct g_consumer *cp;
+ struct g_geom *gp;
+ struct g_provider *pp;
+ struct g_part_scheme *scheme;
+ struct g_part_table *table;
+ uintptr_t *xchg;
+ int acc, error;
+
+ if (flag == EV_CANCEL)
+ return;
+
+ xchg = arg;
+ error = 0;
+ scheme = (void *)(*xchg);
+
+ g_topology_assert();
+
+ LIST_FOREACH(gp, &g_part_class.geom, geom) {
+ table = gp->softc;
+ if (table->gpt_scheme != scheme)
+ continue;
+
+ acc = 0;
+ LIST_FOREACH(pp, &gp->provider, provider)
+ acc += pp->acr + pp->acw + pp->ace;
+ LIST_FOREACH(cp, &gp->consumer, consumer)
+ acc += cp->acr + cp->acw + cp->ace;
+
+ if (!acc)
+ g_part_wither(gp, ENOSYS);
+ else
+ error = EBUSY;
+ }
+
+ if (!error)
+ TAILQ_REMOVE(&g_part_schemes, scheme, scheme_list);
+
+ *xchg = error;
+}
+
+int
+g_part_modevent(module_t mod, int type, struct g_part_scheme *scheme)
+{
+ uintptr_t arg;
+ int error;
+
+ switch (type) {
+ case MOD_LOAD:
+ TAILQ_INSERT_TAIL(&g_part_schemes, scheme, scheme_list);
+
+ error = g_retaste(&g_part_class);
+ if (error)
+ TAILQ_REMOVE(&g_part_schemes, scheme, scheme_list);
+ break;
+ case MOD_UNLOAD:
+ arg = (uintptr_t)scheme;
+ error = g_waitfor_event(g_part_unload_event, &arg, M_WAITOK,
+ NULL);
+ if (!error)
+ error = (arg == (uintptr_t)scheme) ? EDOOFUS : arg;
+ break;
+ default:
+ error = EOPNOTSUPP;
+ break;
+ }
+
+ return (error);
+}
diff --git a/sys/geom/part/g_part.h b/sys/geom/part/g_part.h
index 043cafd..1ca18d3 100644
--- a/sys/geom/part/g_part.h
+++ b/sys/geom/part/g_part.h
@@ -56,8 +56,8 @@ struct g_part_scheme {
size_t gps_entrysz;
int gps_minent;
int gps_maxent;
+ TAILQ_ENTRY(g_part_scheme) scheme_list;
};
-#define G_PART_SCHEME_DECLARE(s) DATA_SET(g_part_scheme_set, s)
struct g_part_entry {
LIST_ENTRY(g_part_entry) gpe_entry;
@@ -152,4 +152,18 @@ struct g_part_parms {
void g_part_geometry_heads(off_t, u_int, off_t *, u_int *);
+int g_part_modevent(module_t, int, struct g_part_scheme *);
+
+#define G_PART_SCHEME_DECLARE(name) \
+ static int name##_modevent(module_t mod, int tp, void *d) \
+ { \
+ return (g_part_modevent(mod, tp, d)); \
+ } \
+ static moduledata_t name##_mod = { \
+ #name, \
+ name##_modevent, \
+ &name##_scheme \
+ }; \
+ DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST)
+
#endif /* !_GEOM_PART_H_ */
diff --git a/sys/geom/part/g_part_apm.c b/sys/geom/part/g_part_apm.c
index 12746e3..3b4ec73 100644
--- a/sys/geom/part/g_part_apm.c
+++ b/sys/geom/part/g_part_apm.c
@@ -94,7 +94,7 @@ static struct g_part_scheme g_part_apm_scheme = {
.gps_minent = 16,
.gps_maxent = INT_MAX,
};
-G_PART_SCHEME_DECLARE(g_part_apm_scheme);
+G_PART_SCHEME_DECLARE(g_part_apm);
static int
apm_parse_type(const char *type, char *buf, size_t bufsz)
diff --git a/sys/geom/part/g_part_bsd.c b/sys/geom/part/g_part_bsd.c
index b7018c6..533cd507 100644
--- a/sys/geom/part/g_part_bsd.c
+++ b/sys/geom/part/g_part_bsd.c
@@ -93,7 +93,7 @@ static struct g_part_scheme g_part_bsd_scheme = {
.gps_minent = 8,
.gps_maxent = 20,
};
-G_PART_SCHEME_DECLARE(g_part_bsd_scheme);
+G_PART_SCHEME_DECLARE(g_part_bsd);
static int
bsd_parse_type(const char *type, uint8_t *fstype)
diff --git a/sys/geom/part/g_part_gpt.c b/sys/geom/part/g_part_gpt.c
index 12d28b5..c6cd356 100644
--- a/sys/geom/part/g_part_gpt.c
+++ b/sys/geom/part/g_part_gpt.c
@@ -117,7 +117,7 @@ static struct g_part_scheme g_part_gpt_scheme = {
.gps_minent = 128,
.gps_maxent = INT_MAX,
};
-G_PART_SCHEME_DECLARE(g_part_gpt_scheme);
+G_PART_SCHEME_DECLARE(g_part_gpt);
static struct uuid gpt_uuid_efi = GPT_ENT_TYPE_EFI;
static struct uuid gpt_uuid_freebsd = GPT_ENT_TYPE_FREEBSD;
diff --git a/sys/geom/part/g_part_mbr.c b/sys/geom/part/g_part_mbr.c
index c12bf24..f1800ea 100644
--- a/sys/geom/part/g_part_mbr.c
+++ b/sys/geom/part/g_part_mbr.c
@@ -94,7 +94,7 @@ static struct g_part_scheme g_part_mbr_scheme = {
.gps_minent = NDOSPART,
.gps_maxent = NDOSPART,
};
-G_PART_SCHEME_DECLARE(g_part_mbr_scheme);
+G_PART_SCHEME_DECLARE(g_part_mbr);
static int
mbr_parse_type(const char *type, u_char *dp_typ)
diff --git a/sys/geom/part/g_part_vtoc8.c b/sys/geom/part/g_part_vtoc8.c
index e9412eb..05804c7 100644
--- a/sys/geom/part/g_part_vtoc8.c
+++ b/sys/geom/part/g_part_vtoc8.c
@@ -88,7 +88,7 @@ static struct g_part_scheme g_part_vtoc8_scheme = {
.gps_minent = VTOC8_NPARTS,
.gps_maxent = VTOC8_NPARTS,
};
-G_PART_SCHEME_DECLARE(g_part_vtoc8_scheme);
+G_PART_SCHEME_DECLARE(g_part_vtoc8);
static int
vtoc8_parse_type(const char *type, uint16_t *tag)
OpenPOWER on IntegriCloud