Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Copyright (C) 2019 Oracle.  All Rights Reserved.
0004  * Author: Darrick J. Wong <darrick.wong@oracle.com>
0005  */
0006 #include "xfs.h"
0007 #include "xfs_fs.h"
0008 #include "xfs_shared.h"
0009 #include "xfs_format.h"
0010 #include "xfs_log_format.h"
0011 #include "xfs_trans_resv.h"
0012 #include "xfs_mount.h"
0013 #include "xfs_inode.h"
0014 #include "xfs_trace.h"
0015 #include "xfs_health.h"
0016 #include "xfs_ag.h"
0017 
0018 /*
0019  * Warn about metadata corruption that we detected but haven't fixed, and
0020  * make sure we're not sitting on anything that would get in the way of
0021  * recovery.
0022  */
0023 void
0024 xfs_health_unmount(
0025     struct xfs_mount    *mp)
0026 {
0027     struct xfs_perag    *pag;
0028     xfs_agnumber_t      agno;
0029     unsigned int        sick = 0;
0030     unsigned int        checked = 0;
0031     bool            warn = false;
0032 
0033     if (xfs_is_shutdown(mp))
0034         return;
0035 
0036     /* Measure AG corruption levels. */
0037     for_each_perag(mp, agno, pag) {
0038         xfs_ag_measure_sickness(pag, &sick, &checked);
0039         if (sick) {
0040             trace_xfs_ag_unfixed_corruption(mp, agno, sick);
0041             warn = true;
0042         }
0043     }
0044 
0045     /* Measure realtime volume corruption levels. */
0046     xfs_rt_measure_sickness(mp, &sick, &checked);
0047     if (sick) {
0048         trace_xfs_rt_unfixed_corruption(mp, sick);
0049         warn = true;
0050     }
0051 
0052     /*
0053      * Measure fs corruption and keep the sample around for the warning.
0054      * See the note below for why we exempt FS_COUNTERS.
0055      */
0056     xfs_fs_measure_sickness(mp, &sick, &checked);
0057     if (sick & ~XFS_SICK_FS_COUNTERS) {
0058         trace_xfs_fs_unfixed_corruption(mp, sick);
0059         warn = true;
0060     }
0061 
0062     if (warn) {
0063         xfs_warn(mp,
0064 "Uncorrected metadata errors detected; please run xfs_repair.");
0065 
0066         /*
0067          * We discovered uncorrected metadata problems at some point
0068          * during this filesystem mount and have advised the
0069          * administrator to run repair once the unmount completes.
0070          *
0071          * However, we must be careful -- when FSCOUNTERS are flagged
0072          * unhealthy, the unmount procedure omits writing the clean
0073          * unmount record to the log so that the next mount will run
0074          * recovery and recompute the summary counters.  In other
0075          * words, we leave a dirty log to get the counters fixed.
0076          *
0077          * Unfortunately, xfs_repair cannot recover dirty logs, so if
0078          * there were filesystem problems, FSCOUNTERS was flagged, and
0079          * the administrator takes our advice to run xfs_repair,
0080          * they'll have to zap the log before repairing structures.
0081          * We don't really want to encourage this, so we mark the
0082          * FSCOUNTERS healthy so that a subsequent repair run won't see
0083          * a dirty log.
0084          */
0085         if (sick & XFS_SICK_FS_COUNTERS)
0086             xfs_fs_mark_healthy(mp, XFS_SICK_FS_COUNTERS);
0087     }
0088 }
0089 
0090 /* Mark unhealthy per-fs metadata. */
0091 void
0092 xfs_fs_mark_sick(
0093     struct xfs_mount    *mp,
0094     unsigned int        mask)
0095 {
0096     ASSERT(!(mask & ~XFS_SICK_FS_PRIMARY));
0097     trace_xfs_fs_mark_sick(mp, mask);
0098 
0099     spin_lock(&mp->m_sb_lock);
0100     mp->m_fs_sick |= mask;
0101     mp->m_fs_checked |= mask;
0102     spin_unlock(&mp->m_sb_lock);
0103 }
0104 
0105 /* Mark a per-fs metadata healed. */
0106 void
0107 xfs_fs_mark_healthy(
0108     struct xfs_mount    *mp,
0109     unsigned int        mask)
0110 {
0111     ASSERT(!(mask & ~XFS_SICK_FS_PRIMARY));
0112     trace_xfs_fs_mark_healthy(mp, mask);
0113 
0114     spin_lock(&mp->m_sb_lock);
0115     mp->m_fs_sick &= ~mask;
0116     mp->m_fs_checked |= mask;
0117     spin_unlock(&mp->m_sb_lock);
0118 }
0119 
0120 /* Sample which per-fs metadata are unhealthy. */
0121 void
0122 xfs_fs_measure_sickness(
0123     struct xfs_mount    *mp,
0124     unsigned int        *sick,
0125     unsigned int        *checked)
0126 {
0127     spin_lock(&mp->m_sb_lock);
0128     *sick = mp->m_fs_sick;
0129     *checked = mp->m_fs_checked;
0130     spin_unlock(&mp->m_sb_lock);
0131 }
0132 
0133 /* Mark unhealthy realtime metadata. */
0134 void
0135 xfs_rt_mark_sick(
0136     struct xfs_mount    *mp,
0137     unsigned int        mask)
0138 {
0139     ASSERT(!(mask & ~XFS_SICK_RT_PRIMARY));
0140     trace_xfs_rt_mark_sick(mp, mask);
0141 
0142     spin_lock(&mp->m_sb_lock);
0143     mp->m_rt_sick |= mask;
0144     mp->m_rt_checked |= mask;
0145     spin_unlock(&mp->m_sb_lock);
0146 }
0147 
0148 /* Mark a realtime metadata healed. */
0149 void
0150 xfs_rt_mark_healthy(
0151     struct xfs_mount    *mp,
0152     unsigned int        mask)
0153 {
0154     ASSERT(!(mask & ~XFS_SICK_RT_PRIMARY));
0155     trace_xfs_rt_mark_healthy(mp, mask);
0156 
0157     spin_lock(&mp->m_sb_lock);
0158     mp->m_rt_sick &= ~mask;
0159     mp->m_rt_checked |= mask;
0160     spin_unlock(&mp->m_sb_lock);
0161 }
0162 
0163 /* Sample which realtime metadata are unhealthy. */
0164 void
0165 xfs_rt_measure_sickness(
0166     struct xfs_mount    *mp,
0167     unsigned int        *sick,
0168     unsigned int        *checked)
0169 {
0170     spin_lock(&mp->m_sb_lock);
0171     *sick = mp->m_rt_sick;
0172     *checked = mp->m_rt_checked;
0173     spin_unlock(&mp->m_sb_lock);
0174 }
0175 
0176 /* Mark unhealthy per-ag metadata. */
0177 void
0178 xfs_ag_mark_sick(
0179     struct xfs_perag    *pag,
0180     unsigned int        mask)
0181 {
0182     ASSERT(!(mask & ~XFS_SICK_AG_PRIMARY));
0183     trace_xfs_ag_mark_sick(pag->pag_mount, pag->pag_agno, mask);
0184 
0185     spin_lock(&pag->pag_state_lock);
0186     pag->pag_sick |= mask;
0187     pag->pag_checked |= mask;
0188     spin_unlock(&pag->pag_state_lock);
0189 }
0190 
0191 /* Mark per-ag metadata ok. */
0192 void
0193 xfs_ag_mark_healthy(
0194     struct xfs_perag    *pag,
0195     unsigned int        mask)
0196 {
0197     ASSERT(!(mask & ~XFS_SICK_AG_PRIMARY));
0198     trace_xfs_ag_mark_healthy(pag->pag_mount, pag->pag_agno, mask);
0199 
0200     spin_lock(&pag->pag_state_lock);
0201     pag->pag_sick &= ~mask;
0202     pag->pag_checked |= mask;
0203     spin_unlock(&pag->pag_state_lock);
0204 }
0205 
0206 /* Sample which per-ag metadata are unhealthy. */
0207 void
0208 xfs_ag_measure_sickness(
0209     struct xfs_perag    *pag,
0210     unsigned int        *sick,
0211     unsigned int        *checked)
0212 {
0213     spin_lock(&pag->pag_state_lock);
0214     *sick = pag->pag_sick;
0215     *checked = pag->pag_checked;
0216     spin_unlock(&pag->pag_state_lock);
0217 }
0218 
0219 /* Mark the unhealthy parts of an inode. */
0220 void
0221 xfs_inode_mark_sick(
0222     struct xfs_inode    *ip,
0223     unsigned int        mask)
0224 {
0225     ASSERT(!(mask & ~XFS_SICK_INO_PRIMARY));
0226     trace_xfs_inode_mark_sick(ip, mask);
0227 
0228     spin_lock(&ip->i_flags_lock);
0229     ip->i_sick |= mask;
0230     ip->i_checked |= mask;
0231     spin_unlock(&ip->i_flags_lock);
0232 
0233     /*
0234      * Keep this inode around so we don't lose the sickness report.  Scrub
0235      * grabs inodes with DONTCACHE assuming that most inode are ok, which
0236      * is not the case here.
0237      */
0238     spin_lock(&VFS_I(ip)->i_lock);
0239     VFS_I(ip)->i_state &= ~I_DONTCACHE;
0240     spin_unlock(&VFS_I(ip)->i_lock);
0241 }
0242 
0243 /* Mark parts of an inode healed. */
0244 void
0245 xfs_inode_mark_healthy(
0246     struct xfs_inode    *ip,
0247     unsigned int        mask)
0248 {
0249     ASSERT(!(mask & ~XFS_SICK_INO_PRIMARY));
0250     trace_xfs_inode_mark_healthy(ip, mask);
0251 
0252     spin_lock(&ip->i_flags_lock);
0253     ip->i_sick &= ~mask;
0254     ip->i_checked |= mask;
0255     spin_unlock(&ip->i_flags_lock);
0256 }
0257 
0258 /* Sample which parts of an inode are unhealthy. */
0259 void
0260 xfs_inode_measure_sickness(
0261     struct xfs_inode    *ip,
0262     unsigned int        *sick,
0263     unsigned int        *checked)
0264 {
0265     spin_lock(&ip->i_flags_lock);
0266     *sick = ip->i_sick;
0267     *checked = ip->i_checked;
0268     spin_unlock(&ip->i_flags_lock);
0269 }
0270 
0271 /* Mappings between internal sick masks and ioctl sick masks. */
0272 
0273 struct ioctl_sick_map {
0274     unsigned int        sick_mask;
0275     unsigned int        ioctl_mask;
0276 };
0277 
0278 static const struct ioctl_sick_map fs_map[] = {
0279     { XFS_SICK_FS_COUNTERS, XFS_FSOP_GEOM_SICK_COUNTERS},
0280     { XFS_SICK_FS_UQUOTA,   XFS_FSOP_GEOM_SICK_UQUOTA },
0281     { XFS_SICK_FS_GQUOTA,   XFS_FSOP_GEOM_SICK_GQUOTA },
0282     { XFS_SICK_FS_PQUOTA,   XFS_FSOP_GEOM_SICK_PQUOTA },
0283     { 0, 0 },
0284 };
0285 
0286 static const struct ioctl_sick_map rt_map[] = {
0287     { XFS_SICK_RT_BITMAP,   XFS_FSOP_GEOM_SICK_RT_BITMAP },
0288     { XFS_SICK_RT_SUMMARY,  XFS_FSOP_GEOM_SICK_RT_SUMMARY },
0289     { 0, 0 },
0290 };
0291 
0292 static inline void
0293 xfgeo_health_tick(
0294     struct xfs_fsop_geom        *geo,
0295     unsigned int            sick,
0296     unsigned int            checked,
0297     const struct ioctl_sick_map *m)
0298 {
0299     if (checked & m->sick_mask)
0300         geo->checked |= m->ioctl_mask;
0301     if (sick & m->sick_mask)
0302         geo->sick |= m->ioctl_mask;
0303 }
0304 
0305 /* Fill out fs geometry health info. */
0306 void
0307 xfs_fsop_geom_health(
0308     struct xfs_mount        *mp,
0309     struct xfs_fsop_geom        *geo)
0310 {
0311     const struct ioctl_sick_map *m;
0312     unsigned int            sick;
0313     unsigned int            checked;
0314 
0315     geo->sick = 0;
0316     geo->checked = 0;
0317 
0318     xfs_fs_measure_sickness(mp, &sick, &checked);
0319     for (m = fs_map; m->sick_mask; m++)
0320         xfgeo_health_tick(geo, sick, checked, m);
0321 
0322     xfs_rt_measure_sickness(mp, &sick, &checked);
0323     for (m = rt_map; m->sick_mask; m++)
0324         xfgeo_health_tick(geo, sick, checked, m);
0325 }
0326 
0327 static const struct ioctl_sick_map ag_map[] = {
0328     { XFS_SICK_AG_SB,   XFS_AG_GEOM_SICK_SB },
0329     { XFS_SICK_AG_AGF,  XFS_AG_GEOM_SICK_AGF },
0330     { XFS_SICK_AG_AGFL, XFS_AG_GEOM_SICK_AGFL },
0331     { XFS_SICK_AG_AGI,  XFS_AG_GEOM_SICK_AGI },
0332     { XFS_SICK_AG_BNOBT,    XFS_AG_GEOM_SICK_BNOBT },
0333     { XFS_SICK_AG_CNTBT,    XFS_AG_GEOM_SICK_CNTBT },
0334     { XFS_SICK_AG_INOBT,    XFS_AG_GEOM_SICK_INOBT },
0335     { XFS_SICK_AG_FINOBT,   XFS_AG_GEOM_SICK_FINOBT },
0336     { XFS_SICK_AG_RMAPBT,   XFS_AG_GEOM_SICK_RMAPBT },
0337     { XFS_SICK_AG_REFCNTBT, XFS_AG_GEOM_SICK_REFCNTBT },
0338     { 0, 0 },
0339 };
0340 
0341 /* Fill out ag geometry health info. */
0342 void
0343 xfs_ag_geom_health(
0344     struct xfs_perag        *pag,
0345     struct xfs_ag_geometry      *ageo)
0346 {
0347     const struct ioctl_sick_map *m;
0348     unsigned int            sick;
0349     unsigned int            checked;
0350 
0351     ageo->ag_sick = 0;
0352     ageo->ag_checked = 0;
0353 
0354     xfs_ag_measure_sickness(pag, &sick, &checked);
0355     for (m = ag_map; m->sick_mask; m++) {
0356         if (checked & m->sick_mask)
0357             ageo->ag_checked |= m->ioctl_mask;
0358         if (sick & m->sick_mask)
0359             ageo->ag_sick |= m->ioctl_mask;
0360     }
0361 }
0362 
0363 static const struct ioctl_sick_map ino_map[] = {
0364     { XFS_SICK_INO_CORE,    XFS_BS_SICK_INODE },
0365     { XFS_SICK_INO_BMBTD,   XFS_BS_SICK_BMBTD },
0366     { XFS_SICK_INO_BMBTA,   XFS_BS_SICK_BMBTA },
0367     { XFS_SICK_INO_BMBTC,   XFS_BS_SICK_BMBTC },
0368     { XFS_SICK_INO_DIR, XFS_BS_SICK_DIR },
0369     { XFS_SICK_INO_XATTR,   XFS_BS_SICK_XATTR },
0370     { XFS_SICK_INO_SYMLINK, XFS_BS_SICK_SYMLINK },
0371     { XFS_SICK_INO_PARENT,  XFS_BS_SICK_PARENT },
0372     { 0, 0 },
0373 };
0374 
0375 /* Fill out bulkstat health info. */
0376 void
0377 xfs_bulkstat_health(
0378     struct xfs_inode        *ip,
0379     struct xfs_bulkstat     *bs)
0380 {
0381     const struct ioctl_sick_map *m;
0382     unsigned int            sick;
0383     unsigned int            checked;
0384 
0385     bs->bs_sick = 0;
0386     bs->bs_checked = 0;
0387 
0388     xfs_inode_measure_sickness(ip, &sick, &checked);
0389     for (m = ino_map; m->sick_mask; m++) {
0390         if (checked & m->sick_mask)
0391             bs->bs_checked |= m->ioctl_mask;
0392         if (sick & m->sick_mask)
0393             bs->bs_sick |= m->ioctl_mask;
0394     }
0395 }