LCOV - code coverage report
Current view: top level - fs/xfs - xfs_health.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc4-xfsx @ Mon Jul 31 20:08:34 PDT 2023 Lines: 251 297 84.5 %
Date: 2023-07-31 20:08:34 Functions: 27 32 84.4 %

          Line data    Source code
       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_mount.h"
      13             : #include "xfs_inode.h"
      14             : #include "xfs_trace.h"
      15             : #include "xfs_health.h"
      16             : #include "xfs_ag.h"
      17             : #include "xfs_btree.h"
      18             : #include "xfs_da_format.h"
      19             : #include "xfs_da_btree.h"
      20             : #include "xfs_quota_defs.h"
      21             : #include "xfs_rtgroup.h"
      22             : 
      23             : /*
      24             :  * Warn about metadata corruption that we detected but haven't fixed, and
      25             :  * make sure we're not sitting on anything that would get in the way of
      26             :  * recovery.
      27             :  */
      28             : void
      29       66825 : xfs_health_unmount(
      30             :         struct xfs_mount        *mp)
      31             : {
      32       66825 :         struct xfs_perag        *pag;
      33       66825 :         struct xfs_rtgroup      *rtg;
      34       66825 :         xfs_agnumber_t          agno;
      35       66825 :         xfs_rgnumber_t          rgno;
      36       66825 :         unsigned int            sick = 0;
      37       66825 :         unsigned int            checked = 0;
      38       66825 :         bool                    warn = false;
      39             : 
      40      133650 :         if (xfs_is_shutdown(mp))
      41       12884 :                 return;
      42             : 
      43             :         /* Measure AG corruption levels. */
      44      528649 :         for_each_perag(mp, agno, pag) {
      45      474708 :                 xfs_ag_measure_sickness(pag, &sick, &checked);
      46      474708 :                 if (sick) {
      47         129 :                         trace_xfs_ag_unfixed_corruption(mp, agno, sick);
      48         129 :                         warn = true;
      49             :                 }
      50             :         }
      51             : 
      52             :         /* Measure realtime group corruption levels. */
      53      150493 :         for_each_rtgroup(mp, rgno, rtg) {
      54       96552 :                 xfs_rtgroup_measure_sickness(rtg, &sick, &checked);
      55       96552 :                 if (sick) {
      56           0 :                         trace_xfs_rtgroup_unfixed_corruption(rtg, sick);
      57           0 :                         warn = true;
      58             :                 }
      59             :         }
      60             : 
      61             :         /* Measure realtime volume corruption levels. */
      62       53941 :         xfs_rt_measure_sickness(mp, &sick, &checked);
      63       53941 :         if (sick) {
      64           0 :                 trace_xfs_rt_unfixed_corruption(mp, sick);
      65           0 :                 warn = true;
      66             :         }
      67             : 
      68             :         /*
      69             :          * Measure fs corruption and keep the sample around for the warning.
      70             :          * See the note below for why we exempt FS_COUNTERS.
      71             :          */
      72       53941 :         xfs_fs_measure_sickness(mp, &sick, &checked);
      73       53941 :         if (sick & ~XFS_SICK_FS_COUNTERS) {
      74          26 :                 trace_xfs_fs_unfixed_corruption(mp, sick);
      75          26 :                 warn = true;
      76             :         }
      77             : 
      78       53941 :         if (warn) {
      79         136 :                 xfs_warn(mp,
      80             : "Uncorrected metadata errors detected; please run xfs_repair.");
      81             : 
      82             :                 /*
      83             :                  * We discovered uncorrected metadata problems at some point
      84             :                  * during this filesystem mount and have advised the
      85             :                  * administrator to run repair once the unmount completes.
      86             :                  *
      87             :                  * However, we must be careful -- when FSCOUNTERS are flagged
      88             :                  * unhealthy, the unmount procedure omits writing the clean
      89             :                  * unmount record to the log so that the next mount will run
      90             :                  * recovery and recompute the summary counters.  In other
      91             :                  * words, we leave a dirty log to get the counters fixed.
      92             :                  *
      93             :                  * Unfortunately, xfs_repair cannot recover dirty logs, so if
      94             :                  * there were filesystem problems, FSCOUNTERS was flagged, and
      95             :                  * the administrator takes our advice to run xfs_repair,
      96             :                  * they'll have to zap the log before repairing structures.
      97             :                  * We don't really want to encourage this, so we mark the
      98             :                  * FSCOUNTERS healthy so that a subsequent repair run won't see
      99             :                  * a dirty log.
     100             :                  */
     101         136 :                 if (sick & XFS_SICK_FS_COUNTERS)
     102           0 :                         xfs_fs_mark_healthy(mp, XFS_SICK_FS_COUNTERS);
     103             :         }
     104             : }
     105             : 
     106             : /* Mark unhealthy per-fs metadata. */
     107             : void
     108      813645 : xfs_fs_mark_sick(
     109             :         struct xfs_mount        *mp,
     110             :         unsigned int            mask)
     111             : {
     112      813645 :         ASSERT(!(mask & ~XFS_SICK_FS_ALL));
     113      813645 :         trace_xfs_fs_mark_sick(mp, mask);
     114             : 
     115      813363 :         spin_lock(&mp->m_sb_lock);
     116      814093 :         mp->m_fs_sick |= mask;
     117      814093 :         spin_unlock(&mp->m_sb_lock);
     118      814089 : }
     119             : 
     120             : /* Mark per-fs metadata as having been checked. */
     121             : void
     122      814045 : xfs_fs_mark_checked(
     123             :         struct xfs_mount        *mp,
     124             :         unsigned int            mask)
     125             : {
     126      814045 :         ASSERT(!(mask & ~XFS_SICK_FS_PRIMARY));
     127             : 
     128      814045 :         spin_lock(&mp->m_sb_lock);
     129      814051 :         mp->m_fs_checked |= mask;
     130      814051 :         spin_unlock(&mp->m_sb_lock);
     131      814044 : }
     132             : 
     133             : /* Mark a per-fs metadata healed. */
     134             : void
     135      482078 : xfs_fs_mark_healthy(
     136             :         struct xfs_mount        *mp,
     137             :         unsigned int            mask)
     138             : {
     139      482078 :         ASSERT(!(mask & ~XFS_SICK_FS_ALL));
     140      482078 :         trace_xfs_fs_mark_healthy(mp, mask);
     141             : 
     142      482069 :         spin_lock(&mp->m_sb_lock);
     143      482100 :         mp->m_fs_sick &= ~mask;
     144      482100 :         if (!(mp->m_fs_sick & XFS_SICK_FS_PRIMARY))
     145             :                 mp->m_fs_sick &= ~XFS_SICK_FS_SECONDARY;
     146      482100 :         mp->m_fs_checked |= mask;
     147      482100 :         spin_unlock(&mp->m_sb_lock);
     148      482100 : }
     149             : 
     150             : /* Sample which per-fs metadata are unhealthy. */
     151             : void
     152      135103 : xfs_fs_measure_sickness(
     153             :         struct xfs_mount        *mp,
     154             :         unsigned int            *sick,
     155             :         unsigned int            *checked)
     156             : {
     157      189044 :         spin_lock(&mp->m_sb_lock);
     158     7416347 :         *sick = mp->m_fs_sick;
     159     7416347 :         *checked = mp->m_fs_checked;
     160     7416347 :         spin_unlock(&mp->m_sb_lock);
     161      135103 : }
     162             : 
     163             : /* Mark unhealthy realtime metadata. */
     164             : void
     165           0 : xfs_rt_mark_sick(
     166             :         struct xfs_mount        *mp,
     167             :         unsigned int            mask)
     168             : {
     169           0 :         ASSERT(!(mask & ~XFS_SICK_RT_ALL));
     170           0 :         trace_xfs_rt_mark_sick(mp, mask);
     171             : 
     172           0 :         spin_lock(&mp->m_sb_lock);
     173           0 :         mp->m_rt_sick |= mask;
     174           0 :         spin_unlock(&mp->m_sb_lock);
     175           0 : }
     176             : 
     177             : /* Mark realtime metadata as having been checked. */
     178             : void
     179           0 : xfs_rt_mark_checked(
     180             :         struct xfs_mount        *mp,
     181             :         unsigned int            mask)
     182             : {
     183           0 :         ASSERT(!(mask & ~XFS_SICK_RT_PRIMARY));
     184           0 :         trace_xfs_rt_mark_sick(mp, mask);
     185             : 
     186           0 :         spin_lock(&mp->m_sb_lock);
     187           0 :         mp->m_rt_checked |= mask;
     188           0 :         spin_unlock(&mp->m_sb_lock);
     189           0 : }
     190             : 
     191             : /* Mark a realtime metadata healed. */
     192             : void
     193      197151 : xfs_rt_mark_healthy(
     194             :         struct xfs_mount        *mp,
     195             :         unsigned int            mask)
     196             : {
     197      197151 :         ASSERT(!(mask & ~XFS_SICK_RT_ALL));
     198      197151 :         trace_xfs_rt_mark_healthy(mp, mask);
     199             : 
     200      197151 :         spin_lock(&mp->m_sb_lock);
     201      197151 :         mp->m_rt_sick &= ~mask;
     202      197151 :         if (!(mp->m_rt_sick & XFS_SICK_RT_PRIMARY))
     203             :                 mp->m_rt_sick &= ~XFS_SICK_RT_SECONDARY;
     204      197151 :         mp->m_rt_checked |= mask;
     205      197151 :         spin_unlock(&mp->m_sb_lock);
     206      197151 : }
     207             : 
     208             : /* Sample which realtime metadata are unhealthy. */
     209             : void
     210       25682 : xfs_rt_measure_sickness(
     211             :         struct xfs_mount        *mp,
     212             :         unsigned int            *sick,
     213             :         unsigned int            *checked)
     214             : {
     215       79623 :         spin_lock(&mp->m_sb_lock);
     216     7306926 :         *sick = mp->m_rt_sick;
     217     7306926 :         *checked = mp->m_rt_checked;
     218     7306926 :         spin_unlock(&mp->m_sb_lock);
     219       25682 : }
     220             : 
     221             : /* Mark unhealthy per-ag metadata given a raw AG number. */
     222             : void
     223        2018 : xfs_agno_mark_sick(
     224             :         struct xfs_mount        *mp,
     225             :         xfs_agnumber_t          agno,
     226             :         unsigned int            mask)
     227             : {
     228        2018 :         struct xfs_perag        *pag = xfs_perag_get(mp, agno);
     229             : 
     230             :         /* per-ag structure not set up yet? */
     231        2018 :         if (!pag)
     232             :                 return;
     233             : 
     234        2018 :         xfs_ag_mark_sick(pag, mask);
     235        2018 :         xfs_perag_put(pag);
     236             : }
     237             : 
     238             : /* Mark unhealthy per-ag metadata. */
     239             : void
     240        5516 : xfs_ag_mark_sick(
     241             :         struct xfs_perag        *pag,
     242             :         unsigned int            mask)
     243             : {
     244        5516 :         ASSERT(!(mask & ~XFS_SICK_AG_ALL));
     245        5516 :         trace_xfs_ag_mark_sick(pag->pag_mount, pag->pag_agno, mask);
     246             : 
     247        5516 :         spin_lock(&pag->pag_state_lock);
     248        5516 :         pag->pag_sick |= mask;
     249        5516 :         spin_unlock(&pag->pag_state_lock);
     250        5516 : }
     251             : 
     252             : /* Mark per-ag metadata as having been checked. */
     253             : void
     254         100 : xfs_ag_mark_checked(
     255             :         struct xfs_perag        *pag,
     256             :         unsigned int            mask)
     257             : {
     258         100 :         ASSERT(!(mask & ~XFS_SICK_AG_PRIMARY));
     259             : 
     260         100 :         spin_lock(&pag->pag_state_lock);
     261         100 :         pag->pag_checked |= mask;
     262         100 :         spin_unlock(&pag->pag_state_lock);
     263         100 : }
     264             : 
     265             : /* Mark per-ag metadata ok. */
     266             : void
     267     6340352 : xfs_ag_mark_healthy(
     268             :         struct xfs_perag        *pag,
     269             :         unsigned int            mask)
     270             : {
     271     6340352 :         ASSERT(!(mask & ~XFS_SICK_AG_ALL));
     272     6340352 :         trace_xfs_ag_mark_healthy(pag->pag_mount, pag->pag_agno, mask);
     273             : 
     274     6338898 :         spin_lock(&pag->pag_state_lock);
     275     6340627 :         pag->pag_sick &= ~mask;
     276     6340627 :         if (!(pag->pag_sick & XFS_SICK_AG_PRIMARY))
     277             :                 pag->pag_sick &= ~XFS_SICK_AG_SECONDARY;
     278     6340627 :         pag->pag_checked |= mask;
     279     6340627 :         spin_unlock(&pag->pag_state_lock);
     280     6340541 : }
     281             : 
     282             : /* Sample which per-ag metadata are unhealthy. */
     283             : void
     284  4480215355 : xfs_ag_measure_sickness(
     285             :         struct xfs_perag        *pag,
     286             :         unsigned int            *sick,
     287             :         unsigned int            *checked)
     288             : {
     289  4480690063 :         spin_lock(&pag->pag_state_lock);
     290  4482402661 :         *sick = pag->pag_sick;
     291  4482402661 :         *checked = pag->pag_checked;
     292  4482402661 :         spin_unlock(&pag->pag_state_lock);
     293  4482773548 : }
     294             : 
     295             : /* Mark unhealthy per-rtgroup metadata given a raw rt group number. */
     296             : void
     297           0 : xfs_rgno_mark_sick(
     298             :         struct xfs_mount        *mp,
     299             :         xfs_rgnumber_t          rgno,
     300             :         unsigned int            mask)
     301             : {
     302           0 :         struct xfs_rtgroup      *rtg = xfs_rtgroup_get(mp, rgno);
     303             : 
     304             :         /* per-rtgroup structure not set up yet? */
     305           0 :         if (!rtg)
     306             :                 return;
     307             : 
     308           0 :         xfs_rtgroup_mark_sick(rtg, mask);
     309           0 :         xfs_rtgroup_put(rtg);
     310             : }
     311             : 
     312             : /* Mark unhealthy per-rtgroup metadata. */
     313             : void
     314           2 : xfs_rtgroup_mark_sick(
     315             :         struct xfs_rtgroup      *rtg,
     316             :         unsigned int            mask)
     317             : {
     318           2 :         ASSERT(!(mask & ~XFS_SICK_RT_ALL));
     319           2 :         trace_xfs_rtgroup_mark_sick(rtg, mask);
     320             : 
     321           2 :         spin_lock(&rtg->rtg_state_lock);
     322           2 :         rtg->rtg_sick |= mask;
     323           2 :         spin_unlock(&rtg->rtg_state_lock);
     324           2 : }
     325             : 
     326             : /* Mark per-rtgroup metadata as having been checked. */
     327             : void
     328           0 : xfs_rtgroup_mark_checked(
     329             :         struct xfs_rtgroup      *rtg,
     330             :         unsigned int            mask)
     331             : {
     332           0 :         ASSERT(!(mask & ~XFS_SICK_RT_PRIMARY));
     333             : 
     334           0 :         spin_lock(&rtg->rtg_state_lock);
     335           0 :         rtg->rtg_checked |= mask;
     336           0 :         spin_unlock(&rtg->rtg_state_lock);
     337           0 : }
     338             : 
     339             : /* Mark per-rtgroup metadata ok. */
     340             : void
     341      385903 : xfs_rtgroup_mark_healthy(
     342             :         struct xfs_rtgroup      *rtg,
     343             :         unsigned int            mask)
     344             : {
     345      385903 :         ASSERT(!(mask & ~XFS_SICK_RT_ALL));
     346      385903 :         trace_xfs_rtgroup_mark_healthy(rtg, mask);
     347             : 
     348      385841 :         spin_lock(&rtg->rtg_state_lock);
     349      385927 :         rtg->rtg_sick &= ~mask;
     350      385927 :         if (!(rtg->rtg_sick & XFS_SICK_RT_PRIMARY))
     351             :                 rtg->rtg_sick &= ~XFS_SICK_RT_SECONDARY;
     352      385927 :         rtg->rtg_checked |= mask;
     353      385927 :         spin_unlock(&rtg->rtg_state_lock);
     354      385939 : }
     355             : 
     356             : /* Sample which per-rtgroup metadata are unhealthy. */
     357             : void
     358       55008 : xfs_rtgroup_measure_sickness(
     359             :         struct xfs_rtgroup      *rtg,
     360             :         unsigned int            *sick,
     361             :         unsigned int            *checked)
     362             : {
     363      151560 :         spin_lock(&rtg->rtg_state_lock);
     364      171031 :         *sick = rtg->rtg_sick;
     365      171031 :         *checked = rtg->rtg_checked;
     366      171031 :         spin_unlock(&rtg->rtg_state_lock);
     367       55008 : }
     368             : 
     369             : /* Mark the unhealthy parts of an inode. */
     370             : void
     371        1438 : xfs_inode_mark_sick(
     372             :         struct xfs_inode        *ip,
     373             :         unsigned int            mask)
     374             : {
     375        1438 :         ASSERT(!(mask & ~XFS_SICK_INO_ALL));
     376        1438 :         trace_xfs_inode_mark_sick(ip, mask);
     377             : 
     378        1438 :         spin_lock(&ip->i_flags_lock);
     379        1438 :         ip->i_sick |= mask;
     380        1438 :         spin_unlock(&ip->i_flags_lock);
     381             : 
     382             :         /*
     383             :          * Keep this inode around so we don't lose the sickness report.  Scrub
     384             :          * grabs inodes with DONTCACHE assuming that most inode are ok, which
     385             :          * is not the case here.
     386             :          */
     387        1438 :         spin_lock(&VFS_I(ip)->i_lock);
     388        1438 :         VFS_I(ip)->i_state &= ~I_DONTCACHE;
     389        1438 :         spin_unlock(&VFS_I(ip)->i_lock);
     390        1438 : }
     391             : 
     392             : /* Mark inode metadata as having been checked. */
     393             : void
     394          33 : xfs_inode_mark_checked(
     395             :         struct xfs_inode        *ip,
     396             :         unsigned int            mask)
     397             : {
     398          33 :         ASSERT(!(mask & ~XFS_SICK_INO_PRIMARY));
     399             : 
     400          33 :         spin_lock(&ip->i_flags_lock);
     401          33 :         ip->i_checked |= mask;
     402          33 :         spin_unlock(&ip->i_flags_lock);
     403          33 : }
     404             : 
     405             : /* Mark parts of an inode healed. */
     406             : void
     407   721728644 : xfs_inode_mark_healthy(
     408             :         struct xfs_inode        *ip,
     409             :         unsigned int            mask)
     410             : {
     411   721728644 :         ASSERT(!(mask & ~XFS_SICK_INO_ALL));
     412   721728644 :         trace_xfs_inode_mark_healthy(ip, mask);
     413             : 
     414   721529706 :         spin_lock(&ip->i_flags_lock);
     415   723486143 :         ip->i_sick &= ~mask;
     416   723486143 :         if (!(ip->i_sick & XFS_SICK_INO_PRIMARY))
     417   723381732 :                 ip->i_sick &= ~XFS_SICK_INO_SECONDARY;
     418   723486143 :         ip->i_checked |= mask;
     419   723486143 :         spin_unlock(&ip->i_flags_lock);
     420   723463242 : }
     421             : 
     422             : /* Sample which parts of an inode are unhealthy. */
     423             : void
     424    76215549 : xfs_inode_measure_sickness(
     425             :         struct xfs_inode        *ip,
     426             :         unsigned int            *sick,
     427             :         unsigned int            *checked)
     428             : {
     429    76215549 :         spin_lock(&ip->i_flags_lock);
     430 82568607091 :         *sick = ip->i_sick;
     431 82568607091 :         *checked = ip->i_checked;
     432 82568607091 :         spin_unlock(&ip->i_flags_lock);
     433    76404548 : }
     434             : 
     435             : /* Mappings between internal sick masks and ioctl sick masks. */
     436             : 
     437             : struct ioctl_sick_map {
     438             :         unsigned int            sick_mask;
     439             :         unsigned int            ioctl_mask;
     440             : };
     441             : 
     442             : static const struct ioctl_sick_map fs_map[] = {
     443             :         { XFS_SICK_FS_COUNTERS, XFS_FSOP_GEOM_SICK_COUNTERS},
     444             :         { XFS_SICK_FS_UQUOTA,   XFS_FSOP_GEOM_SICK_UQUOTA },
     445             :         { XFS_SICK_FS_GQUOTA,   XFS_FSOP_GEOM_SICK_GQUOTA },
     446             :         { XFS_SICK_FS_PQUOTA,   XFS_FSOP_GEOM_SICK_PQUOTA },
     447             :         { XFS_SICK_FS_QUOTACHECK, XFS_FSOP_GEOM_SICK_QUOTACHECK },
     448             :         { XFS_SICK_FS_NLINKS,   XFS_FSOP_GEOM_SICK_NLINKS },
     449             :         { XFS_SICK_FS_METADIR,  XFS_FSOP_GEOM_SICK_METADIR },
     450             :         { 0, 0 },
     451             : };
     452             : 
     453             : static const struct ioctl_sick_map rt_map[] = {
     454             :         { XFS_SICK_RT_BITMAP,   XFS_FSOP_GEOM_SICK_RT_BITMAP },
     455             :         { XFS_SICK_RT_SUMMARY,  XFS_FSOP_GEOM_SICK_RT_SUMMARY },
     456             :         { 0, 0 },
     457             : };
     458             : 
     459             : static inline void
     460    64877824 : xfgeo_health_tick(
     461             :         struct xfs_fsop_geom            *geo,
     462             :         unsigned int                    sick,
     463             :         unsigned int                    checked,
     464             :         const struct ioctl_sick_map     *m)
     465             : {
     466    64877824 :         if (checked & m->sick_mask)
     467     4903936 :                 geo->checked |= m->ioctl_mask;
     468    64877824 :         if (sick & m->sick_mask)
     469      167634 :                 geo->sick |= m->ioctl_mask;
     470    64877824 : }
     471             : 
     472             : /* Fill out fs geometry health info. */
     473             : void
     474     7207371 : xfs_fsop_geom_health(
     475             :         struct xfs_mount                *mp,
     476             :         struct xfs_fsop_geom            *geo)
     477             : {
     478     7207371 :         const struct ioctl_sick_map     *m;
     479     7207371 :         unsigned int                    sick;
     480     7207371 :         unsigned int                    checked;
     481             : 
     482     7207371 :         geo->sick = 0;
     483     7207371 :         geo->checked = 0;
     484             : 
     485     7207371 :         xfs_fs_measure_sickness(mp, &sick, &checked);
     486    64905822 :         for (m = fs_map; m->sick_mask; m++)
     487    50459591 :                 xfgeo_health_tick(geo, sick, checked, m);
     488             : 
     489     7218928 :         xfs_rt_measure_sickness(mp, &sick, &checked);
     490    28891450 :         for (m = rt_map; m->sick_mask; m++)
     491    14446857 :                 xfgeo_health_tick(geo, sick, checked, m);
     492     7217290 : }
     493             : 
     494             : static const struct ioctl_sick_map ag_map[] = {
     495             :         { XFS_SICK_AG_SB,       XFS_AG_GEOM_SICK_SB },
     496             :         { XFS_SICK_AG_AGF,      XFS_AG_GEOM_SICK_AGF },
     497             :         { XFS_SICK_AG_AGFL,     XFS_AG_GEOM_SICK_AGFL },
     498             :         { XFS_SICK_AG_AGI,      XFS_AG_GEOM_SICK_AGI },
     499             :         { XFS_SICK_AG_BNOBT,    XFS_AG_GEOM_SICK_BNOBT },
     500             :         { XFS_SICK_AG_CNTBT,    XFS_AG_GEOM_SICK_CNTBT },
     501             :         { XFS_SICK_AG_INOBT,    XFS_AG_GEOM_SICK_INOBT },
     502             :         { XFS_SICK_AG_FINOBT,   XFS_AG_GEOM_SICK_FINOBT },
     503             :         { XFS_SICK_AG_RMAPBT,   XFS_AG_GEOM_SICK_RMAPBT },
     504             :         { XFS_SICK_AG_REFCNTBT, XFS_AG_GEOM_SICK_REFCNTBT },
     505             :         { XFS_SICK_AG_INODES,   XFS_AG_GEOM_SICK_INODES },
     506             :         { 0, 0 },
     507             : };
     508             : 
     509             : /* Fill out ag geometry health info. */
     510             : void
     511       89454 : xfs_ag_geom_health(
     512             :         struct xfs_perag                *pag,
     513             :         struct xfs_ag_geometry          *ageo)
     514             : {
     515       89454 :         const struct ioctl_sick_map     *m;
     516       89454 :         unsigned int                    sick;
     517       89454 :         unsigned int                    checked;
     518             : 
     519       89454 :         ageo->ag_sick = 0;
     520       89454 :         ageo->ag_checked = 0;
     521             : 
     522       89454 :         xfs_ag_measure_sickness(pag, &sick, &checked);
     523     1162902 :         for (m = ag_map; m->sick_mask; m++) {
     524      983994 :                 if (checked & m->sick_mask)
     525      974833 :                         ageo->ag_checked |= m->ioctl_mask;
     526      983994 :                 if (sick & m->sick_mask)
     527          12 :                         ageo->ag_sick |= m->ioctl_mask;
     528             :         }
     529       89454 : }
     530             : 
     531             : static const struct ioctl_sick_map rtgroup_map[] = {
     532             :         { XFS_SICK_RT_SUPER,    XFS_RTGROUP_GEOM_SICK_SUPER },
     533             :         { XFS_SICK_RT_BITMAP,   XFS_RTGROUP_GEOM_SICK_BITMAP },
     534             :         { XFS_SICK_RT_RMAPBT,   XFS_RTGROUP_GEOM_SICK_RMAPBT },
     535             :         { XFS_SICK_RT_REFCNTBT, XFS_RTGROUP_GEOM_SICK_REFCNTBT },
     536             :         { 0, 0 },
     537             : };
     538             : 
     539             : /* Fill out rtgroup geometry health info. */
     540             : void
     541       19471 : xfs_rtgroup_geom_health(
     542             :         struct xfs_rtgroup      *rtg,
     543             :         struct xfs_rtgroup_geometry *rgeo)
     544             : {
     545       19471 :         const struct ioctl_sick_map     *m;
     546       19471 :         unsigned int                    sick;
     547       19471 :         unsigned int                    checked;
     548             : 
     549       19471 :         rgeo->rg_sick = 0;
     550       19471 :         rgeo->rg_checked = 0;
     551             : 
     552       19471 :         xfs_rtgroup_measure_sickness(rtg, &sick, &checked);
     553      116826 :         for (m = rtgroup_map; m->sick_mask; m++) {
     554       77884 :                 if (checked & m->sick_mask)
     555       58183 :                         rgeo->rg_checked |= m->ioctl_mask;
     556       77884 :                 if (sick & m->sick_mask)
     557           0 :                         rgeo->rg_sick |= m->ioctl_mask;
     558             :         }
     559       19471 : }
     560             : 
     561             : static const struct ioctl_sick_map ino_map[] = {
     562             :         { XFS_SICK_INO_CORE,    XFS_BS_SICK_INODE },
     563             :         { XFS_SICK_INO_BMBTD,   XFS_BS_SICK_BMBTD },
     564             :         { XFS_SICK_INO_BMBTA,   XFS_BS_SICK_BMBTA },
     565             :         { XFS_SICK_INO_BMBTC,   XFS_BS_SICK_BMBTC },
     566             :         { XFS_SICK_INO_DIR,     XFS_BS_SICK_DIR },
     567             :         { XFS_SICK_INO_XATTR,   XFS_BS_SICK_XATTR },
     568             :         { XFS_SICK_INO_SYMLINK, XFS_BS_SICK_SYMLINK },
     569             :         { XFS_SICK_INO_PARENT,  XFS_BS_SICK_PARENT },
     570             :         { XFS_SICK_INO_DIRTREE, XFS_BS_SICK_DIRTREE },
     571             :         { 0, 0 },
     572             : };
     573             : 
     574             : /* Fill out bulkstat health info. */
     575             : void
     576 81727966102 : xfs_bulkstat_health(
     577             :         struct xfs_inode                *ip,
     578             :         struct xfs_bulkstat             *bs)
     579             : {
     580 81727966102 :         const struct ioctl_sick_map     *m;
     581 81727966102 :         unsigned int                    sick;
     582 81727966102 :         unsigned int                    checked;
     583             : 
     584 81727966102 :         bs->bs_sick = 0;
     585 81727966102 :         bs->bs_checked = 0;
     586             : 
     587 81727966102 :         xfs_inode_measure_sickness(ip, &sick, &checked);
     588 >90213*10^7 :         for (m = ino_map; m->sick_mask; m++) {
     589 >73685*10^7 :                 if (checked & m->sick_mask)
     590 15843569007 :                         bs->bs_checked |= m->ioctl_mask;
     591 >73685*10^7 :                 if (sick & m->sick_mask)
     592          66 :                         bs->bs_sick |= m->ioctl_mask;
     593             :         }
     594 82786551135 : }
     595             : 
     596             : /* Mark a block mapping sick. */
     597             : void
     598          20 : xfs_bmap_mark_sick(
     599             :         struct xfs_inode        *ip,
     600             :         int                     whichfork)
     601             : {
     602          20 :         unsigned int            mask;
     603             : 
     604          20 :         switch (whichfork) {
     605             :         case XFS_DATA_FORK:
     606             :                 mask = XFS_SICK_INO_BMBTD;
     607             :                 break;
     608             :         case XFS_ATTR_FORK:
     609             :                 mask = XFS_SICK_INO_BMBTA;
     610             :                 break;
     611             :         case XFS_COW_FORK:
     612             :                 mask = XFS_SICK_INO_BMBTC;
     613             :                 break;
     614           0 :         default:
     615           0 :                 ASSERT(0);
     616           0 :                 return;
     617             :         }
     618             : 
     619          20 :         xfs_inode_mark_sick(ip, mask);
     620             : }
     621             : 
     622             : /* Record observations of btree corruption with the health tracking system. */
     623             : void
     624        1363 : xfs_btree_mark_sick(
     625             :         struct xfs_btree_cur            *cur)
     626             : {
     627        1363 :         unsigned int                    mask;
     628             : 
     629        1363 :         if (cur->bc_flags & XFS_BTREE_IN_XFILE)
     630             :                 return;
     631             : 
     632        1363 :         switch (cur->bc_btnum) {
     633          10 :         case XFS_BTNUM_BMAP:
     634          10 :                 xfs_bmap_mark_sick(cur->bc_ino.ip, cur->bc_ino.whichfork);
     635          10 :                 return;
     636           2 :         case XFS_BTNUM_RTRMAP:
     637           2 :                 xfs_rtgroup_mark_sick(cur->bc_ino.rtg, XFS_SICK_RT_RMAPBT);
     638           2 :                 return;
     639           0 :         case XFS_BTNUM_RTREFC:
     640           0 :                 xfs_rtgroup_mark_sick(cur->bc_ino.rtg, XFS_SICK_RT_REFCNTBT);
     641           0 :                 return;
     642             :         case XFS_BTNUM_BNO:
     643             :                 mask = XFS_SICK_AG_BNOBT;
     644             :                 break;
     645         640 :         case XFS_BTNUM_CNT:
     646         640 :                 mask = XFS_SICK_AG_CNTBT;
     647         640 :                 break;
     648          11 :         case XFS_BTNUM_INO:
     649          11 :                 mask = XFS_SICK_AG_INOBT;
     650          11 :                 break;
     651          10 :         case XFS_BTNUM_FINO:
     652          10 :                 mask = XFS_SICK_AG_FINOBT;
     653          10 :                 break;
     654          20 :         case XFS_BTNUM_RMAP:
     655          20 :                 mask = XFS_SICK_AG_RMAPBT;
     656          20 :                 break;
     657          30 :         case XFS_BTNUM_REFC:
     658          30 :                 mask = XFS_SICK_AG_REFCNTBT;
     659          30 :                 break;
     660           0 :         default:
     661           0 :                 ASSERT(0);
     662           0 :                 return;
     663             :         }
     664             : 
     665        1351 :         xfs_ag_mark_sick(cur->bc_ag.pag, mask);
     666             : }
     667             : 
     668             : /*
     669             :  * Record observations of dir/attr btree corruption with the health tracking
     670             :  * system.
     671             :  */
     672             : void
     673         271 : xfs_dirattr_mark_sick(
     674             :         struct xfs_inode        *ip,
     675             :         int                     whichfork)
     676             : {
     677         271 :         unsigned int            mask;
     678             : 
     679         271 :         switch (whichfork) {
     680             :         case XFS_DATA_FORK:
     681             :                 mask = XFS_SICK_INO_DIR;
     682             :                 break;
     683          51 :         case XFS_ATTR_FORK:
     684          51 :                 mask = XFS_SICK_INO_XATTR;
     685          51 :                 break;
     686           0 :         default:
     687           0 :                 ASSERT(0);
     688           0 :                 return;
     689             :         }
     690             : 
     691         271 :         xfs_inode_mark_sick(ip, mask);
     692             : }
     693             : 
     694             : /*
     695             :  * Record observations of dir/attr btree corruption with the health tracking
     696             :  * system.
     697             :  */
     698             : void
     699           0 : xfs_da_mark_sick(
     700             :         struct xfs_da_args      *args)
     701             : {
     702           0 :         xfs_dirattr_mark_sick(args->dp, args->whichfork);
     703           0 : }

Generated by: LCOV version 1.14