Author: mav
Date: Fri Nov 13 09:32:04 2015
New Revision: 290757
URL: https://svnweb.freebsd.org/changeset/base/290757

Log:
  MFC r289422:
  4185 add new cryptographic checksums to ZFS: SHA-512, Skein, Edon-R
  
  Reviewed by: George Wilson <george.wil...@delphix.com>
  Reviewed by: Prakash Surya <prakash.su...@delphix.com>
  Reviewed by: Saso Kiselkov <saso.kisel...@nexenta.com>
  Reviewed by: Richard Lowe <richl...@richlowe.net>
  Approved by: Garrett D'Amore <garr...@damore.org>
  Author: Matthew Ahrens <mahr...@delphix.com>
  
  illumos/illumos-gate@45818ee124adeaaf947698996b4f4c722afc6d1f
  
  This is only a partial merge of respective ZFS infrastructure changes.
  At this moment FreeBSD kernel has no those crypto algorithms, so the
  parts of the code to enable them are commented out.  When they are
  implemented, it will be trivial to plug them in.

Added:
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/edonr_zfs.c
     - copied unchanged from r289422, 
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/edonr_zfs.c
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/skein_zfs.c
     - copied unchanged from r289422, 
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/skein_zfs.c
Modified:
  stable/10/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
  stable/10/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c
  stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c
  stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h
  stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_fletcher.c
  stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_fletcher.h
  stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_prop.c
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sha256.c
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio_checksum.h
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_checksum.c
  stable/10/sys/cddl/contrib/opensolaris/uts/common/sys/debug.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
==============================================================================
--- stable/10/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c       
Fri Nov 13 09:30:17 2015        (r290756)
+++ stable/10/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c       
Fri Nov 13 09:32:04 2015        (r290757)
@@ -1487,6 +1487,12 @@ zfs_setprop_error(libzfs_handle_t *hdl, 
                            "property setting is not allowed on "
                            "bootable datasets"));
                        (void) zfs_error(hdl, EZFS_NOTSUP, errbuf);
+               } else if (prop == ZFS_PROP_CHECKSUM ||
+                   prop == ZFS_PROP_DEDUP) {
+                       (void) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+                           "property setting is not allowed on "
+                           "root pools"));
+                       (void) zfs_error(hdl, EZFS_NOTSUP, errbuf);
                } else {
                        (void) zfs_standard_error(hdl, err, errbuf);
                }

Modified: stable/10/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c
==============================================================================
--- stable/10/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c      
Fri Nov 13 09:30:17 2015        (r290756)
+++ stable/10/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c      
Fri Nov 13 09:32:04 2015        (r290757)
@@ -1423,7 +1423,7 @@ zfs_send_resume_token_to_nvlist(libzfs_h
 
        /* verify checksum */
        zio_cksum_t cksum;
-       fletcher_4_native(compressed, len, &cksum);
+       fletcher_4_native(compressed, len, NULL, &cksum);
        if (cksum.zc_word[0] != checksum) {
                free(compressed);
                zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,

Modified: stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c Fri Nov 
13 09:30:17 2015        (r290756)
+++ stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c Fri Nov 
13 09:32:04 2015        (r290757)
@@ -230,4 +230,19 @@ zpool_feature_init(void)
            "org.open-zfs:large_blocks", "large_blocks",
            "Support for blocks larger than 128KB.",
            ZFEATURE_FLAG_PER_DATASET, large_blocks_deps);
+
+#ifdef illumos
+       zfeature_register(SPA_FEATURE_SHA512,
+           "org.illumos:sha512", "sha512",
+           "SHA-512/256 hash algorithm.",
+           ZFEATURE_FLAG_PER_DATASET, NULL);
+       zfeature_register(SPA_FEATURE_SKEIN,
+           "org.illumos:skein", "skein",
+           "Skein hash algorithm.",
+           ZFEATURE_FLAG_PER_DATASET, NULL);
+       zfeature_register(SPA_FEATURE_EDONR,
+           "org.illumos:edonr", "edonr",
+           "Edon-R hash algorithm.",
+           ZFEATURE_FLAG_PER_DATASET, NULL);
+#endif
 }

Modified: stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h Fri Nov 
13 09:30:17 2015        (r290756)
+++ stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h Fri Nov 
13 09:32:04 2015        (r290757)
@@ -51,6 +51,11 @@ typedef enum spa_feature {
        SPA_FEATURE_BOOKMARKS,
        SPA_FEATURE_FS_SS_LIMIT,
        SPA_FEATURE_LARGE_BLOCKS,
+#ifdef illumos
+       SPA_FEATURE_SHA512,
+       SPA_FEATURE_SKEIN,
+       SPA_FEATURE_EDONR,
+#endif
        SPA_FEATURES
 } spa_feature_t;
 

Modified: stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_fletcher.c
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_fletcher.c    Fri Nov 
13 09:30:17 2015        (r290756)
+++ stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_fletcher.c    Fri Nov 
13 09:32:04 2015        (r290757)
@@ -22,6 +22,9 @@
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+/*
+ * Copyright 2013 Saso Kiselkov. All rights reserved.
+ */
 
 /*
  * Fletcher Checksums
@@ -131,8 +134,10 @@
 #include <sys/zio.h>
 #include <sys/spa.h>
 
+/*ARGSUSED*/
 void
-fletcher_2_native(const void *buf, uint64_t size, zio_cksum_t *zcp)
+fletcher_2_native(const void *buf, uint64_t size,
+    const void *ctx_template, zio_cksum_t *zcp)
 {
        const uint64_t *ip = buf;
        const uint64_t *ipend = ip + (size / sizeof (uint64_t));
@@ -148,8 +153,10 @@ fletcher_2_native(const void *buf, uint6
        ZIO_SET_CHECKSUM(zcp, a0, a1, b0, b1);
 }
 
+/*ARGSUSED*/
 void
-fletcher_2_byteswap(const void *buf, uint64_t size, zio_cksum_t *zcp)
+fletcher_2_byteswap(const void *buf, uint64_t size,
+    const void *ctx_template, zio_cksum_t *zcp)
 {
        const uint64_t *ip = buf;
        const uint64_t *ipend = ip + (size / sizeof (uint64_t));
@@ -165,8 +172,10 @@ fletcher_2_byteswap(const void *buf, uin
        ZIO_SET_CHECKSUM(zcp, a0, a1, b0, b1);
 }
 
+/*ARGSUSED*/
 void
-fletcher_4_native(const void *buf, uint64_t size, zio_cksum_t *zcp)
+fletcher_4_native(const void *buf, uint64_t size,
+    const void *ctx_template, zio_cksum_t *zcp)
 {
        const uint32_t *ip = buf;
        const uint32_t *ipend = ip + (size / sizeof (uint32_t));
@@ -182,8 +191,10 @@ fletcher_4_native(const void *buf, uint6
        ZIO_SET_CHECKSUM(zcp, a, b, c, d);
 }
 
+/*ARGSUSED*/
 void
-fletcher_4_byteswap(const void *buf, uint64_t size, zio_cksum_t *zcp)
+fletcher_4_byteswap(const void *buf, uint64_t size,
+    const void *ctx_template, zio_cksum_t *zcp)
 {
        const uint32_t *ip = buf;
        const uint32_t *ipend = ip + (size / sizeof (uint32_t));

Modified: stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_fletcher.h
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_fletcher.h    Fri Nov 
13 09:30:17 2015        (r290756)
+++ stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_fletcher.h    Fri Nov 
13 09:32:04 2015        (r290757)
@@ -22,6 +22,9 @@
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+/*
+ * Copyright 2013 Saso Kiselkov. All rights reserved.
+ */
 
 #ifndef        _ZFS_FLETCHER_H
 #define        _ZFS_FLETCHER_H
@@ -37,14 +40,12 @@ extern "C" {
  * fletcher checksum functions
  */
 
-void fletcher_2_native(const void *, uint64_t, zio_cksum_t *);
-void fletcher_2_byteswap(const void *, uint64_t, zio_cksum_t *);
-void fletcher_4_native(const void *, uint64_t, zio_cksum_t *);
-void fletcher_4_byteswap(const void *, uint64_t, zio_cksum_t *);
-void fletcher_4_incremental_native(const void *, uint64_t,
-    zio_cksum_t *);
-void fletcher_4_incremental_byteswap(const void *, uint64_t,
-    zio_cksum_t *);
+void fletcher_2_native(const void *, uint64_t, const void *, zio_cksum_t *);
+void fletcher_2_byteswap(const void *, uint64_t, const void *, zio_cksum_t *);
+void fletcher_4_native(const void *, uint64_t, const void *, zio_cksum_t *);
+void fletcher_4_byteswap(const void *, uint64_t, const void *, zio_cksum_t *);
+void fletcher_4_incremental_native(const void *, uint64_t, zio_cksum_t *);
+void fletcher_4_incremental_byteswap(const void *, uint64_t, zio_cksum_t *);
 
 #ifdef __cplusplus
 }

Modified: stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_prop.c
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_prop.c        Fri Nov 
13 09:30:17 2015        (r290756)
+++ stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_prop.c        Fri Nov 
13 09:32:04 2015        (r290757)
@@ -71,6 +71,11 @@ zfs_prop_init(void)
                { "fletcher4",  ZIO_CHECKSUM_FLETCHER_4 },
                { "sha256",     ZIO_CHECKSUM_SHA256 },
                { "noparity",   ZIO_CHECKSUM_NOPARITY },
+#ifdef illumos
+               { "sha512",     ZIO_CHECKSUM_SHA512 },
+               { "skein",      ZIO_CHECKSUM_SKEIN },
+               { "edonr",      ZIO_CHECKSUM_EDONR },
+#endif
                { NULL }
        };
 
@@ -81,6 +86,16 @@ zfs_prop_init(void)
                { "sha256",     ZIO_CHECKSUM_SHA256 },
                { "sha256,verify",
                                ZIO_CHECKSUM_SHA256 | ZIO_CHECKSUM_VERIFY },
+#ifdef illumos
+               { "sha512",     ZIO_CHECKSUM_SHA512 },
+               { "sha512,verify",
+                               ZIO_CHECKSUM_SHA512 | ZIO_CHECKSUM_VERIFY },
+               { "skein",      ZIO_CHECKSUM_SKEIN },
+               { "skein,verify",
+                               ZIO_CHECKSUM_SKEIN | ZIO_CHECKSUM_VERIFY },
+               { "edonr,verify",
+                               ZIO_CHECKSUM_EDONR | ZIO_CHECKSUM_VERIFY },
+#endif
                { NULL }
        };
 
@@ -225,12 +240,12 @@ zfs_prop_init(void)
        zprop_register_index(ZFS_PROP_CHECKSUM, "checksum",
            ZIO_CHECKSUM_DEFAULT, PROP_INHERIT, ZFS_TYPE_FILESYSTEM |
            ZFS_TYPE_VOLUME,
-           "on | off | fletcher2 | fletcher4 | sha256", "CHECKSUM",
-           checksum_table);
+           "on | off | fletcher2 | fletcher4 | sha256 | sha512 | "
+           "skein | edonr", "CHECKSUM", checksum_table);
        zprop_register_index(ZFS_PROP_DEDUP, "dedup", ZIO_CHECKSUM_OFF,
            PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
-           "on | off | verify | sha256[,verify]", "DEDUP",
-           dedup_table);
+           "on | off | verify | sha256[,verify], sha512[,verify], "
+           "skein[,verify], edonr,verify", "DEDUP", dedup_table);
        zprop_register_index(ZFS_PROP_COMPRESSION, "compression",
            ZIO_COMPRESS_DEFAULT, PROP_INHERIT,
            ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,

Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c      Fri Nov 
13 09:30:17 2015        (r290756)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c      Fri Nov 
13 09:32:04 2015        (r290757)
@@ -1555,7 +1555,7 @@ arc_cksum_verify(arc_buf_t *buf)
                mutex_exit(&buf->b_hdr->b_l1hdr.b_freeze_lock);
                return;
        }
-       fletcher_2_native(buf->b_data, buf->b_hdr->b_size, &zc);
+       fletcher_2_native(buf->b_data, buf->b_hdr->b_size, NULL, &zc);
        if (!ZIO_CHECKSUM_EQUAL(*buf->b_hdr->b_freeze_cksum, zc))
                panic("buffer modified while frozen!");
        mutex_exit(&buf->b_hdr->b_l1hdr.b_freeze_lock);
@@ -1568,7 +1568,7 @@ arc_cksum_equal(arc_buf_t *buf)
        int equal;
 
        mutex_enter(&buf->b_hdr->b_l1hdr.b_freeze_lock);
-       fletcher_2_native(buf->b_data, buf->b_hdr->b_size, &zc);
+       fletcher_2_native(buf->b_data, buf->b_hdr->b_size, NULL, &zc);
        equal = ZIO_CHECKSUM_EQUAL(*buf->b_hdr->b_freeze_cksum, zc);
        mutex_exit(&buf->b_hdr->b_l1hdr.b_freeze_lock);
 
@@ -1588,7 +1588,7 @@ arc_cksum_compute(arc_buf_t *buf, boolea
        }
        buf->b_hdr->b_freeze_cksum = kmem_alloc(sizeof (zio_cksum_t), KM_SLEEP);
        fletcher_2_native(buf->b_data, buf->b_hdr->b_size,
-           buf->b_hdr->b_freeze_cksum);
+           NULL, buf->b_hdr->b_freeze_cksum);
        mutex_exit(&buf->b_hdr->b_l1hdr.b_freeze_lock);
 #ifdef illumos
        arc_buf_watch(buf);

Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c      Fri Nov 
13 09:30:17 2015        (r290756)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c      Fri Nov 
13 09:32:04 2015        (r290757)
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
  */
 
 #include <sys/zfs_context.h>
@@ -65,7 +65,8 @@ ddt_object_create(ddt_t *ddt, enum ddt_t
        spa_t *spa = ddt->ddt_spa;
        objset_t *os = ddt->ddt_os;
        uint64_t *objectp = &ddt->ddt_object[type][class];
-       boolean_t prehash = zio_checksum_table[ddt->ddt_checksum].ci_dedup;
+       boolean_t prehash = zio_checksum_table[ddt->ddt_checksum].ci_flags &
+           ZCHECKSUM_FLAG_DEDUP;
        char name[DDT_NAMELEN];
 
        ddt_object_name(ddt, type, class, name);

Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c      Fri Nov 
13 09:30:17 2015        (r290756)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c      Fri Nov 
13 09:32:04 2015        (r290757)
@@ -1494,7 +1494,8 @@ dmu_sync_done(zio_t *zio, arc_buf_t *buf
 
                        ASSERT(BP_EQUAL(bp, bp_orig));
                        ASSERT(zio->io_prop.zp_compress != ZIO_COMPRESS_OFF);
-                       ASSERT(zio_checksum_table[chksum].ci_dedup);
+                       ASSERT(zio_checksum_table[chksum].ci_flags &
+                           ZCHECKSUM_FLAG_NOPWRITE);
                }
                dr->dt.dl.dr_overridden_by = *zio->io_bp;
                dr->dt.dl.dr_override_state = DR_OVERRIDDEN;
@@ -1842,8 +1843,10 @@ dmu_write_policy(objset_t *os, dnode_t *
                 * as well.  Otherwise, the metadata checksum defaults
                 * to fletcher4.
                 */
-               if (zio_checksum_table[checksum].ci_correctable < 1 ||
-                   zio_checksum_table[checksum].ci_eck)
+               if (!(zio_checksum_table[checksum].ci_flags &
+                   ZCHECKSUM_FLAG_METADATA) ||
+                   (zio_checksum_table[checksum].ci_flags &
+                   ZCHECKSUM_FLAG_EMBEDDED))
                        checksum = ZIO_CHECKSUM_FLETCHER_4;
 
                if (os->os_redundant_metadata == ZFS_REDUNDANT_METADATA_ALL ||
@@ -1882,17 +1885,20 @@ dmu_write_policy(objset_t *os, dnode_t *
                 */
                if (dedup_checksum != ZIO_CHECKSUM_OFF) {
                        dedup = (wp & WP_DMU_SYNC) ? B_FALSE : B_TRUE;
-                       if (!zio_checksum_table[checksum].ci_dedup)
+                       if (!(zio_checksum_table[checksum].ci_flags &
+                           ZCHECKSUM_FLAG_DEDUP))
                                dedup_verify = B_TRUE;
                }
 
                /*
-                * Enable nopwrite if we have a cryptographically secure
-                * checksum that has no known collisions (i.e. SHA-256)
-                * and compression is enabled.  We don't enable nopwrite if
-                * dedup is enabled as the two features are mutually exclusive.
+                * Enable nopwrite if we have secure enough checksum
+                * algorithm (see comment in zio_nop_write) and
+                * compression is enabled.  We don't enable nopwrite if
+                * dedup is enabled as the two features are mutually
+                * exclusive.
                 */
-               nopwrite = (!dedup && zio_checksum_table[checksum].ci_dedup &&
+               nopwrite = (!dedup && (zio_checksum_table[checksum].ci_flags &
+                   ZCHECKSUM_FLAG_NOPWRITE) &&
                    compress != ZIO_COMPRESS_OFF && zfs_nopwrite_enabled);
        }
 

Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c Fri Nov 
13 09:30:17 2015        (r290756)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c Fri Nov 
13 09:32:04 2015        (r290757)
@@ -292,7 +292,8 @@ dump_write(dmu_sendarg_t *dsp, dmu_objec
                drrw->drr_checksumtype = ZIO_CHECKSUM_OFF;
        } else {
                drrw->drr_checksumtype = BP_GET_CHECKSUM(bp);
-               if (zio_checksum_table[drrw->drr_checksumtype].ci_dedup)
+               if (zio_checksum_table[drrw->drr_checksumtype].ci_flags &
+                   ZCHECKSUM_FLAG_DEDUP)
                        drrw->drr_checksumflags |= DRR_CHECKSUM_DEDUP;
                DDK_SET_LSIZE(&drrw->drr_key, BP_GET_LSIZE(bp));
                DDK_SET_PSIZE(&drrw->drr_key, BP_GET_PSIZE(bp));

Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c      
Fri Nov 13 09:30:17 2015        (r290756)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c      
Fri Nov 13 09:32:04 2015        (r290757)
@@ -52,6 +52,8 @@
 #include <sys/dsl_destroy.h>
 #include <sys/dsl_userhold.h>
 #include <sys/dsl_bookmark.h>
+#include <sys/dmu_send.h>
+#include <sys/zio_checksum.h>
 #include <sys/zio_compress.h>
 #include <zfs_fletcher.h>
 
@@ -133,10 +135,16 @@ dsl_dataset_block_born(dsl_dataset_t *ds
        dsl_dataset_phys(ds)->ds_compressed_bytes += compressed;
        dsl_dataset_phys(ds)->ds_uncompressed_bytes += uncompressed;
        dsl_dataset_phys(ds)->ds_unique_bytes += used;
+
        if (BP_GET_LSIZE(bp) > SPA_OLD_MAXBLOCKSIZE) {
                ds->ds_feature_activation_needed[SPA_FEATURE_LARGE_BLOCKS] =
                    B_TRUE;
        }
+
+       spa_feature_t f = zio_checksum_to_feature(BP_GET_CHECKSUM(bp));
+       if (f != SPA_FEATURE_NONE)
+               ds->ds_feature_activation_needed[f] = B_TRUE;
+
        mutex_exit(&ds->ds_lock);
        dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD, delta,
            compressed, uncompressed, tx);
@@ -1791,7 +1799,7 @@ get_receive_resume_stats(dsl_dataset_t *
                    packed_size, packed_size, 6);
 
                zio_cksum_t cksum;
-               fletcher_4_native(compressed, compressed_size, &cksum);
+               fletcher_4_native(compressed, compressed_size, NULL, &cksum);
 
                str = kmem_alloc(compressed_size * 2 + 1, KM_SLEEP);
                for (int i = 0; i < compressed_size; i++) {

Copied: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/edonr_zfs.c 
(from r289422, head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/edonr_zfs.c)
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/edonr_zfs.c        
Fri Nov 13 09:32:04 2015        (r290757, copy of r289422, 
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/edonr_zfs.c)
@@ -0,0 +1,102 @@
+/*
+ * 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/zfs_context.h>
+#include <sys/zio.h>
+#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*/
+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.
+ */
+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]);
+}
+
+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))).
+        */
+       CTASSERT(EDONR_BLOCK_SIZE == 2 * (EDONR_MODE / 8));
+       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 = kmem_zalloc(sizeof (*ctx), KM_SLEEP);
+       EdonRInit(ctx, EDONR_MODE);
+       EdonRUpdate(ctx, salt_block, sizeof (salt_block) * 8);
+       return (ctx);
+}
+
+void
+zio_checksum_edonr_tmpl_free(void *ctx_template)
+{
+       EdonRState      *ctx = ctx_template;
+
+       bzero(ctx, sizeof (*ctx));
+       kmem_free(ctx, sizeof (*ctx));
+}

Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sha256.c
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sha256.c   Fri Nov 
13 09:30:17 2015        (r290756)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sha256.c   Fri Nov 
13 09:32:04 2015        (r290757)
@@ -22,6 +22,9 @@
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+/*
+ * Copyright 2013 Saso Kiselkov. All rights reserved.
+ */
 #include <sys/zfs_context.h>
 #include <sys/zio.h>
 #ifdef _KERNEL
@@ -30,8 +33,10 @@
 #include <sha256.h>
 #endif
 
+/*ARGSUSED*/
 void
-zio_checksum_SHA256(const void *buf, uint64_t size, zio_cksum_t *zcp)
+zio_checksum_SHA256(const void *buf, uint64_t size,
+    const void *ctx_template, zio_cksum_t *zcp)
 {
        SHA256_CTX ctx;
        zio_cksum_t tmp;
@@ -52,3 +57,31 @@ zio_checksum_SHA256(const void *buf, uin
        zcp->zc_word[2] = BE_64(tmp.zc_word[2]);
        zcp->zc_word[3] = BE_64(tmp.zc_word[3]);
 }
+
+#ifdef illumos
+/*ARGSUSED*/
+void
+zio_checksum_SHA512_native(const void *buf, uint64_t size,
+    const void *ctx_template, zio_cksum_t *zcp)
+{
+       SHA2_CTX        ctx;
+
+       SHA2Init(SHA512_256, &ctx);
+       SHA2Update(&ctx, buf, size);
+       SHA2Final(zcp, &ctx);
+}
+
+/*ARGSUSED*/
+void
+zio_checksum_SHA512_byteswap(const void *buf, uint64_t size,
+    const void *ctx_template, zio_cksum_t *zcp)
+{
+       zio_cksum_t     tmp;
+
+       zio_checksum_SHA512_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]);
+}
+#endif

Copied: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/skein_zfs.c 
(from r289422, head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/skein_zfs.c)
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/skein_zfs.c        
Fri Nov 13 09:32:04 2015        (r290757, copy of r289422, 
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/skein_zfs.c)
@@ -0,0 +1,91 @@
+/*
+ * 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/zfs_context.h>
+#include <sys/zio.h>
+#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*/
+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).
+ */
+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.
+ */
+void *
+zio_checksum_skein_tmpl_init(const zio_cksum_salt_t *salt)
+{
+       Skein_512_Ctxt_t        *ctx;
+
+       ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP);
+       (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.
+ */
+void
+zio_checksum_skein_tmpl_free(void *ctx_template)
+{
+       Skein_512_Ctxt_t        *ctx = ctx_template;
+
+       bzero(ctx, sizeof (*ctx));
+       kmem_free(ctx, sizeof (*ctx));
+}

Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c      Fri Nov 
13 09:30:17 2015        (r290756)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c      Fri Nov 
13 09:32:04 2015        (r290757)
@@ -25,6 +25,7 @@
  * Copyright (c) 2015, Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2013 Martin Matuska <m...@freebsd.org>. All rights reserved.
  * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
+ * Copyright 2013 Saso Kiselkov. All rights reserved.
  */
 
 /*
@@ -2579,6 +2580,19 @@ spa_load_impl(spa_t *spa, uint64_t pool_
                return (spa_load(spa, state, SPA_IMPORT_EXISTING, B_TRUE));
        }
 
+       /* Grab the secret checksum salt from the MOS. */
+       error = zap_lookup(spa->spa_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
+           DMU_POOL_CHECKSUM_SALT, 1,
+           sizeof (spa->spa_cksum_salt.zcs_bytes),
+           spa->spa_cksum_salt.zcs_bytes);
+       if (error == ENOENT) {
+               /* Generate a new salt for subsequent use */
+               (void) random_get_pseudo_bytes(spa->spa_cksum_salt.zcs_bytes,
+                   sizeof (spa->spa_cksum_salt.zcs_bytes));
+       } else if (error != 0) {
+               return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
+       }
+
        if (spa_dir_prop(spa, DMU_POOL_SYNC_BPOBJ, &obj) != 0)
                return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
        error = bpobj_open(&spa->spa_deferred_bpobj, spa->spa_meta_objset, obj);
@@ -3747,6 +3761,12 @@ spa_create(const char *pool, nvlist_t *n
                spa_history_create_obj(spa, tx);
 
        /*
+        * Generate some random noise for salted checksums to operate on.
+        */
+       (void) random_get_pseudo_bytes(spa->spa_cksum_salt.zcs_bytes,
+           sizeof (spa->spa_cksum_salt.zcs_bytes));
+
+       /*
         * Set pool properties.
         */
        spa->spa_bootfs = zpool_prop_default_numeric(ZPOOL_PROP_BOOTFS);
@@ -6551,6 +6571,20 @@ spa_sync_upgrades(spa_t *spa, dmu_tx_t *
                if (lz4_en && !lz4_ac)
                        spa_feature_incr(spa, SPA_FEATURE_LZ4_COMPRESS, tx);
        }
+
+       /*
+        * If we haven't written the salt, do so now.  Note that the
+        * feature may not be activated yet, but that's fine since
+        * the presence of this ZAP entry is backwards compatible.
+        */
+       if (zap_contains(spa->spa_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
+           DMU_POOL_CHECKSUM_SALT) == ENOENT) {
+               VERIFY0(zap_add(spa->spa_meta_objset,
+                   DMU_POOL_DIRECTORY_OBJECT, DMU_POOL_CHECKSUM_SALT, 1,
+                   sizeof (spa->spa_cksum_salt.zcs_bytes),
+                   spa->spa_cksum_salt.zcs_bytes, tx));
+       }
+
        rrw_exit(&dp->dp_config_rwlock, FTAG);
 }
 

Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c Fri Nov 
13 09:30:17 2015        (r290756)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c Fri Nov 
13 09:32:04 2015        (r290757)
@@ -24,6 +24,7 @@
  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2013 Martin Matuska <m...@freebsd.org>. All rights reserved.
  * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
+ * Copyright 2013 Saso Kiselkov. All rights reserved.
  */
 
 #include <sys/zfs_context.h>
@@ -51,7 +52,7 @@
 #include <sys/arc.h>
 #include <sys/ddt.h>
 #include "zfs_prop.h"
-#include "zfeature_common.h"
+#include <sys/zfeature.h>
 
 /*
  * SPA locking
@@ -608,6 +609,7 @@ spa_add(const char *name, nvlist_t *conf
        mutex_init(&spa->spa_history_lock, NULL, MUTEX_DEFAULT, NULL);
        mutex_init(&spa->spa_proc_lock, NULL, MUTEX_DEFAULT, NULL);
        mutex_init(&spa->spa_props_lock, NULL, MUTEX_DEFAULT, NULL);
+       mutex_init(&spa->spa_cksum_tmpls_lock, NULL, MUTEX_DEFAULT, NULL);
        mutex_init(&spa->spa_scrub_lock, NULL, MUTEX_DEFAULT, NULL);
        mutex_init(&spa->spa_suspend_lock, NULL, MUTEX_DEFAULT, NULL);
        mutex_init(&spa->spa_vdev_top_lock, NULL, MUTEX_DEFAULT, NULL);
@@ -770,6 +772,8 @@ spa_remove(spa_t *spa)
        for (int t = 0; t < TXG_SIZE; t++)
                bplist_destroy(&spa->spa_free_bplist[t]);
 
+       zio_checksum_templates_free(spa);
+
        cv_destroy(&spa->spa_async_cv);
        cv_destroy(&spa->spa_evicting_os_cv);
        cv_destroy(&spa->spa_proc_cv);
@@ -783,6 +787,7 @@ spa_remove(spa_t *spa)
        mutex_destroy(&spa->spa_history_lock);
        mutex_destroy(&spa->spa_proc_lock);
        mutex_destroy(&spa->spa_props_lock);
+       mutex_destroy(&spa->spa_cksum_tmpls_lock);
        mutex_destroy(&spa->spa_scrub_lock);
        mutex_destroy(&spa->spa_suspend_lock);
        mutex_destroy(&spa->spa_vdev_top_lock);

Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h  Fri Nov 
13 09:30:17 2015        (r290756)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h  Fri Nov 
13 09:32:04 2015        (r290757)
@@ -27,6 +27,7 @@
  * Copyright 2013 DEY Storage Systems, Inc.
  * Copyright 2014 HybridCluster. All rights reserved.
  * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
+ * Copyright 2013 Saso Kiselkov. All rights reserved.
  */
 
 /* Portions Copyright 2010 Robert Milkowski */
@@ -320,6 +321,7 @@ typedef struct dmu_buf {
 #define        DMU_POOL_FREE_BPOBJ             "free_bpobj"
 #define        DMU_POOL_BPTREE_OBJ             "bptree_obj"
 #define        DMU_POOL_EMPTY_BPOBJ            "empty_bpobj"
+#define        DMU_POOL_CHECKSUM_SALT          "org.illumos:checksum_salt"
 
 /*
  * Allocate an object from this objset.  The range of object numbers

Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h  Fri Nov 
13 09:30:17 2015        (r290756)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h  Fri Nov 
13 09:32:04 2015        (r290757)
@@ -23,6 +23,7 @@
  * Copyright (c) 2011, 2014 by Delphix. All rights reserved.
  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
+ * Copyright 2013 Saso Kiselkov. All rights reserved.
  */
 
 #ifndef _SYS_SPA_H
@@ -163,6 +164,14 @@ typedef struct zio_cksum {
 } zio_cksum_t;
 
 /*
+ * Some checksums/hashes need a 256-bit initialization salt. This salt is kept
+ * secret and is suitable for use in MAC algorithms as the key.
+ */
+typedef struct zio_cksum_salt {
+       uint8_t         zcs_bytes[32];
+} zio_cksum_salt_t;
+
+/*
  * Each block is described by its DVAs, time of birth, checksum, etc.
  * The word-by-word, bit-by-bit layout of the blkptr is as follows:
  *

Modified: 
stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h     
Fri Nov 13 09:30:17 2015        (r290756)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h     
Fri Nov 13 09:32:04 2015        (r290757)
@@ -24,6 +24,7 @@
  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2013 Martin Matuska <m...@freebsd.org>. All rights reserved.
  * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
+ * Copyright 2013 Saso Kiselkov. All rights reserved.
  */
 
 #ifndef _SYS_SPA_IMPL_H
@@ -166,6 +167,10 @@ struct spa {
        uint64_t        spa_syncing_txg;        /* txg currently syncing */
        bpobj_t         spa_deferred_bpobj;     /* deferred-free bplist */
        bplist_t        spa_free_bplist[TXG_SIZE]; /* bplist of stuff to free */
+       zio_cksum_salt_t spa_cksum_salt;        /* secret salt for cksum */
+       /* checksum context templates */
+       kmutex_t        spa_cksum_tmpls_lock;
+       void            *spa_cksum_tmpls[ZIO_CHECKSUM_FUNCTIONS];
        uberblock_t     spa_ubsync;             /* last synced uberblock */
        uberblock_t     spa_uberblock;          /* current uberblock */
        boolean_t       spa_extreme_rewind;     /* rewind past deferred frees */

Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h  Fri Nov 
13 09:30:17 2015        (r290756)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h  Fri Nov 
13 09:32:04 2015        (r290757)
@@ -82,6 +82,11 @@ enum zio_checksum {
        ZIO_CHECKSUM_SHA256,
        ZIO_CHECKSUM_ZILOG2,
        ZIO_CHECKSUM_NOPARITY,
+#ifdef illumos
+       ZIO_CHECKSUM_SHA512,
+       ZIO_CHECKSUM_SKEIN,
+       ZIO_CHECKSUM_EDONR,
+#endif
        ZIO_CHECKSUM_FUNCTIONS
 };
 

Modified: 
stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio_checksum.h
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio_checksum.h 
Fri Nov 13 09:30:17 2015        (r290756)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio_checksum.h 
Fri Nov 13 09:32:04 2015        (r290757)
@@ -20,13 +20,15 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2014, 2015 by Delphix. All rights reserved.
+ * Copyright Saso Kiselkov 2013, All rights reserved.
  */
 
 #ifndef _SYS_ZIO_CHECKSUM_H
 #define        _SYS_ZIO_CHECKSUM_H
 
 #include <sys/zio.h>
+#include <zfeature_common.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -35,17 +37,34 @@ extern "C" {
 /*
  * Signature for checksum functions.
  */
-typedef void zio_checksum_func_t(const void *, uint64_t, zio_cksum_t *);
+typedef void zio_checksum_t(const void *data, uint64_t size,
+    const void *ctx_template, zio_cksum_t *zcp);
+typedef void *zio_checksum_tmpl_init_t(const zio_cksum_salt_t *salt);
+typedef void zio_checksum_tmpl_free_t(void *ctx_template);
+
+typedef enum zio_checksum_flags {
+       /* Strong enough for metadata? */
+       ZCHECKSUM_FLAG_METADATA = (1 << 1),
+       /* ZIO embedded checksum */
+       ZCHECKSUM_FLAG_EMBEDDED = (1 << 2),
+       /* Strong enough for dedup (without verification)? */
+       ZCHECKSUM_FLAG_DEDUP = (1 << 3),
+       /* Uses salt value */
+       ZCHECKSUM_FLAG_SALTED = (1 << 4),
+       /* Strong enough for nopwrite? */
+       ZCHECKSUM_FLAG_NOPWRITE = (1 << 5)
+} zio_checksum_flags_t;
 
 /*
  * Information about each checksum function.
  */
 typedef struct zio_checksum_info {
-       zio_checksum_func_t *ci_func[2]; /* checksum function per byteorder */
-       int             ci_correctable; /* number of correctable bits   */
-       int             ci_eck;         /* uses zio embedded checksum? */
-       boolean_t       ci_dedup;       /* strong enough for dedup? */
-       char            *ci_name;       /* descriptive name */
+       /* checksum function for each byteorder */
+       zio_checksum_t                  *ci_func[2];
+       zio_checksum_tmpl_init_t        *ci_tmpl_init;
+       zio_checksum_tmpl_free_t        *ci_tmpl_free;
+       zio_checksum_flags_t            ci_flags;
+       char                            *ci_name;       /* descriptive name */
 } zio_checksum_info_t;
 
 typedef struct zio_bad_cksum {
@@ -62,12 +81,30 @@ extern zio_checksum_info_t zio_checksum_
 /*
  * Checksum routines.
  */
-extern zio_checksum_func_t zio_checksum_SHA256;
+extern zio_checksum_t zio_checksum_SHA256;
+#ifdef illumos
+extern zio_checksum_t zio_checksum_SHA512_native;
+extern zio_checksum_t zio_checksum_SHA512_byteswap;
+
+/* Skein */
+extern zio_checksum_t zio_checksum_skein_native;
+extern zio_checksum_t zio_checksum_skein_byteswap;
+extern zio_checksum_tmpl_init_t zio_checksum_skein_tmpl_init;
+extern zio_checksum_tmpl_free_t zio_checksum_skein_tmpl_free;
+
+/* Edon-R */
+extern zio_checksum_t zio_checksum_edonr_native;
+extern zio_checksum_t zio_checksum_edonr_byteswap;
+extern zio_checksum_tmpl_init_t zio_checksum_edonr_tmpl_init;
+extern zio_checksum_tmpl_free_t zio_checksum_edonr_tmpl_free;
+#endif
 
 extern void zio_checksum_compute(zio_t *zio, enum zio_checksum checksum,
     void *data, uint64_t size);
 extern int zio_checksum_error(zio_t *zio, zio_bad_cksum_t *out);
 extern enum zio_checksum spa_dedup_checksum(spa_t *spa);
+extern void zio_checksum_templates_free(spa_t *spa);
+extern spa_feature_t zio_checksum_to_feature(enum zio_checksum cksum);
 
 #ifdef __cplusplus
 }

Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c        
Fri Nov 13 09:30:17 2015        (r290756)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c        
Fri Nov 13 09:32:04 2015        (r290757)
@@ -185,6 +185,7 @@
 #include <sys/dsl_bookmark.h>
 #include <sys/dsl_userhold.h>
 #include <sys/zfeature.h>
+#include <sys/zio_checksum.h>
 
 #include "zfs_namecheck.h"
 #include "zfs_prop.h"
@@ -3902,11 +3903,6 @@ zfs_check_settable(const char *dsname, n
                        return (SET_ERROR(ENOTSUP));
                break;
 
-       case ZFS_PROP_DEDUP:
-               if (zfs_earlier_version(dsname, SPA_VERSION_DEDUP))
-                       return (SET_ERROR(ENOTSUP));
-               break;
-
        case ZFS_PROP_RECORDSIZE:
                /* Record sizes above 128k need the feature to be enabled */
                if (nvpair_value_uint64(pair, &intval) == 0 &&
@@ -3957,6 +3953,45 @@ zfs_check_settable(const char *dsname, n
                                return (SET_ERROR(ENOTSUP));
                }
                break;
+
+       case ZFS_PROP_CHECKSUM:
+       case ZFS_PROP_DEDUP:
+       {
+               spa_feature_t feature;
+               spa_t *spa;
+
+               /* dedup feature version checks */
+               if (prop == ZFS_PROP_DEDUP &&
+                   zfs_earlier_version(dsname, SPA_VERSION_DEDUP))
+                       return (SET_ERROR(ENOTSUP));
+
+               if (nvpair_value_uint64(pair, &intval) != 0)
+                       return (SET_ERROR(EINVAL));
+
+               /* check prop value is enabled in features */
+               feature = zio_checksum_to_feature(intval);
+               if (feature == SPA_FEATURE_NONE)
+                       break;
+
+               if ((err = spa_open(dsname, &spa, FTAG)) != 0)
+                       return (err);
+               /*
+                * Salted checksums are not supported on root pools.
+                */
+               if (spa_bootfs(spa) != 0 &&
+                   intval < ZIO_CHECKSUM_FUNCTIONS &&
+                   (zio_checksum_table[intval].ci_flags &
+                   ZCHECKSUM_FLAG_SALTED)) {
+                       spa_close(spa, FTAG);
+                       return (SET_ERROR(ERANGE));
+               }
+               if (!spa_feature_is_enabled(spa, feature)) {
+                       spa_close(spa, FTAG);
+                       return (SET_ERROR(ENOTSUP));
+               }
+               spa_close(spa, FTAG);
+               break;
+       }
        }
 
        return (zfs_secpolicy_setprop(dsname, prop, pair, CRED()));

Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c      Fri Nov 
13 09:30:17 2015        (r290756)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c      Fri Nov 
13 09:32:04 2015        (r290757)
@@ -999,7 +999,7 @@ zio_write_phys(zio_t *pio, vdev_t *vd, u
 
        zio->io_prop.zp_checksum = checksum;
 
-       if (zio_checksum_table[checksum].ci_eck) {
+       if (zio_checksum_table[checksum].ci_flags & ZCHECKSUM_FLAG_EMBEDDED) {
                /*
                 * zec checksums are necessarily destructive -- they modify
                 * the end of the write buffer to hold the verifier/checksum.
@@ -1211,8 +1211,8 @@ zio_write_bp_init(zio_t *zio)
                if (BP_IS_HOLE(bp) || !zp->zp_dedup)
                        return (ZIO_PIPELINE_CONTINUE);
 
-               ASSERT(zio_checksum_table[zp->zp_checksum].ci_dedup ||
-                   zp->zp_dedup_verify);
+               ASSERT((zio_checksum_table[zp->zp_checksum].ci_flags &
+                   ZCHECKSUM_FLAG_DEDUP) || zp->zp_dedup_verify);
 
                if (BP_GET_CHECKSUM(bp) == zp->zp_checksum) {
                        BP_SET_DEDUP(bp, 1);
@@ -2074,12 +2074,22 @@ zio_write_gang_block(zio_t *pio)
 }
 
 /*
- * The zio_nop_write stage in the pipeline determines if allocating
- * a new bp is necessary.  By leveraging a cryptographically secure checksum,
- * such as SHA256, we can compare the checksums of the new data and the old
- * to determine if allocating a new block is required.  The nopwrite
- * feature can handle writes in either syncing or open context (i.e. zil
- * writes) and as a result is mutually exclusive with dedup.
+ * The zio_nop_write stage in the pipeline determines if allocating a
+ * new bp is necessary.  The nopwrite feature can handle writes in
+ * either syncing or open context (i.e. zil writes) and as a result is
+ * mutually exclusive with dedup.
+ *
+ * By leveraging a cryptographically secure checksum, such as SHA256, we
+ * can compare the checksums of the new data and the old to determine if
+ * allocating a new block is required.  Note that our requirements for
+ * cryptographic strength are fairly weak: there can't be any accidental
+ * hash collisions, but we don't need to be secure against intentional
+ * (malicious) collisions.  To trigger a nopwrite, you have to be able
+ * to write the file to begin with, and triggering an incorrect (hash
+ * collision) nopwrite is no worse than simply writing to the file.

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to