diff options
author | Toomas Soome <tsoome@me.com> | 2017-12-04 12:26:50 +0200 |
---|---|---|
committer | Dan McDonald <danmcd@joyent.com> | 2018-06-19 14:05:33 -0400 |
commit | 4a04e8db7f069cc2eb910470e630778f35ef3c44 (patch) | |
tree | f47141ae0d42a8987c8b493a5f8ca540ce5a00f3 | |
parent | 9d1ccc13a7df03b1b5b6754fc08c980a323c5a37 (diff) | |
download | illumos-joyent-4a04e8db7f069cc2eb910470e630778f35ef3c44.tar.gz |
8905 loader: add skein/edonr support
Reviewed by: Andy Fiddaman <omnios@citrus-it.co.uk>
Reviewed by: Ken Mays <kmays2000@gmail.com>
Reviewed by: C Fraire <cfraire@me.com>
Approved by: Dan McDonald <danmcd@joyent.com>
-rw-r--r-- | usr/src/boot/sys/boot/efi/boot1/Makefile | 5 | ||||
-rw-r--r-- | usr/src/boot/sys/boot/i386/gptzfsboot/gptldr.S | 2 | ||||
-rw-r--r-- | usr/src/boot/sys/boot/zfs/Makefile.com | 18 | ||||
-rw-r--r-- | usr/src/boot/sys/boot/zfs/zfsimpl.c | 146 | ||||
-rw-r--r-- | usr/src/boot/sys/cddl/boot/zfs/edonr_zfs.c | 100 | ||||
-rw-r--r-- | usr/src/boot/sys/cddl/boot/zfs/skein_zfs.c | 90 | ||||
-rw-r--r-- | usr/src/boot/sys/cddl/boot/zfs/zfsimpl.h | 7 | ||||
-rw-r--r-- | usr/src/boot/sys/cddl/boot/zfs/zfssubr.c | 75 | ||||
-rw-r--r-- | usr/src/boot/sys/sys/types.h | 5 | ||||
-rw-r--r-- | usr/src/uts/common/sys/debug.h | 2 | ||||
-rw-r--r-- | usr/src/uts/common/sys/systm.h | 7 |
11 files changed, 410 insertions, 47 deletions
diff --git a/usr/src/boot/sys/boot/efi/boot1/Makefile b/usr/src/boot/sys/boot/efi/boot1/Makefile index aee4ba24fb..9c0f56d75e 100644 --- a/usr/src/boot/sys/boot/efi/boot1/Makefile +++ b/usr/src/boot/sys/boot/efi/boot1/Makefile @@ -33,7 +33,7 @@ OBJS= multiboot.o boot1.o self_reloc.o start.o ufs_module.o zfs_module.o \ ASFLAGS=-m64 -fPIC CFLAGS= -O2 -CPPFLAGS= -nostdinc +CPPFLAGS= -nostdinc -D_STANDALONE CPPFLAGS += -I. CPPFLAGS += -I./../include CPPFLAGS += -I./../include/${MACHINE} @@ -51,6 +51,9 @@ CPPFLAGS += -I./../../../cddl/boot/zfs/ # Always add MI sources and REGULAR efi loader bits CPPFLAGS += -I./../../common +# For sys/skein.h +CPPFLAGS += -I$(SRC)/uts/common + include ../Makefile.inc FILES= boot1.efi diff --git a/usr/src/boot/sys/boot/i386/gptzfsboot/gptldr.S b/usr/src/boot/sys/boot/i386/gptzfsboot/gptldr.S index 9b646aee66..1b1fd9ba9c 100644 --- a/usr/src/boot/sys/boot/i386/gptzfsboot/gptldr.S +++ b/usr/src/boot/sys/boot/i386/gptzfsboot/gptldr.S @@ -45,7 +45,7 @@ /* Misc. Constants */ .set SIZ_PAG,0x1000 # Page size .set SIZ_SEC,0x200 # Sector size - .set COPY_BLKS,0x4 # Number of blocks + .set COPY_BLKS,0x8 # Number of blocks # to copy for boot2 .set COPY_BLK_SZ,0x8000 # Copy in 32k blocks; must be # a multiple of 16 bytes diff --git a/usr/src/boot/sys/boot/zfs/Makefile.com b/usr/src/boot/sys/boot/zfs/Makefile.com index 9873feb785..ee5c8ac1b8 100644 --- a/usr/src/boot/sys/boot/zfs/Makefile.com +++ b/usr/src/boot/sys/boot/zfs/Makefile.com @@ -29,13 +29,21 @@ CC= $(GCC_ROOT)/bin/gcc CPPFLAGS= SRCS += ../zfs.c ../gzip.c -OBJS += zfs.o gzip.o +SRCS += $(SRC)/common/crypto/edonr/edonr.c +SRCS += $(SRC)/common/crypto/skein/skein.c +SRCS += $(SRC)/common/crypto/skein/skein_iv.c +SRCS += $(SRC)/common/crypto/skein/skein_block.c +OBJS += zfs.o gzip.o edonr.o skein.o skein_iv.o skein_block.o -CFLAGS= -O2 -nostdinc -I../../../../include -I../../.. +CFLAGS= -O2 -D_STANDALONE -nostdinc -I../../../../include -I../../.. CFLAGS += -I../../common -I../../.. -I.. -I. CFLAGS += -I../../../../lib/libstand CFLAGS += -I../../../../lib/libz CFLAGS += -I../../../cddl/boot/zfs +CFLAGS += -I$(SRC)/uts/common + +# Do not unroll skein loops, reduce code size +CFLAGS += -DSKEIN_LOOP=111 CFLAGS += -ffreestanding CFLAGS += -mno-mmx -mno-3dnow -mno-sse -mno-sse2 -mno-sse3 -msoft-float @@ -59,4 +67,10 @@ libzfsboot.a: $(OBJS) %.o: ../%.c $(COMPILE.c) -o $@ $< +%.o: $(SRC)/common/crypto/edonr/%.c + $(COMPILE.c) -o $@ $< + +%.o: $(SRC)/common/crypto/skein/%.c + $(COMPILE.c) -o $@ $< + zfs.o: ../zfsimpl.c diff --git a/usr/src/boot/sys/boot/zfs/zfsimpl.c b/usr/src/boot/sys/boot/zfs/zfsimpl.c index 73c9d52e0a..b3edf4653a 100644 --- a/usr/src/boot/sys/boot/zfs/zfsimpl.c +++ b/usr/src/boot/sys/boot/zfs/zfsimpl.c @@ -58,6 +58,8 @@ static const char *features_for_read[] = { "com.delphix:embedded_data", "org.open-zfs:large_blocks", "org.illumos:sha512", + "org.illumos:skein", + "org.illumos:edonr", "org.zfsonlinux:large_dnode", "com.joyent:multi_vdev_crash_dump", NULL @@ -79,6 +81,9 @@ static char *zfs_temp_buf, *zfs_temp_end, *zfs_temp_ptr; static int zio_read(const spa_t *spa, const blkptr_t *bp, void *buf); static int zfs_get_root(const spa_t *spa, uint64_t *objid); static int zfs_rlookup(const spa_t *spa, uint64_t objnum, char *result); +static int zap_lookup(const spa_t *spa, const dnode_phys_t *dnode, + const char *name, uint64_t integer_size, uint64_t num_integers, + void *value); static void zfs_init(void) @@ -421,7 +426,7 @@ vdev_read_phys(vdev_t *vdev, const blkptr_t *bp, void *buf, rc = vdev->v_phys_read(vdev, vdev->v_read_priv, offset, buf, psize); if (rc) return (rc); - if (bp && zio_checksum_verify(bp, buf)) + if (bp && zio_checksum_verify(vdev->spa, bp, buf)) return (EIO); return (0); @@ -1091,8 +1096,10 @@ vdev_probe(vdev_phys_read_t *phys_read, void *read_priv, spa_t **spap) STAILQ_FOREACH(pool_vdev, &spa->spa_vdevs, v_childlink) if (top_vdev == pool_vdev) break; - if (!pool_vdev && top_vdev) + if (!pool_vdev && top_vdev) { + top_vdev->spa = spa; STAILQ_INSERT_TAIL(&spa->spa_vdevs, top_vdev, v_childlink); + } /* * We should already have created an incomplete vdev for this @@ -1153,6 +1160,7 @@ vdev_probe(vdev_phys_read_t *phys_read, void *read_priv, spa_t **spap) } zfs_free(upbuf, VDEV_UBERBLOCK_SIZE(vdev)); + vdev->spa = spa; if (spap != NULL) *spap = spa; return (0); @@ -1201,7 +1209,7 @@ zio_read_gang(const spa_t *spa, const blkptr_t *bp, void *buf) pbuf += BP_GET_PSIZE(gbp); } - if (zio_checksum_verify(bp, buf)) + if (zio_checksum_verify(spa, bp, buf)) return (EIO); return (0); } @@ -1451,12 +1459,93 @@ fzap_leaf_value(const zap_leaf_t *zl, const zap_leaf_chunk_t *zc) return value; } +static void +stv(int len, void *addr, uint64_t value) +{ + switch (len) { + case 1: + *(uint8_t *)addr = value; + return; + case 2: + *(uint16_t *)addr = value; + return; + case 4: + *(uint32_t *)addr = value; + return; + case 8: + *(uint64_t *)addr = value; + return; + } +} + +/* + * Extract a array from a zap leaf entry. + */ +static void +fzap_leaf_array(const zap_leaf_t *zl, const zap_leaf_chunk_t *zc, + uint64_t integer_size, uint64_t num_integers, void *buf) +{ + uint64_t array_int_len = zc->l_entry.le_value_intlen; + uint64_t value = 0; + uint64_t *u64 = buf; + char *p = buf; + int len = MIN(zc->l_entry.le_value_numints, num_integers); + int chunk = zc->l_entry.le_value_chunk; + int byten = 0; + + if (integer_size == 8 && len == 1) { + *u64 = fzap_leaf_value(zl, zc); + return; + } + + while (len > 0) { + struct zap_leaf_array *la = &ZAP_LEAF_CHUNK(zl, chunk).l_array; + int i; + + ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(zl)); + for (i = 0; i < ZAP_LEAF_ARRAY_BYTES && len > 0; i++) { + value = (value << 8) | la->la_array[i]; + byten++; + if (byten == array_int_len) { + stv(integer_size, p, value); + byten = 0; + len--; + if (len == 0) + return; + p += integer_size; + } + } + chunk = la->la_next; + } +} + +static int +fzap_check_size(uint64_t integer_size, uint64_t num_integers) +{ + + switch (integer_size) { + case 1: + case 2: + case 4: + case 8: + break; + default: + return (EINVAL); + } + + if (integer_size * num_integers > ZAP_MAXVALUELEN) + return (E2BIG); + + return (0); +} + /* * Lookup a value in a fatzap directory. Assumes that the zap scratch * buffer contains the directory header. */ static int -fzap_lookup(const spa_t *spa, const dnode_phys_t *dnode, const char *name, uint64_t *value) +fzap_lookup(const spa_t *spa, const dnode_phys_t *dnode, const char *name, + uint64_t integer_size, uint64_t num_integers, void *value) { int bsize = dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT; zap_phys_t zh = *(zap_phys_t *) zap_scratch; @@ -1468,6 +1557,9 @@ fzap_lookup(const spa_t *spa, const dnode_phys_t *dnode, const char *name, uint6 if (zh.zap_magic != ZAP_MAGIC) return (EIO); + if ((rc = fzap_check_size(integer_size, num_integers)) != 0) + return (rc); + z.zap_block_shift = ilog2(bsize); z.zap_phys = (zap_phys_t *) zap_scratch; @@ -1523,9 +1615,10 @@ fzap_lookup(const spa_t *spa, const dnode_phys_t *dnode, const char *name, uint6 zc = &ZAP_LEAF_CHUNK(&zl, zc->l_entry.le_next); } if (fzap_name_equal(&zl, zc, name)) { - if (zc->l_entry.le_value_intlen * zc->l_entry.le_value_numints > 8) - return (E2BIG); - *value = fzap_leaf_value(&zl, zc); + if (zc->l_entry.le_value_intlen > integer_size) + return (EINVAL); + + fzap_leaf_array(&zl, zc, integer_size, num_integers, value); return (0); } @@ -1536,7 +1629,8 @@ fzap_lookup(const spa_t *spa, const dnode_phys_t *dnode, const char *name, uint6 * Lookup a name in a zap object and return its value as a uint64_t. */ static int -zap_lookup(const spa_t *spa, const dnode_phys_t *dnode, const char *name, uint64_t *value) +zap_lookup(const spa_t *spa, const dnode_phys_t *dnode, const char *name, + uint64_t integer_size, uint64_t num_integers, void *value) { int rc; uint64_t zap_type; @@ -1549,8 +1643,10 @@ zap_lookup(const spa_t *spa, const dnode_phys_t *dnode, const char *name, uint64 zap_type = *(uint64_t *) zap_scratch; if (zap_type == ZBT_MICRO) return mzap_lookup(dnode, name, value); - else if (zap_type == ZBT_HEADER) - return fzap_lookup(spa, dnode, name, value); + else if (zap_type == ZBT_HEADER) { + return fzap_lookup(spa, dnode, name, integer_size, + num_integers, value); + } printf("ZFS: invalid zap_type=%d\n", (int)zap_type); return (EIO); } @@ -1889,7 +1985,8 @@ zfs_lookup_dataset(const spa_t *spa, const char *name, uint64_t *objnum) if (objset_get_dnode(spa, &spa->spa_mos, DMU_POOL_DIRECTORY_OBJECT, &dir)) return (EIO); - if (zap_lookup(spa, &dir, DMU_POOL_ROOT_DATASET, &dir_obj)) + if (zap_lookup(spa, &dir, DMU_POOL_ROOT_DATASET, sizeof (dir_obj), + 1, &dir_obj)) return (EIO); p = name; @@ -1919,7 +2016,8 @@ zfs_lookup_dataset(const spa_t *spa, const char *name, uint64_t *objnum) return (EIO); /* Actual loop condition #2. */ - if (zap_lookup(spa, &child_dir_zap, element, &dir_obj) != 0) + if (zap_lookup(spa, &child_dir_zap, element, sizeof (dir_obj), + 1, &dir_obj) != 0) return (ENOENT); } @@ -2048,9 +2146,9 @@ zfs_get_root(const spa_t *spa, uint64_t *objid) /* * Lookup the pool_props and see if we can find a bootfs. */ - if (zap_lookup(spa, &dir, DMU_POOL_PROPS, &props) == 0 + if (zap_lookup(spa, &dir, DMU_POOL_PROPS, sizeof (props), 1, &props) == 0 && objset_get_dnode(spa, &spa->spa_mos, props, &propdir) == 0 - && zap_lookup(spa, &propdir, "bootfs", &bootfs) == 0 + && zap_lookup(spa, &propdir, "bootfs", sizeof (bootfs), 1, &bootfs) == 0 && bootfs != 0) { *objid = bootfs; @@ -2059,7 +2157,7 @@ zfs_get_root(const spa_t *spa, uint64_t *objid) /* * Lookup the root dataset directory */ - if (zap_lookup(spa, &dir, DMU_POOL_ROOT_DATASET, &root) + if (zap_lookup(spa, &dir, DMU_POOL_ROOT_DATASET, sizeof (root), 1, &root) || objset_get_dnode(spa, &spa->spa_mos, root, &dir)) { printf("ZFS: can't find root dsl_dir\n"); return (EIO); @@ -2134,7 +2232,7 @@ check_mos_features(const spa_t *spa) &dir)) != 0) return (rc); if ((rc = zap_lookup(spa, &dir, DMU_POOL_FEATURES_FOR_READ, - &objnum)) != 0) { + sizeof (objnum), 1, &objnum)) != 0) { /* * It is older pool without features. As we have already * tested the label, just return without raising the error. @@ -2166,6 +2264,7 @@ check_mos_features(const spa_t *spa) static int zfs_spa_init(spa_t *spa) { + dnode_phys_t dir; int rc; if (zio_read(spa, &spa->spa_uberblock.ub_rootbp, &spa->spa_mos)) { @@ -2177,6 +2276,17 @@ zfs_spa_init(spa_t *spa) return (EIO); } + if (objset_get_dnode(spa, &spa->spa_mos, DMU_POOL_DIRECTORY_OBJECT, + &dir)) { + printf("ZFS: failed to read pool %s directory object\n", + spa->spa_name); + return (EIO); + } + /* this is allowed to fail, older pools do not have salt */ + rc = zap_lookup(spa, &dir, DMU_POOL_CHECKSUM_SALT, 1, + sizeof (spa->spa_cksum_salt.zcs_bytes), + spa->spa_cksum_salt.zcs_bytes); + rc = check_mos_features(spa); if (rc != 0) { printf("ZFS: pool %s is not supported\n", spa->spa_name); @@ -2329,7 +2439,7 @@ zfs_lookup(const struct zfsmount *mnt, const char *upath, dnode_phys_t *dnode) return (rc); } - rc = zap_lookup(spa, &dn, ZFS_ROOT_OBJ, &objnum); + rc = zap_lookup(spa, &dn, ZFS_ROOT_OBJ, sizeof(objnum), 1, &objnum); if (rc) { free(entry); return (rc); @@ -2389,7 +2499,7 @@ zfs_lookup(const struct zfsmount *mnt, const char *upath, dnode_phys_t *dnode) goto done; } - rc = zap_lookup(spa, &dn, element, &objnum); + rc = zap_lookup(spa, &dn, element, sizeof(objnum), 1, &objnum); if (rc) goto done; objnum = ZFS_DIRENT_OBJ(objnum); diff --git a/usr/src/boot/sys/cddl/boot/zfs/edonr_zfs.c b/usr/src/boot/sys/cddl/boot/zfs/edonr_zfs.c new file mode 100644 index 0000000000..ff1cd0566f --- /dev/null +++ b/usr/src/boot/sys/cddl/boot/zfs/edonr_zfs.c @@ -0,0 +1,100 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2013 Saso Kiselkov. All rights reserved. + * Use is subject to license terms. + */ +#include <sys/edonr.h> + +#define EDONR_MODE 512 +#define EDONR_BLOCK_SIZE EdonR512_BLOCK_SIZE + +/* + * Native zio_checksum interface for the Edon-R hash function. + */ +/*ARGSUSED*/ +static void +zio_checksum_edonr_native(const void *buf, uint64_t size, + const void *ctx_template, zio_cksum_t *zcp) +{ + uint8_t digest[EDONR_MODE / 8]; + EdonRState ctx; + + ASSERT(ctx_template != NULL); + bcopy(ctx_template, &ctx, sizeof (ctx)); + EdonRUpdate(&ctx, buf, size * 8); + EdonRFinal(&ctx, digest); + bcopy(digest, zcp->zc_word, sizeof (zcp->zc_word)); +} + +/* + * Byteswapped zio_checksum interface for the Edon-R hash function. + */ +static void +zio_checksum_edonr_byteswap(const void *buf, uint64_t size, + const void *ctx_template, zio_cksum_t *zcp) +{ + zio_cksum_t tmp; + + zio_checksum_edonr_native(buf, size, ctx_template, &tmp); + zcp->zc_word[0] = BSWAP_64(zcp->zc_word[0]); + zcp->zc_word[1] = BSWAP_64(zcp->zc_word[1]); + zcp->zc_word[2] = BSWAP_64(zcp->zc_word[2]); + zcp->zc_word[3] = BSWAP_64(zcp->zc_word[3]); +} + +static void * +zio_checksum_edonr_tmpl_init(const zio_cksum_salt_t *salt) +{ + EdonRState *ctx; + uint8_t salt_block[EDONR_BLOCK_SIZE]; + + /* + * Edon-R needs all but the last hash invocation to be on full-size + * blocks, but the salt is too small. Rather than simply padding it + * with zeros, we expand the salt into a new salt block of proper + * size by double-hashing it (the new salt block will be composed of + * H(salt) || H(H(salt))). + */ + EdonRHash(EDONR_MODE, salt->zcs_bytes, sizeof (salt->zcs_bytes) * 8, + salt_block); + EdonRHash(EDONR_MODE, salt_block, EDONR_MODE, salt_block + + EDONR_MODE / 8); + + /* + * Feed the new salt block into the hash function - this will serve + * as our MAC key. + */ + ctx = malloc(sizeof (*ctx)); + bzero(ctx, sizeof (*ctx)); + EdonRInit(ctx, EDONR_MODE); + EdonRUpdate(ctx, salt_block, sizeof (salt_block) * 8); + return (ctx); +} + +static void +zio_checksum_edonr_tmpl_free(void *ctx_template) +{ + EdonRState *ctx = ctx_template; + + bzero(ctx, sizeof (*ctx)); + free(ctx); +} diff --git a/usr/src/boot/sys/cddl/boot/zfs/skein_zfs.c b/usr/src/boot/sys/cddl/boot/zfs/skein_zfs.c new file mode 100644 index 0000000000..d8ef49d399 --- /dev/null +++ b/usr/src/boot/sys/cddl/boot/zfs/skein_zfs.c @@ -0,0 +1,90 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2013 Saso Kiselkov. All rights reserved. + */ +#include <sys/skein.h> + +/* + * Computes a native 256-bit skein MAC checksum. Please note that this + * function requires the presence of a ctx_template that should be allocated + * using zio_checksum_skein_tmpl_init. + */ +/*ARGSUSED*/ +static void +zio_checksum_skein_native(const void *buf, uint64_t size, + const void *ctx_template, zio_cksum_t *zcp) +{ + Skein_512_Ctxt_t ctx; + + ASSERT(ctx_template != NULL); + bcopy(ctx_template, &ctx, sizeof (ctx)); + (void) Skein_512_Update(&ctx, buf, size); + (void) Skein_512_Final(&ctx, (uint8_t *)zcp); + bzero(&ctx, sizeof (ctx)); +} + +/* + * Byteswapped version of zio_checksum_skein_native. This just invokes + * the native checksum function and byteswaps the resulting checksum (since + * skein is internally endian-insensitive). + */ +static void +zio_checksum_skein_byteswap(const void *buf, uint64_t size, + const void *ctx_template, zio_cksum_t *zcp) +{ + zio_cksum_t tmp; + + zio_checksum_skein_native(buf, size, ctx_template, &tmp); + zcp->zc_word[0] = BSWAP_64(tmp.zc_word[0]); + zcp->zc_word[1] = BSWAP_64(tmp.zc_word[1]); + zcp->zc_word[2] = BSWAP_64(tmp.zc_word[2]); + zcp->zc_word[3] = BSWAP_64(tmp.zc_word[3]); +} + +/* + * Allocates a skein MAC template suitable for using in skein MAC checksum + * computations and returns a pointer to it. + */ +static void * +zio_checksum_skein_tmpl_init(const zio_cksum_salt_t *salt) +{ + Skein_512_Ctxt_t *ctx; + + ctx = malloc(sizeof (*ctx)); + bzero(ctx, sizeof (*ctx)); + (void) Skein_512_InitExt(ctx, sizeof (zio_cksum_t) * 8, 0, + salt->zcs_bytes, sizeof (salt->zcs_bytes)); + return (ctx); +} + +/* + * Frees a skein context template previously allocated using + * zio_checksum_skein_tmpl_init. + */ +static void +zio_checksum_skein_tmpl_free(void *ctx_template) +{ + Skein_512_Ctxt_t *ctx = ctx_template; + + bzero(ctx, sizeof (*ctx)); + free(ctx); +} diff --git a/usr/src/boot/sys/cddl/boot/zfs/zfsimpl.h b/usr/src/boot/sys/cddl/boot/zfs/zfsimpl.h index cfddbfe974..8cd5cf8f2b 100644 --- a/usr/src/boot/sys/cddl/boot/zfs/zfsimpl.h +++ b/usr/src/boot/sys/cddl/boot/zfs/zfsimpl.h @@ -1073,6 +1073,8 @@ typedef enum dmu_objset_type { DMU_OST_NUMTYPES } dmu_objset_type_t; +#define ZAP_MAXVALUELEN (1024 * 8) + /* * header for all bonus and spill buffers. * The header has a fixed portion with a variable number @@ -1208,6 +1210,7 @@ typedef struct dsl_dataset_phys { #define DMU_POOL_DEFLATE "deflate" #define DMU_POOL_HISTORY "history" #define DMU_POOL_PROPS "pool_props" +#define DMU_POOL_CHECKSUM_SALT "org.illumos:checksum_salt" #define ZAP_MAGIC 0x2F52AB2ABULL @@ -1513,6 +1516,7 @@ typedef struct znode_phys { * In-core vdev representation. */ struct vdev; +struct spa; typedef int vdev_phys_read_t(struct vdev *vdev, void *priv, off_t offset, void *buf, size_t bytes); typedef int vdev_read_t(struct vdev *vdev, const blkptr_t *bp, @@ -1537,6 +1541,7 @@ typedef struct vdev { vdev_phys_read_t *v_phys_read; /* read from raw leaf vdev */ vdev_read_t *v_read; /* read from vdev */ void *v_read_priv; /* private data for read function */ + struct spa *spa; /* link to spa */ } vdev_t; /* @@ -1552,6 +1557,8 @@ typedef struct spa { struct uberblock spa_uberblock; /* best uberblock so far */ vdev_list_t spa_vdevs; /* list of all toplevel vdevs */ objset_phys_t spa_mos; /* MOS for this pool */ + zio_cksum_salt_t spa_cksum_salt; /* secret salt for cksum */ + void *spa_cksum_tmpls[ZIO_CHECKSUM_FUNCTIONS]; int spa_inited; /* initialized */ vdev_t *spa_boot_vdev; /* boot device for kernel */ } spa_t; diff --git a/usr/src/boot/sys/cddl/boot/zfs/zfssubr.c b/usr/src/boot/sys/cddl/boot/zfs/zfssubr.c index 30d6a71e8d..e38f14f33b 100644 --- a/usr/src/boot/sys/cddl/boot/zfs/zfssubr.c +++ b/usr/src/boot/sys/cddl/boot/zfs/zfssubr.c @@ -105,6 +105,8 @@ typedef struct zio_checksum_info { #include "fletcher.c" #include "sha256.c" +#include "skein_zfs.c" +#include "edonr_zfs.c" static zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = { {{NULL, NULL}, NULL, NULL, 0, "inherit"}, @@ -131,11 +133,14 @@ static zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = { NULL, NULL, ZCHECKSUM_FLAG_METADATA | ZCHECKSUM_FLAG_DEDUP | ZCHECKSUM_FLAG_NOPWRITE, "SHA512"}, /* no skein and edonr for now */ - {{NULL, NULL}, NULL, NULL, ZCHECKSUM_FLAG_METADATA | - ZCHECKSUM_FLAG_DEDUP | ZCHECKSUM_FLAG_SALTED | - ZCHECKSUM_FLAG_NOPWRITE, "skein"}, - {{NULL, NULL}, NULL, NULL, ZCHECKSUM_FLAG_METADATA | - ZCHECKSUM_FLAG_SALTED | ZCHECKSUM_FLAG_NOPWRITE, "edonr"}, + {{zio_checksum_skein_native, zio_checksum_skein_byteswap}, + zio_checksum_skein_tmpl_init, zio_checksum_skein_tmpl_free, + ZCHECKSUM_FLAG_METADATA | ZCHECKSUM_FLAG_DEDUP | + ZCHECKSUM_FLAG_SALTED | ZCHECKSUM_FLAG_NOPWRITE, "skein"}, + {{zio_checksum_edonr_native, zio_checksum_edonr_byteswap}, + zio_checksum_edonr_tmpl_init, zio_checksum_edonr_tmpl_free, + ZCHECKSUM_FLAG_METADATA | ZCHECKSUM_FLAG_SALTED | + ZCHECKSUM_FLAG_NOPWRITE, "edonr"}, }; /* @@ -228,33 +233,48 @@ zio_checksum_label_verifier(zio_cksum_t *zcp, uint64_t offset) * templates and installs the template into the spa_t. */ static void -zio_checksum_template_init(enum zio_checksum checksum, const spa_t *spa) +zio_checksum_template_init(enum zio_checksum checksum, spa_t *spa) { zio_checksum_info_t *ci = &zio_checksum_table[checksum]; if (ci->ci_tmpl_init == NULL) return; -#if 0 /* for now we dont have anything here */ + if (spa->spa_cksum_tmpls[checksum] != NULL) return; - VERIFY(ci->ci_tmpl_free != NULL); - mutex_enter(&spa->spa_cksum_tmpls_lock); if (spa->spa_cksum_tmpls[checksum] == NULL) { spa->spa_cksum_tmpls[checksum] = ci->ci_tmpl_init(&spa->spa_cksum_salt); - VERIFY(spa->spa_cksum_tmpls[checksum] != NULL); } - mutex_exit(&spa->spa_cksum_tmpls_lock); -#endif +} + +/* + * Called by a spa_t that's about to be deallocated. This steps through + * all of the checksum context templates and deallocates any that were + * initialized using the algorithm-specific template init function. + */ +void +zio_checksum_templates_free(spa_t *spa) +{ + for (enum zio_checksum checksum = 0; + checksum < ZIO_CHECKSUM_FUNCTIONS; checksum++) { + if (spa->spa_cksum_tmpls[checksum] != NULL) { + zio_checksum_info_t *ci = &zio_checksum_table[checksum]; + + ci->ci_tmpl_free(spa->spa_cksum_tmpls[checksum]); + spa->spa_cksum_tmpls[checksum] = NULL; + } + } } static int -zio_checksum_verify(const blkptr_t *bp, void *data) +zio_checksum_verify(const spa_t *spa, const blkptr_t *bp, void *data) { uint64_t size; unsigned int checksum; zio_checksum_info_t *ci; + void *ctx = NULL; zio_cksum_t actual_cksum, expected_cksum, verifier; int byteswap; @@ -267,7 +287,11 @@ zio_checksum_verify(const blkptr_t *bp, void *data) if (ci->ci_func[0] == NULL || ci->ci_func[1] == NULL) return (EINVAL); - zio_checksum_template_init(checksum, NULL); + if (spa != NULL) { + zio_checksum_template_init(checksum, (spa_t *) spa); + ctx = spa->spa_cksum_tmpls[checksum]; + } + if (ci->ci_flags & ZCHECKSUM_FLAG_EMBEDDED) { zio_eck_t *eck; @@ -291,7 +315,7 @@ zio_checksum_verify(const blkptr_t *bp, void *data) expected_cksum = eck->zec_cksum; eck->zec_cksum = verifier; - ci->ci_func[byteswap](data, size, NULL, &actual_cksum); + ci->ci_func[byteswap](data, size, ctx, &actual_cksum); eck->zec_cksum = expected_cksum; if (byteswap) @@ -299,11 +323,11 @@ zio_checksum_verify(const blkptr_t *bp, void *data) sizeof (zio_cksum_t)); } else { expected_cksum = bp->blk_cksum; - ci->ci_func[0](data, size, NULL, &actual_cksum); + ci->ci_func[0](data, size, ctx, &actual_cksum); } if (!ZIO_CHECKSUM_EQUAL(actual_cksum, expected_cksum)) { - /*printf("ZFS: read checksum failed\n");*/ + /* printf("ZFS: read checksum %s failed\n", ci->ci_name); */ return (EIO); } @@ -1313,10 +1337,11 @@ vdev_child(vdev_t *pvd, uint64_t devidx) * any ereports we generate can note it. */ static int -raidz_checksum_verify(const blkptr_t *bp, void *data, uint64_t size) +raidz_checksum_verify(const spa_t *spa, const blkptr_t *bp, void *data, + uint64_t size) { - return (zio_checksum_verify(bp, data)); + return (zio_checksum_verify(spa, bp, data)); } /* @@ -1365,8 +1390,8 @@ raidz_parity_verify(raidz_map_t *rm) * cases we'd only use parity information in column 0. */ static int -vdev_raidz_combrec(raidz_map_t *rm, const blkptr_t *bp, void *data, - off_t offset, uint64_t bytes, int total_errors, int data_errors) +vdev_raidz_combrec(const spa_t *spa, raidz_map_t *rm, const blkptr_t *bp, + void *data, off_t offset, uint64_t bytes, int total_errors, int data_errors) { raidz_col_t *rc; void *orig[VDEV_RAIDZ_MAXPARITY]; @@ -1445,7 +1470,7 @@ vdev_raidz_combrec(raidz_map_t *rm, const blkptr_t *bp, void *data, * success. */ code = vdev_raidz_reconstruct(rm, tgts, n); - if (raidz_checksum_verify(bp, data, bytes) == 0) { + if (raidz_checksum_verify(spa, bp, data, bytes) == 0) { for (i = 0; i < n; i++) { c = tgts[i]; rc = &rm->rm_col[c]; @@ -1616,7 +1641,7 @@ reconstruct: */ if (total_errors <= rm->rm_firstdatacol - parity_untried) { if (data_errors == 0) { - if (raidz_checksum_verify(bp, data, bytes) == 0) { + if (raidz_checksum_verify(vd->spa, bp, data, bytes) == 0) { /* * If we read parity information (unnecessarily * as it happens since no reconstruction was @@ -1661,7 +1686,7 @@ reconstruct: code = vdev_raidz_reconstruct(rm, tgts, n); - if (raidz_checksum_verify(bp, data, bytes) == 0) { + if (raidz_checksum_verify(vd->spa, bp, data, bytes) == 0) { /* * If we read more parity disks than were used * for reconstruction, confirm that the other @@ -1735,7 +1760,7 @@ reconstruct: if (total_errors > rm->rm_firstdatacol) { error = EIO; } else if (total_errors < rm->rm_firstdatacol && - (code = vdev_raidz_combrec(rm, bp, data, offset, bytes, + (code = vdev_raidz_combrec(vd->spa, rm, bp, data, offset, bytes, total_errors, data_errors)) != 0) { /* * If we didn't use all the available parity for the diff --git a/usr/src/boot/sys/sys/types.h b/usr/src/boot/sys/sys/types.h index 579b104924..ee3d847278 100644 --- a/usr/src/boot/sys/sys/types.h +++ b/usr/src/boot/sys/sys/types.h @@ -58,6 +58,11 @@ typedef unsigned int uint; /* Sys V compatibility */ #endif /* + * POSIX Extensions + */ +typedef unsigned int uint_t; + +/* * XXX POSIX sized integrals that should appear only in <sys/stdint.h>. */ #include <sys/_stdint.h> diff --git a/usr/src/uts/common/sys/debug.h b/usr/src/uts/common/sys/debug.h index 645716cd9c..e4a959205a 100644 --- a/usr/src/uts/common/sys/debug.h +++ b/usr/src/uts/common/sys/debug.h @@ -36,7 +36,9 @@ #ifndef _SYS_DEBUG_H #define _SYS_DEBUG_H +#if !defined(_STANDALONE) #include <sys/isa_defs.h> +#endif #include <sys/types.h> #include <sys/note.h> diff --git a/usr/src/uts/common/sys/systm.h b/usr/src/uts/common/sys/systm.h index 32af97f4fa..0a56d5d191 100644 --- a/usr/src/uts/common/sys/systm.h +++ b/usr/src/uts/common/sys/systm.h @@ -31,15 +31,21 @@ #ifndef _SYS_SYSTM_H #define _SYS_SYSTM_H +#if defined(_STANDALONE) +#include <sys/cdefs.h> +#include <string.h> +#else #include <sys/types.h> #include <sys/t_lock.h> #include <sys/proc.h> #include <sys/dditypes.h> +#endif #ifdef __cplusplus extern "C" { #endif +#if !defined(_STANDALONE) /* * The pc_t is the type of the kernel's program counter. In general, a * pc_t is a uintptr_t -- except for a sparcv9 kernel, in which case all @@ -508,6 +514,7 @@ extern int __lintzero; /* for spoofing lint */ #define __lintzero 0 #endif /* __lint */ #endif /* _KERNEL || _BOOT */ +#endif /* !_STANDALONE */ #ifdef __cplusplus } |