xref: /linux/fs/xfs/xfs_error.c (revision 8fa5723aa7e053d498336b48448b292fc2e0458b)
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_inum.h"
23 #include "xfs_trans.h"
24 #include "xfs_sb.h"
25 #include "xfs_ag.h"
26 #include "xfs_dir2.h"
27 #include "xfs_dmapi.h"
28 #include "xfs_mount.h"
29 #include "xfs_bmap_btree.h"
30 #include "xfs_dir2_sf.h"
31 #include "xfs_attr_sf.h"
32 #include "xfs_dinode.h"
33 #include "xfs_inode.h"
34 #include "xfs_utils.h"
35 #include "xfs_error.h"
36 
37 #ifdef DEBUG
38 
39 int	xfs_etrap[XFS_ERROR_NTRAP] = {
40 	0,
41 };
42 
43 int
44 xfs_error_trap(int e)
45 {
46 	int i;
47 
48 	if (!e)
49 		return 0;
50 	for (i = 0; i < XFS_ERROR_NTRAP; i++) {
51 		if (xfs_etrap[i] == 0)
52 			break;
53 		if (e != xfs_etrap[i])
54 			continue;
55 		cmn_err(CE_NOTE, "xfs_error_trap: error %d", e);
56 		BUG();
57 		break;
58 	}
59 	return e;
60 }
61 
62 int	xfs_etest[XFS_NUM_INJECT_ERROR];
63 int64_t	xfs_etest_fsid[XFS_NUM_INJECT_ERROR];
64 char *	xfs_etest_fsname[XFS_NUM_INJECT_ERROR];
65 
66 int
67 xfs_error_test(int error_tag, int *fsidp, char *expression,
68 	       int line, char *file, unsigned long randfactor)
69 {
70 	int i;
71 	int64_t fsid;
72 
73 	if (random32() % randfactor)
74 		return 0;
75 
76 	memcpy(&fsid, fsidp, sizeof(xfs_fsid_t));
77 
78 	for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {
79 		if (xfs_etest[i] == error_tag && xfs_etest_fsid[i] == fsid) {
80 			cmn_err(CE_WARN,
81 	"Injecting error (%s) at file %s, line %d, on filesystem \"%s\"",
82 				expression, file, line, xfs_etest_fsname[i]);
83 			return 1;
84 		}
85 	}
86 
87 	return 0;
88 }
89 
90 int
91 xfs_errortag_add(int error_tag, xfs_mount_t *mp)
92 {
93 	int i;
94 	int len;
95 	int64_t fsid;
96 
97 	memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));
98 
99 	for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {
100 		if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) {
101 			cmn_err(CE_WARN, "XFS error tag #%d on", error_tag);
102 			return 0;
103 		}
104 	}
105 
106 	for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {
107 		if (xfs_etest[i] == 0) {
108 			cmn_err(CE_WARN, "Turned on XFS error tag #%d",
109 				error_tag);
110 			xfs_etest[i] = error_tag;
111 			xfs_etest_fsid[i] = fsid;
112 			len = strlen(mp->m_fsname);
113 			xfs_etest_fsname[i] = kmem_alloc(len + 1, KM_SLEEP);
114 			strcpy(xfs_etest_fsname[i], mp->m_fsname);
115 			return 0;
116 		}
117 	}
118 
119 	cmn_err(CE_WARN, "error tag overflow, too many turned on");
120 
121 	return 1;
122 }
123 
124 int
125 xfs_errortag_clearall(xfs_mount_t *mp, int loud)
126 {
127 	int64_t fsid;
128 	int cleared = 0;
129 	int i;
130 
131 	memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));
132 
133 
134 	for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) {
135 		if ((fsid == 0LL || xfs_etest_fsid[i] == fsid) &&
136 		     xfs_etest[i] != 0) {
137 			cleared = 1;
138 			cmn_err(CE_WARN, "Clearing XFS error tag #%d",
139 				xfs_etest[i]);
140 			xfs_etest[i] = 0;
141 			xfs_etest_fsid[i] = 0LL;
142 			kmem_free(xfs_etest_fsname[i]);
143 			xfs_etest_fsname[i] = NULL;
144 		}
145 	}
146 
147 	if (loud || cleared)
148 		cmn_err(CE_WARN,
149 			"Cleared all XFS error tags for filesystem \"%s\"",
150 			mp->m_fsname);
151 
152 	return 0;
153 }
154 #endif /* DEBUG */
155 
156 static void
157 xfs_fs_vcmn_err(int level, xfs_mount_t *mp, char *fmt, va_list ap)
158 {
159 	if (mp != NULL) {
160 		char	*newfmt;
161 		int	len = 16 + mp->m_fsname_len + strlen(fmt);
162 
163 		newfmt = kmem_alloc(len, KM_SLEEP);
164 		sprintf(newfmt, "Filesystem \"%s\": %s", mp->m_fsname, fmt);
165 		icmn_err(level, newfmt, ap);
166 		kmem_free(newfmt);
167 	} else {
168 		icmn_err(level, fmt, ap);
169 	}
170 }
171 
172 void
173 xfs_fs_cmn_err(int level, xfs_mount_t *mp, char *fmt, ...)
174 {
175 	va_list ap;
176 
177 	va_start(ap, fmt);
178 	xfs_fs_vcmn_err(level, mp, fmt, ap);
179 	va_end(ap);
180 }
181 
182 void
183 xfs_cmn_err(int panic_tag, int level, xfs_mount_t *mp, char *fmt, ...)
184 {
185 	va_list ap;
186 
187 #ifdef DEBUG
188 	xfs_panic_mask |= XFS_PTAG_SHUTDOWN_CORRUPT;
189 #endif
190 
191 	if (xfs_panic_mask && (xfs_panic_mask & panic_tag)
192 	    && (level & CE_ALERT)) {
193 		level &= ~CE_ALERT;
194 		level |= CE_PANIC;
195 		cmn_err(CE_ALERT, "XFS: Transforming an alert into a BUG.");
196 	}
197 	va_start(ap, fmt);
198 	xfs_fs_vcmn_err(level, mp, fmt, ap);
199 	va_end(ap);
200 }
201 
202 void
203 xfs_error_report(
204 	char		*tag,
205 	int		level,
206 	xfs_mount_t	*mp,
207 	char		*fname,
208 	int		linenum,
209 	inst_t		*ra)
210 {
211 	if (level <= xfs_error_level) {
212 		xfs_cmn_err(XFS_PTAG_ERROR_REPORT,
213 			    CE_ALERT, mp,
214 		"XFS internal error %s at line %d of file %s.  Caller 0x%p\n",
215 			    tag, linenum, fname, ra);
216 
217 		xfs_stack_trace();
218 	}
219 }
220 
221 void
222 xfs_corruption_error(
223 	char		*tag,
224 	int		level,
225 	xfs_mount_t	*mp,
226 	void		*p,
227 	char		*fname,
228 	int		linenum,
229 	inst_t		*ra)
230 {
231 	if (level <= xfs_error_level)
232 		xfs_hex_dump(p, 16);
233 	xfs_error_report(tag, level, mp, fname, linenum, ra);
234 }
235