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	"@(#)decode_errors.c	1.6	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 
     30 #include "diskomizer64mpism.h"
     31 #include "args.h"
     32 #include "bits.h"
     33 
     34 static void
     35 decode_matching(int pri, struct aio_str *aiop)
     36 {
     37 	struct fds *fd;
     38 
     39 	fd = find_path(aiop->error.dev->fdhead, aiop->error.path_id);
     40 
     41 	if (aiop->error.dev->fdhead->next != aiop->error.dev->fdhead) {
     42 		plog(pri, "Buffer matches last write to block "
     43 		    "byte offset 0t%lld (%#llx) on path %s (%s) to dev %s\n",
     44 		    diskomizer_off2byteoff(aiop->error.doff),
     45 		    diskomizer_off2byteoff(aiop->error.doff),
     46 		    fd->longname, fd->shortname,
     47 		    aiop->error.dev->logicalname);
     48 	} else {
     49 		plog(pri, "Buffer matches last write to block "
     50 		    "byte offset 0t%lld (%#llx) on dev %s (%s)\n",
     51 		    diskomizer_off2byteoff(aiop->error.doff),
     52 		    diskomizer_off2byteoff(aiop->error.doff),
     53 		    fd->shortname, aiop->error.dev->logicalname);
     54 	}
     55 	if (aiop->error.delta) {
     56 		time_log(pri, aiop->error.last_requested,
     57 		    "which was submitted to be written at");
     58 		time_log(pri, aiop->error.last_requested +
     59 		    aiop->error.delta,
     60 		    "                     and returned at");
     61 	} else {
     62 		time_log(pri, aiop->error.last_requested,
     63 		    "which was written at");
     64 	}
     65 }
     66 
     67 static void
     68 decode_length_mismatch(int pri, struct aio_str *aiop)
     69 {
     70 	plog(pri, "Wrong length in header, expected %#lx, got %#lx\n",
     71 	    (long)INDEX_TO_DIOLEN(aiop->iolen), (long)aiop->error.len);
     72 	if (aiop->error.desc.MATCHING_DEVICE) {
     73 		time_log(pri, aiop->error.last_requested,
     74 		    "The read header was submitted to byte offset"
     75 		    " 0t%lld (%#llx) on path %s (%s) at",
     76 		    diskomizer_off2byteoff(aiop->error.doff),
     77 		    diskomizer_off2byteoff(aiop->error.doff),
     78 		    aiop->error.fd->longname, aiop->error.fd->shortname);
     79 	}
     80 }
     81 
     82 static void
     83 decode_bits(int pri, struct diff_return *dr)
     84 {
     85 	union {
     86 		uchar_t c[sizeof (dr->bits) / sizeof (uchar_t)];
     87 		uint16_t s[sizeof (dr->bits) / sizeof (uint16_t)];
     88 		uint32_t i[sizeof (dr->bits) / sizeof (uint32_t)];
     89 		uint64_t l;
     90 	} bits;
     91 	uchar_t bc;
     92 	uint64_t ans;
     93 	char nbits;
     94 	char nchars;
     95 	char all_bits[64];
     96 
     97 	if ((bc = count_uint64_bits(dr->bits)) == 64 || bc == 0) {
     98 		return;
     99 	}
    100 
    101 	bits.l = dr->bits;
    102 
    103 	if (bits.i[0] == bits.i[1]) {
    104 		if (bits.s[0] == bits.s[1]) {
    105 			if (bits.c[0] == bits.c[1]) {
    106 				nchars = 2;
    107 				nbits = 8;
    108 				ans = bits.c[0];
    109 				bc = count_uint8_bits(bits.c[0]);
    110 				what_uint8_bits_set(ans, all_bits);
    111 			} else {
    112 				nchars = 4;
    113 				nbits = 16;
    114 				ans = bits.s[0];
    115 				bc = count_uint16_bits(bits.s[0]);
    116 				what_uint16_bits_set(ans, all_bits);
    117 			}
    118 		} else {
    119 			nchars = 8;
    120 			nbits = 32;
    121 			ans = bits.i[0];
    122 			bc = count_uint32_bits(bits.i[0]);
    123 			what_uint32_bits_set(ans, all_bits);
    124 		}
    125 	} else {
    126 		nchars = 16;
    127 		nbits = 64;
    128 		ans = bits.l;
    129 		what_uint64_bits_set(ans, all_bits);
    130 	}
    131 
    132 
    133 	if (bc == 1 && !OPTION(obscure_raw_bits)) {
    134 		plog(pri,
    135 		    "bit flip%s seen in bit %d of a %d bit word\n",
    136 		    dr->count == 1 ? " is" : "s are",
    137 		    (int)all_bits[0], nbits);
    138 	} else if (bc < nbits/2 && bc < 8 &&!OPTION(obscure_raw_bits)) {
    139 		char str[25];
    140 		int i;
    141 		int j;
    142 
    143 		str[0] = NULL;
    144 
    145 		for (i = j = 0; i < bc; i++)  {
    146 			int x = snprintf(&str[j], sizeof (str) - j, "%s%2.2d",
    147 			    i > 0 ? "," : "", all_bits[i]);
    148 			j += x;
    149 		}
    150 		plog(pri,
    151 		    "bit flips are seen in bits %s of a %d bit word\n",
    152 		    str, nbits);
    153 	} else {
    154 		plog(pri,
    155 		    "bit flips are seen in these %d bit aligned bits "
    156 		    "0x%*.*llx\n", nbits, nchars, nchars, ans);
    157 	}
    158 }
    159 
    160 void
    161 decode_errors(int pri, struct aio_str *aiop, int read_count)
    162 {
    163 	if (aiop->error.desc.LENGTH_MISMATCH) {
    164 		decode_length_mismatch(pri, aiop);
    165 	}
    166 	if (aiop->error.desc.MATCHING_LAST) {
    167 		decode_matching(pri, aiop);
    168 	}
    169 	if (aiop->error.diff_file != NULL) {
    170 		plog(LOG_ERR, "Diffs file dumped to %s\n",
    171 		    aiop->error.diff_file);
    172 		aiop->error.diff_file = NULL;
    173 	}
    174 	if (read_count != 0) {
    175 		plog(LOG_ERR, "Block has previously been read successfully "
    176 		    "%d time%s and is now in error.\n", read_count,
    177 		    read_count > 1 ? "s" : "");
    178 	}
    179 }
    180 
    181 void
    182 report_error_desc(int pri, struct aio_str *aiop, const char *str)
    183 {
    184 	if (aiop->error.desc.HEADER_CHECKSUM_ERR) {
    185 		struct bufhdr_a hdr = get_bufhdr_a(aiop->buf);
    186 
    187 		plog(pri, "bad header checksum, expected %#llx, got %#llx\n",
    188 		    (long long)hdr.hdrchksum, aiop->error.bad_checksum);
    189 	} else if (aiop->error.desc.BODY_CHECKSUM_ERR) {
    190 		struct bufhdr_a hdr = get_bufhdr_a(aiop->buf);
    191 
    192 		plog(pri,
    193 		    "bad body checksum for %s, expected %#llx, got %#llx%s\n",
    194 		    hdr.type.BUF_EXECUTABLE ? "func" : "data",
    195 		    hdr.chksum, aiop->error.bad_checksum,
    196 		    opts.fix_bad_checksums ? " (Fixed)" : "");
    197 	}
    198 	/*
    199 	 * If less than 1% of the total bits transported are corrupt
    200 	 * then consider this to be "bit" corruption and report it as such
    201 	 */
    202 	if (aiop->error.dr.count &&
    203 	    (100 * (opts.obscure_bit_percentage * aiop->error.dr.count)) <
    204 	    (INDEX_TO_DIOLEN(aiop->iolen) * CHAR_BIT)) {
    205 		plog(pri, "%s%s bit corruption detected: %lld bit%s flipped\n",
    206 		    str, aiop->retrycnt > 0 ? " retry" : "",
    207 		    aiop->error.dr.count, aiop->error.dr.count == 1 ? "" : "s");
    208 		decode_bits(pri, &aiop->error.dr);
    209 	} else {
    210 		plog(pri, "%s%s corruption detected\n",
    211 		    str, aiop->retrycnt > 0 ? " retry" : "");
    212 	}
    213 
    214 }
    215