1 /* 2 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. 3 * All Rights Reserved. 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 #include "xfs.h" 19 #include "xfs_fs.h" 20 #include "xfs_types.h" 21 #include "xfs_log.h" 22 #include "xfs_trans.h" 23 #include "xfs_sb.h" 24 #include "xfs_ag.h" 25 #include "xfs_mount.h" 26 #include "xfs_bmap_btree.h" 27 #include "xfs_dinode.h" 28 #include "xfs_inode.h" 29 #include "xfs_utils.h" 30 #include "xfs_error.h" 31 32 #ifdef DEBUG 33 34 int xfs_etrap[XFS_ERROR_NTRAP] = { 35 0, 36 }; 37 38 int 39 xfs_error_trap(int e) 40 { 41 int i; 42 43 if (!e) 44 return 0; 45 for (i = 0; i < XFS_ERROR_NTRAP; i++) { 46 if (xfs_etrap[i] == 0) 47 break; 48 if (e != xfs_etrap[i]) 49 continue; 50 xfs_notice(NULL, "%s: error %d", __func__, e); 51 BUG(); 52 break; 53 } 54 return e; 55 } 56 57 int xfs_etest[XFS_NUM_INJECT_ERROR]; 58 int64_t xfs_etest_fsid[XFS_NUM_INJECT_ERROR]; 59 char * xfs_etest_fsname[XFS_NUM_INJECT_ERROR]; 60 int xfs_error_test_active; 61 62 int 63 xfs_error_test(int error_tag, int *fsidp, char *expression, 64 int line, char *file, unsigned long randfactor) 65 { 66 int i; 67 int64_t fsid; 68 69 if (random32() % randfactor) 70 return 0; 71 72 memcpy(&fsid, fsidp, sizeof(xfs_fsid_t)); 73 74 for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) { 75 if (xfs_etest[i] == error_tag && xfs_etest_fsid[i] == fsid) { 76 xfs_warn(NULL, 77 "Injecting error (%s) at file %s, line %d, on filesystem \"%s\"", 78 expression, file, line, xfs_etest_fsname[i]); 79 return 1; 80 } 81 } 82 83 return 0; 84 } 85 86 int 87 xfs_errortag_add(int error_tag, xfs_mount_t *mp) 88 { 89 int i; 90 int len; 91 int64_t fsid; 92 93 memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t)); 94 95 for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) { 96 if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) { 97 xfs_warn(mp, "error tag #%d on", error_tag); 98 return 0; 99 } 100 } 101 102 for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) { 103 if (xfs_etest[i] == 0) { 104 xfs_warn(mp, "Turned on XFS error tag #%d", 105 error_tag); 106 xfs_etest[i] = error_tag; 107 xfs_etest_fsid[i] = fsid; 108 len = strlen(mp->m_fsname); 109 xfs_etest_fsname[i] = kmem_alloc(len + 1, KM_SLEEP); 110 strcpy(xfs_etest_fsname[i], mp->m_fsname); 111 xfs_error_test_active++; 112 return 0; 113 } 114 } 115 116 xfs_warn(mp, "error tag overflow, too many turned on"); 117 118 return 1; 119 } 120 121 int 122 xfs_errortag_clearall(xfs_mount_t *mp, int loud) 123 { 124 int64_t fsid; 125 int cleared = 0; 126 int i; 127 128 memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t)); 129 130 131 for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) { 132 if ((fsid == 0LL || xfs_etest_fsid[i] == fsid) && 133 xfs_etest[i] != 0) { 134 cleared = 1; 135 xfs_warn(mp, "Clearing XFS error tag #%d", 136 xfs_etest[i]); 137 xfs_etest[i] = 0; 138 xfs_etest_fsid[i] = 0LL; 139 kmem_free(xfs_etest_fsname[i]); 140 xfs_etest_fsname[i] = NULL; 141 xfs_error_test_active--; 142 } 143 } 144 145 if (loud || cleared) 146 xfs_warn(mp, "Cleared all XFS error tags for filesystem"); 147 148 return 0; 149 } 150 #endif /* DEBUG */ 151 152 void 153 xfs_error_report( 154 const char *tag, 155 int level, 156 struct xfs_mount *mp, 157 const char *filename, 158 int linenum, 159 inst_t *ra) 160 { 161 if (level <= xfs_error_level) { 162 xfs_alert_tag(mp, XFS_PTAG_ERROR_REPORT, 163 "Internal error %s at line %d of file %s. Caller 0x%p\n", 164 tag, linenum, filename, ra); 165 166 xfs_stack_trace(); 167 } 168 } 169 170 void 171 xfs_corruption_error( 172 const char *tag, 173 int level, 174 struct xfs_mount *mp, 175 void *p, 176 const char *filename, 177 int linenum, 178 inst_t *ra) 179 { 180 if (level <= xfs_error_level) 181 xfs_hex_dump(p, 16); 182 xfs_error_report(tag, level, mp, filename, linenum, ra); 183 xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair"); 184 } 185