1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. 4 * Copyright (C) 2017 Oracle. 5 * All Rights Reserved. 6 */ 7 #include "xfs.h" 8 #include "xfs_fs.h" 9 #include "xfs_format.h" 10 #include "xfs_log_format.h" 11 #include "xfs_shared.h" 12 #include "xfs_trans_resv.h" 13 #include "xfs_bit.h" 14 #include "xfs_sb.h" 15 #include "xfs_mount.h" 16 #include "xfs_defer.h" 17 #include "xfs_inode.h" 18 #include "xfs_btree.h" 19 #include "xfs_rmap.h" 20 #include "xfs_alloc_btree.h" 21 #include "xfs_alloc.h" 22 #include "xfs_ialloc.h" 23 24 /* Find the size of the AG, in blocks. */ 25 xfs_agblock_t 26 xfs_ag_block_count( 27 struct xfs_mount *mp, 28 xfs_agnumber_t agno) 29 { 30 ASSERT(agno < mp->m_sb.sb_agcount); 31 32 if (agno < mp->m_sb.sb_agcount - 1) 33 return mp->m_sb.sb_agblocks; 34 return mp->m_sb.sb_dblocks - (agno * mp->m_sb.sb_agblocks); 35 } 36 37 /* 38 * Verify that an AG block number pointer neither points outside the AG 39 * nor points at static metadata. 40 */ 41 bool 42 xfs_verify_agbno( 43 struct xfs_mount *mp, 44 xfs_agnumber_t agno, 45 xfs_agblock_t agbno) 46 { 47 xfs_agblock_t eoag; 48 49 eoag = xfs_ag_block_count(mp, agno); 50 if (agbno >= eoag) 51 return false; 52 if (agbno <= XFS_AGFL_BLOCK(mp)) 53 return false; 54 return true; 55 } 56 57 /* 58 * Verify that an FS block number pointer neither points outside the 59 * filesystem nor points at static AG metadata. 60 */ 61 bool 62 xfs_verify_fsbno( 63 struct xfs_mount *mp, 64 xfs_fsblock_t fsbno) 65 { 66 xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, fsbno); 67 68 if (agno >= mp->m_sb.sb_agcount) 69 return false; 70 return xfs_verify_agbno(mp, agno, XFS_FSB_TO_AGBNO(mp, fsbno)); 71 } 72 73 /* Calculate the first and last possible inode number in an AG. */ 74 void 75 xfs_agino_range( 76 struct xfs_mount *mp, 77 xfs_agnumber_t agno, 78 xfs_agino_t *first, 79 xfs_agino_t *last) 80 { 81 xfs_agblock_t bno; 82 xfs_agblock_t eoag; 83 84 eoag = xfs_ag_block_count(mp, agno); 85 86 /* 87 * Calculate the first inode, which will be in the first 88 * cluster-aligned block after the AGFL. 89 */ 90 bno = round_up(XFS_AGFL_BLOCK(mp) + 1, mp->m_cluster_align); 91 *first = XFS_AGB_TO_AGINO(mp, bno); 92 93 /* 94 * Calculate the last inode, which will be at the end of the 95 * last (aligned) cluster that can be allocated in the AG. 96 */ 97 bno = round_down(eoag, mp->m_cluster_align); 98 *last = XFS_AGB_TO_AGINO(mp, bno) - 1; 99 } 100 101 /* 102 * Verify that an AG inode number pointer neither points outside the AG 103 * nor points at static metadata. 104 */ 105 bool 106 xfs_verify_agino( 107 struct xfs_mount *mp, 108 xfs_agnumber_t agno, 109 xfs_agino_t agino) 110 { 111 xfs_agino_t first; 112 xfs_agino_t last; 113 114 xfs_agino_range(mp, agno, &first, &last); 115 return agino >= first && agino <= last; 116 } 117 118 /* 119 * Verify that an AG inode number pointer neither points outside the AG 120 * nor points at static metadata, or is NULLAGINO. 121 */ 122 bool 123 xfs_verify_agino_or_null( 124 struct xfs_mount *mp, 125 xfs_agnumber_t agno, 126 xfs_agino_t agino) 127 { 128 return agino == NULLAGINO || xfs_verify_agino(mp, agno, agino); 129 } 130 131 /* 132 * Verify that an FS inode number pointer neither points outside the 133 * filesystem nor points at static AG metadata. 134 */ 135 bool 136 xfs_verify_ino( 137 struct xfs_mount *mp, 138 xfs_ino_t ino) 139 { 140 xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, ino); 141 xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ino); 142 143 if (agno >= mp->m_sb.sb_agcount) 144 return false; 145 if (XFS_AGINO_TO_INO(mp, agno, agino) != ino) 146 return false; 147 return xfs_verify_agino(mp, agno, agino); 148 } 149 150 /* Is this an internal inode number? */ 151 bool 152 xfs_internal_inum( 153 struct xfs_mount *mp, 154 xfs_ino_t ino) 155 { 156 return ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino || 157 (xfs_sb_version_hasquota(&mp->m_sb) && 158 xfs_is_quota_inode(&mp->m_sb, ino)); 159 } 160 161 /* 162 * Verify that a directory entry's inode number doesn't point at an internal 163 * inode, empty space, or static AG metadata. 164 */ 165 bool 166 xfs_verify_dir_ino( 167 struct xfs_mount *mp, 168 xfs_ino_t ino) 169 { 170 if (xfs_internal_inum(mp, ino)) 171 return false; 172 return xfs_verify_ino(mp, ino); 173 } 174 175 /* 176 * Verify that an realtime block number pointer doesn't point off the 177 * end of the realtime device. 178 */ 179 bool 180 xfs_verify_rtbno( 181 struct xfs_mount *mp, 182 xfs_rtblock_t rtbno) 183 { 184 return rtbno < mp->m_sb.sb_rblocks; 185 } 186 187 /* Calculate the range of valid icount values. */ 188 void 189 xfs_icount_range( 190 struct xfs_mount *mp, 191 unsigned long long *min, 192 unsigned long long *max) 193 { 194 unsigned long long nr_inos = 0; 195 xfs_agnumber_t agno; 196 197 /* root, rtbitmap, rtsum all live in the first chunk */ 198 *min = XFS_INODES_PER_CHUNK; 199 200 for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { 201 xfs_agino_t first, last; 202 203 xfs_agino_range(mp, agno, &first, &last); 204 nr_inos += last - first + 1; 205 } 206 *max = nr_inos; 207 } 208 209 /* Sanity-checking of inode counts. */ 210 bool 211 xfs_verify_icount( 212 struct xfs_mount *mp, 213 unsigned long long icount) 214 { 215 unsigned long long min, max; 216 217 xfs_icount_range(mp, &min, &max); 218 return icount >= min && icount <= max; 219 } 220 221 /* Sanity-checking of dir/attr block offsets. */ 222 bool 223 xfs_verify_dablk( 224 struct xfs_mount *mp, 225 xfs_fileoff_t dabno) 226 { 227 xfs_dablk_t max_dablk = -1U; 228 229 return dabno <= max_dablk; 230 } 231