g_bde.c revision 111119
1105464Sphk/*- 2105464Sphk * Copyright (c) 2002 Poul-Henning Kamp 3105464Sphk * Copyright (c) 2002 Networks Associates Technology, Inc. 4105464Sphk * All rights reserved. 5105464Sphk * 6105464Sphk * This software was developed for the FreeBSD Project by Poul-Henning Kamp 7105464Sphk * and NAI Labs, the Security Research Division of Network Associates, Inc. 8105464Sphk * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 9105464Sphk * DARPA CHATS research program. 10105464Sphk * 11105464Sphk * Redistribution and use in source and binary forms, with or without 12105464Sphk * modification, are permitted provided that the following conditions 13105464Sphk * are met: 14105464Sphk * 1. Redistributions of source code must retain the above copyright 15105464Sphk * notice, this list of conditions and the following disclaimer. 16105464Sphk * 2. Redistributions in binary form must reproduce the above copyright 17105464Sphk * notice, this list of conditions and the following disclaimer in the 18105464Sphk * documentation and/or other materials provided with the distribution. 19105464Sphk * 20105464Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21105464Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22105464Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23105464Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24105464Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25105464Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26105464Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27105464Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28105464Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29105464Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30105464Sphk * SUCH DAMAGE. 31105464Sphk * 32105464Sphk * $FreeBSD: head/sys/geom/bde/g_bde.c 111119 2003-02-19 05:47:46Z imp $ 33105464Sphk * 34105464Sphk */ 35105464Sphk 36105464Sphk#include <sys/param.h> 37105464Sphk#include <sys/stdint.h> 38105464Sphk#include <sys/bio.h> 39105464Sphk#include <sys/lock.h> 40105464Sphk#include <sys/mutex.h> 41105464Sphk#include <sys/malloc.h> 42105464Sphk#include <sys/systm.h> 43105464Sphk#include <sys/kernel.h> 44105464Sphk#include <sys/kthread.h> 45105464Sphk 46106407Sphk#include <crypto/rijndael/rijndael.h> 47106407Sphk#include <crypto/sha2/sha2.h> 48106407Sphk#include <geom/geom.h> 49106407Sphk#include <geom/bde/g_bde.h> 50105464Sphk#define BDE_CLASS_NAME "BDE" 51105464Sphk 52105464Sphkstatic void 53105464Sphkg_bde_start(struct bio *bp) 54105464Sphk{ 55105464Sphk struct g_geom *gp; 56105464Sphk struct g_consumer *cp; 57105464Sphk struct g_bde_softc *sc; 58105464Sphk 59105464Sphk gp = bp->bio_to->geom; 60105464Sphk cp = LIST_FIRST(&gp->consumer); 61105464Sphk sc = gp->softc; 62105464Sphk switch (bp->bio_cmd) { 63105464Sphk case BIO_DELETE: 64105464Sphk case BIO_READ: 65105464Sphk case BIO_WRITE: 66105464Sphk g_bde_start1(bp); 67105464Sphk break; 68105464Sphk case BIO_GETATTR: 69105464Sphk case BIO_SETATTR: 70105464Sphk g_io_deliver(bp, EOPNOTSUPP); 71105464Sphk break; 72105464Sphk default: 73105464Sphk g_io_deliver(bp, EOPNOTSUPP); 74105464Sphk return; 75105464Sphk } 76105464Sphk return; 77105464Sphk} 78105464Sphk 79105464Sphkstatic void 80105464Sphkg_bde_orphan(struct g_consumer *cp) 81105464Sphk{ 82105464Sphk struct g_geom *gp; 83105464Sphk struct g_provider *pp; 84105464Sphk struct g_bde_softc *sc; 85105464Sphk int error; 86105464Sphk 87105464Sphk g_trace(G_T_TOPOLOGY, "g_bde_orphan(%p/%s)", cp, cp->provider->name); 88105464Sphk g_topology_assert(); 89105464Sphk KASSERT(cp->provider->error != 0, 90105464Sphk ("g_bde_orphan with error == 0")); 91105464Sphk 92105464Sphk gp = cp->geom; 93105464Sphk sc = gp->softc; 94105464Sphk gp->flags |= G_GEOM_WITHER; 95105464Sphk error = cp->provider->error; 96105464Sphk LIST_FOREACH(pp, &gp->provider, provider) 97105464Sphk g_orphan_provider(pp, error); 98105464Sphk bzero(sc, sizeof(struct g_bde_softc)); /* destroy evidence */ 99105464Sphk return; 100105464Sphk} 101105464Sphk 102105464Sphkstatic int 103105464Sphkg_bde_access(struct g_provider *pp, int dr, int dw, int de) 104105464Sphk{ 105105464Sphk struct g_geom *gp; 106105464Sphk struct g_consumer *cp; 107105464Sphk 108105464Sphk gp = pp->geom; 109105464Sphk cp = LIST_FIRST(&gp->consumer); 110105464Sphk if (cp->acr == 0 && cp->acw == 0 && cp->ace == 0) { 111105464Sphk de++; 112105464Sphk dr++; 113105464Sphk } 114105464Sphk /* ... and let go of it on last close */ 115105464Sphk if ((cp->acr + dr) == 0 && (cp->acw + dw) == 0 && (cp->ace + de) == 1) { 116105464Sphk de--; 117105464Sphk dr--; 118105464Sphk } 119105464Sphk return (g_access_rel(cp, dr, dw, de)); 120105464Sphk} 121105464Sphk 122105464Sphkstatic int 123106518Sphkg_bde_config(struct g_configargs *ga) 124105464Sphk{ 125105464Sphk struct g_geom *gp; 126105464Sphk struct g_consumer *cp; 127105464Sphk struct g_provider *pp; 128105464Sphk struct g_bde_key *kp; 129105464Sphk int error; 130105464Sphk u_int sectorsize; 131105464Sphk off_t mediasize; 132105464Sphk struct g_bde_softc *sc; 133105464Sphk 134106518Sphk g_trace(G_T_TOPOLOGY, "g_bde_config(%d)", ga->flag); 135105464Sphk g_topology_assert(); 136105465Sphk gp = NULL; 137106518Sphk if (ga->flag == GCFG_DISMANTLE) { 138105464Sphk /* 139107831Sphk * Orderly detachment. 140105464Sphk */ 141105464Sphk if (ga->geom != NULL) { 142105464Sphk gp = ga->geom; 143105464Sphk } else if (ga->provider != NULL) { 144105464Sphk if (ga->provider->geom->class == ga->class) { 145105464Sphk gp = ga->provider->geom; 146105464Sphk } else { 147105464Sphk LIST_FOREACH(cp, &ga->provider->consumers, 148105464Sphk consumers) { 149105464Sphk if (cp->geom->class == ga->class) { 150105464Sphk gp = cp->geom; 151105464Sphk break; 152105464Sphk } 153105464Sphk } 154105464Sphk } 155105464Sphk if (gp == NULL) 156105464Sphk return (EINVAL); 157105464Sphk } else { 158105464Sphk return (EINVAL); 159105464Sphk } 160105464Sphk KASSERT(gp != NULL, ("NULL geom")); 161105464Sphk pp = LIST_FIRST(&gp->provider); 162105464Sphk KASSERT(pp != NULL, ("NULL provider")); 163105464Sphk if (pp->acr > 0 || pp->acw > 0 || pp->ace > 0) 164105464Sphk return (EBUSY); 165105464Sphk g_orphan_provider(pp, ENXIO); 166105464Sphk sc = gp->softc; 167105464Sphk cp = LIST_FIRST(&gp->consumer); 168105464Sphk KASSERT(cp != NULL, ("NULL consumer")); 169105464Sphk sc->dead = 1; 170105464Sphk wakeup(sc); 171105464Sphk error = g_access_rel(cp, -1, -1, -1); 172105464Sphk KASSERT(error == 0, ("error on close")); 173105464Sphk g_detach(cp); 174105464Sphk g_destroy_consumer(cp); 175105464Sphk g_topology_unlock(); 176105464Sphk while (sc->dead != 2 && !LIST_EMPTY(&pp->consumers)) 177105464Sphk tsleep(sc, PRIBIO, "g_bdedie", hz); 178106407Sphk g_waitidle(); 179105464Sphk g_topology_lock(); 180105464Sphk g_destroy_provider(pp); 181105464Sphk mtx_destroy(&sc->worklist_mutex); 182105464Sphk bzero(&sc->key, sizeof sc->key); 183105464Sphk g_free(sc); 184105464Sphk g_destroy_geom(gp); 185105464Sphk return (0); 186105464Sphk } 187105464Sphk 188106518Sphk if (ga->flag != GCFG_CREATE) 189105464Sphk return (EOPNOTSUPP); 190105464Sphk 191105464Sphk if (ga->provider == NULL) 192105464Sphk return (EINVAL); 193105464Sphk /* 194105464Sphk * Attach 195105464Sphk */ 196105464Sphk gp = g_new_geomf(ga->class, "%s.bde", ga->provider->name); 197105464Sphk gp->start = g_bde_start; 198105464Sphk gp->orphan = g_bde_orphan; 199105464Sphk gp->access = g_bde_access; 200105464Sphk gp->spoiled = g_std_spoiled; 201105464Sphk cp = g_new_consumer(gp); 202105464Sphk g_attach(cp, ga->provider); 203105464Sphk error = g_access_rel(cp, 1, 1, 1); 204105464Sphk if (error) { 205105464Sphk g_detach(cp); 206105464Sphk g_destroy_consumer(cp); 207105464Sphk g_destroy_geom(gp); 208105464Sphk return (error); 209105464Sphk } 210105464Sphk g_topology_unlock(); 211106407Sphk g_waitidle(); 212105464Sphk while (1) { 213105551Sphk sectorsize = cp->provider->sectorsize; 214105551Sphk mediasize = cp->provider->mediasize; 215111119Simp sc = g_malloc(sizeof(struct g_bde_softc), M_WAITOK | M_ZERO); 216105464Sphk gp->softc = sc; 217105464Sphk sc->geom = gp; 218105464Sphk sc->consumer = cp; 219105464Sphk 220105464Sphk error = g_bde_decrypt_lock(sc, ga->ptr, 221106407Sphk (u_char *)ga->ptr + (sizeof sc->sha2), 222106407Sphk mediasize, sectorsize, NULL); 223106407Sphk bzero(sc->sha2, sizeof sc->sha2); 224105464Sphk if (error) 225105464Sphk break; 226105464Sphk kp = &sc->key; 227105464Sphk 228105464Sphk /* Initialize helper-fields */ 229105464Sphk kp->keys_per_sector = kp->sectorsize / G_BDE_SKEYLEN; 230105464Sphk kp->zone_cont = kp->keys_per_sector * kp->sectorsize; 231105464Sphk kp->zone_width = kp->zone_cont + kp->sectorsize; 232105464Sphk kp->media_width = kp->sectorN - kp->sector0 - 233105464Sphk G_BDE_MAXKEYS * kp->sectorsize; 234105464Sphk 235105464Sphk /* Our external parameters */ 236105464Sphk sc->zone_cont = kp->zone_cont; 237105464Sphk sc->mediasize = g_bde_max_sector(kp); 238105464Sphk sc->sectorsize = kp->sectorsize; 239105464Sphk 240105464Sphk TAILQ_INIT(&sc->freelist); 241105464Sphk TAILQ_INIT(&sc->worklist); 242105464Sphk mtx_init(&sc->worklist_mutex, "g_bde_worklist", NULL, MTX_DEF); 243105464Sphk mtx_lock(&Giant); 244105464Sphk /* XXX: error check */ 245105464Sphk kthread_create(g_bde_worker, gp, &sc->thread, 0, 0, 246105464Sphk "g_bde %s", gp->name); 247105464Sphk mtx_unlock(&Giant); 248105464Sphk g_topology_lock(); 249105464Sphk pp = g_new_providerf(gp, gp->name); 250110697Sphk pp->flags |= G_PF_CANDELETE; 251110712Sphk pp->stripesize = kp->zone_cont; 252110712Sphk pp->stripeoffset = 0; 253105464Sphk pp->mediasize = sc->mediasize; 254105542Sphk pp->sectorsize = sc->sectorsize; 255105464Sphk g_error_provider(pp, 0); 256105464Sphk g_topology_unlock(); 257105464Sphk break; 258105464Sphk } 259105464Sphk g_topology_lock(); 260105464Sphk if (error == 0) { 261105464Sphk ga->geom = gp; 262105464Sphk return (0); 263105464Sphk } else { 264105464Sphk g_access_rel(cp, -1, -1, -1); 265105464Sphk } 266105464Sphk g_detach(cp); 267105464Sphk g_destroy_consumer(cp); 268105464Sphk if (gp->softc != NULL) 269105464Sphk g_free(gp->softc); 270105464Sphk g_destroy_geom(gp); 271105464Sphk return (error); 272105464Sphk} 273105464Sphk 274105464Sphkstatic struct g_class g_bde_class = { 275105464Sphk BDE_CLASS_NAME, 276105464Sphk NULL, 277106518Sphk g_bde_config, 278105464Sphk G_CLASS_INITIALIZER 279105464Sphk}; 280105464Sphk 281105464SphkDECLARE_GEOM_CLASS(g_bde_class, g_bde); 282