Skip to content

Commit 31965ef

Browse files
committed
xfs: make errortag a per-mountpoint structure
Remove the xfs_etest structure in favor of a per-mountpoint structure. This will give us the flexibility to set as many error injection points as we want, and later enable us to set up sysfs knobs to set the trigger frequency as we wish. This comes at a cost of higher memory use, but unti we hit 1024 injection points (we're at 29) or a lot of mounts this shouldn't be a huge issue. Signed-off-by: Darrick J. Wong <[email protected]> Reviewed-by: Brian Foster <[email protected]> Reviewed-by: Carlos Maiolino <[email protected]>
1 parent 3977543 commit 31965ef

File tree

5 files changed

+111
-89
lines changed

5 files changed

+111
-89
lines changed

fs/xfs/xfs_error.c

Lines changed: 80 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -25,100 +25,106 @@
2525

2626
#ifdef DEBUG
2727

28-
int xfs_etest[XFS_NUM_INJECT_ERROR];
29-
int64_t xfs_etest_fsid[XFS_NUM_INJECT_ERROR];
30-
char * xfs_etest_fsname[XFS_NUM_INJECT_ERROR];
31-
int xfs_error_test_active;
28+
static unsigned int xfs_errortag_random_default[] = {
29+
XFS_RANDOM_DEFAULT,
30+
XFS_RANDOM_IFLUSH_1,
31+
XFS_RANDOM_IFLUSH_2,
32+
XFS_RANDOM_IFLUSH_3,
33+
XFS_RANDOM_IFLUSH_4,
34+
XFS_RANDOM_IFLUSH_5,
35+
XFS_RANDOM_IFLUSH_6,
36+
XFS_RANDOM_DA_READ_BUF,
37+
XFS_RANDOM_BTREE_CHECK_LBLOCK,
38+
XFS_RANDOM_BTREE_CHECK_SBLOCK,
39+
XFS_RANDOM_ALLOC_READ_AGF,
40+
XFS_RANDOM_IALLOC_READ_AGI,
41+
XFS_RANDOM_ITOBP_INOTOBP,
42+
XFS_RANDOM_IUNLINK,
43+
XFS_RANDOM_IUNLINK_REMOVE,
44+
XFS_RANDOM_DIR_INO_VALIDATE,
45+
XFS_RANDOM_BULKSTAT_READ_CHUNK,
46+
XFS_RANDOM_IODONE_IOERR,
47+
XFS_RANDOM_STRATREAD_IOERR,
48+
XFS_RANDOM_STRATCMPL_IOERR,
49+
XFS_RANDOM_DIOWRITE_IOERR,
50+
XFS_RANDOM_BMAPIFORMAT,
51+
XFS_RANDOM_FREE_EXTENT,
52+
XFS_RANDOM_RMAP_FINISH_ONE,
53+
XFS_RANDOM_REFCOUNT_CONTINUE_UPDATE,
54+
XFS_RANDOM_REFCOUNT_FINISH_ONE,
55+
XFS_RANDOM_BMAP_FINISH_ONE,
56+
XFS_RANDOM_AG_RESV_CRITICAL,
57+
};
3258

3359
int
34-
xfs_error_test(int error_tag, int *fsidp, char *expression,
35-
int line, char *file, unsigned long randfactor)
60+
xfs_errortag_init(
61+
struct xfs_mount *mp)
3662
{
37-
int i;
38-
int64_t fsid;
63+
mp->m_errortag = kmem_zalloc(sizeof(unsigned int) * XFS_ERRTAG_MAX,
64+
KM_SLEEP | KM_MAYFAIL);
65+
if (!mp->m_errortag)
66+
return -ENOMEM;
67+
return 0;
68+
}
3969

40-
if (prandom_u32() % randfactor)
41-
return 0;
70+
void
71+
xfs_errortag_del(
72+
struct xfs_mount *mp)
73+
{
74+
kmem_free(mp->m_errortag);
75+
}
4276

43-
memcpy(&fsid, fsidp, sizeof(xfs_fsid_t));
77+
bool
78+
xfs_errortag_test(
79+
struct xfs_mount *mp,
80+
const char *expression,
81+
const char *file,
82+
int line,
83+
unsigned int error_tag)
84+
{
85+
unsigned int randfactor;
4486

45-
for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) {
46-
if (xfs_etest[i] == error_tag && xfs_etest_fsid[i] == fsid) {
47-
xfs_warn(NULL,
48-
"Injecting error (%s) at file %s, line %d, on filesystem \"%s\"",
49-
expression, file, line, xfs_etest_fsname[i]);
50-
return 1;
51-
}
52-
}
87+
ASSERT(error_tag < XFS_ERRTAG_MAX);
88+
randfactor = mp->m_errortag[error_tag];
89+
if (!randfactor || prandom_u32() % randfactor)
90+
return false;
5391

54-
return 0;
92+
xfs_warn_ratelimited(mp,
93+
"Injecting error (%s) at file %s, line %d, on filesystem \"%s\"",
94+
expression, file, line, mp->m_fsname);
95+
return true;
5596
}
5697

5798
int
58-
xfs_errortag_add(unsigned int error_tag, xfs_mount_t *mp)
99+
xfs_errortag_set(
100+
struct xfs_mount *mp,
101+
unsigned int error_tag,
102+
unsigned int tag_value)
59103
{
60-
int i;
61-
int len;
62-
int64_t fsid;
63-
64104
if (error_tag >= XFS_ERRTAG_MAX)
65105
return -EINVAL;
66106

67-
memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));
68-
69-
for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) {
70-
if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) {
71-
xfs_warn(mp, "error tag #%d on", error_tag);
72-
return 0;
73-
}
74-
}
75-
76-
for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) {
77-
if (xfs_etest[i] == 0) {
78-
xfs_warn(mp, "Turned on XFS error tag #%d",
79-
error_tag);
80-
xfs_etest[i] = error_tag;
81-
xfs_etest_fsid[i] = fsid;
82-
len = strlen(mp->m_fsname);
83-
xfs_etest_fsname[i] = kmem_alloc(len + 1, KM_SLEEP);
84-
strcpy(xfs_etest_fsname[i], mp->m_fsname);
85-
xfs_error_test_active++;
86-
return 0;
87-
}
88-
}
89-
90-
xfs_warn(mp, "error tag overflow, too many turned on");
91-
92-
return 1;
107+
mp->m_errortag[error_tag] = tag_value;
108+
return 0;
93109
}
94110

95111
int
96-
xfs_errortag_clearall(xfs_mount_t *mp, int loud)
112+
xfs_errortag_add(
113+
struct xfs_mount *mp,
114+
unsigned int error_tag)
97115
{
98-
int64_t fsid;
99-
int cleared = 0;
100-
int i;
101-
102-
memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));
103-
104-
105-
for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) {
106-
if ((fsid == 0LL || xfs_etest_fsid[i] == fsid) &&
107-
xfs_etest[i] != 0) {
108-
cleared = 1;
109-
xfs_warn(mp, "Clearing XFS error tag #%d",
110-
xfs_etest[i]);
111-
xfs_etest[i] = 0;
112-
xfs_etest_fsid[i] = 0LL;
113-
kmem_free(xfs_etest_fsname[i]);
114-
xfs_etest_fsname[i] = NULL;
115-
xfs_error_test_active--;
116-
}
117-
}
116+
if (error_tag >= XFS_ERRTAG_MAX)
117+
return -EINVAL;
118118

119-
if (loud || cleared)
120-
xfs_warn(mp, "Cleared all XFS error tags for filesystem");
119+
return xfs_errortag_set(mp, error_tag,
120+
xfs_errortag_random_default[error_tag]);
121+
}
121122

123+
int
124+
xfs_errortag_clearall(
125+
struct xfs_mount *mp)
126+
{
127+
memset(mp->m_errortag, 0, sizeof(unsigned int) * XFS_ERRTAG_MAX);
122128
return 0;
123129
}
124130
#endif /* DEBUG */

fs/xfs/xfs_error.h

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -131,21 +131,24 @@ extern void xfs_verifier_error(struct xfs_buf *bp);
131131
#define XFS_RANDOM_AG_RESV_CRITICAL 4
132132

133133
#ifdef DEBUG
134-
extern int xfs_error_test_active;
135-
extern int xfs_error_test(int, int *, char *, int, char *, unsigned long);
136-
137-
#define XFS_NUM_INJECT_ERROR 10
134+
extern int xfs_errortag_init(struct xfs_mount *mp);
135+
extern void xfs_errortag_del(struct xfs_mount *mp);
136+
extern bool xfs_errortag_test(struct xfs_mount *mp, const char *expression,
137+
const char *file, int line, unsigned int error_tag);
138138
#define XFS_TEST_ERROR(expr, mp, tag, rf) \
139-
((expr) || (xfs_error_test_active && \
140-
xfs_error_test((tag), (mp)->m_fixedfsid, "expr", __LINE__, __FILE__, \
141-
(rf))))
139+
((expr) || xfs_errortag_test((mp), #expr, __FILE__, __LINE__, (tag)))
142140

143-
extern int xfs_errortag_add(unsigned int error_tag, struct xfs_mount *mp);
144-
extern int xfs_errortag_clearall(struct xfs_mount *mp, int loud);
141+
extern int xfs_errortag_set(struct xfs_mount *mp, unsigned int error_tag,
142+
unsigned int tag_value);
143+
extern int xfs_errortag_add(struct xfs_mount *mp, unsigned int error_tag);
144+
extern int xfs_errortag_clearall(struct xfs_mount *mp);
145145
#else
146+
#define xfs_errortag_init(mp) (0)
147+
#define xfs_errortag_del(mp)
146148
#define XFS_TEST_ERROR(expr, mp, tag, rf) (expr)
147-
#define xfs_errortag_add(tag, mp) (ENOSYS)
148-
#define xfs_errortag_clearall(mp, loud) (ENOSYS)
149+
#define xfs_errortag_set(mp, tag, val) (ENOSYS)
150+
#define xfs_errortag_add(mp, tag) (ENOSYS)
151+
#define xfs_errortag_clearall(mp) (ENOSYS)
149152
#endif /* DEBUG */
150153

151154
/*

fs/xfs/xfs_ioctl.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2037,14 +2037,14 @@ xfs_file_ioctl(
20372037
if (copy_from_user(&in, arg, sizeof(in)))
20382038
return -EFAULT;
20392039

2040-
return xfs_errortag_add(in.errtag, mp);
2040+
return xfs_errortag_add(mp, in.errtag);
20412041
}
20422042

20432043
case XFS_IOC_ERROR_CLEARALL:
20442044
if (!capable(CAP_SYS_ADMIN))
20452045
return -EPERM;
20462046

2047-
return xfs_errortag_clearall(mp, 1);
2047+
return xfs_errortag_clearall(mp);
20482048

20492049
case XFS_IOC_FREE_EOFBLOCKS: {
20502050
struct xfs_fs_eofblocks eofb;

fs/xfs/xfs_mount.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -720,10 +720,13 @@ xfs_mountfs(
720720
if (error)
721721
goto out_del_stats;
722722

723+
error = xfs_errortag_init(mp);
724+
if (error)
725+
goto out_remove_error_sysfs;
723726

724727
error = xfs_uuid_mount(mp);
725728
if (error)
726-
goto out_remove_error_sysfs;
729+
goto out_remove_errortag;
727730

728731
/*
729732
* Set the minimum read and write sizes
@@ -1042,6 +1045,8 @@ xfs_mountfs(
10421045
xfs_da_unmount(mp);
10431046
out_remove_uuid:
10441047
xfs_uuid_unmount(mp);
1048+
out_remove_errortag:
1049+
xfs_errortag_del(mp);
10451050
out_remove_error_sysfs:
10461051
xfs_error_sysfs_del(mp);
10471052
out_del_stats:
@@ -1145,10 +1150,11 @@ xfs_unmountfs(
11451150
xfs_uuid_unmount(mp);
11461151

11471152
#if defined(DEBUG)
1148-
xfs_errortag_clearall(mp, 0);
1153+
xfs_errortag_clearall(mp);
11491154
#endif
11501155
xfs_free_perag(mp);
11511156

1157+
xfs_errortag_del(mp);
11521158
xfs_error_sysfs_del(mp);
11531159
xfs_sysfs_del(&mp->m_stats.xs_kobj);
11541160
xfs_sysfs_del(&mp->m_kobj);

fs/xfs/xfs_mount.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,13 @@ typedef struct xfs_mount {
198198

199199
bool m_fail_unmount;
200200
#ifdef DEBUG
201+
/*
202+
* Frequency with which errors are injected. Replaces xfs_etest; the
203+
* value stored in here is the inverse of the frequency with which the
204+
* error triggers. 1 = always, 2 = half the time, etc.
205+
*/
206+
unsigned int *m_errortag;
207+
201208
/*
202209
* DEBUG mode instrumentation to test and/or trigger delayed allocation
203210
* block killing in the event of failed writes. When enabled, all

0 commit comments

Comments
 (0)