1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/zfs_context.h> 30 #include <sys/spa.h> 31 #include <sys/zio.h> 32 #include <sys/zio_checksum.h> 33 34 /* 35 * Checksum vectors. 36 * 37 * In the SPA, everything is checksummed. We support checksum vectors 38 * for three distinct reasons: 39 * 40 * 1. Different kinds of data need different levels of protection. 41 * For SPA metadata, we always want a very strong checksum. 42 * For user data, we let users make the trade-off between speed 43 * and checksum strength. 44 * 45 * 2. Cryptographic hash and MAC algorithms are an area of active research. 46 * It is likely that in future hash functions will be at least as strong 47 * as current best-of-breed, and may be substantially faster as well. 48 * We want the ability to take advantage of these new hashes as soon as 49 * they become available. 50 * 51 * 3. If someone develops hardware that can compute a strong hash quickly, 52 * we want the ability to take advantage of that hardware. 53 * 54 * Of course, we don't want a checksum upgrade to invalidate existing 55 * data, so we store the checksum *function* in five bits of the DVA. 56 * This gives us room for up to 32 different checksum functions. 57 * 58 * When writing a block, we always checksum it with the latest-and-greatest 59 * checksum function of the appropriate strength. When reading a block, 60 * we compare the expected checksum against the actual checksum, which we 61 * compute via the checksum function specified in the DVA encoding. 62 */ 63 64 /*ARGSUSED*/ 65 static void 66 zio_checksum_off(const void *buf, uint64_t size, zio_cksum_t *zcp) 67 { 68 ZIO_SET_CHECKSUM(zcp, 0, 0, 0, 0); 69 } 70 71 zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = { 72 NULL, NULL, 0, 0, "inherit", 73 NULL, NULL, 0, 0, "on", 74 zio_checksum_off, zio_checksum_off, 0, 0, "off", 75 zio_checksum_SHA256, zio_checksum_SHA256, 1, 1, "label", 76 zio_checksum_SHA256, zio_checksum_SHA256, 1, 1, "gang_header", 77 fletcher_2_native, fletcher_2_byteswap, 0, 1, "zilog", 78 fletcher_2_native, fletcher_2_byteswap, 0, 0, "fletcher2", 79 fletcher_4_native, fletcher_4_byteswap, 1, 0, "fletcher4", 80 zio_checksum_SHA256, zio_checksum_SHA256, 1, 0, "SHA256", 81 }; 82 83 uint8_t 84 zio_checksum_select(uint8_t child, uint8_t parent) 85 { 86 ASSERT(child < ZIO_CHECKSUM_FUNCTIONS); 87 ASSERT(parent < ZIO_CHECKSUM_FUNCTIONS); 88 ASSERT(parent != ZIO_CHECKSUM_INHERIT && parent != ZIO_CHECKSUM_ON); 89 90 if (child == ZIO_CHECKSUM_INHERIT) 91 return (parent); 92 93 if (child == ZIO_CHECKSUM_ON) 94 return (ZIO_CHECKSUM_ON_VALUE); 95 96 return (child); 97 } 98 99 /* 100 * Generate the checksum. 101 */ 102 void 103 zio_checksum(uint_t checksum, zio_cksum_t *zcp, void *data, uint64_t size) 104 { 105 zio_block_tail_t *zbt = (zio_block_tail_t *)((char *)data + size) - 1; 106 zio_checksum_info_t *ci = &zio_checksum_table[checksum]; 107 zio_cksum_t zbt_cksum; 108 109 ASSERT(checksum < ZIO_CHECKSUM_FUNCTIONS); 110 ASSERT(ci->ci_func[0] != NULL); 111 112 if (ci->ci_zbt) { 113 *zcp = zbt->zbt_cksum; 114 zbt->zbt_magic = ZBT_MAGIC; 115 ci->ci_func[0](data, size, &zbt_cksum); 116 zbt->zbt_cksum = zbt_cksum; 117 } else { 118 ci->ci_func[0](data, size, zcp); 119 } 120 } 121 122 int 123 zio_checksum_error(zio_t *zio) 124 { 125 blkptr_t *bp = zio->io_bp; 126 dva_t *dva = ZIO_GET_DVA(zio); 127 zio_cksum_t zc = bp->blk_cksum; 128 uint_t checksum = DVA_GET_GANG(dva) ? ZIO_CHECKSUM_GANG_HEADER : 129 BP_GET_CHECKSUM(bp); 130 int byteswap = BP_SHOULD_BYTESWAP(bp); 131 void *data = zio->io_data; 132 uint64_t size = zio->io_size; 133 zio_block_tail_t *zbt = (zio_block_tail_t *)((char *)data + size) - 1; 134 zio_checksum_info_t *ci = &zio_checksum_table[checksum]; 135 zio_cksum_t actual_cksum, expected_cksum; 136 137 if (checksum >= ZIO_CHECKSUM_FUNCTIONS || ci->ci_func[0] == NULL) 138 return (EINVAL); 139 140 if (ci->ci_zbt) { 141 if (checksum == ZIO_CHECKSUM_GANG_HEADER) 142 zio_set_gang_verifier(zio, &zc); 143 144 if (zbt->zbt_magic == BSWAP_64(ZBT_MAGIC)) { 145 expected_cksum = zbt->zbt_cksum; 146 byteswap_uint64_array(&expected_cksum, 147 sizeof (zio_cksum_t)); 148 zbt->zbt_cksum = zc; 149 byteswap_uint64_array(&zbt->zbt_cksum, 150 sizeof (zio_cksum_t)); 151 ci->ci_func[1](data, size, &actual_cksum); 152 zbt->zbt_cksum = expected_cksum; 153 byteswap_uint64_array(&zbt->zbt_cksum, 154 sizeof (zio_cksum_t)); 155 } else { 156 expected_cksum = zbt->zbt_cksum; 157 zbt->zbt_cksum = zc; 158 ci->ci_func[0](data, size, &actual_cksum); 159 zbt->zbt_cksum = expected_cksum; 160 } 161 zc = expected_cksum; 162 } else { 163 ASSERT(!DVA_GET_GANG(dva)); 164 ci->ci_func[byteswap](data, size, &actual_cksum); 165 } 166 167 if ((actual_cksum.zc_word[0] - zc.zc_word[0]) | 168 (actual_cksum.zc_word[1] - zc.zc_word[1]) | 169 (actual_cksum.zc_word[2] - zc.zc_word[2]) | 170 (actual_cksum.zc_word[3] - zc.zc_word[3])) 171 return (ECKSUM); 172 173 return (0); 174 } 175