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 #pragma ident "@(#)checker.c 1.8 09/05/26 SMI" 23 24 /* 25 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 #ifndef _LARGEFILE64_SOURCE 30 #define _LARGEFILE64_SOURCE 31 #endif /* _LARGEFILE64_SOURCE */ 32 33 #include <strings.h> 34 #include <string.h> 35 #include "diskomizer64mpism.h" 36 #include <diskomizer/daio.h> 37 38 /* 39 * This converts from long long to check_t without just throwing away 40 * the high order bits. If u_longlong_t is the same size as check_t 41 * the optimizer can (and does) throw this away. 42 */ 43 44 static check_t 45 ll_to_check(u_longlong_t ll) 46 { 47 union { 48 u_longlong_t ll; 49 check_t check[sizeof (u_longlong_t)/sizeof (check_t)]; 50 } u; 51 check_t x = 0; 52 int i; 53 54 u.ll = ll; 55 56 for (i = 0; i < (sizeof (u_longlong_t)/sizeof (check_t)); i++) { 57 x ^= u.check[i]; 58 } 59 60 return (x); 61 } 62 63 check_t 64 check_sum(uchar_t *buf, size_t len) 65 { 66 int i; 67 u_longlong_t total = 0; 68 69 #ifdef __sparc 70 if (((ulong_t)buf % sizeof (check_t)) == 0) { 71 #endif 72 check_t *ptr = (check_t *)buf; 73 for (i = 0; i < len/sizeof (check_t); i++) { 74 total += *(ptr + i); 75 } 76 #ifdef __sparc 77 } else { 78 union { 79 check_t check; 80 uchar_t c[sizeof (check_t)]; 81 } u; 82 int j; 83 84 for (i = 0; i < len/sizeof (check_t); i++) { 85 for (j = 0; j < sizeof (check_t); j++) { 86 u.c[j] = *(buf + (i * sizeof (check_t)) + j); 87 } 88 total += u.check; 89 } 90 } 91 #endif 92 return (ll_to_check(total)); 93 } 94 95 96 static int 97 do_memcmp(uchar_t *buf, size_t len, struct daio_id *id) 98 { 99 if (id->hdr_len && memcmp(&buf[0], id->hdr, id->hdr_len) != 0) { 100 return (-1); 101 } 102 if (memcmp(&buf[id->hdr_len], &id->buf[id->hdr_len], 103 len - (id->hdr_len + id->footer_len)) != 0) { 104 return (-1); 105 } 106 if (id->footer_len && memcmp(&buf[id->hdr_len + len - id->footer_len], 107 id->footer, id->footer_len) != 0) { 108 return (-1); 109 } 110 return (0); 111 } 112 static int 113 do_chksum(uchar_t *buf, size_t len, struct daio_id *id) 114 { 115 if (id->hdr_len && memcmp(&buf[0], id->hdr, id->hdr_len) != 0) { 116 return (-1); 117 } 118 if (check_sum(&buf[id->hdr_len], 119 len - (id->hdr_len + id->footer_len)) != id->chksum) { 120 return (-1); 121 } 122 if (id->footer_len && memcmp(&buf[id->hdr_len + len - id->footer_len], 123 id->footer, id->footer_len) != 0) { 124 return (-1); 125 } 126 return (0); 127 } 128 /* 129 * Readonly check. 130 * 131 * Since we are readonly the hdr, footer and buf pointers can not point to 132 * the data that was written so we use these for our own purpose. 133 * 134 * If buf is NULL it is assumed that this is the first read of this block 135 * so no actual check is done, but the check sum just stored in the chksum. 136 * 137 * if it is not null then it this is a subsequent read. 138 */ 139 static int 140 do_readonly_check(uchar_t *buf, size_t len, struct daio_id *id) 141 { 142 if (id->buf != NULL) { 143 if (check_sum(&buf[0], len) != id->chksum) { 144 return (-1); 145 } 146 } else { 147 id->chksum = check_sum(&buf[0], len); 148 id->buf = (uchar_t *)1; 149 } 150 return (0); 151 } 152 /*ARGSUSED*/ 153 static int 154 do_none_ro(uchar_t *buf, size_t len, struct daio_id *id) 155 { 156 id->buf = (uchar_t *)1; 157 return (0); 158 } 159 static int 160 do_none(uchar_t *buf, size_t len, struct daio_id *id) 161 { 162 return (0); 163 } 164 int 165 does_check(data_checker_t x) 166 { 167 return (do_none != x || do_none_ro == x); 168 } 169 struct checker { 170 char *name; 171 char *desc; 172 data_checker_t checker; 173 data_checker_t readonly; 174 }; 175 176 static struct checker checkers[] = { 177 {"CHECKSUM", "Using check sums to check data", do_chksum, 178 do_readonly_check}, 179 {"FULL", "Doing full comparison to check data", do_memcmp, 180 do_readonly_check}, 181 {"READONLY", "Using check sums to check read only data", 182 do_readonly_check, do_readonly_check}, 183 {"NONE", "Not checking data", do_none, do_none_ro}, 184 }; 185 #define N_CHECKERS (sizeof (checkers)/sizeof (struct checker)) 186 187 data_checker_t 188 choose_data_checker(const char *checker) 189 { 190 ulong_t i; 191 192 for (i = 0; i < N_CHECKERS; i++) { 193 if (strcasecmp(checker, checkers[i].name) == 0) 194 return (is_readonly() ? 195 checkers[i].readonly : checkers[i].checker); 196 } 197 return (NULL); 198 } 199 static struct checker * 200 find_checker(data_checker_t checker) 201 { 202 ulong_t i; 203 204 for (i = 0; i < N_CHECKERS; i++) { 205 if (checker == checkers[i].checker) 206 return (&checkers[i]); 207 } 208 for (i = 0; i < N_CHECKERS; i++) { 209 if (checker == checkers[i].readonly) 210 return (&checkers[i]); 211 } 212 return (NULL); 213 } 214 char * 215 checker_name(data_checker_t checker) 216 { 217 static char unknown[] = "UNKNOWN"; 218 struct checker *cp; 219 220 if ((cp = find_checker(checker)) != NULL) { 221 return (cp->name); 222 } 223 return (&unknown[0]); 224 } 225 char * 226 checker_string(data_checker_t checker) 227 { 228 static char unknown[] = "Unknown checker"; 229 struct checker *cp; 230 231 if ((cp = find_checker(checker)) != NULL) { 232 return (cp->desc); 233 } 234 return (&unknown[0]); 235 } 236