Home | History | Annotate | Download | only in diskomizer
      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