1*4860a05dSDarrick J. Wong // SPDX-License-Identifier: GPL-2.0+ 2*4860a05dSDarrick J. Wong /* 3*4860a05dSDarrick J. Wong * Copyright (C) 2019 Oracle. All Rights Reserved. 4*4860a05dSDarrick J. Wong * Author: Darrick J. Wong <darrick.wong@oracle.com> 5*4860a05dSDarrick J. Wong */ 6*4860a05dSDarrick J. Wong #include "xfs.h" 7*4860a05dSDarrick J. Wong #include "xfs_fs.h" 8*4860a05dSDarrick J. Wong #include "xfs_shared.h" 9*4860a05dSDarrick J. Wong #include "xfs_format.h" 10*4860a05dSDarrick J. Wong #include "xfs_trans_resv.h" 11*4860a05dSDarrick J. Wong #include "xfs_mount.h" 12*4860a05dSDarrick J. Wong #include "xfs_defer.h" 13*4860a05dSDarrick J. Wong #include "xfs_btree.h" 14*4860a05dSDarrick J. Wong #include "xfs_bit.h" 15*4860a05dSDarrick J. Wong #include "xfs_log_format.h" 16*4860a05dSDarrick J. Wong #include "xfs_trans.h" 17*4860a05dSDarrick J. Wong #include "xfs_sb.h" 18*4860a05dSDarrick J. Wong #include "xfs_inode.h" 19*4860a05dSDarrick J. Wong #include "xfs_health.h" 20*4860a05dSDarrick J. Wong #include "scrub/scrub.h" 21*4860a05dSDarrick J. Wong #include "scrub/health.h" 22*4860a05dSDarrick J. Wong 23*4860a05dSDarrick J. Wong /* 24*4860a05dSDarrick J. Wong * Scrub and In-Core Filesystem Health Assessments 25*4860a05dSDarrick J. Wong * =============================================== 26*4860a05dSDarrick J. Wong * 27*4860a05dSDarrick J. Wong * Online scrub and repair have the time and the ability to perform stronger 28*4860a05dSDarrick J. Wong * checks than we can do from the metadata verifiers, because they can 29*4860a05dSDarrick J. Wong * cross-reference records between data structures. Therefore, scrub is in a 30*4860a05dSDarrick J. Wong * good position to update the online filesystem health assessments to reflect 31*4860a05dSDarrick J. Wong * the good/bad state of the data structure. 32*4860a05dSDarrick J. Wong * 33*4860a05dSDarrick J. Wong * We therefore extend scrub in the following ways to achieve this: 34*4860a05dSDarrick J. Wong * 35*4860a05dSDarrick J. Wong * 1. Create a "sick_mask" field in the scrub context. When we're setting up a 36*4860a05dSDarrick J. Wong * scrub call, set this to the default XFS_SICK_* flag(s) for the selected 37*4860a05dSDarrick J. Wong * scrub type (call it A). Scrub and repair functions can override the default 38*4860a05dSDarrick J. Wong * sick_mask value if they choose. 39*4860a05dSDarrick J. Wong * 40*4860a05dSDarrick J. Wong * 2. If the scrubber returns a runtime error code, we exit making no changes 41*4860a05dSDarrick J. Wong * to the incore sick state. 42*4860a05dSDarrick J. Wong * 43*4860a05dSDarrick J. Wong * 3. If the scrubber finds that A is clean, use sick_mask to clear the incore 44*4860a05dSDarrick J. Wong * sick flags before exiting. 45*4860a05dSDarrick J. Wong * 46*4860a05dSDarrick J. Wong * 4. If the scrubber finds that A is corrupt, use sick_mask to set the incore 47*4860a05dSDarrick J. Wong * sick flags. If the user didn't want to repair then we exit, leaving the 48*4860a05dSDarrick J. Wong * metadata structure unfixed and the sick flag set. 49*4860a05dSDarrick J. Wong * 50*4860a05dSDarrick J. Wong * 5. Now we know that A is corrupt and the user wants to repair, so run the 51*4860a05dSDarrick J. Wong * repairer. If the repairer returns an error code, we exit with that error 52*4860a05dSDarrick J. Wong * code, having made no further changes to the incore sick state. 53*4860a05dSDarrick J. Wong * 54*4860a05dSDarrick J. Wong * 6. If repair rebuilds A correctly and the subsequent re-scrub of A is clean, 55*4860a05dSDarrick J. Wong * use sick_mask to clear the incore sick flags. This should have the effect 56*4860a05dSDarrick J. Wong * that A is no longer marked sick. 57*4860a05dSDarrick J. Wong * 58*4860a05dSDarrick J. Wong * 7. If repair rebuilds A incorrectly, the re-scrub will find it corrupt and 59*4860a05dSDarrick J. Wong * use sick_mask to set the incore sick flags. This should have no externally 60*4860a05dSDarrick J. Wong * visible effect since we already set them in step (4). 61*4860a05dSDarrick J. Wong * 62*4860a05dSDarrick J. Wong * There are some complications to this story, however. For certain types of 63*4860a05dSDarrick J. Wong * complementary metadata indices (e.g. inobt/finobt), it is easier to rebuild 64*4860a05dSDarrick J. Wong * both structures at the same time. The following principles apply to this 65*4860a05dSDarrick J. Wong * type of repair strategy: 66*4860a05dSDarrick J. Wong * 67*4860a05dSDarrick J. Wong * 8. Any repair function that rebuilds multiple structures should update 68*4860a05dSDarrick J. Wong * sick_mask_visible to reflect whatever other structures are rebuilt, and 69*4860a05dSDarrick J. Wong * verify that all the rebuilt structures can pass a scrub check. The outcomes 70*4860a05dSDarrick J. Wong * of 5-7 still apply, but with a sick_mask that covers everything being 71*4860a05dSDarrick J. Wong * rebuilt. 72*4860a05dSDarrick J. Wong */ 73*4860a05dSDarrick J. Wong 74*4860a05dSDarrick J. Wong /* Map our scrub type to a sick mask and a set of health update functions. */ 75*4860a05dSDarrick J. Wong 76*4860a05dSDarrick J. Wong enum xchk_health_group { 77*4860a05dSDarrick J. Wong XHG_FS = 1, 78*4860a05dSDarrick J. Wong XHG_RT, 79*4860a05dSDarrick J. Wong XHG_AG, 80*4860a05dSDarrick J. Wong XHG_INO, 81*4860a05dSDarrick J. Wong }; 82*4860a05dSDarrick J. Wong 83*4860a05dSDarrick J. Wong struct xchk_health_map { 84*4860a05dSDarrick J. Wong enum xchk_health_group group; 85*4860a05dSDarrick J. Wong unsigned int sick_mask; 86*4860a05dSDarrick J. Wong }; 87*4860a05dSDarrick J. Wong 88*4860a05dSDarrick J. Wong static const struct xchk_health_map type_to_health_flag[XFS_SCRUB_TYPE_NR] = { 89*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_SB] = { XHG_AG, XFS_SICK_AG_SB }, 90*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_AGF] = { XHG_AG, XFS_SICK_AG_AGF }, 91*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_AGFL] = { XHG_AG, XFS_SICK_AG_AGFL }, 92*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_AGI] = { XHG_AG, XFS_SICK_AG_AGI }, 93*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_BNOBT] = { XHG_AG, XFS_SICK_AG_BNOBT }, 94*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_CNTBT] = { XHG_AG, XFS_SICK_AG_CNTBT }, 95*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_INOBT] = { XHG_AG, XFS_SICK_AG_INOBT }, 96*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_FINOBT] = { XHG_AG, XFS_SICK_AG_FINOBT }, 97*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_RMAPBT] = { XHG_AG, XFS_SICK_AG_RMAPBT }, 98*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_REFCNTBT] = { XHG_AG, XFS_SICK_AG_REFCNTBT }, 99*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_INODE] = { XHG_INO, XFS_SICK_INO_CORE }, 100*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_BMBTD] = { XHG_INO, XFS_SICK_INO_BMBTD }, 101*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_BMBTA] = { XHG_INO, XFS_SICK_INO_BMBTA }, 102*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_BMBTC] = { XHG_INO, XFS_SICK_INO_BMBTC }, 103*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_DIR] = { XHG_INO, XFS_SICK_INO_DIR }, 104*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_XATTR] = { XHG_INO, XFS_SICK_INO_XATTR }, 105*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_SYMLINK] = { XHG_INO, XFS_SICK_INO_SYMLINK }, 106*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_PARENT] = { XHG_INO, XFS_SICK_INO_PARENT }, 107*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_RTBITMAP] = { XHG_RT, XFS_SICK_RT_BITMAP }, 108*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_RTSUM] = { XHG_RT, XFS_SICK_RT_SUMMARY }, 109*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_UQUOTA] = { XHG_FS, XFS_SICK_FS_UQUOTA }, 110*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_GQUOTA] = { XHG_FS, XFS_SICK_FS_GQUOTA }, 111*4860a05dSDarrick J. Wong [XFS_SCRUB_TYPE_PQUOTA] = { XHG_FS, XFS_SICK_FS_PQUOTA }, 112*4860a05dSDarrick J. Wong }; 113*4860a05dSDarrick J. Wong 114*4860a05dSDarrick J. Wong /* Return the health status mask for this scrub type. */ 115*4860a05dSDarrick J. Wong unsigned int 116*4860a05dSDarrick J. Wong xchk_health_mask_for_scrub_type( 117*4860a05dSDarrick J. Wong __u32 scrub_type) 118*4860a05dSDarrick J. Wong { 119*4860a05dSDarrick J. Wong return type_to_health_flag[scrub_type].sick_mask; 120*4860a05dSDarrick J. Wong } 121*4860a05dSDarrick J. Wong 122*4860a05dSDarrick J. Wong /* 123*4860a05dSDarrick J. Wong * Update filesystem health assessments based on what we found and did. 124*4860a05dSDarrick J. Wong * 125*4860a05dSDarrick J. Wong * If the scrubber finds errors, we mark sick whatever's mentioned in 126*4860a05dSDarrick J. Wong * sick_mask, no matter whether this is a first scan or an 127*4860a05dSDarrick J. Wong * evaluation of repair effectiveness. 128*4860a05dSDarrick J. Wong * 129*4860a05dSDarrick J. Wong * Otherwise, no direct corruption was found, so mark whatever's in 130*4860a05dSDarrick J. Wong * sick_mask as healthy. 131*4860a05dSDarrick J. Wong */ 132*4860a05dSDarrick J. Wong void 133*4860a05dSDarrick J. Wong xchk_update_health( 134*4860a05dSDarrick J. Wong struct xfs_scrub *sc) 135*4860a05dSDarrick J. Wong { 136*4860a05dSDarrick J. Wong struct xfs_perag *pag; 137*4860a05dSDarrick J. Wong bool bad; 138*4860a05dSDarrick J. Wong 139*4860a05dSDarrick J. Wong if (!sc->sick_mask) 140*4860a05dSDarrick J. Wong return; 141*4860a05dSDarrick J. Wong 142*4860a05dSDarrick J. Wong bad = (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT); 143*4860a05dSDarrick J. Wong switch (type_to_health_flag[sc->sm->sm_type].group) { 144*4860a05dSDarrick J. Wong case XHG_AG: 145*4860a05dSDarrick J. Wong pag = xfs_perag_get(sc->mp, sc->sm->sm_agno); 146*4860a05dSDarrick J. Wong if (bad) 147*4860a05dSDarrick J. Wong xfs_ag_mark_sick(pag, sc->sick_mask); 148*4860a05dSDarrick J. Wong else 149*4860a05dSDarrick J. Wong xfs_ag_mark_healthy(pag, sc->sick_mask); 150*4860a05dSDarrick J. Wong xfs_perag_put(pag); 151*4860a05dSDarrick J. Wong break; 152*4860a05dSDarrick J. Wong case XHG_INO: 153*4860a05dSDarrick J. Wong if (!sc->ip) 154*4860a05dSDarrick J. Wong return; 155*4860a05dSDarrick J. Wong if (bad) 156*4860a05dSDarrick J. Wong xfs_inode_mark_sick(sc->ip, sc->sick_mask); 157*4860a05dSDarrick J. Wong else 158*4860a05dSDarrick J. Wong xfs_inode_mark_healthy(sc->ip, sc->sick_mask); 159*4860a05dSDarrick J. Wong break; 160*4860a05dSDarrick J. Wong case XHG_FS: 161*4860a05dSDarrick J. Wong if (bad) 162*4860a05dSDarrick J. Wong xfs_fs_mark_sick(sc->mp, sc->sick_mask); 163*4860a05dSDarrick J. Wong else 164*4860a05dSDarrick J. Wong xfs_fs_mark_healthy(sc->mp, sc->sick_mask); 165*4860a05dSDarrick J. Wong break; 166*4860a05dSDarrick J. Wong case XHG_RT: 167*4860a05dSDarrick J. Wong if (bad) 168*4860a05dSDarrick J. Wong xfs_rt_mark_sick(sc->mp, sc->sick_mask); 169*4860a05dSDarrick J. Wong else 170*4860a05dSDarrick J. Wong xfs_rt_mark_healthy(sc->mp, sc->sick_mask); 171*4860a05dSDarrick J. Wong break; 172*4860a05dSDarrick J. Wong default: 173*4860a05dSDarrick J. Wong ASSERT(0); 174*4860a05dSDarrick J. Wong break; 175*4860a05dSDarrick J. Wong } 176*4860a05dSDarrick J. Wong } 177