FreeBSD ZFS
The Zettabyte File System
|
00001 /* 00002 * CDDL HEADER START 00003 * 00004 * The contents of this file are subject to the terms of the 00005 * Common Development and Distribution License (the "License"). 00006 * You may not use this file except in compliance with the License. 00007 * 00008 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 00009 * or http://www.opensolaris.org/os/licensing. 00010 * See the License for the specific language governing permissions 00011 * and limitations under the License. 00012 * 00013 * When distributing Covered Code, include this CDDL HEADER in each 00014 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 00015 * If applicable, add the following below this CDDL HEADER, with the 00016 * fields enclosed by brackets "[]" replaced with your own identifying 00017 * information: Portions Copyright [yyyy] [name of copyright owner] 00018 * 00019 * CDDL HEADER END 00020 */ 00021 /* 00022 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 00023 */ 00024 00025 #include <sys/zfs_context.h> 00026 #include <sys/spa.h> 00027 #include <sys/zio.h> 00028 #include <sys/zio_checksum.h> 00029 #include <sys/zil.h> 00030 #include <zfs_fletcher.h> 00031 00063 /*ARGSUSED*/ 00064 static void 00065 zio_checksum_off(const void *buf, uint64_t size, zio_cksum_t *zcp) 00066 { 00067 ZIO_SET_CHECKSUM(zcp, 0, 0, 0, 0); 00068 } 00069 00070 zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = { 00071 {{NULL, NULL}, 0, 0, 0, "inherit"}, 00072 {{NULL, NULL}, 0, 0, 0, "on"}, 00073 {{zio_checksum_off, zio_checksum_off}, 0, 0, 0, "off"}, 00074 {{zio_checksum_SHA256, zio_checksum_SHA256}, 1, 1, 0, "label"}, 00075 {{zio_checksum_SHA256, zio_checksum_SHA256}, 1, 1, 0, "gang_header"}, 00076 {{fletcher_2_native, fletcher_2_byteswap}, 0, 1, 0, "zilog"}, 00077 {{fletcher_2_native, fletcher_2_byteswap}, 0, 0, 0, "fletcher2"}, 00078 {{fletcher_4_native, fletcher_4_byteswap}, 1, 0, 0, "fletcher4"}, 00079 {{zio_checksum_SHA256, zio_checksum_SHA256}, 1, 0, 1, "sha256"}, 00080 {{fletcher_4_native, fletcher_4_byteswap}, 0, 1, 0, "zilog2"}, 00081 }; 00082 00083 enum zio_checksum 00084 zio_checksum_select(enum zio_checksum child, enum zio_checksum parent) 00085 { 00086 ASSERT(child < ZIO_CHECKSUM_FUNCTIONS); 00087 ASSERT(parent < ZIO_CHECKSUM_FUNCTIONS); 00088 ASSERT(parent != ZIO_CHECKSUM_INHERIT && parent != ZIO_CHECKSUM_ON); 00089 00090 if (child == ZIO_CHECKSUM_INHERIT) 00091 return (parent); 00092 00093 if (child == ZIO_CHECKSUM_ON) 00094 return (ZIO_CHECKSUM_ON_VALUE); 00095 00096 return (child); 00097 } 00098 00099 enum zio_checksum 00100 zio_checksum_dedup_select(spa_t *spa, enum zio_checksum child, 00101 enum zio_checksum parent) 00102 { 00103 ASSERT((child & ZIO_CHECKSUM_MASK) < ZIO_CHECKSUM_FUNCTIONS); 00104 ASSERT((parent & ZIO_CHECKSUM_MASK) < ZIO_CHECKSUM_FUNCTIONS); 00105 ASSERT(parent != ZIO_CHECKSUM_INHERIT && parent != ZIO_CHECKSUM_ON); 00106 00107 if (child == ZIO_CHECKSUM_INHERIT) 00108 return (parent); 00109 00110 if (child == ZIO_CHECKSUM_ON) 00111 return (spa_dedup_checksum(spa)); 00112 00113 if (child == (ZIO_CHECKSUM_ON | ZIO_CHECKSUM_VERIFY)) 00114 return (spa_dedup_checksum(spa) | ZIO_CHECKSUM_VERIFY); 00115 00116 ASSERT(zio_checksum_table[child & ZIO_CHECKSUM_MASK].ci_dedup || 00117 (child & ZIO_CHECKSUM_VERIFY) || child == ZIO_CHECKSUM_OFF); 00118 00119 return (child); 00120 } 00121 00126 static void 00127 zio_checksum_gang_verifier(zio_cksum_t *zcp, blkptr_t *bp) 00128 { 00129 dva_t *dva = BP_IDENTITY(bp); 00130 uint64_t txg = BP_PHYSICAL_BIRTH(bp); 00131 00132 ASSERT(BP_IS_GANG(bp)); 00133 00134 ZIO_SET_CHECKSUM(zcp, DVA_GET_VDEV(dva), DVA_GET_OFFSET(dva), txg, 0); 00135 } 00136 00142 static void 00143 zio_checksum_label_verifier(zio_cksum_t *zcp, uint64_t offset) 00144 { 00145 ZIO_SET_CHECKSUM(zcp, offset, 0, 0, 0); 00146 } 00147 00151 void 00152 zio_checksum_compute(zio_t *zio, enum zio_checksum checksum, 00153 void *data, uint64_t size) 00154 { 00155 blkptr_t *bp = zio->io_bp; 00156 uint64_t offset = zio->io_offset; 00157 zio_checksum_info_t *ci = &zio_checksum_table[checksum]; 00158 zio_cksum_t cksum; 00159 00160 ASSERT((uint_t)checksum < ZIO_CHECKSUM_FUNCTIONS); 00161 ASSERT(ci->ci_func[0] != NULL); 00162 00163 if (ci->ci_eck) { 00164 zio_eck_t *eck; 00165 00166 if (checksum == ZIO_CHECKSUM_ZILOG2) { 00167 zil_chain_t *zilc = data; 00168 00169 size = P2ROUNDUP_TYPED(zilc->zc_nused, ZIL_MIN_BLKSZ, 00170 uint64_t); 00171 eck = &zilc->zc_eck; 00172 } else { 00173 eck = (zio_eck_t *)((char *)data + size) - 1; 00174 } 00175 if (checksum == ZIO_CHECKSUM_GANG_HEADER) 00176 zio_checksum_gang_verifier(&eck->zec_cksum, bp); 00177 else if (checksum == ZIO_CHECKSUM_LABEL) 00178 zio_checksum_label_verifier(&eck->zec_cksum, offset); 00179 else 00180 bp->blk_cksum = eck->zec_cksum; 00181 eck->zec_magic = ZEC_MAGIC; 00182 ci->ci_func[0](data, size, &cksum); 00183 eck->zec_cksum = cksum; 00184 } else { 00185 ci->ci_func[0](data, size, &bp->blk_cksum); 00186 } 00187 } 00188 00189 int 00190 zio_checksum_error(zio_t *zio, zio_bad_cksum_t *info) 00191 { 00192 blkptr_t *bp = zio->io_bp; 00193 uint_t checksum = (bp == NULL ? zio->io_prop.zp_checksum : 00194 (BP_IS_GANG(bp) ? ZIO_CHECKSUM_GANG_HEADER : BP_GET_CHECKSUM(bp))); 00195 int byteswap; 00196 int error; 00197 uint64_t size = (bp == NULL ? zio->io_size : 00198 (BP_IS_GANG(bp) ? SPA_GANGBLOCKSIZE : BP_GET_PSIZE(bp))); 00199 uint64_t offset = zio->io_offset; 00200 void *data = zio->io_data; 00201 zio_checksum_info_t *ci = &zio_checksum_table[checksum]; 00202 zio_cksum_t actual_cksum, expected_cksum, verifier; 00203 00204 if (checksum >= ZIO_CHECKSUM_FUNCTIONS || ci->ci_func[0] == NULL) 00205 return (EINVAL); 00206 00207 if (ci->ci_eck) { 00208 zio_eck_t *eck; 00209 00210 if (checksum == ZIO_CHECKSUM_ZILOG2) { 00211 zil_chain_t *zilc = data; 00212 uint64_t nused; 00213 00214 eck = &zilc->zc_eck; 00215 if (eck->zec_magic == ZEC_MAGIC) 00216 nused = zilc->zc_nused; 00217 else if (eck->zec_magic == BSWAP_64(ZEC_MAGIC)) 00218 nused = BSWAP_64(zilc->zc_nused); 00219 else 00220 return (ECKSUM); 00221 00222 if (nused > size) 00223 return (ECKSUM); 00224 00225 size = P2ROUNDUP_TYPED(nused, ZIL_MIN_BLKSZ, uint64_t); 00226 } else { 00227 eck = (zio_eck_t *)((char *)data + size) - 1; 00228 } 00229 00230 if (checksum == ZIO_CHECKSUM_GANG_HEADER) 00231 zio_checksum_gang_verifier(&verifier, bp); 00232 else if (checksum == ZIO_CHECKSUM_LABEL) 00233 zio_checksum_label_verifier(&verifier, offset); 00234 else 00235 verifier = bp->blk_cksum; 00236 00237 byteswap = (eck->zec_magic == BSWAP_64(ZEC_MAGIC)); 00238 00239 if (byteswap) 00240 byteswap_uint64_array(&verifier, sizeof (zio_cksum_t)); 00241 00242 expected_cksum = eck->zec_cksum; 00243 eck->zec_cksum = verifier; 00244 ci->ci_func[byteswap](data, size, &actual_cksum); 00245 eck->zec_cksum = expected_cksum; 00246 00247 if (byteswap) 00248 byteswap_uint64_array(&expected_cksum, 00249 sizeof (zio_cksum_t)); 00250 } else { 00251 ASSERT(!BP_IS_GANG(bp)); 00252 byteswap = BP_SHOULD_BYTESWAP(bp); 00253 expected_cksum = bp->blk_cksum; 00254 ci->ci_func[byteswap](data, size, &actual_cksum); 00255 } 00256 00257 info->zbc_expected = expected_cksum; 00258 info->zbc_actual = actual_cksum; 00259 info->zbc_checksum_name = ci->ci_name; 00260 info->zbc_byteswapped = byteswap; 00261 info->zbc_injected = 0; 00262 info->zbc_has_cksum = 1; 00263 00264 if (!ZIO_CHECKSUM_EQUAL(actual_cksum, expected_cksum)) 00265 return (ECKSUM); 00266 00267 if (zio_injection_enabled && !zio->io_error && 00268 (error = zio_handle_fault_injection(zio, ECKSUM)) != 0) { 00269 00270 info->zbc_injected = 1; 00271 return (error); 00272 } 00273 00274 return (0); 00275 }