diff options
author | pjd <pjd@FreeBSD.org> | 2011-04-21 13:31:43 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2011-04-21 13:31:43 +0000 |
commit | 7e657fb243221cb5e19b84eea2d3c3fbb33872f2 (patch) | |
tree | e629481143e0cfe9a038347228212cae293b3d49 /sys/geom/eli/g_eli.c | |
parent | 9e319712527975803ad2e903a7f8398e4c4cf275 (diff) | |
download | FreeBSD-src-7e657fb243221cb5e19b84eea2d3c3fbb33872f2.zip FreeBSD-src-7e657fb243221cb5e19b84eea2d3c3fbb33872f2.tar.gz |
Instead of allocating memory for all the keys at device attach,
create reasonably large cache for the keys that is filled when
needed. The previous version was problematic for very large providers
(hundreds of terabytes or serval petabytes). Every terabyte of data
needs around 256kB for keys. Make the default cache limit big enough
to fit all the keys needed for 4TB providers, which will eat at most
1MB of memory.
MFC after: 2 weeks
Diffstat (limited to 'sys/geom/eli/g_eli.c')
-rw-r--r-- | sys/geom/eli/g_eli.c | 51 |
1 files changed, 10 insertions, 41 deletions
diff --git a/sys/geom/eli/g_eli.c b/sys/geom/eli/g_eli.c index 9f712cf..8edd147 100644 --- a/sys/geom/eli/g_eli.c +++ b/sys/geom/eli/g_eli.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2005-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org> + * Copyright (c) 2005-2011 Pawel Jakub Dawidek <pawel@dawidek.net> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -329,7 +329,7 @@ g_eli_newsession(struct g_eli_worker *wr) crie.cri_klen = sc->sc_ekeylen; if (sc->sc_ealgo == CRYPTO_AES_XTS) crie.cri_klen <<= 1; - crie.cri_key = sc->sc_ekeys[0]; + crie.cri_key = sc->sc_ekey; if (sc->sc_flags & G_ELI_FLAG_AUTH) { bzero(&cria, sizeof(cria)); cria.cri_alg = sc->sc_aalgo; @@ -522,34 +522,6 @@ again: } /* - * Select encryption key. If G_ELI_FLAG_SINGLE_KEY is present we only have one - * key available for all the data. If the flag is not present select the key - * based on data offset. - */ -uint8_t * -g_eli_crypto_key(struct g_eli_softc *sc, off_t offset, size_t blocksize) -{ - u_int nkey; - - if (sc->sc_nekeys == 1) - return (sc->sc_ekeys[0]); - - KASSERT(sc->sc_nekeys > 1, ("%s: sc_nekeys=%u", __func__, - sc->sc_nekeys)); - KASSERT((sc->sc_flags & G_ELI_FLAG_SINGLE_KEY) == 0, - ("%s: SINGLE_KEY flag set, but sc_nekeys=%u", __func__, - sc->sc_nekeys)); - - /* We switch key every 2^G_ELI_KEY_SHIFT blocks. */ - nkey = (offset >> G_ELI_KEY_SHIFT) / blocksize; - - KASSERT(nkey < sc->sc_nekeys, ("%s: nkey=%u >= sc_nekeys=%u", __func__, - nkey, sc->sc_nekeys)); - - return (sc->sc_ekeys[nkey]); -} - -/* * Here we generate IV. It is unique for every sector. */ void @@ -766,6 +738,7 @@ g_eli_create(struct gctl_req *req, struct g_class *mp, struct g_provider *bpp, bioq_init(&sc->sc_queue); mtx_init(&sc->sc_queue_mtx, "geli:queue", NULL, MTX_DEF); + mtx_init(&sc->sc_ekeys_lock, "geli:ekeys", NULL, MTX_DEF); pp = NULL; cp = g_new_consumer(gp); @@ -909,11 +882,7 @@ failed: } g_destroy_consumer(cp); g_destroy_geom(gp); - if (sc->sc_ekeys != NULL) { - bzero(sc->sc_ekeys, - sc->sc_nekeys * (sizeof(uint8_t *) + G_ELI_DATAKEYLEN)); - free(sc->sc_ekeys, M_ELI); - } + g_eli_key_destroy(sc); bzero(sc, sizeof(*sc)); free(sc, M_ELI); return (NULL); @@ -953,12 +922,7 @@ g_eli_destroy(struct g_eli_softc *sc, boolean_t force) } mtx_destroy(&sc->sc_queue_mtx); gp->softc = NULL; - if (sc->sc_ekeys != NULL) { - /* The sc_ekeys field can be NULL is device is suspended. */ - bzero(sc->sc_ekeys, - sc->sc_nekeys * (sizeof(uint8_t *) + G_ELI_DATAKEYLEN)); - free(sc->sc_ekeys, M_ELI); - } + g_eli_key_destroy(sc); bzero(sc, sizeof(*sc)); free(sc, M_ELI); @@ -1191,6 +1155,11 @@ g_eli_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, return; if (pp != NULL || cp != NULL) return; /* Nothing here. */ + + sbuf_printf(sb, "%s<KeysTotal>%ju</KeysTotal>", indent, + (uintmax_t)sc->sc_ekeys_total); + sbuf_printf(sb, "%s<KeysAllocated>%ju</KeysAllocated>", indent, + (uintmax_t)sc->sc_ekeys_allocated); sbuf_printf(sb, "%s<Flags>", indent); if (sc->sc_flags == 0) sbuf_printf(sb, "NONE"); |