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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/zfs_context.h> 27 #include <sys/spa.h> 28 #include <sys/zio.h> 29 #include <sys/zio_checksum.h> 30 31 /* 32 * Checksum vectors. 33 * 34 * In the SPA, everything is checksummed. We support checksum vectors 35 * for three distinct reasons: 36 * 37 * 1. Different kinds of data need different levels of protection. 38 * For SPA metadata, we always want a very strong checksum. 39 * For user data, we let users make the trade-off between speed 40 * and checksum strength. 41 * 42 * 2. Cryptographic hash and MAC algorithms are an area of active research. 43 * It is likely that in future hash functions will be at least as strong 44 * as current best-of-breed, and may be substantially faster as well. 45 * We want the ability to take advantage of these new hashes as soon as 46 * they become available. 47 * 48 * 3. If someone develops hardware that can compute a strong hash quickly, 49 * we want the ability to take advantage of that hardware. 50 * 51 * Of course, we don't want a checksum upgrade to invalidate existing 52 * data, so we store the checksum *function* in five bits of the DVA. 53 * This gives us room for up to 32 different checksum functions. 54 * 55 * When writing a block, we always checksum it with the latest-and-greatest 56 * checksum function of the appropriate strength. When reading a block, 57 * we compare the expected checksum against the actual checksum, which we 58 * compute via the checksum function specified in the DVA encoding. 59 */ 60 61 /*ARGSUSED*/ 62 static void 63 zio_checksum_off(const void *buf, uint64_t size, zio_cksum_t *zcp) 64 { 65 ZIO_SET_CHECKSUM(zcp, 0, 0, 0, 0); 66 } 67 68 zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = { 69 {{NULL, NULL}, 0, 0, "inherit"}, 70 {{NULL, NULL}, 0, 0, "on"}, 71 {{zio_checksum_off, zio_checksum_off}, 0, 0, "off"}, 72 {{zio_checksum_SHA256, zio_checksum_SHA256}, 1, 1, "label"}, 73 {{zio_checksum_SHA256, zio_checksum_SHA256}, 1, 1, "gang_header"}, 74 {{fletcher_2_native, fletcher_2_byteswap}, 0, 1, "zilog"}, 75 {{fletcher_2_native, fletcher_2_byteswap}, 0, 0, "fletcher2"}, 76 {{fletcher_4_native, fletcher_4_byteswap}, 1, 0, "fletcher4"}, 77 {{zio_checksum_SHA256, zio_checksum_SHA256}, 1, 0, "SHA256"}, 78 }; 79 80 uint8_t 81 zio_checksum_select(uint8_t child, uint8_t parent) 82 { 83 ASSERT(child < ZIO_CHECKSUM_FUNCTIONS); 84 ASSERT(parent < ZIO_CHECKSUM_FUNCTIONS); 85 ASSERT(parent != ZIO_CHECKSUM_INHERIT && parent != ZIO_CHECKSUM_ON); 86 87 if (child == ZIO_CHECKSUM_INHERIT) 88 return (parent); 89 90 if (child == ZIO_CHECKSUM_ON) 91 return (ZIO_CHECKSUM_ON_VALUE); 92 93 return (child); 94 } 95 96 /* 97 * Set the external verifier for a gang block based on <vdev, offset, txg>, 98 * a tuple which is guaranteed to be unique for the life of the pool. 99 */ 100 static void 101 zio_checksum_gang_verifier(zio_cksum_t *zcp, blkptr_t *bp) 102 { 103 dva_t *dva = BP_IDENTITY(bp); 104 uint64_t txg = bp->blk_birth; 105 106 ASSERT(BP_IS_GANG(bp)); 107 108 ZIO_SET_CHECKSUM(zcp, DVA_GET_VDEV(dva), DVA_GET_OFFSET(dva), txg, 0); 109 } 110 111 /* 112 * Set the external verifier for a label block based on its offset. 113 * The vdev is implicit, and the txg is unknowable at pool open time -- 114 * hence the logic in vdev_uberblock_load() to find the most recent copy. 115 */ 116 static void 117 zio_checksum_label_verifier(zio_cksum_t *zcp, uint64_t offset) 118 { 119 ZIO_SET_CHECKSUM(zcp, offset, 0, 0, 0); 120 } 121 122 /* 123 * Generate the checksum. 124 */ 125 void 126 zio_checksum_compute(zio_t *zio, enum zio_checksum checksum, 127 void *data, uint64_t size) 128 { 129 blkptr_t *bp = zio->io_bp; 130 uint64_t offset = zio->io_offset; 131 zio_block_tail_t *zbt = (zio_block_tail_t *)((char *)data + size) - 1; 132 zio_checksum_info_t *ci = &zio_checksum_table[checksum]; 133 zio_cksum_t zbt_cksum; 134 135 ASSERT((uint_t)checksum < ZIO_CHECKSUM_FUNCTIONS); 136 ASSERT(ci->ci_func[0] != NULL); 137 138 if (ci->ci_zbt) { 139 if (checksum == ZIO_CHECKSUM_GANG_HEADER) 140 zio_checksum_gang_verifier(&zbt->zbt_cksum, bp); 141 else if (checksum == ZIO_CHECKSUM_LABEL) 142 zio_checksum_label_verifier(&zbt->zbt_cksum, offset); 143 else 144 bp->blk_cksum = zbt->zbt_cksum; 145 zbt->zbt_magic = ZBT_MAGIC; 146 ci->ci_func[0](data, size, &zbt_cksum); 147 zbt->zbt_cksum = zbt_cksum; 148 } else { 149 ci->ci_func[0](data, size, &bp->blk_cksum); 150 } 151 } 152 153 int 154 zio_checksum_error(zio_t *zio, zio_bad_cksum_t *info) 155 { 156 blkptr_t *bp = zio->io_bp; 157 uint_t checksum = (bp == NULL ? zio->io_prop.zp_checksum : 158 (BP_IS_GANG(bp) ? ZIO_CHECKSUM_GANG_HEADER : BP_GET_CHECKSUM(bp))); 159 int byteswap; 160 int error; 161 uint64_t size = (bp == NULL ? zio->io_size : 162 (BP_IS_GANG(bp) ? SPA_GANGBLOCKSIZE : BP_GET_PSIZE(bp))); 163 uint64_t offset = zio->io_offset; 164 void *data = zio->io_data; 165 zio_block_tail_t *zbt = (zio_block_tail_t *)((char *)data + size) - 1; 166 zio_checksum_info_t *ci = &zio_checksum_table[checksum]; 167 zio_cksum_t actual_cksum, expected_cksum, verifier; 168 169 if (checksum >= ZIO_CHECKSUM_FUNCTIONS || ci->ci_func[0] == NULL) 170 return (EINVAL); 171 172 if (ci->ci_zbt) { 173 if (checksum == ZIO_CHECKSUM_GANG_HEADER) 174 zio_checksum_gang_verifier(&verifier, bp); 175 else if (checksum == ZIO_CHECKSUM_LABEL) 176 zio_checksum_label_verifier(&verifier, offset); 177 else 178 verifier = bp->blk_cksum; 179 180 byteswap = (zbt->zbt_magic == BSWAP_64(ZBT_MAGIC)); 181 182 if (byteswap) 183 byteswap_uint64_array(&verifier, sizeof (zio_cksum_t)); 184 185 expected_cksum = zbt->zbt_cksum; 186 zbt->zbt_cksum = verifier; 187 ci->ci_func[byteswap](data, size, &actual_cksum); 188 zbt->zbt_cksum = expected_cksum; 189 190 if (byteswap) 191 byteswap_uint64_array(&expected_cksum, 192 sizeof (zio_cksum_t)); 193 } else { 194 ASSERT(!BP_IS_GANG(bp)); 195 byteswap = BP_SHOULD_BYTESWAP(bp); 196 expected_cksum = bp->blk_cksum; 197 ci->ci_func[byteswap](data, size, &actual_cksum); 198 } 199 200 info->zbc_expected = expected_cksum; 201 info->zbc_actual = actual_cksum; 202 info->zbc_checksum_name = ci->ci_name; 203 info->zbc_byteswapped = byteswap; 204 info->zbc_injected = 0; 205 info->zbc_has_cksum = 1; 206 207 if (!ZIO_CHECKSUM_EQUAL(actual_cksum, expected_cksum)) 208 return (ECKSUM); 209 210 if (zio_injection_enabled && !zio->io_error && 211 (error = zio_handle_fault_injection(zio, ECKSUM)) != 0) { 212 213 info->zbc_injected = 1; 214 return (error); 215 } 216 217 return (0); 218 } 219