]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - fs/xfs/xfs_error.c
[XFS] Remove xfs_macros.c, xfs_macros.h, rework headers a whole lot.
[linux-2.6-omap-h63xx.git] / fs / xfs / xfs_error.c
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 #include "xfs.h"
33 #include "xfs_fs.h"
34 #include "xfs_types.h"
35 #include "xfs_log.h"
36 #include "xfs_inum.h"
37 #include "xfs_trans.h"
38 #include "xfs_sb.h"
39 #include "xfs_dir.h"
40 #include "xfs_dir2.h"
41 #include "xfs_dmapi.h"
42 #include "xfs_mount.h"
43 #include "xfs_bmap_btree.h"
44 #include "xfs_dir_sf.h"
45 #include "xfs_dir2_sf.h"
46 #include "xfs_attr_sf.h"
47 #include "xfs_dinode.h"
48 #include "xfs_inode.h"
49 #include "xfs_utils.h"
50 #include "xfs_error.h"
51
52 #ifdef DEBUG
53
54 int     xfs_etrap[XFS_ERROR_NTRAP] = {
55         0,
56 };
57
58 int
59 xfs_error_trap(int e)
60 {
61         int i;
62
63         if (!e)
64                 return 0;
65         for (i = 0; i < XFS_ERROR_NTRAP; i++) {
66                 if (xfs_etrap[i] == 0)
67                         break;
68                 if (e != xfs_etrap[i])
69                         continue;
70                 cmn_err(CE_NOTE, "xfs_error_trap: error %d", e);
71                 debug_stop_all_cpus((void *)-1LL);
72                 BUG();
73                 break;
74         }
75         return e;
76 }
77 #endif
78
79 #if (defined(DEBUG) || defined(INDUCE_IO_ERROR))
80
81 int     xfs_etest[XFS_NUM_INJECT_ERROR];
82 int64_t xfs_etest_fsid[XFS_NUM_INJECT_ERROR];
83 char *  xfs_etest_fsname[XFS_NUM_INJECT_ERROR];
84
85 void
86 xfs_error_test_init(void)
87 {
88         memset(xfs_etest, 0, sizeof(xfs_etest));
89         memset(xfs_etest_fsid, 0, sizeof(xfs_etest_fsid));
90         memset(xfs_etest_fsname, 0, sizeof(xfs_etest_fsname));
91 }
92
93 int
94 xfs_error_test(int error_tag, int *fsidp, char *expression,
95                int line, char *file, unsigned long randfactor)
96 {
97         int i;
98         int64_t fsid;
99
100         if (random() % randfactor)
101                 return 0;
102
103         memcpy(&fsid, fsidp, sizeof(xfs_fsid_t));
104
105         for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {
106                 if (xfs_etest[i] == error_tag && xfs_etest_fsid[i] == fsid) {
107                         cmn_err(CE_WARN,
108         "Injecting error (%s) at file %s, line %d, on filesystem \"%s\"",
109                                 expression, file, line, xfs_etest_fsname[i]);
110                         return 1;
111                 }
112         }
113
114         return 0;
115 }
116
117 int
118 xfs_errortag_add(int error_tag, xfs_mount_t *mp)
119 {
120         int i;
121         int len;
122         int64_t fsid;
123
124         memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));
125
126         for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {
127                 if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) {
128                         cmn_err(CE_WARN, "XFS error tag #%d on", error_tag);
129                         return 0;
130                 }
131         }
132
133         for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {
134                 if (xfs_etest[i] == 0) {
135                         cmn_err(CE_WARN, "Turned on XFS error tag #%d",
136                                 error_tag);
137                         xfs_etest[i] = error_tag;
138                         xfs_etest_fsid[i] = fsid;
139                         len = strlen(mp->m_fsname);
140                         xfs_etest_fsname[i] = kmem_alloc(len + 1, KM_SLEEP);
141                         strcpy(xfs_etest_fsname[i], mp->m_fsname);
142                         return 0;
143                 }
144         }
145
146         cmn_err(CE_WARN, "error tag overflow, too many turned on");
147
148         return 1;
149 }
150
151 int
152 xfs_errortag_clear(int error_tag, xfs_mount_t *mp)
153 {
154         int i;
155         int64_t fsid;
156
157         memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));
158
159         for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) {
160                 if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) {
161                         xfs_etest[i] = 0;
162                         xfs_etest_fsid[i] = 0LL;
163                         kmem_free(xfs_etest_fsname[i],
164                                   strlen(xfs_etest_fsname[i]) + 1);
165                         xfs_etest_fsname[i] = NULL;
166                         cmn_err(CE_WARN, "Cleared XFS error tag #%d",
167                                 error_tag);
168                         return 0;
169                 }
170         }
171
172         cmn_err(CE_WARN, "XFS error tag %d not on", error_tag);
173
174         return 1;
175 }
176
177 int
178 xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud)
179 {
180         int i;
181         int cleared = 0;
182
183         for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) {
184                 if ((fsid == 0LL || xfs_etest_fsid[i] == fsid) &&
185                      xfs_etest[i] != 0) {
186                         cleared = 1;
187                         cmn_err(CE_WARN, "Clearing XFS error tag #%d",
188                                 xfs_etest[i]);
189                         xfs_etest[i] = 0;
190                         xfs_etest_fsid[i] = 0LL;
191                         kmem_free(xfs_etest_fsname[i],
192                                   strlen(xfs_etest_fsname[i]) + 1);
193                         xfs_etest_fsname[i] = NULL;
194                 }
195         }
196
197         if (loud || cleared)
198                 cmn_err(CE_WARN,
199                         "Cleared all XFS error tags for filesystem \"%s\"",
200                         fsname);
201
202         return 0;
203 }
204
205 int
206 xfs_errortag_clearall(xfs_mount_t *mp)
207 {
208         int64_t fsid;
209
210         memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));
211
212         return xfs_errortag_clearall_umount(fsid, mp->m_fsname, 1);
213 }
214 #endif /* DEBUG || INDUCE_IO_ERROR */
215
216 static void
217 xfs_fs_vcmn_err(int level, xfs_mount_t *mp, char *fmt, va_list ap)
218 {
219         if (mp != NULL) {
220                 char    *newfmt;
221                 int     len = 16 + mp->m_fsname_len + strlen(fmt);
222
223                 newfmt = kmem_alloc(len, KM_SLEEP);
224                 sprintf(newfmt, "Filesystem \"%s\": %s", mp->m_fsname, fmt);
225                 icmn_err(level, newfmt, ap);
226                 kmem_free(newfmt, len);
227         } else {
228                 icmn_err(level, fmt, ap);
229         }
230 }
231
232 void
233 xfs_fs_cmn_err(int level, xfs_mount_t *mp, char *fmt, ...)
234 {
235         va_list ap;
236
237         va_start(ap, fmt);
238         xfs_fs_vcmn_err(level, mp, fmt, ap);
239         va_end(ap);
240 }
241
242 void
243 xfs_cmn_err(int panic_tag, int level, xfs_mount_t *mp, char *fmt, ...)
244 {
245         va_list ap;
246
247 #ifdef DEBUG
248         xfs_panic_mask |= XFS_PTAG_SHUTDOWN_CORRUPT;
249 #endif
250
251         if (xfs_panic_mask && (xfs_panic_mask & panic_tag)
252             && (level & CE_ALERT)) {
253                 level &= ~CE_ALERT;
254                 level |= CE_PANIC;
255                 cmn_err(CE_ALERT, "XFS: Transforming an alert into a BUG.");
256         }
257         va_start(ap, fmt);
258         xfs_fs_vcmn_err(level, mp, fmt, ap);
259         va_end(ap);
260 }
261
262 void
263 xfs_error_report(
264         char            *tag,
265         int             level,
266         xfs_mount_t     *mp,
267         char            *fname,
268         int             linenum,
269         inst_t          *ra)
270 {
271         if (level <= xfs_error_level) {
272                 xfs_cmn_err(XFS_PTAG_ERROR_REPORT,
273                             CE_ALERT, mp,
274                 "XFS internal error %s at line %d of file %s.  Caller 0x%p\n",
275                             tag, linenum, fname, ra);
276
277                 xfs_stack_trace();
278         }
279 }
280
281 STATIC void
282 xfs_hex_dump(void *p, int length)
283 {
284         __uint8_t *uip = (__uint8_t*)p;
285         int     i;
286         char    sbuf[128], *s;
287
288         s = sbuf;
289         *s = '\0';
290         for (i=0; i<length; i++, uip++) {
291                 if ((i % 16) == 0) {
292                         if (*s != '\0')
293                                 cmn_err(CE_ALERT, "%s\n", sbuf);
294                         s = sbuf;
295                         sprintf(s, "0x%x: ", i);
296                         while( *s != '\0')
297                                 s++;
298                 }
299                 sprintf(s, "%02x ", *uip);
300
301                 /*
302                  * the kernel sprintf is a void; user sprintf returns
303                  * the sprintf'ed string's length.  Find the new end-
304                  * of-string
305                  */
306                 while( *s != '\0')
307                         s++;
308         }
309         cmn_err(CE_ALERT, "%s\n", sbuf);
310 }
311
312 void
313 xfs_corruption_error(
314         char            *tag,
315         int             level,
316         xfs_mount_t     *mp,
317         void            *p,
318         char            *fname,
319         int             linenum,
320         inst_t          *ra)
321 {
322         if (level <= xfs_error_level)
323                 xfs_hex_dump(p, 16);
324         xfs_error_report(tag, level, mp, fname, linenum, ra);
325 }