o Slightly refactor the ctlreq code to maximize code sharing between
verbs. Only the create verb operates on a provider. All other verbs operate on a GPT geom. Also, the GPT entry oriented verbs require a non-downgraded GPT. o Have all verbs take an optional flags parameter. The flags parameter is a string of single-letter flags. The typical use of these flags is to enable certain behaviour in support fo the gpt(8) tool. o Add dummy implementations for the destroy and recover verbs. This change causes test 2 of the GPT regression test suite to fail. The presence of a geom parameter is now required even for unknown verbs.
This commit is contained in:
parent
86a8393963
commit
ceba44f8d4
@ -120,8 +120,8 @@ static struct uuid g_gpt_unused = GPT_ENT_TYPE_UNUSED;
|
||||
static void g_gpt_wither(struct g_geom *, int);
|
||||
|
||||
static struct g_provider *
|
||||
g_gpt_ctl_add(struct gctl_req *req, struct g_geom *gp, struct uuid *type,
|
||||
uint64_t start, uint64_t end)
|
||||
g_gpt_ctl_add(struct gctl_req *req, const char *flags, struct g_geom *gp,
|
||||
struct uuid *type, uint64_t start, uint64_t end)
|
||||
{
|
||||
struct g_provider *pp;
|
||||
struct g_gpt_softc *softc;
|
||||
@ -184,7 +184,7 @@ g_gpt_ctl_add(struct gctl_req *req, struct g_geom *gp, struct uuid *type,
|
||||
}
|
||||
|
||||
static struct g_geom *
|
||||
g_gpt_ctl_create(struct gctl_req *req, struct g_class *mp,
|
||||
g_gpt_ctl_create(struct gctl_req *req, const char *flags, struct g_class *mp,
|
||||
struct g_provider *pp, uint32_t entries)
|
||||
{
|
||||
struct uuid uuid;
|
||||
@ -281,6 +281,16 @@ g_gpt_ctl_create(struct gctl_req *req, struct g_class *mp,
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
g_gpt_ctl_destroy(struct gctl_req *req, const char *flags, struct g_geom *gp)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
g_gpt_ctl_recover(struct gctl_req *req, const char *flags, struct g_geom *gp)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
g_gpt_has_pmbr(struct g_consumer *cp, int *error)
|
||||
{
|
||||
@ -559,6 +569,7 @@ g_gpt_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
|
||||
struct g_geom *gp;
|
||||
struct g_provider *pp;
|
||||
struct g_gpt_softc *softc;
|
||||
const char *flags;
|
||||
char const *s;
|
||||
uint64_t start, end;
|
||||
long entries;
|
||||
@ -567,37 +578,122 @@ g_gpt_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
|
||||
G_GPT_TRACE((G_T_TOPOLOGY, "%s(%s,%s)", __func__, mp->name, verb));
|
||||
g_topology_assert();
|
||||
|
||||
/*
|
||||
* All verbs take an optional flags parameter. The flags parameter
|
||||
* is a string with each letter an independent flag. Each verb has
|
||||
* it's own set of valid flags and the meaning of the flags is
|
||||
* specific to the verb. Typically the presence of a letter (=flag)
|
||||
* in the string means true and the absence means false.
|
||||
*/
|
||||
s = gctl_get_asciiparam(req, "flags");
|
||||
flags = (s == NULL) ? "" : s;
|
||||
|
||||
/*
|
||||
* Only the create verb takes a provider parameter. Make this a
|
||||
* special case so that more code sharing is possible for the
|
||||
* common case.
|
||||
*/
|
||||
if (!strcmp(verb, "create")) {
|
||||
/*
|
||||
* Create a GPT on a pristine disk-like provider.
|
||||
* Required parameters/attributes:
|
||||
* provider
|
||||
* Optional parameters/attributes:
|
||||
* entries
|
||||
*/
|
||||
s = gctl_get_asciiparam(req, "provider");
|
||||
if (s == NULL) {
|
||||
gctl_error(req, "%d provider", ENOATTR);
|
||||
return;
|
||||
}
|
||||
pp = g_provider_by_name(s);
|
||||
if (pp == NULL) {
|
||||
gctl_error(req, "%d provider '%s'", EINVAL, s);
|
||||
return;
|
||||
}
|
||||
/* Check that there isn't already a GPT on the provider. */
|
||||
LIST_FOREACH(gp, &mp->geom, geom) {
|
||||
if (!strcmp(s, gp->name)) {
|
||||
gctl_error(req, "%d geom '%s'", EEXIST, s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
s = gctl_get_asciiparam(req, "entries");
|
||||
if (s != NULL) {
|
||||
entries = strtol(s, (char **)(uintptr_t)&s, 0);
|
||||
if (entries < 128 || *s != '\0') {
|
||||
gctl_error(req, "%d entries %ld", EINVAL,
|
||||
entries);
|
||||
return;
|
||||
}
|
||||
} else
|
||||
entries = 128; /* Documented mininum */
|
||||
gp = g_gpt_ctl_create(req, flags, mp, pp, entries);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* All but the create verb, which is handled above, operate on an
|
||||
* existing GPT geom. The geom parameter is non-optional, so get
|
||||
* it here first.
|
||||
*/
|
||||
s = gctl_get_asciiparam(req, "geom");
|
||||
if (s == NULL) {
|
||||
gctl_error(req, "%d geom", ENOATTR);
|
||||
return;
|
||||
}
|
||||
/* Get the GPT geom with the given name. */
|
||||
LIST_FOREACH(gp, &mp->geom, geom) {
|
||||
if (!strcmp(s, gp->name))
|
||||
break;
|
||||
}
|
||||
if (gp == NULL) {
|
||||
gctl_error(req, "%d geom '%s'", EINVAL, s);
|
||||
return;
|
||||
}
|
||||
softc = gp->softc;
|
||||
|
||||
/*
|
||||
* Now handle the verbs that can operate on a downgraded or
|
||||
* partially corrupted GPT. In particular these are the verbs
|
||||
* that don't deal with the table entries. We implement the
|
||||
* policy that all table entry related requests require a
|
||||
* valid GPT.
|
||||
*/
|
||||
if (!strcmp(verb, "destroy")) {
|
||||
/*
|
||||
* Destroy a GPT completely.
|
||||
*/
|
||||
g_gpt_ctl_destroy(req, flags, gp);
|
||||
return;
|
||||
} else if (!strcmp(verb, "recover")) {
|
||||
/*
|
||||
* Recover a downgraded GPT.
|
||||
*/
|
||||
g_gpt_ctl_recover(req, flags, gp);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that the GPT is complete and valid before we make changes
|
||||
* to the table entries.
|
||||
*/
|
||||
if (softc->state[GPT_HDR_PRIMARY] != GPT_HDR_OK ||
|
||||
softc->state[GPT_HDR_SECONDARY] != GPT_HDR_OK) {
|
||||
gctl_error(req, "%d geom '%s'", ENXIO, s);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(verb, "add")) {
|
||||
/*
|
||||
* Add a partition entry to a GPT.
|
||||
* Required parameters/attributes:
|
||||
* geom
|
||||
* type
|
||||
* start
|
||||
* end
|
||||
* Optional parameters/attributes:
|
||||
* label
|
||||
*/
|
||||
s = gctl_get_asciiparam(req, "geom");
|
||||
if (s == NULL) {
|
||||
gctl_error(req, "%d geom", ENOATTR);
|
||||
return;
|
||||
}
|
||||
/* Get the GPT geom with the given name. */
|
||||
LIST_FOREACH(gp, &mp->geom, geom) {
|
||||
if (!strcmp(s, gp->name))
|
||||
break;
|
||||
}
|
||||
if (gp == NULL) {
|
||||
gctl_error(req, "%d geom '%s'", EINVAL, s);
|
||||
return;
|
||||
}
|
||||
softc = gp->softc;
|
||||
if (softc->state[GPT_HDR_PRIMARY] != GPT_HDR_OK ||
|
||||
softc->state[GPT_HDR_SECONDARY] != GPT_HDR_OK) {
|
||||
gctl_error(req, "%d geom '%s'", ENXIO, s);
|
||||
return;
|
||||
}
|
||||
s = gctl_get_asciiparam(req, "type");
|
||||
if (s == NULL) {
|
||||
gctl_error(req, "%d type", ENOATTR);
|
||||
@ -634,53 +730,17 @@ g_gpt_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
|
||||
(intmax_t)end);
|
||||
return;
|
||||
}
|
||||
pp = g_gpt_ctl_add(req, gp, &type, start, end);
|
||||
} else if (!strcmp(verb, "create")) {
|
||||
/*
|
||||
* Create a GPT on a pristine disk-like provider.
|
||||
* Required parameters/attributes:
|
||||
* provider
|
||||
* Optional parameters/attributes:
|
||||
* entries
|
||||
*/
|
||||
s = gctl_get_asciiparam(req, "provider");
|
||||
if (s == NULL) {
|
||||
gctl_error(req, "%d provider", ENOATTR);
|
||||
return;
|
||||
}
|
||||
pp = g_provider_by_name(s);
|
||||
if (pp == NULL) {
|
||||
gctl_error(req, "%d provider '%s'", EINVAL, s);
|
||||
return;
|
||||
}
|
||||
/* Check that there isn't already a GPT on the provider. */
|
||||
LIST_FOREACH(gp, &mp->geom, geom) {
|
||||
if (!strcmp(s, gp->name)) {
|
||||
gctl_error(req, "%d geom '%s'", EEXIST, s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
s = gctl_get_asciiparam(req, "entries");
|
||||
if (s != NULL) {
|
||||
entries = strtol(s, (char **)(uintptr_t)&s, 0);
|
||||
if (entries < 128 || *s != '\0') {
|
||||
gctl_error(req, "%d entries %ld", EINVAL,
|
||||
entries);
|
||||
return;
|
||||
}
|
||||
} else
|
||||
entries = 128; /* Documented mininum */
|
||||
gp = g_gpt_ctl_create(req, mp, pp, entries);
|
||||
} else if (!strcmp(verb, "destroy")) {
|
||||
/* Destroy a GPT completely. */
|
||||
pp = g_gpt_ctl_add(req, flags, gp, &type, start, end);
|
||||
return;
|
||||
} else if (!strcmp(verb, "modify")) {
|
||||
/* Modify a partition entry. */
|
||||
} else if (!strcmp(verb, "recover")) {
|
||||
/* Recover a downgraded GPT. */
|
||||
return;
|
||||
} else if (!strcmp(verb, "remove")) {
|
||||
/* Remove a partition entry from a GPT. */
|
||||
} else
|
||||
gctl_error(req, "%d verb '%s'", EINVAL, verb);
|
||||
return;
|
||||
}
|
||||
|
||||
gctl_error(req, "%d verb '%s'", EINVAL, verb);
|
||||
}
|
||||
|
||||
static int
|
||||
|
Loading…
Reference in New Issue
Block a user