162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2019 Oracle. All Rights Reserved. 462306a36Sopenharmony_ci * Author: Darrick J. Wong <darrick.wong@oracle.com> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#include "xfs.h" 762306a36Sopenharmony_ci#include "xfs_fs.h" 862306a36Sopenharmony_ci#include "xfs_shared.h" 962306a36Sopenharmony_ci#include "xfs_format.h" 1062306a36Sopenharmony_ci#include "xfs_log_format.h" 1162306a36Sopenharmony_ci#include "xfs_trans_resv.h" 1262306a36Sopenharmony_ci#include "xfs_mount.h" 1362306a36Sopenharmony_ci#include "xfs_inode.h" 1462306a36Sopenharmony_ci#include "xfs_trace.h" 1562306a36Sopenharmony_ci#include "xfs_health.h" 1662306a36Sopenharmony_ci#include "xfs_ag.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* 1962306a36Sopenharmony_ci * Warn about metadata corruption that we detected but haven't fixed, and 2062306a36Sopenharmony_ci * make sure we're not sitting on anything that would get in the way of 2162306a36Sopenharmony_ci * recovery. 2262306a36Sopenharmony_ci */ 2362306a36Sopenharmony_civoid 2462306a36Sopenharmony_cixfs_health_unmount( 2562306a36Sopenharmony_ci struct xfs_mount *mp) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci struct xfs_perag *pag; 2862306a36Sopenharmony_ci xfs_agnumber_t agno; 2962306a36Sopenharmony_ci unsigned int sick = 0; 3062306a36Sopenharmony_ci unsigned int checked = 0; 3162306a36Sopenharmony_ci bool warn = false; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci if (xfs_is_shutdown(mp)) 3462306a36Sopenharmony_ci return; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci /* Measure AG corruption levels. */ 3762306a36Sopenharmony_ci for_each_perag(mp, agno, pag) { 3862306a36Sopenharmony_ci xfs_ag_measure_sickness(pag, &sick, &checked); 3962306a36Sopenharmony_ci if (sick) { 4062306a36Sopenharmony_ci trace_xfs_ag_unfixed_corruption(mp, agno, sick); 4162306a36Sopenharmony_ci warn = true; 4262306a36Sopenharmony_ci } 4362306a36Sopenharmony_ci } 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci /* Measure realtime volume corruption levels. */ 4662306a36Sopenharmony_ci xfs_rt_measure_sickness(mp, &sick, &checked); 4762306a36Sopenharmony_ci if (sick) { 4862306a36Sopenharmony_ci trace_xfs_rt_unfixed_corruption(mp, sick); 4962306a36Sopenharmony_ci warn = true; 5062306a36Sopenharmony_ci } 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci /* 5362306a36Sopenharmony_ci * Measure fs corruption and keep the sample around for the warning. 5462306a36Sopenharmony_ci * See the note below for why we exempt FS_COUNTERS. 5562306a36Sopenharmony_ci */ 5662306a36Sopenharmony_ci xfs_fs_measure_sickness(mp, &sick, &checked); 5762306a36Sopenharmony_ci if (sick & ~XFS_SICK_FS_COUNTERS) { 5862306a36Sopenharmony_ci trace_xfs_fs_unfixed_corruption(mp, sick); 5962306a36Sopenharmony_ci warn = true; 6062306a36Sopenharmony_ci } 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci if (warn) { 6362306a36Sopenharmony_ci xfs_warn(mp, 6462306a36Sopenharmony_ci"Uncorrected metadata errors detected; please run xfs_repair."); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci /* 6762306a36Sopenharmony_ci * We discovered uncorrected metadata problems at some point 6862306a36Sopenharmony_ci * during this filesystem mount and have advised the 6962306a36Sopenharmony_ci * administrator to run repair once the unmount completes. 7062306a36Sopenharmony_ci * 7162306a36Sopenharmony_ci * However, we must be careful -- when FSCOUNTERS are flagged 7262306a36Sopenharmony_ci * unhealthy, the unmount procedure omits writing the clean 7362306a36Sopenharmony_ci * unmount record to the log so that the next mount will run 7462306a36Sopenharmony_ci * recovery and recompute the summary counters. In other 7562306a36Sopenharmony_ci * words, we leave a dirty log to get the counters fixed. 7662306a36Sopenharmony_ci * 7762306a36Sopenharmony_ci * Unfortunately, xfs_repair cannot recover dirty logs, so if 7862306a36Sopenharmony_ci * there were filesystem problems, FSCOUNTERS was flagged, and 7962306a36Sopenharmony_ci * the administrator takes our advice to run xfs_repair, 8062306a36Sopenharmony_ci * they'll have to zap the log before repairing structures. 8162306a36Sopenharmony_ci * We don't really want to encourage this, so we mark the 8262306a36Sopenharmony_ci * FSCOUNTERS healthy so that a subsequent repair run won't see 8362306a36Sopenharmony_ci * a dirty log. 8462306a36Sopenharmony_ci */ 8562306a36Sopenharmony_ci if (sick & XFS_SICK_FS_COUNTERS) 8662306a36Sopenharmony_ci xfs_fs_mark_healthy(mp, XFS_SICK_FS_COUNTERS); 8762306a36Sopenharmony_ci } 8862306a36Sopenharmony_ci} 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci/* Mark unhealthy per-fs metadata. */ 9162306a36Sopenharmony_civoid 9262306a36Sopenharmony_cixfs_fs_mark_sick( 9362306a36Sopenharmony_ci struct xfs_mount *mp, 9462306a36Sopenharmony_ci unsigned int mask) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci ASSERT(!(mask & ~XFS_SICK_FS_PRIMARY)); 9762306a36Sopenharmony_ci trace_xfs_fs_mark_sick(mp, mask); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci spin_lock(&mp->m_sb_lock); 10062306a36Sopenharmony_ci mp->m_fs_sick |= mask; 10162306a36Sopenharmony_ci mp->m_fs_checked |= mask; 10262306a36Sopenharmony_ci spin_unlock(&mp->m_sb_lock); 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci/* Mark a per-fs metadata healed. */ 10662306a36Sopenharmony_civoid 10762306a36Sopenharmony_cixfs_fs_mark_healthy( 10862306a36Sopenharmony_ci struct xfs_mount *mp, 10962306a36Sopenharmony_ci unsigned int mask) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci ASSERT(!(mask & ~XFS_SICK_FS_PRIMARY)); 11262306a36Sopenharmony_ci trace_xfs_fs_mark_healthy(mp, mask); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci spin_lock(&mp->m_sb_lock); 11562306a36Sopenharmony_ci mp->m_fs_sick &= ~mask; 11662306a36Sopenharmony_ci mp->m_fs_checked |= mask; 11762306a36Sopenharmony_ci spin_unlock(&mp->m_sb_lock); 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci/* Sample which per-fs metadata are unhealthy. */ 12162306a36Sopenharmony_civoid 12262306a36Sopenharmony_cixfs_fs_measure_sickness( 12362306a36Sopenharmony_ci struct xfs_mount *mp, 12462306a36Sopenharmony_ci unsigned int *sick, 12562306a36Sopenharmony_ci unsigned int *checked) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci spin_lock(&mp->m_sb_lock); 12862306a36Sopenharmony_ci *sick = mp->m_fs_sick; 12962306a36Sopenharmony_ci *checked = mp->m_fs_checked; 13062306a36Sopenharmony_ci spin_unlock(&mp->m_sb_lock); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci/* Mark unhealthy realtime metadata. */ 13462306a36Sopenharmony_civoid 13562306a36Sopenharmony_cixfs_rt_mark_sick( 13662306a36Sopenharmony_ci struct xfs_mount *mp, 13762306a36Sopenharmony_ci unsigned int mask) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci ASSERT(!(mask & ~XFS_SICK_RT_PRIMARY)); 14062306a36Sopenharmony_ci trace_xfs_rt_mark_sick(mp, mask); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci spin_lock(&mp->m_sb_lock); 14362306a36Sopenharmony_ci mp->m_rt_sick |= mask; 14462306a36Sopenharmony_ci mp->m_rt_checked |= mask; 14562306a36Sopenharmony_ci spin_unlock(&mp->m_sb_lock); 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci/* Mark a realtime metadata healed. */ 14962306a36Sopenharmony_civoid 15062306a36Sopenharmony_cixfs_rt_mark_healthy( 15162306a36Sopenharmony_ci struct xfs_mount *mp, 15262306a36Sopenharmony_ci unsigned int mask) 15362306a36Sopenharmony_ci{ 15462306a36Sopenharmony_ci ASSERT(!(mask & ~XFS_SICK_RT_PRIMARY)); 15562306a36Sopenharmony_ci trace_xfs_rt_mark_healthy(mp, mask); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci spin_lock(&mp->m_sb_lock); 15862306a36Sopenharmony_ci mp->m_rt_sick &= ~mask; 15962306a36Sopenharmony_ci mp->m_rt_checked |= mask; 16062306a36Sopenharmony_ci spin_unlock(&mp->m_sb_lock); 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci/* Sample which realtime metadata are unhealthy. */ 16462306a36Sopenharmony_civoid 16562306a36Sopenharmony_cixfs_rt_measure_sickness( 16662306a36Sopenharmony_ci struct xfs_mount *mp, 16762306a36Sopenharmony_ci unsigned int *sick, 16862306a36Sopenharmony_ci unsigned int *checked) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci spin_lock(&mp->m_sb_lock); 17162306a36Sopenharmony_ci *sick = mp->m_rt_sick; 17262306a36Sopenharmony_ci *checked = mp->m_rt_checked; 17362306a36Sopenharmony_ci spin_unlock(&mp->m_sb_lock); 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci/* Mark unhealthy per-ag metadata. */ 17762306a36Sopenharmony_civoid 17862306a36Sopenharmony_cixfs_ag_mark_sick( 17962306a36Sopenharmony_ci struct xfs_perag *pag, 18062306a36Sopenharmony_ci unsigned int mask) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci ASSERT(!(mask & ~XFS_SICK_AG_PRIMARY)); 18362306a36Sopenharmony_ci trace_xfs_ag_mark_sick(pag->pag_mount, pag->pag_agno, mask); 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci spin_lock(&pag->pag_state_lock); 18662306a36Sopenharmony_ci pag->pag_sick |= mask; 18762306a36Sopenharmony_ci pag->pag_checked |= mask; 18862306a36Sopenharmony_ci spin_unlock(&pag->pag_state_lock); 18962306a36Sopenharmony_ci} 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci/* Mark per-ag metadata ok. */ 19262306a36Sopenharmony_civoid 19362306a36Sopenharmony_cixfs_ag_mark_healthy( 19462306a36Sopenharmony_ci struct xfs_perag *pag, 19562306a36Sopenharmony_ci unsigned int mask) 19662306a36Sopenharmony_ci{ 19762306a36Sopenharmony_ci ASSERT(!(mask & ~XFS_SICK_AG_PRIMARY)); 19862306a36Sopenharmony_ci trace_xfs_ag_mark_healthy(pag->pag_mount, pag->pag_agno, mask); 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci spin_lock(&pag->pag_state_lock); 20162306a36Sopenharmony_ci pag->pag_sick &= ~mask; 20262306a36Sopenharmony_ci pag->pag_checked |= mask; 20362306a36Sopenharmony_ci spin_unlock(&pag->pag_state_lock); 20462306a36Sopenharmony_ci} 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci/* Sample which per-ag metadata are unhealthy. */ 20762306a36Sopenharmony_civoid 20862306a36Sopenharmony_cixfs_ag_measure_sickness( 20962306a36Sopenharmony_ci struct xfs_perag *pag, 21062306a36Sopenharmony_ci unsigned int *sick, 21162306a36Sopenharmony_ci unsigned int *checked) 21262306a36Sopenharmony_ci{ 21362306a36Sopenharmony_ci spin_lock(&pag->pag_state_lock); 21462306a36Sopenharmony_ci *sick = pag->pag_sick; 21562306a36Sopenharmony_ci *checked = pag->pag_checked; 21662306a36Sopenharmony_ci spin_unlock(&pag->pag_state_lock); 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci/* Mark the unhealthy parts of an inode. */ 22062306a36Sopenharmony_civoid 22162306a36Sopenharmony_cixfs_inode_mark_sick( 22262306a36Sopenharmony_ci struct xfs_inode *ip, 22362306a36Sopenharmony_ci unsigned int mask) 22462306a36Sopenharmony_ci{ 22562306a36Sopenharmony_ci ASSERT(!(mask & ~XFS_SICK_INO_PRIMARY)); 22662306a36Sopenharmony_ci trace_xfs_inode_mark_sick(ip, mask); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci spin_lock(&ip->i_flags_lock); 22962306a36Sopenharmony_ci ip->i_sick |= mask; 23062306a36Sopenharmony_ci ip->i_checked |= mask; 23162306a36Sopenharmony_ci spin_unlock(&ip->i_flags_lock); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci /* 23462306a36Sopenharmony_ci * Keep this inode around so we don't lose the sickness report. Scrub 23562306a36Sopenharmony_ci * grabs inodes with DONTCACHE assuming that most inode are ok, which 23662306a36Sopenharmony_ci * is not the case here. 23762306a36Sopenharmony_ci */ 23862306a36Sopenharmony_ci spin_lock(&VFS_I(ip)->i_lock); 23962306a36Sopenharmony_ci VFS_I(ip)->i_state &= ~I_DONTCACHE; 24062306a36Sopenharmony_ci spin_unlock(&VFS_I(ip)->i_lock); 24162306a36Sopenharmony_ci} 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci/* Mark parts of an inode healed. */ 24462306a36Sopenharmony_civoid 24562306a36Sopenharmony_cixfs_inode_mark_healthy( 24662306a36Sopenharmony_ci struct xfs_inode *ip, 24762306a36Sopenharmony_ci unsigned int mask) 24862306a36Sopenharmony_ci{ 24962306a36Sopenharmony_ci ASSERT(!(mask & ~XFS_SICK_INO_PRIMARY)); 25062306a36Sopenharmony_ci trace_xfs_inode_mark_healthy(ip, mask); 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci spin_lock(&ip->i_flags_lock); 25362306a36Sopenharmony_ci ip->i_sick &= ~mask; 25462306a36Sopenharmony_ci ip->i_checked |= mask; 25562306a36Sopenharmony_ci spin_unlock(&ip->i_flags_lock); 25662306a36Sopenharmony_ci} 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci/* Sample which parts of an inode are unhealthy. */ 25962306a36Sopenharmony_civoid 26062306a36Sopenharmony_cixfs_inode_measure_sickness( 26162306a36Sopenharmony_ci struct xfs_inode *ip, 26262306a36Sopenharmony_ci unsigned int *sick, 26362306a36Sopenharmony_ci unsigned int *checked) 26462306a36Sopenharmony_ci{ 26562306a36Sopenharmony_ci spin_lock(&ip->i_flags_lock); 26662306a36Sopenharmony_ci *sick = ip->i_sick; 26762306a36Sopenharmony_ci *checked = ip->i_checked; 26862306a36Sopenharmony_ci spin_unlock(&ip->i_flags_lock); 26962306a36Sopenharmony_ci} 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci/* Mappings between internal sick masks and ioctl sick masks. */ 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_cistruct ioctl_sick_map { 27462306a36Sopenharmony_ci unsigned int sick_mask; 27562306a36Sopenharmony_ci unsigned int ioctl_mask; 27662306a36Sopenharmony_ci}; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_cistatic const struct ioctl_sick_map fs_map[] = { 27962306a36Sopenharmony_ci { XFS_SICK_FS_COUNTERS, XFS_FSOP_GEOM_SICK_COUNTERS}, 28062306a36Sopenharmony_ci { XFS_SICK_FS_UQUOTA, XFS_FSOP_GEOM_SICK_UQUOTA }, 28162306a36Sopenharmony_ci { XFS_SICK_FS_GQUOTA, XFS_FSOP_GEOM_SICK_GQUOTA }, 28262306a36Sopenharmony_ci { XFS_SICK_FS_PQUOTA, XFS_FSOP_GEOM_SICK_PQUOTA }, 28362306a36Sopenharmony_ci { 0, 0 }, 28462306a36Sopenharmony_ci}; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_cistatic const struct ioctl_sick_map rt_map[] = { 28762306a36Sopenharmony_ci { XFS_SICK_RT_BITMAP, XFS_FSOP_GEOM_SICK_RT_BITMAP }, 28862306a36Sopenharmony_ci { XFS_SICK_RT_SUMMARY, XFS_FSOP_GEOM_SICK_RT_SUMMARY }, 28962306a36Sopenharmony_ci { 0, 0 }, 29062306a36Sopenharmony_ci}; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_cistatic inline void 29362306a36Sopenharmony_cixfgeo_health_tick( 29462306a36Sopenharmony_ci struct xfs_fsop_geom *geo, 29562306a36Sopenharmony_ci unsigned int sick, 29662306a36Sopenharmony_ci unsigned int checked, 29762306a36Sopenharmony_ci const struct ioctl_sick_map *m) 29862306a36Sopenharmony_ci{ 29962306a36Sopenharmony_ci if (checked & m->sick_mask) 30062306a36Sopenharmony_ci geo->checked |= m->ioctl_mask; 30162306a36Sopenharmony_ci if (sick & m->sick_mask) 30262306a36Sopenharmony_ci geo->sick |= m->ioctl_mask; 30362306a36Sopenharmony_ci} 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci/* Fill out fs geometry health info. */ 30662306a36Sopenharmony_civoid 30762306a36Sopenharmony_cixfs_fsop_geom_health( 30862306a36Sopenharmony_ci struct xfs_mount *mp, 30962306a36Sopenharmony_ci struct xfs_fsop_geom *geo) 31062306a36Sopenharmony_ci{ 31162306a36Sopenharmony_ci const struct ioctl_sick_map *m; 31262306a36Sopenharmony_ci unsigned int sick; 31362306a36Sopenharmony_ci unsigned int checked; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci geo->sick = 0; 31662306a36Sopenharmony_ci geo->checked = 0; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci xfs_fs_measure_sickness(mp, &sick, &checked); 31962306a36Sopenharmony_ci for (m = fs_map; m->sick_mask; m++) 32062306a36Sopenharmony_ci xfgeo_health_tick(geo, sick, checked, m); 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci xfs_rt_measure_sickness(mp, &sick, &checked); 32362306a36Sopenharmony_ci for (m = rt_map; m->sick_mask; m++) 32462306a36Sopenharmony_ci xfgeo_health_tick(geo, sick, checked, m); 32562306a36Sopenharmony_ci} 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_cistatic const struct ioctl_sick_map ag_map[] = { 32862306a36Sopenharmony_ci { XFS_SICK_AG_SB, XFS_AG_GEOM_SICK_SB }, 32962306a36Sopenharmony_ci { XFS_SICK_AG_AGF, XFS_AG_GEOM_SICK_AGF }, 33062306a36Sopenharmony_ci { XFS_SICK_AG_AGFL, XFS_AG_GEOM_SICK_AGFL }, 33162306a36Sopenharmony_ci { XFS_SICK_AG_AGI, XFS_AG_GEOM_SICK_AGI }, 33262306a36Sopenharmony_ci { XFS_SICK_AG_BNOBT, XFS_AG_GEOM_SICK_BNOBT }, 33362306a36Sopenharmony_ci { XFS_SICK_AG_CNTBT, XFS_AG_GEOM_SICK_CNTBT }, 33462306a36Sopenharmony_ci { XFS_SICK_AG_INOBT, XFS_AG_GEOM_SICK_INOBT }, 33562306a36Sopenharmony_ci { XFS_SICK_AG_FINOBT, XFS_AG_GEOM_SICK_FINOBT }, 33662306a36Sopenharmony_ci { XFS_SICK_AG_RMAPBT, XFS_AG_GEOM_SICK_RMAPBT }, 33762306a36Sopenharmony_ci { XFS_SICK_AG_REFCNTBT, XFS_AG_GEOM_SICK_REFCNTBT }, 33862306a36Sopenharmony_ci { 0, 0 }, 33962306a36Sopenharmony_ci}; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci/* Fill out ag geometry health info. */ 34262306a36Sopenharmony_civoid 34362306a36Sopenharmony_cixfs_ag_geom_health( 34462306a36Sopenharmony_ci struct xfs_perag *pag, 34562306a36Sopenharmony_ci struct xfs_ag_geometry *ageo) 34662306a36Sopenharmony_ci{ 34762306a36Sopenharmony_ci const struct ioctl_sick_map *m; 34862306a36Sopenharmony_ci unsigned int sick; 34962306a36Sopenharmony_ci unsigned int checked; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci ageo->ag_sick = 0; 35262306a36Sopenharmony_ci ageo->ag_checked = 0; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci xfs_ag_measure_sickness(pag, &sick, &checked); 35562306a36Sopenharmony_ci for (m = ag_map; m->sick_mask; m++) { 35662306a36Sopenharmony_ci if (checked & m->sick_mask) 35762306a36Sopenharmony_ci ageo->ag_checked |= m->ioctl_mask; 35862306a36Sopenharmony_ci if (sick & m->sick_mask) 35962306a36Sopenharmony_ci ageo->ag_sick |= m->ioctl_mask; 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci} 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_cistatic const struct ioctl_sick_map ino_map[] = { 36462306a36Sopenharmony_ci { XFS_SICK_INO_CORE, XFS_BS_SICK_INODE }, 36562306a36Sopenharmony_ci { XFS_SICK_INO_BMBTD, XFS_BS_SICK_BMBTD }, 36662306a36Sopenharmony_ci { XFS_SICK_INO_BMBTA, XFS_BS_SICK_BMBTA }, 36762306a36Sopenharmony_ci { XFS_SICK_INO_BMBTC, XFS_BS_SICK_BMBTC }, 36862306a36Sopenharmony_ci { XFS_SICK_INO_DIR, XFS_BS_SICK_DIR }, 36962306a36Sopenharmony_ci { XFS_SICK_INO_XATTR, XFS_BS_SICK_XATTR }, 37062306a36Sopenharmony_ci { XFS_SICK_INO_SYMLINK, XFS_BS_SICK_SYMLINK }, 37162306a36Sopenharmony_ci { XFS_SICK_INO_PARENT, XFS_BS_SICK_PARENT }, 37262306a36Sopenharmony_ci { 0, 0 }, 37362306a36Sopenharmony_ci}; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci/* Fill out bulkstat health info. */ 37662306a36Sopenharmony_civoid 37762306a36Sopenharmony_cixfs_bulkstat_health( 37862306a36Sopenharmony_ci struct xfs_inode *ip, 37962306a36Sopenharmony_ci struct xfs_bulkstat *bs) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci const struct ioctl_sick_map *m; 38262306a36Sopenharmony_ci unsigned int sick; 38362306a36Sopenharmony_ci unsigned int checked; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci bs->bs_sick = 0; 38662306a36Sopenharmony_ci bs->bs_checked = 0; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci xfs_inode_measure_sickness(ip, &sick, &checked); 38962306a36Sopenharmony_ci for (m = ino_map; m->sick_mask; m++) { 39062306a36Sopenharmony_ci if (checked & m->sick_mask) 39162306a36Sopenharmony_ci bs->bs_checked |= m->ioctl_mask; 39262306a36Sopenharmony_ci if (sick & m->sick_mask) 39362306a36Sopenharmony_ci bs->bs_sick |= m->ioctl_mask; 39462306a36Sopenharmony_ci } 39562306a36Sopenharmony_ci} 396