summaryrefslogtreecommitdiffstats
path: root/sys/geom/bde
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2003-03-29 22:14:21 +0000
committerphk <phk@FreeBSD.org>2003-03-29 22:14:21 +0000
commitcdc67e7072fb97bd41f4db2549ff13b3366ae34d (patch)
tree2692f101e6ec3c65bfcf241d0c43e3c69b2c2218 /sys/geom/bde
parent7ae16f68d81bc9e1a1ce60a4ceaf3e5c21ccca58 (diff)
downloadFreeBSD-src-cdc67e7072fb97bd41f4db2549ff13b3366ae34d.zip
FreeBSD-src-cdc67e7072fb97bd41f4db2549ff13b3366ae34d.tar.gz
Add create_geom and destroy_geom methods.
Diffstat (limited to 'sys/geom/bde')
-rw-r--r--sys/geom/bde/g_bde.c159
1 files changed, 159 insertions, 0 deletions
diff --git a/sys/geom/bde/g_bde.c b/sys/geom/bde/g_bde.c
index 6ab96a2..850cf1e 100644
--- a/sys/geom/bde/g_bde.c
+++ b/sys/geom/bde/g_bde.c
@@ -119,6 +119,163 @@ g_bde_access(struct g_provider *pp, int dr, int dw, int de)
}
static int
+g_bde_create_geom(struct gctl_req *req, struct g_class *mp, struct g_provider *pp)
+{
+ struct g_geom *gp;
+ struct g_consumer *cp;
+ struct g_bde_key *kp;
+ int error, i;
+ u_int sectorsize;
+ off_t mediasize;
+ struct g_bde_softc *sc;
+ void *pass;
+ void *key;
+
+ if (pp == NULL)
+ return (gctl_error(req, "Provider needed"));
+ g_trace(G_T_TOPOLOGY, "g_bde_create_geom(%s, %s)", mp->name, pp->name);
+ g_topology_assert();
+ gp = NULL;
+
+ pass = gctl_get_param(req, "pass", &i);
+ if (pass == NULL || i != SHA512_DIGEST_LENGTH) {
+ if (pass != NULL) {
+ bzero(pass, i);
+ g_free(pass);
+ }
+ return (gctl_error(req, "No usable key presented"));
+ }
+ key = gctl_get_param(req, "key", &i);
+ if (key != NULL && i != 16) {
+ bzero(key, i);
+ bzero(pass, SHA512_DIGEST_LENGTH);
+ g_free(pass);
+ g_free(key);
+ return (gctl_error(req, "Invalid key presented"));
+ }
+
+ gp = g_new_geomf(mp, "%s.bde", pp->name);
+ gp->start = g_bde_start;
+ gp->orphan = g_bde_orphan;
+ gp->access = g_bde_access;
+ gp->spoiled = g_std_spoiled;
+ cp = g_new_consumer(gp);
+ g_attach(cp, pp);
+ error = g_access_rel(cp, 1, 1, 1);
+ if (error) {
+ g_detach(cp);
+ g_destroy_consumer(cp);
+ g_destroy_geom(gp);
+ return (error);
+ }
+ g_topology_unlock();
+ g_waitidle();
+ while (1) {
+ sectorsize = cp->provider->sectorsize;
+ mediasize = cp->provider->mediasize;
+ sc = g_malloc(sizeof(struct g_bde_softc), M_WAITOK | M_ZERO);
+ gp->softc = sc;
+ sc->geom = gp;
+ sc->consumer = cp;
+
+ error = g_bde_decrypt_lock(sc, pass, key,
+ mediasize, sectorsize, NULL);
+ bzero(pass, SHA512_DIGEST_LENGTH);
+ if (key != NULL)
+ bzero(key, 16);
+ bzero(sc->sha2, sizeof sc->sha2);
+ if (error)
+ break;
+ kp = &sc->key;
+
+ /* Initialize helper-fields */
+ kp->keys_per_sector = kp->sectorsize / G_BDE_SKEYLEN;
+ kp->zone_cont = kp->keys_per_sector * kp->sectorsize;
+ kp->zone_width = kp->zone_cont + kp->sectorsize;
+ kp->media_width = kp->sectorN - kp->sector0 -
+ G_BDE_MAXKEYS * kp->sectorsize;
+
+ /* Our external parameters */
+ sc->zone_cont = kp->zone_cont;
+ sc->mediasize = g_bde_max_sector(kp);
+ sc->sectorsize = kp->sectorsize;
+
+ TAILQ_INIT(&sc->freelist);
+ TAILQ_INIT(&sc->worklist);
+ mtx_init(&sc->worklist_mutex, "g_bde_worklist", NULL, MTX_DEF);
+ mtx_lock(&Giant);
+ /* XXX: error check */
+ kthread_create(g_bde_worker, gp, &sc->thread, 0, 0,
+ "g_bde %s", gp->name);
+ mtx_unlock(&Giant);
+ g_topology_lock();
+ pp = g_new_providerf(gp, gp->name);
+ pp->flags |= G_PF_CANDELETE;
+ pp->stripesize = kp->zone_cont;
+ pp->stripeoffset = 0;
+ pp->mediasize = sc->mediasize;
+ pp->sectorsize = sc->sectorsize;
+ g_error_provider(pp, 0);
+ g_topology_unlock();
+ break;
+ }
+ g_topology_lock();
+ if (error == 0) {
+ return (0);
+ } else {
+ g_access_rel(cp, -1, -1, -1);
+ }
+ g_detach(cp);
+ g_destroy_consumer(cp);
+ if (gp->softc != NULL)
+ g_free(gp->softc);
+ g_destroy_geom(gp);
+ return (error);
+}
+
+
+static int
+g_bde_destroy_geom(struct gctl_req *req, struct g_class *mp, struct g_geom *gp)
+{
+ struct g_consumer *cp;
+ struct g_provider *pp;
+ int error;
+ struct g_bde_softc *sc;
+
+ g_trace(G_T_TOPOLOGY, "g_bde_destroy_geom(%s, %s)", mp->name, gp->name);
+ g_topology_assert();
+ /*
+ * Orderly detachment.
+ */
+ KASSERT(gp != NULL, ("NULL geom"));
+ pp = LIST_FIRST(&gp->provider);
+ KASSERT(pp != NULL, ("NULL provider"));
+ if (pp->acr > 0 || pp->acw > 0 || pp->ace > 0)
+ return (EBUSY);
+ g_orphan_provider(pp, ENXIO);
+ sc = gp->softc;
+ cp = LIST_FIRST(&gp->consumer);
+ KASSERT(cp != NULL, ("NULL consumer"));
+ sc->dead = 1;
+ wakeup(sc);
+ error = g_access_rel(cp, -1, -1, -1);
+ KASSERT(error == 0, ("error on close"));
+ g_detach(cp);
+ g_destroy_consumer(cp);
+ g_topology_unlock();
+ while (sc->dead != 2 && !LIST_EMPTY(&pp->consumers))
+ tsleep(sc, PRIBIO, "g_bdedie", hz);
+ g_waitidle();
+ g_topology_lock();
+ g_destroy_provider(pp);
+ mtx_destroy(&sc->worklist_mutex);
+ bzero(&sc->key, sizeof sc->key);
+ g_free(sc);
+ g_destroy_geom(gp);
+ return (0);
+}
+
+static int
g_bde_config(struct g_configargs *ga)
{
struct g_geom *gp;
@@ -273,6 +430,8 @@ g_bde_config(struct g_configargs *ga)
static struct g_class g_bde_class = {
.name = BDE_CLASS_NAME,
.config = g_bde_config,
+ .create_geom = g_bde_create_geom,
+ .destroy_geom = g_bde_destroy_geom,
G_CLASS_INITIALIZER
};
OpenPOWER on IntegriCloud