# HG changeset patch # User Toomas Soome # Date 1512383210 -7200 # Node ID 2f1019fa0103bde46f3d8eb4ec547c1c56e76ddd # Parent 969c95446ef0eca30a8821d54c3ab20b000067e6 loader: add skein/edonr support illumos issue #8905 diff -r 969c95446ef0 -r 2f1019fa0103 include/sys/debug.h --- a/include/sys/debug.h Wed Jun 01 18:53:15 2016 +0300 +++ b/include/sys/debug.h Mon Dec 04 12:26:50 2017 +0200 @@ -36,7 +36,9 @@ #ifndef _SYS_DEBUG_H #define _SYS_DEBUG_H +#if !defined(_STANDALONE) #include +#endif #include #include diff -r 969c95446ef0 -r 2f1019fa0103 include/sys/systm.h --- a/include/sys/systm.h Wed Jun 01 18:53:15 2016 +0300 +++ b/include/sys/systm.h Mon Dec 04 12:26:50 2017 +0200 @@ -31,15 +31,21 @@ #ifndef _SYS_SYSTM_H #define _SYS_SYSTM_H +#if defined(_STANDALONE) +#include +#include +#else #include #include #include #include +#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 @@ -503,6 +509,7 @@ #define __lintzero 0 #endif /* __lint */ #endif /* _KERNEL || _BOOT */ +#endif /* !_STANDALONE */ #ifdef __cplusplus } diff -r 969c95446ef0 -r 2f1019fa0103 usr/src/boot/sys/boot/efi/boot1/Makefile --- a/usr/src/boot/sys/boot/efi/boot1/Makefile Wed Jun 01 18:53:15 2016 +0300 +++ b/usr/src/boot/sys/boot/efi/boot1/Makefile Mon Dec 04 12:26:50 2017 +0200 @@ -33,7 +33,7 @@ ASFLAGS=-m64 -fPIC CFLAGS= -O2 -CPPFLAGS= -nostdinc +CPPFLAGS= -nostdinc -D_STANDALONE CPPFLAGS += -I. CPPFLAGS += -I./../include CPPFLAGS += -I./../include/${MACHINE} @@ -51,6 +51,9 @@ # Always add MI sources and REGULAR efi loader bits CPPFLAGS += -I./../../common +# For sys/skein.h +CPPFLAGS += -I$(SRCTOP)/include + include ../Makefile.inc FILES= boot1.efi diff -r 969c95446ef0 -r 2f1019fa0103 usr/src/boot/sys/boot/i386/gptzfsboot/gptldr.S --- a/usr/src/boot/sys/boot/i386/gptzfsboot/gptldr.S Wed Jun 01 18:53:15 2016 +0300 +++ b/usr/src/boot/sys/boot/i386/gptzfsboot/gptldr.S Mon Dec 04 12:26:50 2017 +0200 @@ -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 -r 969c95446ef0 -r 2f1019fa0103 usr/src/boot/sys/boot/zfs/Makefile.com --- a/usr/src/boot/sys/boot/zfs/Makefile.com Wed Jun 01 18:53:15 2016 +0300 +++ b/usr/src/boot/sys/boot/zfs/Makefile.com Mon Dec 04 12:26:50 2017 +0200 @@ -29,13 +29,21 @@ 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$(SRCTOP)/include + +# 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 @@ %.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 -r 969c95446ef0 -r 2f1019fa0103 usr/src/boot/sys/boot/zfs/zfsimpl.c --- a/usr/src/boot/sys/boot/zfs/zfsimpl.c Wed Jun 01 18:53:15 2016 +0300 +++ b/usr/src/boot/sys/boot/zfs/zfsimpl.c Mon Dec 04 12:26:50 2017 +0200 @@ -58,6 +58,8 @@ "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 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 @@ 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 @@ 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 @@ } zfs_free(upbuf, VDEV_UBERBLOCK_SIZE(vdev)); + vdev->spa = spa; if (spap != NULL) *spap = spa; return (0); @@ -1201,7 +1209,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ * 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_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 @@ 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 @@ 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 @@ /* * 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 @@ /* * 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 @@ &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 @@ 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 @@ 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 @@ 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 @@ 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 -r 969c95446ef0 -r 2f1019fa0103 usr/src/boot/sys/cddl/boot/zfs/edonr_zfs.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/boot/sys/cddl/boot/zfs/edonr_zfs.c Mon Dec 04 12:26:50 2017 +0200 @@ -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 + +#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 -r 969c95446ef0 -r 2f1019fa0103 usr/src/boot/sys/cddl/boot/zfs/skein_zfs.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/boot/sys/cddl/boot/zfs/skein_zfs.c Mon Dec 04 12:26:50 2017 +0200 @@ -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 + +/* + * 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 -r 969c95446ef0 -r 2f1019fa0103 usr/src/boot/sys/cddl/boot/zfs/zfsimpl.h --- a/usr/src/boot/sys/cddl/boot/zfs/zfsimpl.h Wed Jun 01 18:53:15 2016 +0300 +++ b/usr/src/boot/sys/cddl/boot/zfs/zfsimpl.h Mon Dec 04 12:26:50 2017 +0200 @@ -1071,6 +1071,8 @@ 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 @@ -1206,6 +1208,7 @@ #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 @@ -1511,6 +1514,7 @@ * 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, @@ -1535,6 +1539,7 @@ 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; /* @@ -1550,6 +1555,8 @@ 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 -r 969c95446ef0 -r 2f1019fa0103 usr/src/boot/sys/cddl/boot/zfs/zfssubr.c --- a/usr/src/boot/sys/cddl/boot/zfs/zfssubr.c Wed Jun 01 18:53:15 2016 +0300 +++ b/usr/src/boot/sys/cddl/boot/zfs/zfssubr.c Mon Dec 04 12:26:50 2017 +0200 @@ -105,6 +105,8 @@ #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 @@ 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 @@ * 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 @@ 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 @@ 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 @@ 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 @@ * 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 @@ * 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 @@ * 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 @@ */ 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 @@ 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 @@ 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 -r 969c95446ef0 -r 2f1019fa0103 usr/src/boot/sys/sys/types.h --- a/usr/src/boot/sys/sys/types.h Wed Jun 01 18:53:15 2016 +0300 +++ b/usr/src/boot/sys/sys/types.h Mon Dec 04 12:26:50 2017 +0200 @@ -58,6 +58,11 @@ #endif /* + * POSIX Extensions + */ +typedef unsigned int uint_t; + +/* * XXX POSIX sized integrals that should appear only in . */ #include