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