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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/param.h> 30 31 static uint_t *mddb_crctab = NULL; 32 33 #ifndef _KERNEL 34 #include <meta.h> 35 #include <assert.h> 36 #define MD_ZALLOC(x) Zalloc(x) 37 #define MD_FREE(x, y) Free(x) 38 #else /* _KERNEL */ 39 #define MD_ZALLOC(x) kmem_zalloc(x, KM_SLEEP) 40 #define MD_FREE(x, y) kmem_free(x, y) 41 #include <sys/thread.h> 42 #include <sys/types.h> 43 #include <sys/kmem.h> 44 #include <sys/debug.h> 45 #endif /* ! _KERNEL */ 46 #include <sys/lvm/md_crc.h> 47 48 #define MDDB_CRCMAGIC 987654 49 50 static uint_t * 51 crcgentab(void) 52 { 53 int b, i; 54 uint_t v; 55 uint_t *crctab; 56 uint_t poly = 0x04c11db7; 57 58 crctab = (uint_t *)MD_ZALLOC(256 * sizeof (int)); 59 for (b = 0; b < 256; b++) { 60 for (v = b << (24), i = 0; i < 8; i++) { 61 if (v & ((unsigned int)1 << 31)) { 62 v = (v << 1) ^ poly; 63 } else { 64 v = v << 1; 65 } 66 } 67 crctab[b] = v; 68 } 69 return (crctab); 70 } 71 72 /* 73 * crc function that allows a number of areas to be skipped (ignored) 74 * during the crc computation. The result area of the record is also ignored 75 * during the crc computation. Ignored areas are used for data that may 76 * be changed after record has been crcgen'd, but before the data has been 77 * written to disk or for when a multi-owner diskset may have multiple 78 * nodes writing the same record data with the exception of the timestamp field. 79 * The list of skip areas must be in ascending order of offset and if any 80 * areas overlap, the list will be modified. 81 */ 82 uint_t 83 crcfunc( 84 uint_t check, 85 uchar_t *record, /* record to be check-summed */ 86 uint_t *result, /* put check-sum here(really u_long) */ 87 size_t size, /* size of record in bytes */ 88 crc_skip_t *skip /* list of areas to skip */ 89 ) 90 { 91 uint_t newcrc; 92 uint_t *crctab; 93 uchar_t *recaddr; 94 crc_skip_t *s, *p; 95 96 /* 97 * Check skip areas to see if they overlap (this should never happen, 98 * but is handled just in case something changes in the future). 99 * Also the skip list must be in ascending order of offset, assert 100 * error if this is not the case. 101 * If any 2 adjacent skip areas overlap, then the skip areas will 102 * be merged into 1 skip area and the other skip area is freed. 103 * If any 2 adjacent skip areas abut (border) each other, then skip 104 * areas are not merged, but are left as 2 independent skip areas. 105 * If the skip areas are identical, no change is made to either skip 106 * area since this is handled later. 107 */ 108 if (skip) { 109 p = NULL; 110 for (s = skip; s != NULL; s = s->skip_next) { 111 if (p == NULL) { 112 p = s; 113 continue; 114 } 115 #ifdef _KERNEL 116 ASSERT(s->skip_offset > p->skip_offset); 117 #else 118 assert(s->skip_offset > p->skip_offset); 119 #endif 120 if ((p->skip_offset + p->skip_size) > s->skip_offset) { 121 /* 122 * Current area overlaps previous, modify 123 * previous area and release current 124 */ 125 p->skip_size += s->skip_size - (p->skip_offset 126 + p->skip_size - s->skip_offset); 127 p->skip_next = s->skip_next; 128 MD_FREE(s, sizeof (crc_skip_t)); 129 s = p; 130 } 131 p = s; 132 } 133 } 134 135 if (! mddb_crctab) 136 mddb_crctab = crcgentab(); 137 138 crctab = mddb_crctab; 139 newcrc = MDDB_CRCMAGIC; 140 141 recaddr = record; 142 s = skip; 143 while (size--) { 144 /* Skip the result pointer */ 145 if (record == (uchar_t *)result) { 146 record += sizeof (uint_t); 147 size -= (sizeof (uint_t) - 1); 148 continue; 149 } 150 151 /* 152 * Skip over next skip area if non-null 153 */ 154 if ((s) && (record == (recaddr + (s->skip_offset)))) { 155 record += s->skip_size; 156 size -= (s->skip_size - 1); 157 s = s->skip_next; 158 continue; 159 } 160 161 newcrc = (newcrc << 8) ^ crctab[(newcrc >> 24) ^ *record++]; 162 } 163 164 /* If we are checking, we either get a 0 - OK, or 1 - Not OK result */ 165 if (check) { 166 if (*((uint_t *)result) == newcrc) 167 return (0); 168 return (1); 169 } 170 171 /* 172 * If we are generating, we stuff the result, if we have a result 173 * pointer, and return the value. 174 */ 175 if (result != NULL) 176 *((uint_t *)result) = newcrc; 177 return (newcrc); 178 } 179 180 void 181 crcfreetab(void) 182 { 183 if (mddb_crctab) { 184 MD_FREE((caddr_t)mddb_crctab, 256 * sizeof (int)); 185 mddb_crctab = NULL; 186 } 187 } 188