diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2019-04-12 10:40:25 -0400 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2019-04-14 21:15:57 -0400 |
commit | 6772c1f11206f270af56d62bc26737864a63608a (patch) | |
tree | d75689f19c91e54fb2de867cbaaa89beccc46f63 /fs/xfs | |
parent | 2bf9d264efededefa8a339e31995a90df13e5fbe (diff) |
xfs: track metadata health status
Add the necessary in-core metadata fields to keep track of which parts
of the filesystem have been observed and which parts were observed to be
unhealthy, and print a warning at unmount time if we have unfixed
problems.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/Makefile | 1 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_health.h | 183 | ||||
-rw-r--r-- | fs/xfs/xfs_health.c | 192 | ||||
-rw-r--r-- | fs/xfs/xfs_icache.c | 4 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.h | 8 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.c | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.h | 23 | ||||
-rw-r--r-- | fs/xfs/xfs_trace.h | 73 |
8 files changed, 485 insertions, 0 deletions
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 7f96bdadc372..786379c143f4 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile | |||
@@ -73,6 +73,7 @@ xfs-y += xfs_aops.o \ | |||
73 | xfs_fsmap.o \ | 73 | xfs_fsmap.o \ |
74 | xfs_fsops.o \ | 74 | xfs_fsops.o \ |
75 | xfs_globals.o \ | 75 | xfs_globals.o \ |
76 | xfs_health.o \ | ||
76 | xfs_icache.o \ | 77 | xfs_icache.o \ |
77 | xfs_ioctl.o \ | 78 | xfs_ioctl.o \ |
78 | xfs_iomap.o \ | 79 | xfs_iomap.o \ |
diff --git a/fs/xfs/libxfs/xfs_health.h b/fs/xfs/libxfs/xfs_health.h new file mode 100644 index 000000000000..95053564a0d5 --- /dev/null +++ b/fs/xfs/libxfs/xfs_health.h | |||
@@ -0,0 +1,183 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * Copyright (C) 2019 Oracle. All Rights Reserved. | ||
4 | * Author: Darrick J. Wong <darrick.wong@oracle.com> | ||
5 | */ | ||
6 | #ifndef __XFS_HEALTH_H__ | ||
7 | #define __XFS_HEALTH_H__ | ||
8 | |||
9 | /* | ||
10 | * In-Core Filesystem Health Assessments | ||
11 | * ===================================== | ||
12 | * | ||
13 | * We'd like to be able to summarize the current health status of the | ||
14 | * filesystem so that the administrator knows when it's necessary to schedule | ||
15 | * some downtime for repairs. Until then, we would also like to avoid abrupt | ||
16 | * shutdowns due to corrupt metadata. | ||
17 | * | ||
18 | * The online scrub feature evaluates the health of all filesystem metadata. | ||
19 | * When scrub detects corruption in a piece of metadata it will set the | ||
20 | * corresponding sickness flag, and repair will clear it if successful. If | ||
21 | * problems remain at unmount time, we can also request manual intervention by | ||
22 | * logging a notice to run xfs_repair. | ||
23 | * | ||
24 | * Each health tracking group uses a pair of fields for reporting. The | ||
25 | * "checked" field tell us if a given piece of metadata has ever been examined, | ||
26 | * and the "sick" field tells us if that piece was found to need repairs. | ||
27 | * Therefore we can conclude that for a given sick flag value: | ||
28 | * | ||
29 | * - checked && sick => metadata needs repair | ||
30 | * - checked && !sick => metadata is ok | ||
31 | * - !checked => has not been examined since mount | ||
32 | */ | ||
33 | |||
34 | struct xfs_mount; | ||
35 | struct xfs_perag; | ||
36 | struct xfs_inode; | ||
37 | |||
38 | /* Observable health issues for metadata spanning the entire filesystem. */ | ||
39 | #define XFS_SICK_FS_COUNTERS (1 << 0) /* summary counters */ | ||
40 | #define XFS_SICK_FS_UQUOTA (1 << 1) /* user quota */ | ||
41 | #define XFS_SICK_FS_GQUOTA (1 << 2) /* group quota */ | ||
42 | #define XFS_SICK_FS_PQUOTA (1 << 3) /* project quota */ | ||
43 | |||
44 | /* Observable health issues for realtime volume metadata. */ | ||
45 | #define XFS_SICK_RT_BITMAP (1 << 0) /* realtime bitmap */ | ||
46 | #define XFS_SICK_RT_SUMMARY (1 << 1) /* realtime summary */ | ||
47 | |||
48 | /* Observable health issues for AG metadata. */ | ||
49 | #define XFS_SICK_AG_SB (1 << 0) /* superblock */ | ||
50 | #define XFS_SICK_AG_AGF (1 << 1) /* AGF header */ | ||
51 | #define XFS_SICK_AG_AGFL (1 << 2) /* AGFL header */ | ||
52 | #define XFS_SICK_AG_AGI (1 << 3) /* AGI header */ | ||
53 | #define XFS_SICK_AG_BNOBT (1 << 4) /* free space by block */ | ||
54 | #define XFS_SICK_AG_CNTBT (1 << 5) /* free space by length */ | ||
55 | #define XFS_SICK_AG_INOBT (1 << 6) /* inode index */ | ||
56 | #define XFS_SICK_AG_FINOBT (1 << 7) /* free inode index */ | ||
57 | #define XFS_SICK_AG_RMAPBT (1 << 8) /* reverse mappings */ | ||
58 | #define XFS_SICK_AG_REFCNTBT (1 << 9) /* reference counts */ | ||
59 | |||
60 | /* Observable health issues for inode metadata. */ | ||
61 | #define XFS_SICK_INO_CORE (1 << 0) /* inode core */ | ||
62 | #define XFS_SICK_INO_BMBTD (1 << 1) /* data fork */ | ||
63 | #define XFS_SICK_INO_BMBTA (1 << 2) /* attr fork */ | ||
64 | #define XFS_SICK_INO_BMBTC (1 << 3) /* cow fork */ | ||
65 | #define XFS_SICK_INO_DIR (1 << 4) /* directory */ | ||
66 | #define XFS_SICK_INO_XATTR (1 << 5) /* extended attributes */ | ||
67 | #define XFS_SICK_INO_SYMLINK (1 << 6) /* symbolic link remote target */ | ||
68 | #define XFS_SICK_INO_PARENT (1 << 7) /* parent pointers */ | ||
69 | |||
70 | /* Primary evidence of health problems in a given group. */ | ||
71 | #define XFS_SICK_FS_PRIMARY (XFS_SICK_FS_COUNTERS | \ | ||
72 | XFS_SICK_FS_UQUOTA | \ | ||
73 | XFS_SICK_FS_GQUOTA | \ | ||
74 | XFS_SICK_FS_PQUOTA) | ||
75 | |||
76 | #define XFS_SICK_RT_PRIMARY (XFS_SICK_RT_BITMAP | \ | ||
77 | XFS_SICK_RT_SUMMARY) | ||
78 | |||
79 | #define XFS_SICK_AG_PRIMARY (XFS_SICK_AG_SB | \ | ||
80 | XFS_SICK_AG_AGF | \ | ||
81 | XFS_SICK_AG_AGFL | \ | ||
82 | XFS_SICK_AG_AGI | \ | ||
83 | XFS_SICK_AG_BNOBT | \ | ||
84 | XFS_SICK_AG_CNTBT | \ | ||
85 | XFS_SICK_AG_INOBT | \ | ||
86 | XFS_SICK_AG_FINOBT | \ | ||
87 | XFS_SICK_AG_RMAPBT | \ | ||
88 | XFS_SICK_AG_REFCNTBT) | ||
89 | |||
90 | #define XFS_SICK_INO_PRIMARY (XFS_SICK_INO_CORE | \ | ||
91 | XFS_SICK_INO_BMBTD | \ | ||
92 | XFS_SICK_INO_BMBTA | \ | ||
93 | XFS_SICK_INO_BMBTC | \ | ||
94 | XFS_SICK_INO_DIR | \ | ||
95 | XFS_SICK_INO_XATTR | \ | ||
96 | XFS_SICK_INO_SYMLINK | \ | ||
97 | XFS_SICK_INO_PARENT) | ||
98 | |||
99 | /* These functions must be provided by the xfs implementation. */ | ||
100 | |||
101 | void xfs_fs_mark_sick(struct xfs_mount *mp, unsigned int mask); | ||
102 | void xfs_fs_mark_healthy(struct xfs_mount *mp, unsigned int mask); | ||
103 | void xfs_fs_measure_sickness(struct xfs_mount *mp, unsigned int *sick, | ||
104 | unsigned int *checked); | ||
105 | |||
106 | void xfs_rt_mark_sick(struct xfs_mount *mp, unsigned int mask); | ||
107 | void xfs_rt_mark_healthy(struct xfs_mount *mp, unsigned int mask); | ||
108 | void xfs_rt_measure_sickness(struct xfs_mount *mp, unsigned int *sick, | ||
109 | unsigned int *checked); | ||
110 | |||
111 | void xfs_ag_mark_sick(struct xfs_perag *pag, unsigned int mask); | ||
112 | void xfs_ag_mark_healthy(struct xfs_perag *pag, unsigned int mask); | ||
113 | void xfs_ag_measure_sickness(struct xfs_perag *pag, unsigned int *sick, | ||
114 | unsigned int *checked); | ||
115 | |||
116 | void xfs_inode_mark_sick(struct xfs_inode *ip, unsigned int mask); | ||
117 | void xfs_inode_mark_healthy(struct xfs_inode *ip, unsigned int mask); | ||
118 | void xfs_inode_measure_sickness(struct xfs_inode *ip, unsigned int *sick, | ||
119 | unsigned int *checked); | ||
120 | |||
121 | /* Now some helpers. */ | ||
122 | |||
123 | static inline bool | ||
124 | xfs_fs_has_sickness(struct xfs_mount *mp, unsigned int mask) | ||
125 | { | ||
126 | unsigned int sick, checked; | ||
127 | |||
128 | xfs_fs_measure_sickness(mp, &sick, &checked); | ||
129 | return sick & mask; | ||
130 | } | ||
131 | |||
132 | static inline bool | ||
133 | xfs_rt_has_sickness(struct xfs_mount *mp, unsigned int mask) | ||
134 | { | ||
135 | unsigned int sick, checked; | ||
136 | |||
137 | xfs_rt_measure_sickness(mp, &sick, &checked); | ||
138 | return sick & mask; | ||
139 | } | ||
140 | |||
141 | static inline bool | ||
142 | xfs_ag_has_sickness(struct xfs_perag *pag, unsigned int mask) | ||
143 | { | ||
144 | unsigned int sick, checked; | ||
145 | |||
146 | xfs_ag_measure_sickness(pag, &sick, &checked); | ||
147 | return sick & mask; | ||
148 | } | ||
149 | |||
150 | static inline bool | ||
151 | xfs_inode_has_sickness(struct xfs_inode *ip, unsigned int mask) | ||
152 | { | ||
153 | unsigned int sick, checked; | ||
154 | |||
155 | xfs_inode_measure_sickness(ip, &sick, &checked); | ||
156 | return sick & mask; | ||
157 | } | ||
158 | |||
159 | static inline bool | ||
160 | xfs_fs_is_healthy(struct xfs_mount *mp) | ||
161 | { | ||
162 | return !xfs_fs_has_sickness(mp, -1U); | ||
163 | } | ||
164 | |||
165 | static inline bool | ||
166 | xfs_rt_is_healthy(struct xfs_mount *mp) | ||
167 | { | ||
168 | return !xfs_rt_has_sickness(mp, -1U); | ||
169 | } | ||
170 | |||
171 | static inline bool | ||
172 | xfs_ag_is_healthy(struct xfs_perag *pag) | ||
173 | { | ||
174 | return !xfs_ag_has_sickness(pag, -1U); | ||
175 | } | ||
176 | |||
177 | static inline bool | ||
178 | xfs_inode_is_healthy(struct xfs_inode *ip) | ||
179 | { | ||
180 | return !xfs_inode_has_sickness(ip, -1U); | ||
181 | } | ||
182 | |||
183 | #endif /* __XFS_HEALTH_H__ */ | ||
diff --git a/fs/xfs/xfs_health.c b/fs/xfs/xfs_health.c new file mode 100644 index 000000000000..941f33037e2f --- /dev/null +++ b/fs/xfs/xfs_health.c | |||
@@ -0,0 +1,192 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * Copyright (C) 2019 Oracle. All Rights Reserved. | ||
4 | * Author: Darrick J. Wong <darrick.wong@oracle.com> | ||
5 | */ | ||
6 | #include "xfs.h" | ||
7 | #include "xfs_fs.h" | ||
8 | #include "xfs_shared.h" | ||
9 | #include "xfs_format.h" | ||
10 | #include "xfs_log_format.h" | ||
11 | #include "xfs_trans_resv.h" | ||
12 | #include "xfs_bit.h" | ||
13 | #include "xfs_sb.h" | ||
14 | #include "xfs_mount.h" | ||
15 | #include "xfs_defer.h" | ||
16 | #include "xfs_da_format.h" | ||
17 | #include "xfs_da_btree.h" | ||
18 | #include "xfs_inode.h" | ||
19 | #include "xfs_trace.h" | ||
20 | #include "xfs_health.h" | ||
21 | |||
22 | /* Mark unhealthy per-fs metadata. */ | ||
23 | void | ||
24 | xfs_fs_mark_sick( | ||
25 | struct xfs_mount *mp, | ||
26 | unsigned int mask) | ||
27 | { | ||
28 | ASSERT(!(mask & ~XFS_SICK_FS_PRIMARY)); | ||
29 | trace_xfs_fs_mark_sick(mp, mask); | ||
30 | |||
31 | spin_lock(&mp->m_sb_lock); | ||
32 | mp->m_fs_sick |= mask; | ||
33 | mp->m_fs_checked |= mask; | ||
34 | spin_unlock(&mp->m_sb_lock); | ||
35 | } | ||
36 | |||
37 | /* Mark a per-fs metadata healed. */ | ||
38 | void | ||
39 | xfs_fs_mark_healthy( | ||
40 | struct xfs_mount *mp, | ||
41 | unsigned int mask) | ||
42 | { | ||
43 | ASSERT(!(mask & ~XFS_SICK_FS_PRIMARY)); | ||
44 | trace_xfs_fs_mark_healthy(mp, mask); | ||
45 | |||
46 | spin_lock(&mp->m_sb_lock); | ||
47 | mp->m_fs_sick &= ~mask; | ||
48 | mp->m_fs_checked |= mask; | ||
49 | spin_unlock(&mp->m_sb_lock); | ||
50 | } | ||
51 | |||
52 | /* Sample which per-fs metadata are unhealthy. */ | ||
53 | void | ||
54 | xfs_fs_measure_sickness( | ||
55 | struct xfs_mount *mp, | ||
56 | unsigned int *sick, | ||
57 | unsigned int *checked) | ||
58 | { | ||
59 | spin_lock(&mp->m_sb_lock); | ||
60 | *sick = mp->m_fs_sick; | ||
61 | *checked = mp->m_fs_checked; | ||
62 | spin_unlock(&mp->m_sb_lock); | ||
63 | } | ||
64 | |||
65 | /* Mark unhealthy realtime metadata. */ | ||
66 | void | ||
67 | xfs_rt_mark_sick( | ||
68 | struct xfs_mount *mp, | ||
69 | unsigned int mask) | ||
70 | { | ||
71 | ASSERT(!(mask & ~XFS_SICK_RT_PRIMARY)); | ||
72 | trace_xfs_rt_mark_sick(mp, mask); | ||
73 | |||
74 | spin_lock(&mp->m_sb_lock); | ||
75 | mp->m_rt_sick |= mask; | ||
76 | mp->m_rt_checked |= mask; | ||
77 | spin_unlock(&mp->m_sb_lock); | ||
78 | } | ||
79 | |||
80 | /* Mark a realtime metadata healed. */ | ||
81 | void | ||
82 | xfs_rt_mark_healthy( | ||
83 | struct xfs_mount *mp, | ||
84 | unsigned int mask) | ||
85 | { | ||
86 | ASSERT(!(mask & ~XFS_SICK_RT_PRIMARY)); | ||
87 | trace_xfs_rt_mark_healthy(mp, mask); | ||
88 | |||
89 | spin_lock(&mp->m_sb_lock); | ||
90 | mp->m_rt_sick &= ~mask; | ||
91 | mp->m_rt_checked |= mask; | ||
92 | spin_unlock(&mp->m_sb_lock); | ||
93 | } | ||
94 | |||
95 | /* Sample which realtime metadata are unhealthy. */ | ||
96 | void | ||
97 | xfs_rt_measure_sickness( | ||
98 | struct xfs_mount *mp, | ||
99 | unsigned int *sick, | ||
100 | unsigned int *checked) | ||
101 | { | ||
102 | spin_lock(&mp->m_sb_lock); | ||
103 | *sick = mp->m_rt_sick; | ||
104 | *checked = mp->m_rt_checked; | ||
105 | spin_unlock(&mp->m_sb_lock); | ||
106 | } | ||
107 | |||
108 | /* Mark unhealthy per-ag metadata. */ | ||
109 | void | ||
110 | xfs_ag_mark_sick( | ||
111 | struct xfs_perag *pag, | ||
112 | unsigned int mask) | ||
113 | { | ||
114 | ASSERT(!(mask & ~XFS_SICK_AG_PRIMARY)); | ||
115 | trace_xfs_ag_mark_sick(pag->pag_mount, pag->pag_agno, mask); | ||
116 | |||
117 | spin_lock(&pag->pag_state_lock); | ||
118 | pag->pag_sick |= mask; | ||
119 | pag->pag_checked |= mask; | ||
120 | spin_unlock(&pag->pag_state_lock); | ||
121 | } | ||
122 | |||
123 | /* Mark per-ag metadata ok. */ | ||
124 | void | ||
125 | xfs_ag_mark_healthy( | ||
126 | struct xfs_perag *pag, | ||
127 | unsigned int mask) | ||
128 | { | ||
129 | ASSERT(!(mask & ~XFS_SICK_AG_PRIMARY)); | ||
130 | trace_xfs_ag_mark_healthy(pag->pag_mount, pag->pag_agno, mask); | ||
131 | |||
132 | spin_lock(&pag->pag_state_lock); | ||
133 | pag->pag_sick &= ~mask; | ||
134 | pag->pag_checked |= mask; | ||
135 | spin_unlock(&pag->pag_state_lock); | ||
136 | } | ||
137 | |||
138 | /* Sample which per-ag metadata are unhealthy. */ | ||
139 | void | ||
140 | xfs_ag_measure_sickness( | ||
141 | struct xfs_perag *pag, | ||
142 | unsigned int *sick, | ||
143 | unsigned int *checked) | ||
144 | { | ||
145 | spin_lock(&pag->pag_state_lock); | ||
146 | *sick = pag->pag_sick; | ||
147 | *checked = pag->pag_checked; | ||
148 | spin_unlock(&pag->pag_state_lock); | ||
149 | } | ||
150 | |||
151 | /* Mark the unhealthy parts of an inode. */ | ||
152 | void | ||
153 | xfs_inode_mark_sick( | ||
154 | struct xfs_inode *ip, | ||
155 | unsigned int mask) | ||
156 | { | ||
157 | ASSERT(!(mask & ~XFS_SICK_INO_PRIMARY)); | ||
158 | trace_xfs_inode_mark_sick(ip, mask); | ||
159 | |||
160 | spin_lock(&ip->i_flags_lock); | ||
161 | ip->i_sick |= mask; | ||
162 | ip->i_checked |= mask; | ||
163 | spin_unlock(&ip->i_flags_lock); | ||
164 | } | ||
165 | |||
166 | /* Mark parts of an inode healed. */ | ||
167 | void | ||
168 | xfs_inode_mark_healthy( | ||
169 | struct xfs_inode *ip, | ||
170 | unsigned int mask) | ||
171 | { | ||
172 | ASSERT(!(mask & ~XFS_SICK_INO_PRIMARY)); | ||
173 | trace_xfs_inode_mark_healthy(ip, mask); | ||
174 | |||
175 | spin_lock(&ip->i_flags_lock); | ||
176 | ip->i_sick &= ~mask; | ||
177 | ip->i_checked |= mask; | ||
178 | spin_unlock(&ip->i_flags_lock); | ||
179 | } | ||
180 | |||
181 | /* Sample which parts of an inode are unhealthy. */ | ||
182 | void | ||
183 | xfs_inode_measure_sickness( | ||
184 | struct xfs_inode *ip, | ||
185 | unsigned int *sick, | ||
186 | unsigned int *checked) | ||
187 | { | ||
188 | spin_lock(&ip->i_flags_lock); | ||
189 | *sick = ip->i_sick; | ||
190 | *checked = ip->i_checked; | ||
191 | spin_unlock(&ip->i_flags_lock); | ||
192 | } | ||
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 245483cc282b..f93924d26630 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c | |||
@@ -70,6 +70,8 @@ xfs_inode_alloc( | |||
70 | ip->i_flags = 0; | 70 | ip->i_flags = 0; |
71 | ip->i_delayed_blks = 0; | 71 | ip->i_delayed_blks = 0; |
72 | memset(&ip->i_d, 0, sizeof(ip->i_d)); | 72 | memset(&ip->i_d, 0, sizeof(ip->i_d)); |
73 | ip->i_sick = 0; | ||
74 | ip->i_checked = 0; | ||
73 | 75 | ||
74 | return ip; | 76 | return ip; |
75 | } | 77 | } |
@@ -446,6 +448,8 @@ xfs_iget_cache_hit( | |||
446 | ip->i_flags |= XFS_INEW; | 448 | ip->i_flags |= XFS_INEW; |
447 | xfs_inode_clear_reclaim_tag(pag, ip->i_ino); | 449 | xfs_inode_clear_reclaim_tag(pag, ip->i_ino); |
448 | inode->i_state = I_NEW; | 450 | inode->i_state = I_NEW; |
451 | ip->i_sick = 0; | ||
452 | ip->i_checked = 0; | ||
449 | 453 | ||
450 | ASSERT(!rwsem_is_locked(&inode->i_rwsem)); | 454 | ASSERT(!rwsem_is_locked(&inode->i_rwsem)); |
451 | init_rwsem(&inode->i_rwsem); | 455 | init_rwsem(&inode->i_rwsem); |
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index e62074a5257c..7bb1961918de 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
@@ -45,6 +45,14 @@ typedef struct xfs_inode { | |||
45 | mrlock_t i_lock; /* inode lock */ | 45 | mrlock_t i_lock; /* inode lock */ |
46 | mrlock_t i_mmaplock; /* inode mmap IO lock */ | 46 | mrlock_t i_mmaplock; /* inode mmap IO lock */ |
47 | atomic_t i_pincount; /* inode pin count */ | 47 | atomic_t i_pincount; /* inode pin count */ |
48 | |||
49 | /* | ||
50 | * Bitsets of inode metadata that have been checked and/or are sick. | ||
51 | * Callers must hold i_flags_lock before accessing this field. | ||
52 | */ | ||
53 | uint16_t i_checked; | ||
54 | uint16_t i_sick; | ||
55 | |||
48 | spinlock_t i_flags_lock; /* inode i_flags lock */ | 56 | spinlock_t i_flags_lock; /* inode i_flags lock */ |
49 | /* Miscellaneous state. */ | 57 | /* Miscellaneous state. */ |
50 | unsigned long i_flags; /* see defined flags below */ | 58 | unsigned long i_flags; /* see defined flags below */ |
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index fd63b0b1307c..6581381c12be 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -231,6 +231,7 @@ xfs_initialize_perag( | |||
231 | error = xfs_iunlink_init(pag); | 231 | error = xfs_iunlink_init(pag); |
232 | if (error) | 232 | if (error) |
233 | goto out_hash_destroy; | 233 | goto out_hash_destroy; |
234 | spin_lock_init(&pag->pag_state_lock); | ||
234 | } | 235 | } |
235 | 236 | ||
236 | index = xfs_set_inode_alloc(mp, agcount); | 237 | index = xfs_set_inode_alloc(mp, agcount); |
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 110f927cf943..cf7facc36a5f 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
@@ -60,6 +60,20 @@ struct xfs_error_cfg { | |||
60 | typedef struct xfs_mount { | 60 | typedef struct xfs_mount { |
61 | struct super_block *m_super; | 61 | struct super_block *m_super; |
62 | xfs_tid_t m_tid; /* next unused tid for fs */ | 62 | xfs_tid_t m_tid; /* next unused tid for fs */ |
63 | |||
64 | /* | ||
65 | * Bitsets of per-fs metadata that have been checked and/or are sick. | ||
66 | * Callers must hold m_sb_lock to access these two fields. | ||
67 | */ | ||
68 | uint8_t m_fs_checked; | ||
69 | uint8_t m_fs_sick; | ||
70 | /* | ||
71 | * Bitsets of rt metadata that have been checked and/or are sick. | ||
72 | * Callers must hold m_sb_lock to access this field. | ||
73 | */ | ||
74 | uint8_t m_rt_checked; | ||
75 | uint8_t m_rt_sick; | ||
76 | |||
63 | struct xfs_ail *m_ail; /* fs active log item list */ | 77 | struct xfs_ail *m_ail; /* fs active log item list */ |
64 | 78 | ||
65 | struct xfs_sb m_sb; /* copy of fs superblock */ | 79 | struct xfs_sb m_sb; /* copy of fs superblock */ |
@@ -369,6 +383,15 @@ typedef struct xfs_perag { | |||
369 | xfs_agino_t pagl_pagino; | 383 | xfs_agino_t pagl_pagino; |
370 | xfs_agino_t pagl_leftrec; | 384 | xfs_agino_t pagl_leftrec; |
371 | xfs_agino_t pagl_rightrec; | 385 | xfs_agino_t pagl_rightrec; |
386 | |||
387 | /* | ||
388 | * Bitsets of per-ag metadata that have been checked and/or are sick. | ||
389 | * Callers should hold pag_state_lock before accessing this field. | ||
390 | */ | ||
391 | uint16_t pag_checked; | ||
392 | uint16_t pag_sick; | ||
393 | spinlock_t pag_state_lock; | ||
394 | |||
372 | spinlock_t pagb_lock; /* lock for pagb_tree */ | 395 | spinlock_t pagb_lock; /* lock for pagb_tree */ |
373 | struct rb_root pagb_tree; /* ordered tree of busy extents */ | 396 | struct rb_root pagb_tree; /* ordered tree of busy extents */ |
374 | unsigned int pagb_gen; /* generation count for pagb_tree */ | 397 | unsigned int pagb_gen; /* generation count for pagb_tree */ |
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 47fb07d86efd..f079841c7af6 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h | |||
@@ -3440,6 +3440,79 @@ DEFINE_AGINODE_EVENT(xfs_iunlink); | |||
3440 | DEFINE_AGINODE_EVENT(xfs_iunlink_remove); | 3440 | DEFINE_AGINODE_EVENT(xfs_iunlink_remove); |
3441 | DEFINE_AG_EVENT(xfs_iunlink_map_prev_fallback); | 3441 | DEFINE_AG_EVENT(xfs_iunlink_map_prev_fallback); |
3442 | 3442 | ||
3443 | DECLARE_EVENT_CLASS(xfs_fs_corrupt_class, | ||
3444 | TP_PROTO(struct xfs_mount *mp, unsigned int flags), | ||
3445 | TP_ARGS(mp, flags), | ||
3446 | TP_STRUCT__entry( | ||
3447 | __field(dev_t, dev) | ||
3448 | __field(unsigned int, flags) | ||
3449 | ), | ||
3450 | TP_fast_assign( | ||
3451 | __entry->dev = mp->m_super->s_dev; | ||
3452 | __entry->flags = flags; | ||
3453 | ), | ||
3454 | TP_printk("dev %d:%d flags 0x%x", | ||
3455 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
3456 | __entry->flags) | ||
3457 | ); | ||
3458 | #define DEFINE_FS_CORRUPT_EVENT(name) \ | ||
3459 | DEFINE_EVENT(xfs_fs_corrupt_class, name, \ | ||
3460 | TP_PROTO(struct xfs_mount *mp, unsigned int flags), \ | ||
3461 | TP_ARGS(mp, flags)) | ||
3462 | DEFINE_FS_CORRUPT_EVENT(xfs_fs_mark_sick); | ||
3463 | DEFINE_FS_CORRUPT_EVENT(xfs_fs_mark_healthy); | ||
3464 | DEFINE_FS_CORRUPT_EVENT(xfs_rt_mark_sick); | ||
3465 | DEFINE_FS_CORRUPT_EVENT(xfs_rt_mark_healthy); | ||
3466 | |||
3467 | DECLARE_EVENT_CLASS(xfs_ag_corrupt_class, | ||
3468 | TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, unsigned int flags), | ||
3469 | TP_ARGS(mp, agno, flags), | ||
3470 | TP_STRUCT__entry( | ||
3471 | __field(dev_t, dev) | ||
3472 | __field(xfs_agnumber_t, agno) | ||
3473 | __field(unsigned int, flags) | ||
3474 | ), | ||
3475 | TP_fast_assign( | ||
3476 | __entry->dev = mp->m_super->s_dev; | ||
3477 | __entry->agno = agno; | ||
3478 | __entry->flags = flags; | ||
3479 | ), | ||
3480 | TP_printk("dev %d:%d agno %u flags 0x%x", | ||
3481 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
3482 | __entry->agno, __entry->flags) | ||
3483 | ); | ||
3484 | #define DEFINE_AG_CORRUPT_EVENT(name) \ | ||
3485 | DEFINE_EVENT(xfs_ag_corrupt_class, name, \ | ||
3486 | TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \ | ||
3487 | unsigned int flags), \ | ||
3488 | TP_ARGS(mp, agno, flags)) | ||
3489 | DEFINE_AG_CORRUPT_EVENT(xfs_ag_mark_sick); | ||
3490 | DEFINE_AG_CORRUPT_EVENT(xfs_ag_mark_healthy); | ||
3491 | |||
3492 | DECLARE_EVENT_CLASS(xfs_inode_corrupt_class, | ||
3493 | TP_PROTO(struct xfs_inode *ip, unsigned int flags), | ||
3494 | TP_ARGS(ip, flags), | ||
3495 | TP_STRUCT__entry( | ||
3496 | __field(dev_t, dev) | ||
3497 | __field(xfs_ino_t, ino) | ||
3498 | __field(unsigned int, flags) | ||
3499 | ), | ||
3500 | TP_fast_assign( | ||
3501 | __entry->dev = ip->i_mount->m_super->s_dev; | ||
3502 | __entry->ino = ip->i_ino; | ||
3503 | __entry->flags = flags; | ||
3504 | ), | ||
3505 | TP_printk("dev %d:%d ino 0x%llx flags 0x%x", | ||
3506 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
3507 | __entry->ino, __entry->flags) | ||
3508 | ); | ||
3509 | #define DEFINE_INODE_CORRUPT_EVENT(name) \ | ||
3510 | DEFINE_EVENT(xfs_inode_corrupt_class, name, \ | ||
3511 | TP_PROTO(struct xfs_inode *ip, unsigned int flags), \ | ||
3512 | TP_ARGS(ip, flags)) | ||
3513 | DEFINE_INODE_CORRUPT_EVENT(xfs_inode_mark_sick); | ||
3514 | DEFINE_INODE_CORRUPT_EVENT(xfs_inode_mark_healthy); | ||
3515 | |||
3443 | #endif /* _TRACE_XFS_H */ | 3516 | #endif /* _TRACE_XFS_H */ |
3444 | 3517 | ||
3445 | #undef TRACE_INCLUDE_PATH | 3518 | #undef TRACE_INCLUDE_PATH |