diff options
author | marcel <marcel@FreeBSD.org> | 2005-11-13 21:53:55 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2005-11-13 21:53:55 +0000 |
commit | 59cb038f4a138252cf6f9c7dcca6438a76fca8fc (patch) | |
tree | ceb3433218903d599face8c1556759f8116270f9 | |
parent | c3427572d7afd589e619448d1f28b53b9c89e348 (diff) | |
download | FreeBSD-src-59cb038f4a138252cf6f9c7dcca6438a76fca8fc.zip FreeBSD-src-59cb038f4a138252cf6f9c7dcca6438a76fca8fc.tar.gz |
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.
-rw-r--r-- | sys/geom/geom_gpt.c | 194 |
1 files changed, 127 insertions, 67 deletions
diff --git a/sys/geom/geom_gpt.c b/sys/geom/geom_gpt.c index e6a52a8..5f07a81 100644 --- a/sys/geom/geom_gpt.c +++ b/sys/geom/geom_gpt.c @@ -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 @@ fail: 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(); - if (!strcmp(verb, "add")) { + /* + * 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")) { /* - * Add a partition entry to a GPT. + * Create a GPT on a pristine disk-like provider. * Required parameters/attributes: - * geom - * type - * start - * end + * provider * Optional parameters/attributes: - * label + * entries */ - s = gctl_get_asciiparam(req, "geom"); + s = gctl_get_asciiparam(req, "provider"); if (s == NULL) { - gctl_error(req, "%d geom", ENOATTR); + gctl_error(req, "%d provider", 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); + pp = g_provider_by_name(s); + if (pp == NULL) { + gctl_error(req, "%d provider '%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; + /* 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: + * type + * start + * end + * Optional parameters/attributes: + * label + */ 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 |