1*495db6fbSLori Alt /* 2*495db6fbSLori Alt * CDDL HEADER START 3*495db6fbSLori Alt * 4*495db6fbSLori Alt * The contents of this file are subject to the terms of the 5*495db6fbSLori Alt * Common Development and Distribution License (the "License"). 6*495db6fbSLori Alt * You may not use this file except in compliance with the License. 7*495db6fbSLori Alt * 8*495db6fbSLori Alt * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*495db6fbSLori Alt * or http://www.opensolaris.org/os/licensing. 10*495db6fbSLori Alt * See the License for the specific language governing permissions 11*495db6fbSLori Alt * and limitations under the License. 12*495db6fbSLori Alt * 13*495db6fbSLori Alt * When distributing Covered Code, include this CDDL HEADER in each 14*495db6fbSLori Alt * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*495db6fbSLori Alt * If applicable, add the following below this CDDL HEADER, with the 16*495db6fbSLori Alt * fields enclosed by brackets "[]" replaced with your own identifying 17*495db6fbSLori Alt * information: Portions Copyright [yyyy] [name of copyright owner] 18*495db6fbSLori Alt * 19*495db6fbSLori Alt * CDDL HEADER END 20*495db6fbSLori Alt */ 21*495db6fbSLori Alt /* 22*495db6fbSLori Alt * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23*495db6fbSLori Alt * Use is subject to license terms. 24*495db6fbSLori Alt */ 25*495db6fbSLori Alt 26*495db6fbSLori Alt /* 27*495db6fbSLori Alt * Fletcher Checksums 28*495db6fbSLori Alt * ------------------ 29*495db6fbSLori Alt * 30*495db6fbSLori Alt * ZFS's 2nd and 4th order Fletcher checksums are defined by the following 31*495db6fbSLori Alt * recurrence relations: 32*495db6fbSLori Alt * 33*495db6fbSLori Alt * a = a + f 34*495db6fbSLori Alt * i i-1 i-1 35*495db6fbSLori Alt * 36*495db6fbSLori Alt * b = b + a 37*495db6fbSLori Alt * i i-1 i 38*495db6fbSLori Alt * 39*495db6fbSLori Alt * c = c + b (fletcher-4 only) 40*495db6fbSLori Alt * i i-1 i 41*495db6fbSLori Alt * 42*495db6fbSLori Alt * d = d + c (fletcher-4 only) 43*495db6fbSLori Alt * i i-1 i 44*495db6fbSLori Alt * 45*495db6fbSLori Alt * Where 46*495db6fbSLori Alt * a_0 = b_0 = c_0 = d_0 = 0 47*495db6fbSLori Alt * and 48*495db6fbSLori Alt * f_0 .. f_(n-1) are the input data. 49*495db6fbSLori Alt * 50*495db6fbSLori Alt * Using standard techniques, these translate into the following series: 51*495db6fbSLori Alt * 52*495db6fbSLori Alt * __n_ __n_ 53*495db6fbSLori Alt * \ | \ | 54*495db6fbSLori Alt * a = > f b = > i * f 55*495db6fbSLori Alt * n /___| n - i n /___| n - i 56*495db6fbSLori Alt * i = 1 i = 1 57*495db6fbSLori Alt * 58*495db6fbSLori Alt * 59*495db6fbSLori Alt * __n_ __n_ 60*495db6fbSLori Alt * \ | i*(i+1) \ | i*(i+1)*(i+2) 61*495db6fbSLori Alt * c = > ------- f d = > ------------- f 62*495db6fbSLori Alt * n /___| 2 n - i n /___| 6 n - i 63*495db6fbSLori Alt * i = 1 i = 1 64*495db6fbSLori Alt * 65*495db6fbSLori Alt * For fletcher-2, the f_is are 64-bit, and [ab]_i are 64-bit accumulators. 66*495db6fbSLori Alt * Since the additions are done mod (2^64), errors in the high bits may not 67*495db6fbSLori Alt * be noticed. For this reason, fletcher-2 is deprecated. 68*495db6fbSLori Alt * 69*495db6fbSLori Alt * For fletcher-4, the f_is are 32-bit, and [abcd]_i are 64-bit accumulators. 70*495db6fbSLori Alt * A conservative estimate of how big the buffer can get before we overflow 71*495db6fbSLori Alt * can be estimated using f_i = 0xffffffff for all i: 72*495db6fbSLori Alt * 73*495db6fbSLori Alt * % bc 74*495db6fbSLori Alt * f=2^32-1;d=0; for (i = 1; d<2^64; i++) { d += f*i*(i+1)*(i+2)/6 }; (i-1)*4 75*495db6fbSLori Alt * 2264 76*495db6fbSLori Alt * quit 77*495db6fbSLori Alt * % 78*495db6fbSLori Alt * 79*495db6fbSLori Alt * So blocks of up to 2k will not overflow. Our largest block size is 80*495db6fbSLori Alt * 128k, which has 32k 4-byte words, so we can compute the largest possible 81*495db6fbSLori Alt * accumulators, then divide by 2^64 to figure the max amount of overflow: 82*495db6fbSLori Alt * 83*495db6fbSLori Alt * % bc 84*495db6fbSLori Alt * a=b=c=d=0; f=2^32-1; for (i=1; i<=32*1024; i++) { a+=f; b+=a; c+=b; d+=c } 85*495db6fbSLori Alt * a/2^64;b/2^64;c/2^64;d/2^64 86*495db6fbSLori Alt * 0 87*495db6fbSLori Alt * 0 88*495db6fbSLori Alt * 1365 89*495db6fbSLori Alt * 11186858 90*495db6fbSLori Alt * quit 91*495db6fbSLori Alt * % 92*495db6fbSLori Alt * 93*495db6fbSLori Alt * So a and b cannot overflow. To make sure each bit of input has some 94*495db6fbSLori Alt * effect on the contents of c and d, we can look at what the factors of 95*495db6fbSLori Alt * the coefficients in the equations for c_n and d_n are. The number of 2s 96*495db6fbSLori Alt * in the factors determines the lowest set bit in the multiplier. Running 97*495db6fbSLori Alt * through the cases for n*(n+1)/2 reveals that the highest power of 2 is 98*495db6fbSLori Alt * 2^14, and for n*(n+1)*(n+2)/6 it is 2^15. So while some data may overflow 99*495db6fbSLori Alt * the 64-bit accumulators, every bit of every f_i effects every accumulator, 100*495db6fbSLori Alt * even for 128k blocks. 101*495db6fbSLori Alt * 102*495db6fbSLori Alt * If we wanted to make a stronger version of fletcher4 (fletcher4c?), 103*495db6fbSLori Alt * we could do our calculations mod (2^32 - 1) by adding in the carries 104*495db6fbSLori Alt * periodically, and store the number of carries in the top 32-bits. 105*495db6fbSLori Alt * 106*495db6fbSLori Alt * -------------------- 107*495db6fbSLori Alt * Checksum Performance 108*495db6fbSLori Alt * -------------------- 109*495db6fbSLori Alt * 110*495db6fbSLori Alt * There are two interesting components to checksum performance: cached and 111*495db6fbSLori Alt * uncached performance. With cached data, fletcher-2 is about four times 112*495db6fbSLori Alt * faster than fletcher-4. With uncached data, the performance difference is 113*495db6fbSLori Alt * negligible, since the cost of a cache fill dominates the processing time. 114*495db6fbSLori Alt * Even though fletcher-4 is slower than fletcher-2, it is still a pretty 115*495db6fbSLori Alt * efficient pass over the data. 116*495db6fbSLori Alt * 117*495db6fbSLori Alt * In normal operation, the data which is being checksummed is in a buffer 118*495db6fbSLori Alt * which has been filled either by: 119*495db6fbSLori Alt * 120*495db6fbSLori Alt * 1. a compression step, which will be mostly cached, or 121*495db6fbSLori Alt * 2. a bcopy() or copyin(), which will be uncached (because the 122*495db6fbSLori Alt * copy is cache-bypassing). 123*495db6fbSLori Alt * 124*495db6fbSLori Alt * For both cached and uncached data, both fletcher checksums are much faster 125*495db6fbSLori Alt * than sha-256, and slower than 'off', which doesn't touch the data at all. 126*495db6fbSLori Alt */ 127*495db6fbSLori Alt 128*495db6fbSLori Alt #include <sys/types.h> 129*495db6fbSLori Alt #include <sys/sysmacros.h> 130*495db6fbSLori Alt #include <sys/byteorder.h> 131*495db6fbSLori Alt #include <sys/spa.h> 132*495db6fbSLori Alt 133*495db6fbSLori Alt void 134*495db6fbSLori Alt fletcher_2_native(const void *buf, uint64_t size, zio_cksum_t *zcp) 135*495db6fbSLori Alt { 136*495db6fbSLori Alt const uint64_t *ip = buf; 137*495db6fbSLori Alt const uint64_t *ipend = ip + (size / sizeof (uint64_t)); 138*495db6fbSLori Alt uint64_t a0, b0, a1, b1; 139*495db6fbSLori Alt 140*495db6fbSLori Alt for (a0 = b0 = a1 = b1 = 0; ip < ipend; ip += 2) { 141*495db6fbSLori Alt a0 += ip[0]; 142*495db6fbSLori Alt a1 += ip[1]; 143*495db6fbSLori Alt b0 += a0; 144*495db6fbSLori Alt b1 += a1; 145*495db6fbSLori Alt } 146*495db6fbSLori Alt 147*495db6fbSLori Alt ZIO_SET_CHECKSUM(zcp, a0, a1, b0, b1); 148*495db6fbSLori Alt } 149*495db6fbSLori Alt 150*495db6fbSLori Alt void 151*495db6fbSLori Alt fletcher_2_byteswap(const void *buf, uint64_t size, zio_cksum_t *zcp) 152*495db6fbSLori Alt { 153*495db6fbSLori Alt const uint64_t *ip = buf; 154*495db6fbSLori Alt const uint64_t *ipend = ip + (size / sizeof (uint64_t)); 155*495db6fbSLori Alt uint64_t a0, b0, a1, b1; 156*495db6fbSLori Alt 157*495db6fbSLori Alt for (a0 = b0 = a1 = b1 = 0; ip < ipend; ip += 2) { 158*495db6fbSLori Alt a0 += BSWAP_64(ip[0]); 159*495db6fbSLori Alt a1 += BSWAP_64(ip[1]); 160*495db6fbSLori Alt b0 += a0; 161*495db6fbSLori Alt b1 += a1; 162*495db6fbSLori Alt } 163*495db6fbSLori Alt 164*495db6fbSLori Alt ZIO_SET_CHECKSUM(zcp, a0, a1, b0, b1); 165*495db6fbSLori Alt } 166*495db6fbSLori Alt 167*495db6fbSLori Alt void 168*495db6fbSLori Alt fletcher_4_native(const void *buf, uint64_t size, zio_cksum_t *zcp) 169*495db6fbSLori Alt { 170*495db6fbSLori Alt const uint32_t *ip = buf; 171*495db6fbSLori Alt const uint32_t *ipend = ip + (size / sizeof (uint32_t)); 172*495db6fbSLori Alt uint64_t a, b, c, d; 173*495db6fbSLori Alt 174*495db6fbSLori Alt for (a = b = c = d = 0; ip < ipend; ip++) { 175*495db6fbSLori Alt a += ip[0]; 176*495db6fbSLori Alt b += a; 177*495db6fbSLori Alt c += b; 178*495db6fbSLori Alt d += c; 179*495db6fbSLori Alt } 180*495db6fbSLori Alt 181*495db6fbSLori Alt ZIO_SET_CHECKSUM(zcp, a, b, c, d); 182*495db6fbSLori Alt } 183*495db6fbSLori Alt 184*495db6fbSLori Alt void 185*495db6fbSLori Alt fletcher_4_byteswap(const void *buf, uint64_t size, zio_cksum_t *zcp) 186*495db6fbSLori Alt { 187*495db6fbSLori Alt const uint32_t *ip = buf; 188*495db6fbSLori Alt const uint32_t *ipend = ip + (size / sizeof (uint32_t)); 189*495db6fbSLori Alt uint64_t a, b, c, d; 190*495db6fbSLori Alt 191*495db6fbSLori Alt for (a = b = c = d = 0; ip < ipend; ip++) { 192*495db6fbSLori Alt a += BSWAP_32(ip[0]); 193*495db6fbSLori Alt b += a; 194*495db6fbSLori Alt c += b; 195*495db6fbSLori Alt d += c; 196*495db6fbSLori Alt } 197*495db6fbSLori Alt 198*495db6fbSLori Alt ZIO_SET_CHECKSUM(zcp, a, b, c, d); 199*495db6fbSLori Alt } 200*495db6fbSLori Alt 201*495db6fbSLori Alt void 202*495db6fbSLori Alt fletcher_4_incremental_native(const void *buf, uint64_t size, 203*495db6fbSLori Alt zio_cksum_t *zcp) 204*495db6fbSLori Alt { 205*495db6fbSLori Alt const uint32_t *ip = buf; 206*495db6fbSLori Alt const uint32_t *ipend = ip + (size / sizeof (uint32_t)); 207*495db6fbSLori Alt uint64_t a, b, c, d; 208*495db6fbSLori Alt 209*495db6fbSLori Alt a = zcp->zc_word[0]; 210*495db6fbSLori Alt b = zcp->zc_word[1]; 211*495db6fbSLori Alt c = zcp->zc_word[2]; 212*495db6fbSLori Alt d = zcp->zc_word[3]; 213*495db6fbSLori Alt 214*495db6fbSLori Alt for (; ip < ipend; ip++) { 215*495db6fbSLori Alt a += ip[0]; 216*495db6fbSLori Alt b += a; 217*495db6fbSLori Alt c += b; 218*495db6fbSLori Alt d += c; 219*495db6fbSLori Alt } 220*495db6fbSLori Alt 221*495db6fbSLori Alt ZIO_SET_CHECKSUM(zcp, a, b, c, d); 222*495db6fbSLori Alt } 223*495db6fbSLori Alt 224*495db6fbSLori Alt void 225*495db6fbSLori Alt fletcher_4_incremental_byteswap(const void *buf, uint64_t size, 226*495db6fbSLori Alt zio_cksum_t *zcp) 227*495db6fbSLori Alt { 228*495db6fbSLori Alt const uint32_t *ip = buf; 229*495db6fbSLori Alt const uint32_t *ipend = ip + (size / sizeof (uint32_t)); 230*495db6fbSLori Alt uint64_t a, b, c, d; 231*495db6fbSLori Alt 232*495db6fbSLori Alt a = zcp->zc_word[0]; 233*495db6fbSLori Alt b = zcp->zc_word[1]; 234*495db6fbSLori Alt c = zcp->zc_word[2]; 235*495db6fbSLori Alt d = zcp->zc_word[3]; 236*495db6fbSLori Alt 237*495db6fbSLori Alt for (; ip < ipend; ip++) { 238*495db6fbSLori Alt a += BSWAP_32(ip[0]); 239*495db6fbSLori Alt b += a; 240*495db6fbSLori Alt c += b; 241*495db6fbSLori Alt d += c; 242*495db6fbSLori Alt } 243*495db6fbSLori Alt 244*495db6fbSLori Alt ZIO_SET_CHECKSUM(zcp, a, b, c, d); 245*495db6fbSLori Alt } 246