summaryrefslogtreecommitdiffstats
path: root/sys/geom
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2006-09-16 10:43:17 +0000
committerpjd <pjd@FreeBSD.org>2006-09-16 10:43:17 +0000
commit2e387b9b852a5ae8c2980ff133e33d076004f6bf (patch)
treed6a32a6317a6d83082fb42a45340d13d9d9c56f0 /sys/geom
parentf5e129df20c2b3984d81e96cfffd8fe2979a18be (diff)
downloadFreeBSD-src-2e387b9b852a5ae8c2980ff133e33d076004f6bf.zip
FreeBSD-src-2e387b9b852a5ae8c2980ff133e33d076004f6bf.tar.gz
Add 'configure' subcommand which for now only allows setting and removing
of the BOOT flag. It can be performed on both attached and detached providers. Requested by: Matthias Lederhofer <matled@gmx.net> MFC after: 1 week
Diffstat (limited to 'sys/geom')
-rw-r--r--sys/geom/eli/g_eli.h8
-rw-r--r--sys/geom/eli/g_eli_ctl.c111
2 files changed, 116 insertions, 3 deletions
diff --git a/sys/geom/eli/g_eli.h b/sys/geom/eli/g_eli.h
index e24f314..5460eea 100644
--- a/sys/geom/eli/g_eli.h
+++ b/sys/geom/eli/g_eli.h
@@ -59,8 +59,9 @@
* 2 - Added G_ELI_FLAG_READONLY.
* - IV is generated from offset converted to little-endian
* (flag G_ELI_FLAG_NATIVE_BYTE_ORDER will be set for older versions).
+ * 3 - Added 'configure' subcommand.
*/
-#define G_ELI_VERSION 2
+#define G_ELI_VERSION 3
/* ON DISK FLAGS. */
/* Use random, onetime keys. */
@@ -228,7 +229,7 @@ eli_metadata_decode_v0(const u_char *data, struct g_eli_metadata *md)
return (0);
}
static __inline int
-eli_metadata_decode_v1v2(const u_char *data, struct g_eli_metadata *md)
+eli_metadata_decode_v1v2v3(const u_char *data, struct g_eli_metadata *md)
{
MD5_CTX ctx;
const u_char *p;
@@ -264,7 +265,8 @@ eli_metadata_decode(const u_char *data, struct g_eli_metadata *md)
break;
case 1:
case 2:
- error = eli_metadata_decode_v1v2(data, md);
+ case 3:
+ error = eli_metadata_decode_v1v2v3(data, md);
break;
default:
error = EINVAL;
diff --git a/sys/geom/eli/g_eli_ctl.c b/sys/geom/eli/g_eli_ctl.c
index e420af3..a788ba2 100644
--- a/sys/geom/eli/g_eli_ctl.c
+++ b/sys/geom/eli/g_eli_ctl.c
@@ -364,6 +364,115 @@ g_eli_ctl_onetime(struct gctl_req *req, struct g_class *mp)
}
static void
+g_eli_ctl_configure(struct gctl_req *req, struct g_class *mp)
+{
+ struct g_eli_softc *sc;
+ struct g_eli_metadata md;
+ struct g_provider *pp;
+ struct g_consumer *cp;
+ char param[16];
+ const char *prov;
+ u_char *sector;
+ int *nargs, *boot, *noboot;
+ int error;
+ u_int i;
+
+ g_topology_assert();
+
+ nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
+ if (nargs == NULL) {
+ gctl_error(req, "No '%s' argument.", "nargs");
+ return;
+ }
+ if (*nargs <= 0) {
+ gctl_error(req, "Missing device(s).");
+ return;
+ }
+
+ boot = gctl_get_paraml(req, "boot", sizeof(*boot));
+ if (boot == NULL) {
+ gctl_error(req, "No '%s' argument.", "boot");
+ return;
+ }
+ noboot = gctl_get_paraml(req, "noboot", sizeof(*noboot));
+ if (noboot == NULL) {
+ gctl_error(req, "No '%s' argument.", "noboot");
+ return;
+ }
+ if (*boot && *noboot) {
+ gctl_error(req, "Options -b and -B are mutually exclusive.");
+ return;
+ }
+ if (!*boot && !*noboot) {
+ gctl_error(req, "No option given.");
+ return;
+ }
+
+ for (i = 0; i < *nargs; i++) {
+ snprintf(param, sizeof(param), "arg%d", i);
+ prov = gctl_get_asciiparam(req, param);
+ if (prov == NULL) {
+ gctl_error(req, "No 'arg%d' argument.", i);
+ return;
+ }
+ sc = g_eli_find_device(mp, prov);
+ if (sc == NULL) {
+ /*
+ * We ignore not attached providers, userland part will
+ * take care of them.
+ */
+ G_ELI_DEBUG(1, "Skipping configuration of not attached "
+ "provider %s.", prov);
+ continue;
+ }
+ if (*boot && (sc->sc_flags & G_ELI_FLAG_BOOT)) {
+ G_ELI_DEBUG(1, "BOOT flag already configured for %s.",
+ prov);
+ continue;
+ } else if (!*boot && !(sc->sc_flags & G_ELI_FLAG_BOOT)) {
+ G_ELI_DEBUG(1, "BOOT flag not configured for %s.",
+ prov);
+ continue;
+ }
+ if (sc->sc_flags & G_ELI_FLAG_RO) {
+ gctl_error(req, "Cannot change configuration of "
+ "read-only provider %s.", prov);
+ continue;
+ }
+ cp = LIST_FIRST(&sc->sc_geom->consumer);
+ pp = cp->provider;
+ error = g_eli_read_metadata(mp, pp, &md);
+ if (error != 0) {
+ gctl_error(req,
+ "Cannot read metadata from %s (error=%d).",
+ prov, error);
+ continue;
+ }
+
+ if (*boot) {
+ md.md_flags |= G_ELI_FLAG_BOOT;
+ sc->sc_flags |= G_ELI_FLAG_BOOT;
+ } else {
+ md.md_flags &= ~G_ELI_FLAG_BOOT;
+ sc->sc_flags &= ~G_ELI_FLAG_BOOT;
+ }
+
+ sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
+ eli_metadata_encode(&md, sector);
+ error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
+ pp->sectorsize);
+ if (error != 0) {
+ gctl_error(req,
+ "Cannot store metadata on %s (error=%d).",
+ prov, error);
+ }
+ bzero(&md, sizeof(md));
+ bzero(sector, sizeof(sector));
+ free(sector, M_ELI);
+ }
+}
+
+static void
g_eli_ctl_setkey(struct gctl_req *req, struct g_class *mp)
{
struct g_eli_softc *sc;
@@ -710,6 +819,8 @@ g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb)
g_eli_ctl_detach(req, mp);
else if (strcmp(verb, "onetime") == 0)
g_eli_ctl_onetime(req, mp);
+ else if (strcmp(verb, "configure") == 0)
+ g_eli_ctl_configure(req, mp);
else if (strcmp(verb, "setkey") == 0)
g_eli_ctl_setkey(req, mp);
else if (strcmp(verb, "delkey") == 0)
OpenPOWER on IntegriCloud