Merge branch 'genetlink_mcast'
[cascardo/linux.git] / fs / xfs / xfs_error.c
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_error.h"
30
31 #ifdef DEBUG
32
33 int     xfs_etrap[XFS_ERROR_NTRAP] = {
34         0,
35 };
36
37 int
38 xfs_error_trap(int e)
39 {
40         int i;
41
42         if (!e)
43                 return 0;
44         for (i = 0; i < XFS_ERROR_NTRAP; i++) {
45                 if (xfs_etrap[i] == 0)
46                         break;
47                 if (e != xfs_etrap[i])
48                         continue;
49                 xfs_notice(NULL, "%s: error %d", __func__, e);
50                 BUG();
51                 break;
52         }
53         return e;
54 }
55
56 int     xfs_etest[XFS_NUM_INJECT_ERROR];
57 int64_t xfs_etest_fsid[XFS_NUM_INJECT_ERROR];
58 char *  xfs_etest_fsname[XFS_NUM_INJECT_ERROR];
59 int     xfs_error_test_active;
60
61 int
62 xfs_error_test(int error_tag, int *fsidp, char *expression,
63                int line, char *file, unsigned long randfactor)
64 {
65         int i;
66         int64_t fsid;
67
68         if (prandom_u32() % randfactor)
69                 return 0;
70
71         memcpy(&fsid, fsidp, sizeof(xfs_fsid_t));
72
73         for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {
74                 if (xfs_etest[i] == error_tag && xfs_etest_fsid[i] == fsid) {
75                         xfs_warn(NULL,
76         "Injecting error (%s) at file %s, line %d, on filesystem \"%s\"",
77                                 expression, file, line, xfs_etest_fsname[i]);
78                         return 1;
79                 }
80         }
81
82         return 0;
83 }
84
85 int
86 xfs_errortag_add(int error_tag, xfs_mount_t *mp)
87 {
88         int i;
89         int len;
90         int64_t fsid;
91
92         memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));
93
94         for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {
95                 if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) {
96                         xfs_warn(mp, "error tag #%d on", error_tag);
97                         return 0;
98                 }
99         }
100
101         for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {
102                 if (xfs_etest[i] == 0) {
103                         xfs_warn(mp, "Turned on XFS error tag #%d",
104                                 error_tag);
105                         xfs_etest[i] = error_tag;
106                         xfs_etest_fsid[i] = fsid;
107                         len = strlen(mp->m_fsname);
108                         xfs_etest_fsname[i] = kmem_alloc(len + 1, KM_SLEEP);
109                         strcpy(xfs_etest_fsname[i], mp->m_fsname);
110                         xfs_error_test_active++;
111                         return 0;
112                 }
113         }
114
115         xfs_warn(mp, "error tag overflow, too many turned on");
116
117         return 1;
118 }
119
120 int
121 xfs_errortag_clearall(xfs_mount_t *mp, int loud)
122 {
123         int64_t fsid;
124         int cleared = 0;
125         int i;
126
127         memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));
128
129
130         for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) {
131                 if ((fsid == 0LL || xfs_etest_fsid[i] == fsid) &&
132                      xfs_etest[i] != 0) {
133                         cleared = 1;
134                         xfs_warn(mp, "Clearing XFS error tag #%d",
135                                 xfs_etest[i]);
136                         xfs_etest[i] = 0;
137                         xfs_etest_fsid[i] = 0LL;
138                         kmem_free(xfs_etest_fsname[i]);
139                         xfs_etest_fsname[i] = NULL;
140                         xfs_error_test_active--;
141                 }
142         }
143
144         if (loud || cleared)
145                 xfs_warn(mp, "Cleared all XFS error tags for filesystem");
146
147         return 0;
148 }
149 #endif /* DEBUG */
150
151 void
152 xfs_error_report(
153         const char              *tag,
154         int                     level,
155         struct xfs_mount        *mp,
156         const char              *filename,
157         int                     linenum,
158         inst_t                  *ra)
159 {
160         if (level <= xfs_error_level) {
161                 xfs_alert_tag(mp, XFS_PTAG_ERROR_REPORT,
162                 "Internal error %s at line %d of file %s.  Caller 0x%p\n",
163                             tag, linenum, filename, ra);
164
165                 xfs_stack_trace();
166         }
167 }
168
169 void
170 xfs_corruption_error(
171         const char              *tag,
172         int                     level,
173         struct xfs_mount        *mp,
174         void                    *p,
175         const char              *filename,
176         int                     linenum,
177         inst_t                  *ra)
178 {
179         if (level <= xfs_error_level)
180                 xfs_hex_dump(p, 64);
181         xfs_error_report(tag, level, mp, filename, linenum, ra);
182         xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair");
183 }