xfs_error.c 4.3 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2 3
 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
 * All Rights Reserved.
L
Linus Torvalds 已提交
4
 *
5 6
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
L
Linus Torvalds 已提交
7 8
 * published by the Free Software Foundation.
 *
9 10 11 12
 * This program is distributed in the hope that it would be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
L
Linus Torvalds 已提交
13
 *
14 15 16
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write the Free Software Foundation,
 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
L
Linus Torvalds 已提交
17 18
 */
#include "xfs.h"
19
#include "xfs_format.h"
20
#include "xfs_fs.h"
21 22
#include "xfs_log_format.h"
#include "xfs_trans_resv.h"
L
Linus Torvalds 已提交
23 24 25 26 27
#include "xfs_mount.h"
#include "xfs_error.h"

#ifdef DEBUG

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
static unsigned int xfs_errortag_random_default[] = {
	XFS_RANDOM_DEFAULT,
	XFS_RANDOM_IFLUSH_1,
	XFS_RANDOM_IFLUSH_2,
	XFS_RANDOM_IFLUSH_3,
	XFS_RANDOM_IFLUSH_4,
	XFS_RANDOM_IFLUSH_5,
	XFS_RANDOM_IFLUSH_6,
	XFS_RANDOM_DA_READ_BUF,
	XFS_RANDOM_BTREE_CHECK_LBLOCK,
	XFS_RANDOM_BTREE_CHECK_SBLOCK,
	XFS_RANDOM_ALLOC_READ_AGF,
	XFS_RANDOM_IALLOC_READ_AGI,
	XFS_RANDOM_ITOBP_INOTOBP,
	XFS_RANDOM_IUNLINK,
	XFS_RANDOM_IUNLINK_REMOVE,
	XFS_RANDOM_DIR_INO_VALIDATE,
	XFS_RANDOM_BULKSTAT_READ_CHUNK,
	XFS_RANDOM_IODONE_IOERR,
	XFS_RANDOM_STRATREAD_IOERR,
	XFS_RANDOM_STRATCMPL_IOERR,
	XFS_RANDOM_DIOWRITE_IOERR,
	XFS_RANDOM_BMAPIFORMAT,
	XFS_RANDOM_FREE_EXTENT,
	XFS_RANDOM_RMAP_FINISH_ONE,
	XFS_RANDOM_REFCOUNT_CONTINUE_UPDATE,
	XFS_RANDOM_REFCOUNT_FINISH_ONE,
	XFS_RANDOM_BMAP_FINISH_ONE,
	XFS_RANDOM_AG_RESV_CRITICAL,
};
L
Linus Torvalds 已提交
58 59

int
60 61
xfs_errortag_init(
	struct xfs_mount	*mp)
L
Linus Torvalds 已提交
62
{
63 64 65 66 67 68
	mp->m_errortag = kmem_zalloc(sizeof(unsigned int) * XFS_ERRTAG_MAX,
			KM_SLEEP | KM_MAYFAIL);
	if (!mp->m_errortag)
		return -ENOMEM;
	return 0;
}
L
Linus Torvalds 已提交
69

70 71 72 73 74 75
void
xfs_errortag_del(
	struct xfs_mount	*mp)
{
	kmem_free(mp->m_errortag);
}
L
Linus Torvalds 已提交
76

77 78 79 80 81 82 83 84 85
bool
xfs_errortag_test(
	struct xfs_mount	*mp,
	const char		*expression,
	const char		*file,
	int			line,
	unsigned int		error_tag)
{
	unsigned int		randfactor;
L
Linus Torvalds 已提交
86

87 88 89 90
	ASSERT(error_tag < XFS_ERRTAG_MAX);
	randfactor = mp->m_errortag[error_tag];
	if (!randfactor || prandom_u32() % randfactor)
		return false;
L
Linus Torvalds 已提交
91

92 93 94 95
	xfs_warn_ratelimited(mp,
"Injecting error (%s) at file %s, line %d, on filesystem \"%s\"",
			expression, file, line, mp->m_fsname);
	return true;
L
Linus Torvalds 已提交
96 97 98
}

int
99 100 101 102
xfs_errortag_set(
	struct xfs_mount	*mp,
	unsigned int		error_tag,
	unsigned int		tag_value)
L
Linus Torvalds 已提交
103
{
104 105 106
	if (error_tag >= XFS_ERRTAG_MAX)
		return -EINVAL;

107 108
	mp->m_errortag[error_tag] = tag_value;
	return 0;
L
Linus Torvalds 已提交
109 110 111
}

int
112 113 114
xfs_errortag_add(
	struct xfs_mount	*mp,
	unsigned int		error_tag)
L
Linus Torvalds 已提交
115
{
116 117
	if (error_tag >= XFS_ERRTAG_MAX)
		return -EINVAL;
L
Linus Torvalds 已提交
118

119 120 121
	return xfs_errortag_set(mp, error_tag,
			xfs_errortag_random_default[error_tag]);
}
L
Linus Torvalds 已提交
122

123 124 125 126 127
int
xfs_errortag_clearall(
	struct xfs_mount	*mp)
{
	memset(mp->m_errortag, 0, sizeof(unsigned int) * XFS_ERRTAG_MAX);
L
Linus Torvalds 已提交
128 129
	return 0;
}
C
Christoph Hellwig 已提交
130
#endif /* DEBUG */
L
Linus Torvalds 已提交
131 132 133

void
xfs_error_report(
134 135 136 137 138
	const char		*tag,
	int			level,
	struct xfs_mount	*mp,
	const char		*filename,
	int			linenum,
C
Christoph Hellwig 已提交
139
	void			*ra)
L
Linus Torvalds 已提交
140 141
{
	if (level <= xfs_error_level) {
142
		xfs_alert_tag(mp, XFS_PTAG_ERROR_REPORT,
143
		"Internal error %s at line %d of file %s.  Caller %pS",
144
			    tag, linenum, filename, ra);
L
Linus Torvalds 已提交
145 146 147 148 149 150 151

		xfs_stack_trace();
	}
}

void
xfs_corruption_error(
152 153 154 155 156 157
	const char		*tag,
	int			level,
	struct xfs_mount	*mp,
	void			*p,
	const char		*filename,
	int			linenum,
C
Christoph Hellwig 已提交
158
	void			*ra)
L
Linus Torvalds 已提交
159 160
{
	if (level <= xfs_error_level)
161
		xfs_hex_dump(p, 64);
162
	xfs_error_report(tag, level, mp, filename, linenum, ra);
163
	xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair");
L
Linus Torvalds 已提交
164
}
E
Eric Sandeen 已提交
165 166 167 168 169 170 171 172 173 174 175

/*
 * Warnings specifically for verifier errors.  Differentiate CRC vs. invalid
 * values, and omit the stack trace unless the error level is tuned high.
 */
void
xfs_verifier_error(
	struct xfs_buf		*bp)
{
	struct xfs_mount *mp = bp->b_target->bt_mount;

176
	xfs_alert(mp, "Metadata %s detected at %pF, %s block 0x%llx",
D
Dave Chinner 已提交
177
		  bp->b_error == -EFSBADCRC ? "CRC error" : "corruption",
178
		  __return_address, bp->b_ops->name, bp->b_bn);
E
Eric Sandeen 已提交
179 180 181 182 183 184 185 186 187 188 189

	xfs_alert(mp, "Unmount and run xfs_repair");

	if (xfs_error_level >= XFS_ERRLEVEL_LOW) {
		xfs_alert(mp, "First 64 bytes of corrupted metadata buffer:");
		xfs_hex_dump(xfs_buf_offset(bp, 0), 64);
	}

	if (xfs_error_level >= XFS_ERRLEVEL_HIGH)
		xfs_stack_trace();
}