1 /* 2 * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of version 2 of the GNU General Public License as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it would be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 * 12 * Further, this software is distributed without any warranty that it is 13 * free of the rightful claim of any third person regarding infringement 14 * or the like. Any license provided herein, whether implied or 15 * otherwise, applies only to this software file. Patent licenses, if 16 * any, provided herein do not apply to combinations of this program with 17 * other software, or any other product whatsoever. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write the Free Software Foundation, Inc., 59 21 * Temple Place - Suite 330, Boston MA 02111-1307, USA. 22 * 23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 24 * Mountain View, CA 94043, or: 25 * 26 * http://www.sgi.com 27 * 28 * For further information regarding this notice, see: 29 * 30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ 31 */ 32 33 #include "xfs.h" 34 35 #include "xfs_macros.h" 36 #include "xfs_types.h" 37 #include "xfs_inum.h" 38 #include "xfs_log.h" 39 #include "xfs_sb.h" 40 #include "xfs_trans.h" 41 #include "xfs_dir.h" 42 #include "xfs_dir2.h" 43 #include "xfs_dmapi.h" 44 #include "xfs_mount.h" 45 #include "xfs_bmap_btree.h" 46 #include "xfs_attr_sf.h" 47 #include "xfs_dir_sf.h" 48 #include "xfs_dir2_sf.h" 49 #include "xfs_dinode.h" 50 #include "xfs_inode.h" 51 #include "xfs_utils.h" 52 #include "xfs_error.h" 53 54 #ifdef DEBUG 55 56 int xfs_etrap[XFS_ERROR_NTRAP] = { 57 0, 58 }; 59 60 int 61 xfs_error_trap(int e) 62 { 63 int i; 64 65 if (!e) 66 return 0; 67 for (i = 0; i < XFS_ERROR_NTRAP; i++) { 68 if (xfs_etrap[i] == 0) 69 break; 70 if (e != xfs_etrap[i]) 71 continue; 72 cmn_err(CE_NOTE, "xfs_error_trap: error %d", e); 73 debug_stop_all_cpus((void *)-1LL); 74 BUG(); 75 break; 76 } 77 return e; 78 } 79 #endif 80 81 #if (defined(DEBUG) || defined(INDUCE_IO_ERROR)) 82 83 int xfs_etest[XFS_NUM_INJECT_ERROR]; 84 int64_t xfs_etest_fsid[XFS_NUM_INJECT_ERROR]; 85 char * xfs_etest_fsname[XFS_NUM_INJECT_ERROR]; 86 87 void 88 xfs_error_test_init(void) 89 { 90 memset(xfs_etest, 0, sizeof(xfs_etest)); 91 memset(xfs_etest_fsid, 0, sizeof(xfs_etest_fsid)); 92 memset(xfs_etest_fsname, 0, sizeof(xfs_etest_fsname)); 93 } 94 95 int 96 xfs_error_test(int error_tag, int *fsidp, char *expression, 97 int line, char *file, unsigned long randfactor) 98 { 99 int i; 100 int64_t fsid; 101 102 if (random() % randfactor) 103 return 0; 104 105 memcpy(&fsid, fsidp, sizeof(xfs_fsid_t)); 106 107 for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) { 108 if (xfs_etest[i] == error_tag && xfs_etest_fsid[i] == fsid) { 109 cmn_err(CE_WARN, 110 "Injecting error (%s) at file %s, line %d, on filesystem \"%s\"", 111 expression, file, line, xfs_etest_fsname[i]); 112 return 1; 113 } 114 } 115 116 return 0; 117 } 118 119 int 120 xfs_errortag_add(int error_tag, xfs_mount_t *mp) 121 { 122 int i; 123 int len; 124 int64_t fsid; 125 126 memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t)); 127 128 for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) { 129 if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) { 130 cmn_err(CE_WARN, "XFS error tag #%d on", error_tag); 131 return 0; 132 } 133 } 134 135 for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) { 136 if (xfs_etest[i] == 0) { 137 cmn_err(CE_WARN, "Turned on XFS error tag #%d", 138 error_tag); 139 xfs_etest[i] = error_tag; 140 xfs_etest_fsid[i] = fsid; 141 len = strlen(mp->m_fsname); 142 xfs_etest_fsname[i] = kmem_alloc(len + 1, KM_SLEEP); 143 strcpy(xfs_etest_fsname[i], mp->m_fsname); 144 return 0; 145 } 146 } 147 148 cmn_err(CE_WARN, "error tag overflow, too many turned on"); 149 150 return 1; 151 } 152 153 int 154 xfs_errortag_clear(int error_tag, xfs_mount_t *mp) 155 { 156 int i; 157 int64_t fsid; 158 159 memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t)); 160 161 for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) { 162 if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) { 163 xfs_etest[i] = 0; 164 xfs_etest_fsid[i] = 0LL; 165 kmem_free(xfs_etest_fsname[i], 166 strlen(xfs_etest_fsname[i]) + 1); 167 xfs_etest_fsname[i] = NULL; 168 cmn_err(CE_WARN, "Cleared XFS error tag #%d", 169 error_tag); 170 return 0; 171 } 172 } 173 174 cmn_err(CE_WARN, "XFS error tag %d not on", error_tag); 175 176 return 1; 177 } 178 179 int 180 xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud) 181 { 182 int i; 183 int cleared = 0; 184 185 for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) { 186 if ((fsid == 0LL || xfs_etest_fsid[i] == fsid) && 187 xfs_etest[i] != 0) { 188 cleared = 1; 189 cmn_err(CE_WARN, "Clearing XFS error tag #%d", 190 xfs_etest[i]); 191 xfs_etest[i] = 0; 192 xfs_etest_fsid[i] = 0LL; 193 kmem_free(xfs_etest_fsname[i], 194 strlen(xfs_etest_fsname[i]) + 1); 195 xfs_etest_fsname[i] = NULL; 196 } 197 } 198 199 if (loud || cleared) 200 cmn_err(CE_WARN, 201 "Cleared all XFS error tags for filesystem \"%s\"", 202 fsname); 203 204 return 0; 205 } 206 207 int 208 xfs_errortag_clearall(xfs_mount_t *mp) 209 { 210 int64_t fsid; 211 212 memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t)); 213 214 return xfs_errortag_clearall_umount(fsid, mp->m_fsname, 1); 215 } 216 #endif /* DEBUG || INDUCE_IO_ERROR */ 217 218 static void 219 xfs_fs_vcmn_err(int level, xfs_mount_t *mp, char *fmt, va_list ap) 220 { 221 if (mp != NULL) { 222 char *newfmt; 223 int len = 16 + mp->m_fsname_len + strlen(fmt); 224 225 newfmt = kmem_alloc(len, KM_SLEEP); 226 sprintf(newfmt, "Filesystem \"%s\": %s", mp->m_fsname, fmt); 227 icmn_err(level, newfmt, ap); 228 kmem_free(newfmt, len); 229 } else { 230 icmn_err(level, fmt, ap); 231 } 232 } 233 234 void 235 xfs_fs_cmn_err(int level, xfs_mount_t *mp, char *fmt, ...) 236 { 237 va_list ap; 238 239 va_start(ap, fmt); 240 xfs_fs_vcmn_err(level, mp, fmt, ap); 241 va_end(ap); 242 } 243 244 void 245 xfs_cmn_err(int panic_tag, int level, xfs_mount_t *mp, char *fmt, ...) 246 { 247 va_list ap; 248 249 #ifdef DEBUG 250 xfs_panic_mask |= XFS_PTAG_SHUTDOWN_CORRUPT; 251 #endif 252 253 if (xfs_panic_mask && (xfs_panic_mask & panic_tag) 254 && (level & CE_ALERT)) { 255 level &= ~CE_ALERT; 256 level |= CE_PANIC; 257 cmn_err(CE_ALERT, "XFS: Transforming an alert into a BUG."); 258 } 259 va_start(ap, fmt); 260 xfs_fs_vcmn_err(level, mp, fmt, ap); 261 va_end(ap); 262 } 263 264 void 265 xfs_error_report( 266 char *tag, 267 int level, 268 xfs_mount_t *mp, 269 char *fname, 270 int linenum, 271 inst_t *ra) 272 { 273 if (level <= xfs_error_level) { 274 xfs_cmn_err(XFS_PTAG_ERROR_REPORT, 275 CE_ALERT, mp, 276 "XFS internal error %s at line %d of file %s. Caller 0x%p\n", 277 tag, linenum, fname, ra); 278 279 xfs_stack_trace(); 280 } 281 } 282 283 void 284 xfs_hex_dump(void *p, int length) 285 { 286 __uint8_t *uip = (__uint8_t*)p; 287 int i; 288 char sbuf[128], *s; 289 290 s = sbuf; 291 *s = '\0'; 292 for (i=0; i<length; i++, uip++) { 293 if ((i % 16) == 0) { 294 if (*s != '\0') 295 cmn_err(CE_ALERT, "%s\n", sbuf); 296 s = sbuf; 297 sprintf(s, "0x%x: ", i); 298 while( *s != '\0') 299 s++; 300 } 301 sprintf(s, "%02x ", *uip); 302 303 /* 304 * the kernel sprintf is a void; user sprintf returns 305 * the sprintf'ed string's length. Find the new end- 306 * of-string 307 */ 308 while( *s != '\0') 309 s++; 310 } 311 cmn_err(CE_ALERT, "%s\n", sbuf); 312 } 313 314 void 315 xfs_corruption_error( 316 char *tag, 317 int level, 318 xfs_mount_t *mp, 319 void *p, 320 char *fname, 321 int linenum, 322 inst_t *ra) 323 { 324 if (level <= xfs_error_level) 325 xfs_hex_dump(p, 16); 326 xfs_error_report(tag, level, mp, fname, linenum, ra); 327 } 328