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 zio_cksum_t zc = bp->blk_cksum; 126 uint_t checksum = BP_IS_GANG(bp) ? ZIO_CHECKSUM_GANG_HEADER : 127 BP_GET_CHECKSUM(bp); 128 int byteswap = BP_SHOULD_BYTESWAP(bp); 129 void *data = zio->io_data; 130 uint64_t size = ZIO_GET_IOSIZE(zio); 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 actual_cksum, expected_cksum; 134 135 if (checksum >= ZIO_CHECKSUM_FUNCTIONS || ci->ci_func[0] == NULL) 136 return (EINVAL); 137 138 if (ci->ci_zbt) { 139 if (checksum == ZIO_CHECKSUM_GANG_HEADER) 140 zio_set_gang_verifier(zio, &zc); 141 142 if (zbt->zbt_magic == BSWAP_64(ZBT_MAGIC)) { 143 expected_cksum = zbt->zbt_cksum; 144 byteswap_uint64_array(&expected_cksum, 145 sizeof (zio_cksum_t)); 146 zbt->zbt_cksum = zc; 147 byteswap_uint64_array(&zbt->zbt_cksum, 148 sizeof (zio_cksum_t)); 149 ci->ci_func[1](data, size, &actual_cksum); 150 zbt->zbt_cksum = expected_cksum; 151 byteswap_uint64_array(&zbt->zbt_cksum, 152 sizeof (zio_cksum_t)); 153 } else { 154 expected_cksum = zbt->zbt_cksum; 155 zbt->zbt_cksum = zc; 156 ci->ci_func[0](data, size, &actual_cksum); 157 zbt->zbt_cksum = expected_cksum; 158 } 159 zc = expected_cksum; 160 } else { 161 ASSERT(!BP_IS_GANG(bp)); 162 ci->ci_func[byteswap](data, size, &actual_cksum); 163 } 164 165 if ((actual_cksum.zc_word[0] - zc.zc_word[0]) | 166 (actual_cksum.zc_word[1] - zc.zc_word[1]) | 167 (actual_cksum.zc_word[2] - zc.zc_word[2]) | 168 (actual_cksum.zc_word[3] - zc.zc_word[3])) 169 return (ECKSUM); 170 171 if (zio_injection_enabled && !zio->io_error) 172 return (zio_handle_fault_injection(zio, ECKSUM)); 173 174 return (0); 175 } 176