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