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.
This commit is contained in:
parent
8a8fcb0089
commit
4ffca444a5
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=177510
@ -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);
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user