xref: /openbmc/linux/fs/xfs/xfs_error.c (revision 1fa6ac37)
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 
157 void
158 xfs_fs_cmn_err(int level, xfs_mount_t *mp, char *fmt, ...)
159 {
160 	va_list ap;
161 
162 	va_start(ap, fmt);
163 	xfs_fs_vcmn_err(level, mp, fmt, ap);
164 	va_end(ap);
165 }
166 
167 void
168 xfs_cmn_err(int panic_tag, int level, xfs_mount_t *mp, char *fmt, ...)
169 {
170 	va_list ap;
171 
172 #ifdef DEBUG
173 	xfs_panic_mask |= (XFS_PTAG_SHUTDOWN_CORRUPT | XFS_PTAG_LOGRES);
174 #endif
175 
176 	if (xfs_panic_mask && (xfs_panic_mask & panic_tag)
177 	    && (level & CE_ALERT)) {
178 		level &= ~CE_ALERT;
179 		level |= CE_PANIC;
180 		cmn_err(CE_ALERT, "XFS: Transforming an alert into a BUG.");
181 	}
182 	va_start(ap, fmt);
183 	xfs_fs_vcmn_err(level, mp, fmt, ap);
184 	va_end(ap);
185 }
186 
187 void
188 xfs_error_report(
189 	const char		*tag,
190 	int			level,
191 	struct xfs_mount	*mp,
192 	const char		*filename,
193 	int			linenum,
194 	inst_t			*ra)
195 {
196 	if (level <= xfs_error_level) {
197 		xfs_cmn_err(XFS_PTAG_ERROR_REPORT,
198 			    CE_ALERT, mp,
199 		"XFS internal error %s at line %d of file %s.  Caller 0x%p\n",
200 			    tag, linenum, filename, ra);
201 
202 		xfs_stack_trace();
203 	}
204 }
205 
206 void
207 xfs_corruption_error(
208 	const char		*tag,
209 	int			level,
210 	struct xfs_mount	*mp,
211 	void			*p,
212 	const char		*filename,
213 	int			linenum,
214 	inst_t			*ra)
215 {
216 	if (level <= xfs_error_level)
217 		xfs_hex_dump(p, 16);
218 	xfs_error_report(tag, level, mp, filename, linenum, ra);
219 }
220