0001
0002
0003
0004
0005
0006 #include "xfs.h"
0007 #include "xfs_fs.h"
0008 #include "xfs_shared.h"
0009 #include "xfs_format.h"
0010 #include "xfs_btree.h"
0011 #include "xfs_trans_resv.h"
0012 #include "xfs_mount.h"
0013 #include "xfs_ag.h"
0014 #include "xfs_health.h"
0015 #include "scrub/scrub.h"
0016 #include "scrub/health.h"
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 enum xchk_health_group {
0072 XHG_FS = 1,
0073 XHG_RT,
0074 XHG_AG,
0075 XHG_INO,
0076 };
0077
0078 struct xchk_health_map {
0079 enum xchk_health_group group;
0080 unsigned int sick_mask;
0081 };
0082
0083 static const struct xchk_health_map type_to_health_flag[XFS_SCRUB_TYPE_NR] = {
0084 [XFS_SCRUB_TYPE_SB] = { XHG_AG, XFS_SICK_AG_SB },
0085 [XFS_SCRUB_TYPE_AGF] = { XHG_AG, XFS_SICK_AG_AGF },
0086 [XFS_SCRUB_TYPE_AGFL] = { XHG_AG, XFS_SICK_AG_AGFL },
0087 [XFS_SCRUB_TYPE_AGI] = { XHG_AG, XFS_SICK_AG_AGI },
0088 [XFS_SCRUB_TYPE_BNOBT] = { XHG_AG, XFS_SICK_AG_BNOBT },
0089 [XFS_SCRUB_TYPE_CNTBT] = { XHG_AG, XFS_SICK_AG_CNTBT },
0090 [XFS_SCRUB_TYPE_INOBT] = { XHG_AG, XFS_SICK_AG_INOBT },
0091 [XFS_SCRUB_TYPE_FINOBT] = { XHG_AG, XFS_SICK_AG_FINOBT },
0092 [XFS_SCRUB_TYPE_RMAPBT] = { XHG_AG, XFS_SICK_AG_RMAPBT },
0093 [XFS_SCRUB_TYPE_REFCNTBT] = { XHG_AG, XFS_SICK_AG_REFCNTBT },
0094 [XFS_SCRUB_TYPE_INODE] = { XHG_INO, XFS_SICK_INO_CORE },
0095 [XFS_SCRUB_TYPE_BMBTD] = { XHG_INO, XFS_SICK_INO_BMBTD },
0096 [XFS_SCRUB_TYPE_BMBTA] = { XHG_INO, XFS_SICK_INO_BMBTA },
0097 [XFS_SCRUB_TYPE_BMBTC] = { XHG_INO, XFS_SICK_INO_BMBTC },
0098 [XFS_SCRUB_TYPE_DIR] = { XHG_INO, XFS_SICK_INO_DIR },
0099 [XFS_SCRUB_TYPE_XATTR] = { XHG_INO, XFS_SICK_INO_XATTR },
0100 [XFS_SCRUB_TYPE_SYMLINK] = { XHG_INO, XFS_SICK_INO_SYMLINK },
0101 [XFS_SCRUB_TYPE_PARENT] = { XHG_INO, XFS_SICK_INO_PARENT },
0102 [XFS_SCRUB_TYPE_RTBITMAP] = { XHG_RT, XFS_SICK_RT_BITMAP },
0103 [XFS_SCRUB_TYPE_RTSUM] = { XHG_RT, XFS_SICK_RT_SUMMARY },
0104 [XFS_SCRUB_TYPE_UQUOTA] = { XHG_FS, XFS_SICK_FS_UQUOTA },
0105 [XFS_SCRUB_TYPE_GQUOTA] = { XHG_FS, XFS_SICK_FS_GQUOTA },
0106 [XFS_SCRUB_TYPE_PQUOTA] = { XHG_FS, XFS_SICK_FS_PQUOTA },
0107 [XFS_SCRUB_TYPE_FSCOUNTERS] = { XHG_FS, XFS_SICK_FS_COUNTERS },
0108 };
0109
0110
0111 unsigned int
0112 xchk_health_mask_for_scrub_type(
0113 __u32 scrub_type)
0114 {
0115 return type_to_health_flag[scrub_type].sick_mask;
0116 }
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128 void
0129 xchk_update_health(
0130 struct xfs_scrub *sc)
0131 {
0132 struct xfs_perag *pag;
0133 bool bad;
0134
0135 if (!sc->sick_mask)
0136 return;
0137
0138 bad = (sc->sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT |
0139 XFS_SCRUB_OFLAG_XCORRUPT));
0140 switch (type_to_health_flag[sc->sm->sm_type].group) {
0141 case XHG_AG:
0142 pag = xfs_perag_get(sc->mp, sc->sm->sm_agno);
0143 if (bad)
0144 xfs_ag_mark_sick(pag, sc->sick_mask);
0145 else
0146 xfs_ag_mark_healthy(pag, sc->sick_mask);
0147 xfs_perag_put(pag);
0148 break;
0149 case XHG_INO:
0150 if (!sc->ip)
0151 return;
0152 if (bad)
0153 xfs_inode_mark_sick(sc->ip, sc->sick_mask);
0154 else
0155 xfs_inode_mark_healthy(sc->ip, sc->sick_mask);
0156 break;
0157 case XHG_FS:
0158 if (bad)
0159 xfs_fs_mark_sick(sc->mp, sc->sick_mask);
0160 else
0161 xfs_fs_mark_healthy(sc->mp, sc->sick_mask);
0162 break;
0163 case XHG_RT:
0164 if (bad)
0165 xfs_rt_mark_sick(sc->mp, sc->sick_mask);
0166 else
0167 xfs_rt_mark_healthy(sc->mp, sc->sick_mask);
0168 break;
0169 default:
0170 ASSERT(0);
0171 break;
0172 }
0173 }
0174
0175
0176 bool
0177 xchk_ag_btree_healthy_enough(
0178 struct xfs_scrub *sc,
0179 struct xfs_perag *pag,
0180 xfs_btnum_t btnum)
0181 {
0182 unsigned int mask = 0;
0183
0184
0185
0186
0187
0188
0189
0190
0191 switch (btnum) {
0192 case XFS_BTNUM_BNO:
0193 if (sc->sm->sm_type == XFS_SCRUB_TYPE_BNOBT)
0194 return true;
0195 mask = XFS_SICK_AG_BNOBT;
0196 break;
0197 case XFS_BTNUM_CNT:
0198 if (sc->sm->sm_type == XFS_SCRUB_TYPE_CNTBT)
0199 return true;
0200 mask = XFS_SICK_AG_CNTBT;
0201 break;
0202 case XFS_BTNUM_INO:
0203 if (sc->sm->sm_type == XFS_SCRUB_TYPE_INOBT)
0204 return true;
0205 mask = XFS_SICK_AG_INOBT;
0206 break;
0207 case XFS_BTNUM_FINO:
0208 if (sc->sm->sm_type == XFS_SCRUB_TYPE_FINOBT)
0209 return true;
0210 mask = XFS_SICK_AG_FINOBT;
0211 break;
0212 case XFS_BTNUM_RMAP:
0213 if (sc->sm->sm_type == XFS_SCRUB_TYPE_RMAPBT)
0214 return true;
0215 mask = XFS_SICK_AG_RMAPBT;
0216 break;
0217 case XFS_BTNUM_REFC:
0218 if (sc->sm->sm_type == XFS_SCRUB_TYPE_REFCNTBT)
0219 return true;
0220 mask = XFS_SICK_AG_REFCNTBT;
0221 break;
0222 default:
0223 ASSERT(0);
0224 return true;
0225 }
0226
0227 if (xfs_ag_has_sickness(pag, mask)) {
0228 sc->sm->sm_flags |= XFS_SCRUB_OFLAG_XFAIL;
0229 return false;
0230 }
0231
0232 return true;
0233 }