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